Multiple verifier reference identities.
[openssl.git] / crypto / x509 / x509_vpm.c
index d7cc231d58b85f09fab870da6416fb6672622c5b..d95943c22c0b0505bae06305f67d3b975fa5abb7 100644 (file)
 
 /* X509_VERIFY_PARAM functions */
 
+#define SET_HOST 0
+#define ADD_HOST 1
+
+static char *str_copy(const char *s) { return OPENSSL_strdup(s); }
+static void str_free(char *s) { OPENSSL_free(s); }
+
+#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
+
+static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
+                                   const unsigned char *name, size_t namelen)
+       {
+       char *copy;
+
+       /*
+        * Refuse names with embedded NUL bytes, except perhaps as final byte.
+        * XXX: Do we need to push an error onto the error stack?
+        */
+       if (namelen == 0)
+               namelen = name ? strlen((char *)name) : 0;
+       else if (name && memchr(name, '\0', namelen > 1 ? namelen-1 : namelen))
+                return 0;
+       if (name && name[namelen-1] == '\0')
+               --namelen;
+
+       if (mode == SET_HOST && id->hosts)
+               {
+               string_stack_free(id->hosts);
+               id->hosts = NULL;
+               }
+       if (name == NULL || namelen == 0)
+               return 1;
+
+       copy = BUF_strndup((char *)name, namelen);
+       if (copy == NULL)
+               return 0;
+
+       if (id->hosts == NULL &&
+           (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL)
+               {
+               OPENSSL_free(copy);
+               return 0;
+               }
+
+       if (!sk_OPENSSL_STRING_push(id->hosts, copy))
+               {
+               OPENSSL_free(copy);
+               if (sk_OPENSSL_STRING_num(id->hosts) == 0)
+                       {
+                       sk_OPENSSL_STRING_free(id->hosts);
+                       id->hosts = NULL;
+                       }
+               return 0;
+               }
+
+       return 1;
+       }
+
 static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
        {
        X509_VERIFY_PARAM_ID *paramid;
@@ -87,10 +144,10 @@ static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
                param->policies = NULL;
                }
        paramid = param->id;
-       if (paramid->host)
+       if (paramid->hosts)
                {
-               OPENSSL_free(paramid->host);
-               paramid->host = NULL;
+               string_stack_free(paramid->hosts);
+               paramid->hosts = NULL;
                }
        if (paramid->email)
                {
@@ -234,11 +291,23 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
                        return 0;
                }
 
-       if (test_x509_verify_param_copy_id(host, NULL))
+       /* Copy the host flags if and only if we're copying the host list */
+       if (test_x509_verify_param_copy_id(hosts, NULL))
                {
-               if (!X509_VERIFY_PARAM_set1_host(dest, id->host, 0))
-                       return 0;
-               dest->id->hostflags = id->hostflags;
+               if (dest->id->hosts)
+                       {
+                       string_stack_free(dest->id->hosts);
+                       dest->id->hosts = NULL;
+                       }
+               if (id->hosts)
+                       {
+                       dest->id->hosts =
+                           sk_OPENSSL_STRING_deep_copy(id->hosts,
+                                                       str_copy, str_free);
+                       if (dest->id->hosts == NULL)
+                               return 0;
+                       dest->id->hostflags = id->hostflags;
+                       }
                }
 
        if (test_x509_verify_param_copy_id(email, NULL))
@@ -398,7 +467,13 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
                                const unsigned char *name, size_t namelen)
        {
-       return int_x509_param_set1(&param->id->host, NULL, name, namelen);
+       return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
+       }
+
+int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
+                               const unsigned char *name, size_t namelen)
+       {
+       return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
        }
 
 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,