summaryrefslogtreecommitdiffstats
path: root/crypto/x509
diff options
context:
space:
mode:
authorViktor Dukhovni <openssl-users@dukhovni.org>2014-06-22 01:38:57 -0400
committerViktor Dukhovni <openssl-users@dukhovni.org>2014-06-22 20:32:35 -0400
commit8abffa4a73fcbf6536e0a42d736ed9211a8204ea (patch)
treec56ae9164778b27dc1b03008b9377b2125cedb28 /crypto/x509
parent66d884f06770f2daaee8016299ef7e1e3b91dfd1 (diff)
Multiple verifier reference identities.
Implemented as STACK_OF(OPENSSL_STRING).
Diffstat (limited to 'crypto/x509')
-rw-r--r--crypto/x509/x509_lcl.h2
-rw-r--r--crypto/x509/x509_vfy.c17
-rw-r--r--crypto/x509/x509_vfy.h2
-rw-r--r--crypto/x509/x509_vpm.c91
4 files changed, 102 insertions, 10 deletions
diff --git a/crypto/x509/x509_lcl.h b/crypto/x509/x509_lcl.h
index a71af342dc..a20bed287d 100644
--- a/crypto/x509/x509_lcl.h
+++ b/crypto/x509/x509_lcl.h
@@ -60,7 +60,7 @@
struct X509_VERIFY_PARAM_ID_st
{
- unsigned char *host; /* If not NULL hostname to match */
+ STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */
unsigned int hostflags; /* Flags to control matching features */
unsigned char *email; /* If not NULL email address to match */
size_t emaillen;
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index b6f16bb772..49425f4622 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -743,12 +743,27 @@ static int check_id_error(X509_STORE_CTX *ctx, int errcode)
return ctx->verify_cb(0, ctx);
}
+static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id)
+ {
+ int i;
+ int n = sk_OPENSSL_STRING_num(id->hosts);
+ unsigned char *name;
+
+ for (i = 0; i < n; ++i)
+ {
+ name = (unsigned char *)sk_OPENSSL_STRING_value(id->hosts, i);
+ if (X509_check_host(x, name, 0, id->hostflags)) > 0)
+ return 1;
+ }
+ return n == 0;
+ }
+
static int check_id(X509_STORE_CTX *ctx)
{
X509_VERIFY_PARAM *vpm = ctx->param;
X509_VERIFY_PARAM_ID *id = vpm->id;
X509 *x = ctx->cert;
- if (id->host && X509_check_host(x, id->host, 0, id->hostflags) <= 0)
+ if (id->hosts && !check_hosts(x, id) <= 0)
{
if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
return 0;
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index 4b61d28d74..4aca857fda 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -560,6 +560,8 @@ 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);
+int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
+ const unsigned char *name, size_t namelen);
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
unsigned int flags);
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c
index d7cc231d58..d95943c22c 100644
--- a/crypto/x509/x509_vpm.c
+++ b/crypto/x509/x509_vpm.c
@@ -69,6 +69,63 @@
/* 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,