Unix build: for mingw and cygwin, create the right location for DLLs
[openssl.git] / crypto / x509 / x_name.c
index ebb66a1aef894ab6d53243d83e7fcf1cbf1725fe..a1e9bbdb669d0cbdda5f61a35cf95077eac5b2b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -8,7 +8,7 @@
  */
 
 #include <stdio.h>
-#include <ctype.h>
+#include "internal/ctype.h"
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
@@ -35,7 +35,7 @@ static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
 
 static int x509_name_encode(X509_NAME *a);
 static int x509_name_canon(X509_NAME *a);
-static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
+static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in);
 static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname,
                           unsigned char **in);
 
@@ -125,6 +125,16 @@ static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
     *pval = NULL;
 }
 
+static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
+{
+    sk_X509_NAME_ENTRY_free(ne);
+}
+
+static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
+{
+    sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
+}
+
 static int x509_name_ex_d2i(ASN1_VALUE **val,
                             const unsigned char **in, long len,
                             const ASN1_ITEM *it, int tag, int aclass,
@@ -173,37 +183,26 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
         for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
             entry = sk_X509_NAME_ENTRY_value(entries, j);
             entry->set = i;
-            if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry)) {
-                /*
-                 * Free all in entries if sk_X509_NAME_ENTRY_push return failure.
-                 * X509_NAME_ENTRY_free will check the null entry.
-                 */
-                sk_X509_NAME_ENTRY_pop_free(entries, X509_NAME_ENTRY_free);
+            if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
                 goto err;
-            }
-            /*
-             * If sk_X509_NAME_ENTRY_push return success, clean the entries[j].
-             * It's necessary when 'goto err;' happens.
-             */
             sk_X509_NAME_ENTRY_set(entries, j, NULL);
         }
-        sk_X509_NAME_ENTRY_free(entries);
-        sk_STACK_OF_X509_NAME_ENTRY_set(intname.s, i, NULL);
     }
-
-    sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
-    intname.s = NULL;
     ret = x509_name_canon(nm.x);
     if (!ret)
         goto err;
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+                                         local_sk_X509_NAME_ENTRY_free);
     nm.x->modified = 0;
     *val = nm.a;
     *in = p;
     return ret;
 
  err:
-    X509_NAME_free(nm.x);
-    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s, sk_X509_NAME_ENTRY_free);
+    if (nm.x != NULL)
+        X509_NAME_free(nm.x);
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+                                         local_sk_X509_NAME_ENTRY_pop_free);
     ASN1err(ASN1_F_X509_NAME_EX_D2I, ERR_R_NESTED_ASN1_ERROR);
     return 0;
 }
@@ -229,16 +228,6 @@ static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
     return ret;
 }
 
-static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
-{
-    sk_X509_NAME_ENTRY_free(ne);
-}
-
-static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
-{
-    sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
-}
-
 static int x509_name_encode(X509_NAME *a)
 {
     union {
@@ -261,8 +250,10 @@ static int x509_name_encode(X509_NAME *a)
             entries = sk_X509_NAME_ENTRY_new_null();
             if (!entries)
                 goto memerr;
-            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries))
+            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) {
+                sk_X509_NAME_ENTRY_free(entries);
                 goto memerr;
+            }
             set = entry->set;
         }
         if (!sk_X509_NAME_ENTRY_push(entries, entry))
@@ -290,7 +281,7 @@ static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
                               int indent,
                               const char *fname, const ASN1_PCTX *pctx)
 {
-    if (X509_NAME_print_ex(out, (X509_NAME *)*pval,
+    if (X509_NAME_print_ex(out, (const X509_NAME *)*pval,
                            indent, pctx->nm_flags) <= 0)
         return 0;
     return 2;
@@ -309,7 +300,7 @@ static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
 static int x509_name_canon(X509_NAME *a)
 {
     unsigned char *p;
-    STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
+    STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname;
     STACK_OF(X509_NAME_ENTRY) *entries = NULL;
     X509_NAME_ENTRY *entry, *tmpentry = NULL;
     int i, set = -1, ret = 0, len;
@@ -322,42 +313,53 @@ static int x509_name_canon(X509_NAME *a)
         return 1;
     }
     intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
-    if (!intname)
+    if (intname == NULL) {
+        X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
         goto err;
+    }
     for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
         entry = sk_X509_NAME_ENTRY_value(a->entries, i);
         if (entry->set != set) {
             entries = sk_X509_NAME_ENTRY_new_null();
-            if (!entries)
+            if (entries == NULL)
                 goto err;
-            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries))
+            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
+                sk_X509_NAME_ENTRY_free(entries);
+                X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
                 goto err;
+            }
             set = entry->set;
         }
         tmpentry = X509_NAME_ENTRY_new();
-        if (tmpentry == NULL)
+        if (tmpentry == NULL) {
+            X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
             goto err;
+        }
         tmpentry->object = OBJ_dup(entry->object);
