Commit dd36fce0 authored by Luiz Angelo Daros de Luca's avatar Luiz Angelo Daros de Luca Committed by Matt Caswell
Browse files

OpenSSL is able to generate a certificate with name constraints with any possible


subjectAltName field. The Name Contraint example in x509v3_config(5) even use IP
as an example:

	nameConstraints=permitted;IP:192.168.0.0/255.255.0.0

However, until now, the verify code for IP name contraints did not exist. Any
check with a IP Address Name Constraint results in a "unsupported name constraint
type" error.

This patch implements support for IP Address Name Constraint (v4 and v6). This code
validaded correcly certificates with multiple IPv4/IPv6 address checking against
a CA certificate with these constraints:

	permitted;IP.1=10.9.0.0/255.255.0.0
	permitted;IP.2=10.48.0.0/255.255.0.0
	permitted;IP.3=10.148.0.0/255.255.0.0
	permitted;IP.4=fdc8:123f:e31f::/ffff:ffff:ffff::

Signed-off-by: default avatarLuiz Angelo Daros de Luca <luizluca@gmail.com>
parent fda29b6d
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ static int nc_dn(X509_NAME *sub, X509_NAME *nm);
static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns);
static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml);
static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base);
static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base);

const X509V3_EXT_METHOD v3_name_constraints = {
	NID_name_constraints, 0,
@@ -362,6 +363,9 @@ static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
		return nc_uri(gen->d.uniformResourceIdentifier,
					base->d.uniformResourceIdentifier);

		case GEN_IPADD:
		return nc_ip(gen->d.iPAddress, base->d.iPAddress);

		default:
		return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
		}
@@ -503,3 +507,34 @@ static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
	return X509_V_OK;

	}

static int nc_ip(ASN1_OCTET_STRING *ip, ASN1_OCTET_STRING *base)
	{
	int hostlen, baselen, i;
	unsigned char *hostptr, *baseptr, *maskptr;
	hostptr = ip->data;
	hostlen = ip->length;
	baseptr = base->data;
	baselen = base->length;

	/* Invalid if not IPv4 or IPv6 */
	if (! ((hostlen == 4) || (hostlen==16)) )
		return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
	if (! ((baselen == 8) || (baselen==32)) )
		return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;

	/* Do not match IPv4 with IPv6 */
	if (hostlen*2 != baselen)
		return X509_V_ERR_PERMITTED_VIOLATION;

	maskptr = base->data + hostlen;

	/* Considering possible not aligned base ipAddress */
	/* Not checking for wrong mask definition: i.e.: 255.0.255.0*/
	for (i = 0; i < hostlen; i++)
		if ((hostptr[i] & maskptr[i]) != (baseptr[i] & maskptr[i]))
			return X509_V_ERR_PERMITTED_VIOLATION;

	return X509_V_OK;

	}