Commit 8abffa4a authored by Viktor Dukhovni's avatar Viktor Dukhovni
Browse files

Multiple verifier reference identities.

Implemented as STACK_OF(OPENSSL_STRING).
parent 66d884f0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+16 −1
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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,
+83 −8
Original line number Diff line number Diff line
@@ -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,12 +291,24 @@ 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 (dest->id->hosts)
			{
		if (!X509_VERIFY_PARAM_set1_host(dest, id->host, 0))
			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,
+23 −11
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@

=head1 NAME

X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags, X509_VERIFY_PARAM_get_flags, X509_VERIFY_PARAM_set_purpose, X509_VERIFY_PARAM_set_trust, X509_VERIFY_PARAM_set_depth, X509_VERIFY_PARAM_get_depth, X509_VERIFY_PARAM_set_time, X509_VERIFY_PARAM_add0_policy, X509_VERIFY_PARAM_set1_policies, X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_set_hostflags, X509_VERIFY_PARAM_set1_email, X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_set1_ip_asc - X509 verification parameters
X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags, X509_VERIFY_PARAM_get_flags, X509_VERIFY_PARAM_set_purpose, X509_VERIFY_PARAM_set_trust, X509_VERIFY_PARAM_set_depth, X509_VERIFY_PARAM_get_depth, X509_VERIFY_PARAM_set_time, X509_VERIFY_PARAM_add0_policy, X509_VERIFY_PARAM_set1_policies, X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_add1_host, X509_VERIFY_PARAM_set_hostflags, X509_VERIFY_PARAM_set1_email, X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_set1_ip_asc - X509 verification parameters

=head1 SYNOPSIS

@@ -28,6 +28,8 @@ X509_VERIFY_PARAM_set_flags, X509_VERIFY_PARAM_clear_flags, X509_VERIFY_PARAM_ge

 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,
@@ -72,16 +74,26 @@ X509_VERIFY_PARAM_set_depth() sets the maximum verification depth to B<depth>.
That is the maximum number of untrusted CA certificates that can appear in a
chain.

X509_VERIFY_PARAM_set1_host() sets the expected DNS hostname to B<name>.  If
B<name> is NUL-terminated, B<namelen> may be zero, otherwise B<namelen> must
be set to the length of B<name>.  When a hostname is specified, certificate
verification automatically invokes L<X509_check_host(3)> with flags equal to
the B<flags> argument given to B<X509_VERIFY_PARAM_set_hostflags()> (default
zero).  Applications are strongly advised to use this interface in preference
to explicitly calling L<X509_check_host(3)>, hostname checks are
out of scope with the DANE-EE(3) certificate usage, and the internal
check will be suppressed as appropriate when DANE support is added
to OpenSSL.
X509_VERIFY_PARAM_set1_host() sets the expected DNS hostname to
B<name> clearing any previously specified host name or names.  If
B<name> is NULL, or empty the list of hostnames is cleared, and
name checks are not performed on the peer certificate.  If B<name>
is NUL-terminated, B<namelen> may be zero, otherwise B<namelen>
must be set to the length of B<name>.  When a hostname is specified,
certificate verification automatically invokes L<X509_check_host(3)>
with flags equal to the B<flags> argument given to
B<X509_VERIFY_PARAM_set_hostflags()> (default zero).  Applications
are strongly advised to use this interface in preference to explicitly
calling L<X509_check_host(3)>, hostname checks are out of scope
with the DANE-EE(3) certificate usage, and the internal check will
be suppressed as appropriate when DANE support is added to OpenSSL.

X509_VERIFY_PARAM_add1_host() adds B<name> as an additional reference
identifer that can match the peer's certificate.  Any previous names
set via X509_VERIFY_PARAM_set1_host() or X509_VERIFY_PARAM_add1_host()
are retained, no change is made if B<name> is NULL or empty.  When
multiple names are configured, the peer is considered verified when
any name matches.

X509_VERIFY_PARAM_set1_email() sets the expected RFC822 email address to
B<email>.  If B<email> is NUL-terminated, B<emaillen> may be zero, otherwise
Loading