-        if (tmpentry->object == NULL)
+        if (tmpentry->object == NULL) {
+            X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
             goto err;
+        }
         if (!asn1_string_canon(tmpentry->value, entry->value))
             goto err;
-        if (!sk_X509_NAME_ENTRY_push(entries, tmpentry))
+        if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) {
+            X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
             goto err;
+        }
         tmpentry = NULL;
     }
 
     /* Finally generate encoding */
-
     len = i2d_name_canon(intname, NULL);
     if (len < 0)
         goto err;
     a->canon_enclen = len;
 
     p = OPENSSL_malloc(a->canon_enclen);
-
-    if (p == NULL)
+    if (p == NULL) {
+        X509err(X509_F_X509_NAME_CANON, ERR_R_MALLOC_FAILURE);
         goto err;
+    }
 
     a->canon_enc = p;
 
@@ -366,7 +368,6 @@ static int x509_name_canon(X509_NAME *a)
     ret = 1;
 
  err:
-
     X509_NAME_ENTRY_free(tmpentry);
     sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
                                          local_sk_X509_NAME_ENTRY_pop_free);
@@ -380,7 +381,7 @@ static int x509_name_canon(X509_NAME *a)
         | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
         | B_ASN1_VISIBLESTRING)
 
-static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
+static int asn1_string_canon(ASN1_STRING *out, const ASN1_STRING *in)
 {
     unsigned char *to, *from;
     int len, i;
@@ -405,11 +406,12 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
     /*
      * Convert string in place to canonical form. Ultimately we may need to
      * handle a wider range of characters but for now ignore anything with
-     * MSB set and rely on the isspace() and tolower() functions.
+     * MSB set and rely on the ossl_isspace() to fail on bad characters without
+     * needing isascii or range checks as well.
      */
 
     /* Ignore leading spaces */
-    while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
+    while (len > 0 && ossl_isspace(*from)) {
         from++;
         len--;
     }
@@ -417,7 +419,7 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
     to = from + len;
 
     /* Ignore trailing spaces */
-    while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) {
+    while (len > 0 && ossl_isspace(to[-1])) {
         to--;
         len--;
     }
@@ -426,13 +428,13 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
 
     i = 0;
     while (i < len) {
-        /* If MSB set just copy across */
-        if (*from & 0x80) {
+        /* If not ASCII set just copy across */
+        if (!ossl_isascii(*from)) {
             *to++ = *from++;
             i++;
         }
         /* Collapse multiple spaces */
-        else if (isspace(*from)) {
+        else if (ossl_isspace(*from)) {
             /* Copy one space across */
             *to++ = ' ';
             /*
@@ -444,9 +446,9 @@ static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
                 from++;
                 i++;
             }
-            while (!(*from & 0x80) && isspace(*from));
+            while (ossl_isspace(*from));
         } else {
-            *to++ = tolower(*from);
+            *to++ = ossl_tolower(*from);
             from++;
             i++;
         }
@@ -479,22 +481,16 @@ static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
 
 int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
 {
-    X509_NAME *in;
-
-    if (!xn || !name)
-        return (0);
-
-    if (*xn != name) {
-        in = X509_NAME_dup(name);
-        if (in != NULL) {
-            X509_NAME_free(*xn);
-            *xn = in;
-        }
-    }
-    return (*xn != NULL);
+    if (*xn == name)
+        return *xn != NULL;
+    if ((name = X509_NAME_dup(name)) == NULL)
+        return 0;
+    X509_NAME_free(*xn);
+    *xn = name;
+    return 1;
 }
 
-int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
+int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
 {
     char *s, *c, *b;
     int l, i;
@@ -512,19 +508,10 @@ int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
 
     c = s;
     for (;;) {
-#ifndef CHARSET_EBCDIC
-        if (((*s == '/') &&
-             ((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') ||
-                                                 ((s[2] >= 'A')
-                                                  && (s[2] <= 'Z')
-                                                  && (s[3] == '='))
-              ))) || (*s == '\0'))
-#else
         if (((*s == '/') &&
-             (isupper(s[1]) && ((s[2] == '=') ||
-                                (isupper(s[2]) && (s[3] == '='))
+             (ossl_isupper(s[1]) && ((s[2] == '=') ||
+                                (ossl_isupper(s[2]) && (s[3] == '='))
               ))) || (*s == '\0'))
-#endif
         {
             i = s - c;
             if (BIO_write(bp, c, i) != i)
@@ -550,8 +537,8 @@ int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
     return 0;
 }
 
-int X509_NAME_get0_der(const unsigned char **pder, size_t *pderlen,
-                       X509_NAME *nm)
+int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
+                       size_t *pderlen)
 {
     /* Make sure encoding is valid */
     if (i2d_X509_NAME(nm, NULL) <= 0)