xref: /onnv-gate/usr/src/lib/libkmf/libkmf/common/rdn_parser.c (revision 5051:cbbb7c8b40a9)
13089Swyllys /*
23089Swyllys  * The contents of this file are subject to the Mozilla Public
33089Swyllys  * License Version 1.1 (the "License"); you may not use this file
43089Swyllys  * except in compliance with the License. You may obtain a copy of
53089Swyllys  * the License at http://www.mozilla.org/MPL/
63089Swyllys  *
73089Swyllys  * Software distributed under the License is distributed on an "AS
83089Swyllys  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
93089Swyllys  * implied. See the License for the specific language governing
103089Swyllys  * rights and limitations under the License.
113089Swyllys  *
123089Swyllys  * The Original Code is the Netscape security libraries.
133089Swyllys  *
143089Swyllys  * The Initial Developer of the Original Code is Netscape
153089Swyllys  * Communications Corporation.  Portions created by Netscape are
163089Swyllys  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
173089Swyllys  * Rights Reserved.
183089Swyllys  *
193089Swyllys  * Contributor(s):
203089Swyllys  *
213089Swyllys  * Alternatively, the contents of this file may be used under the
223089Swyllys  * terms of the GNU General Public License Version 2 or later (the
233089Swyllys  * "GPL"), in which case the provisions of the GPL are applicable
243089Swyllys  * instead of those above.  If you wish to allow use of your
253089Swyllys  * version of this file only under the terms of the GPL and not to
263089Swyllys  * allow others to use your version of this file under the MPL,
273089Swyllys  * indicate your decision by deleting the provisions above and
283089Swyllys  * replace them with the notice and other provisions required by
293089Swyllys  * the GPL.  If you do not delete the provisions above, a recipient
303089Swyllys  * may use your version of this file under either the MPL or the
313089Swyllys  * GPL.
323089Swyllys  */
333089Swyllys /*
343433Shaimay  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
353089Swyllys  * Use is subject to license terms.
363089Swyllys  *
373089Swyllys  * File: rdn_parser.c
383089Swyllys  */
393089Swyllys 
403089Swyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
413089Swyllys 
423089Swyllys 
433089Swyllys #include <strings.h>
443089Swyllys #include <stdlib.h>
453089Swyllys #include <kmfapi.h>
463089Swyllys #include <kmfapiP.h>
473089Swyllys #include <ber_der.h>
483089Swyllys #include <rdn_parser.h>
493089Swyllys #include <stdio.h>
503089Swyllys #include <values.h>
513089Swyllys 
523089Swyllys /*
533089Swyllys  * The order here is important.  The OIDs are arranged in order of
543089Swyllys  * significance.  The CN is the most specific value, the C (country)
553089Swyllys  * is less specific, etc.  Add to this list with care.
563089Swyllys  */
573089Swyllys static const struct NameToKind name2kinds[] = {
583089Swyllys { "CN",		OID_AVA_COMMON_NAME,	(KMF_OID *)&KMFOID_CommonName},
593089Swyllys { "SN",		OID_AVA_SURNAME,	(KMF_OID *)&KMFOID_Surname},
603089Swyllys { "GN",		OID_AVA_GIVEN_NAME,	(KMF_OID *)&KMFOID_GivenName},
613089Swyllys { "emailAddress", OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress},
623089Swyllys { "E",		OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress},
633089Swyllys { "MAIL",	OID_RFC1274_MAIL,	(KMF_OID *)&KMFOID_RFC822mailbox},
643089Swyllys { "STREET",	OID_AVA_STREET_ADDRESS, (KMF_OID *)&KMFOID_StreetAddress},
653089Swyllys { "UID",	OID_RFC1274_UID,	(KMF_OID *)&KMFOID_userid},
663089Swyllys { "OU",		OID_AVA_ORGANIZATIONAL_UNIT_NAME,
673089Swyllys 			(KMF_OID *)&KMFOID_OrganizationalUnitName},
683089Swyllys { "O",		OID_AVA_ORGANIZATION_NAME, (KMF_OID *)&KMFOID_OrganizationName},
693089Swyllys { "L",		OID_AVA_LOCALITY,	(KMF_OID *)&KMFOID_LocalityName},
703089Swyllys { "ST",		OID_AVA_STATE_OR_PROVINCE,
713089Swyllys 	(KMF_OID *)&KMFOID_StateProvinceName},
723089Swyllys { "C",		OID_AVA_COUNTRY_NAME,	(KMF_OID *)&KMFOID_CountryName},
733089Swyllys { "DC",		OID_AVA_DC,		(KMF_OID *)&KMFOID_domainComponent},
743089Swyllys { 0,		OID_UNKNOWN, NULL}
753089Swyllys };
763089Swyllys 
773089Swyllys static KMF_BOOL
783089Swyllys IsPrintable(unsigned char *data, unsigned len)
793089Swyllys {
803089Swyllys 	unsigned char ch, *end;
813089Swyllys 
823089Swyllys 	end = data + len;
833089Swyllys 	while (data < end) {
843089Swyllys 		ch = *data++;
853089Swyllys 		if (!IS_PRINTABLE(ch)) {
863089Swyllys 			return (B_FALSE);
873089Swyllys 		}
883089Swyllys 	}
893089Swyllys 	return (B_TRUE);
903089Swyllys }
913089Swyllys 
923089Swyllys static KMF_BOOL
933089Swyllys Is7Bit(unsigned char *data, unsigned len)
943089Swyllys {
953089Swyllys 	unsigned char ch, *end;
963089Swyllys 
973089Swyllys 	end = data + len;
983089Swyllys 	while (data < end) {
993089Swyllys 		ch = *data++;
1003089Swyllys 		if ((ch & 0x80)) {
1013089Swyllys 			return (B_FALSE);
1023089Swyllys 		}
1033089Swyllys 	}
1043089Swyllys 	return (B_TRUE);
1053089Swyllys }
1063089Swyllys 
1073089Swyllys static void
1083089Swyllys skipSpace(char **pbp, char *endptr)
1093089Swyllys {
1103089Swyllys 	char *bp = *pbp;
1113089Swyllys 	while (bp < endptr && OPTIONAL_SPACE(*bp)) {
1123089Swyllys 		bp++;
1133089Swyllys 	}
1143089Swyllys 	*pbp = bp;
1153089Swyllys }
1163089Swyllys 
1173089Swyllys static KMF_RETURN
1183089Swyllys scanTag(char **pbp, char *endptr, char *tagBuf, int tagBufSize)
1193089Swyllys {
1203089Swyllys 	char *bp, *tagBufp;
1213089Swyllys 	int taglen;
1223089Swyllys 
1233089Swyllys 	if (tagBufSize <= 0)
1243089Swyllys 		return (KMF_ERR_INTERNAL);
1253089Swyllys 
1263089Swyllys 	/* skip optional leading space */
1273089Swyllys 	skipSpace(pbp, endptr);
1283089Swyllys 	if (*pbp == endptr) {
1293089Swyllys 		/* nothing left */
1303089Swyllys 		return (KMF_ERR_RDN_PARSER);
1313089Swyllys 	}
1323089Swyllys 
1333089Swyllys 	/* fill tagBuf */
1343089Swyllys 	taglen = 0;
1353089Swyllys 	bp = *pbp;
1363089Swyllys 	tagBufp = tagBuf;
1373089Swyllys 	while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) {
1383089Swyllys 		if (++taglen >= tagBufSize) {
1393089Swyllys 			*pbp = bp;
1403089Swyllys 			return (KMF_ERR_RDN_PARSER);
1413089Swyllys 		}
1423089Swyllys 		*tagBufp++ = *bp++;
1433089Swyllys 	}
1443089Swyllys 	/* null-terminate tagBuf -- guaranteed at least one space left */
1453089Swyllys 	*tagBufp++ = 0;
1463089Swyllys 	*pbp = bp;
1473089Swyllys 
1483089Swyllys 	/*
1493089Swyllys 	 * skip trailing spaces till we hit something - should be
1503089Swyllys 	 * an equal sign
1513089Swyllys 	 */
1523089Swyllys 	skipSpace(pbp, endptr);
1533089Swyllys 	if (*pbp == endptr) {
1543089Swyllys 		/* nothing left */
1553089Swyllys 		return (KMF_ERR_RDN_PARSER);
1563089Swyllys 	}
1573089Swyllys 	if (**pbp != C_EQUAL) {
1583089Swyllys 		/* should be an equal sign */
1593089Swyllys 		return (KMF_ERR_RDN_PARSER);
1603089Swyllys 	}
1613089Swyllys 	/* skip over the equal sign */
1623089Swyllys 	(*pbp)++;
1633089Swyllys 
1643089Swyllys 	return (KMF_OK);
1653089Swyllys }
1663089Swyllys 
1673089Swyllys static KMF_RETURN
1683089Swyllys scanVal(char **pbp, char *endptr, char *valBuf, int valBufSize)
1693089Swyllys {
1703089Swyllys 	char *bp, *valBufp;
1713089Swyllys 	int vallen;
1723089Swyllys 	boolean_t isQuoted;
1733089Swyllys 
1743089Swyllys 	if (valBufSize <= 0)
1753089Swyllys 		return (KMF_ERR_INTERNAL);
1763089Swyllys 
1773089Swyllys 	/* skip optional leading space */
1783089Swyllys 	skipSpace(pbp, endptr);
1793089Swyllys 	if (*pbp == endptr) {
1803089Swyllys 		/* nothing left */
1813089Swyllys 		return (KMF_ERR_RDN_PARSER);
1823089Swyllys 	}
1833089Swyllys 
1843089Swyllys 	bp = *pbp;
1853089Swyllys 
1863089Swyllys 	/* quoted? */
1873089Swyllys 	if (*bp == C_DOUBLE_QUOTE) {
1883089Swyllys 		isQuoted = B_TRUE;
1893089Swyllys 		/* skip over it */
1903089Swyllys 		bp++;
1913089Swyllys 	} else {
1923089Swyllys 		isQuoted = B_FALSE;
1933089Swyllys 	}
1943089Swyllys 
1953089Swyllys 	valBufp = valBuf;
1963089Swyllys 	vallen = 0;
1973089Swyllys 	while (bp < endptr) {
1983089Swyllys 		char c = *bp;
1993089Swyllys 		if (c == C_BACKSLASH) {
2003089Swyllys 			/* escape character */
2013089Swyllys 			bp++;
2023089Swyllys 			if (bp >= endptr) {
2033089Swyllys 				/*
2043089Swyllys 				 * escape charater must appear with paired char
2053089Swyllys 				 */
2063089Swyllys 				*pbp = bp;
2073089Swyllys 				return (KMF_ERR_RDN_PARSER);
2083089Swyllys 			}
2093089Swyllys 		} else if (!isQuoted && SPECIAL_CHAR(c)) {
2103089Swyllys 			/* unescaped special and not within quoted value */
2113089Swyllys 			break;
2123089Swyllys 		} else if (c == C_DOUBLE_QUOTE) {
2133089Swyllys 			/* reached unescaped double quote */
2143089Swyllys 			break;
2153089Swyllys 		}
2163089Swyllys 		/* append character */
2173089Swyllys 		vallen++;
2183089Swyllys 		if (vallen >= valBufSize) {
2193089Swyllys 			*pbp = bp;
2203089Swyllys 			return (KMF_ERR_RDN_PARSER);
2213089Swyllys 		}
2223089Swyllys 		*valBufp++ = *bp++;
2233089Swyllys 	}
2243089Swyllys 
2253089Swyllys 	/* stip trailing spaces from unquoted values */
2263089Swyllys 	if (!isQuoted) {
2273089Swyllys 		if (valBufp > valBuf) {
2283089Swyllys 			valBufp--;
2293089Swyllys 			while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) {
2303089Swyllys 				valBufp--;
2313089Swyllys 			}
2323089Swyllys 			valBufp++;
2333089Swyllys 		}
2343089Swyllys 	}
2353089Swyllys 
2363089Swyllys 	if (isQuoted) {
2373089Swyllys 		/* insist that we stopped on a double quote */
2383089Swyllys 		if (*bp != C_DOUBLE_QUOTE) {
2393089Swyllys 			*pbp = bp;
2403089Swyllys 			return (KMF_ERR_RDN_PARSER);
2413089Swyllys 		}
2423089Swyllys 		/* skip over the quote and skip optional space */
2433089Swyllys 		bp++;
2443089Swyllys 		skipSpace(&bp, endptr);
2453089Swyllys 	}
2463089Swyllys 
2473089Swyllys 	*pbp = bp;
2483089Swyllys 
2493089Swyllys 	if (valBufp == valBuf) {
2503089Swyllys 		/* empty value -- not allowed */
2513089Swyllys 		return (KMF_ERR_RDN_PARSER);
2523089Swyllys 	}
2533089Swyllys 
2543089Swyllys 	/* null-terminate valBuf -- guaranteed at least one space left */
2553089Swyllys 	*valBufp++ = 0;
2563089Swyllys 
2573089Swyllys 	return (KMF_OK);
2583089Swyllys }
2593089Swyllys 
2603089Swyllys static KMF_RETURN
2613089Swyllys CreateRDN(KMF_X509_TYPE_VALUE_PAIR *ava, KMF_X509_RDN *newrdn)
2623089Swyllys {
2633089Swyllys 	/* Each RDN has 1 AttrTypeAndValue */
2643089Swyllys 	(void) memset(newrdn, 0, sizeof (KMF_X509_RDN));
2653089Swyllys 	newrdn->numberOfPairs = 1;
2663089Swyllys 	newrdn->AttributeTypeAndValue = ava;
2673089Swyllys 
2683089Swyllys 	return (KMF_OK);
2693089Swyllys }
2703089Swyllys 
2713089Swyllys static KMF_RETURN
2723089Swyllys copy_oid(KMF_OID *dst, KMF_OID *src)
2733089Swyllys {
2743089Swyllys 	KMF_RETURN ret = KMF_OK;
2753089Swyllys 
2763089Swyllys 	if (dst == NULL || src == NULL)
2773089Swyllys 		return (KMF_ERR_BAD_PARAMETER);
2783089Swyllys 
2793089Swyllys 	dst->Data = malloc(src->Length);
2803089Swyllys 	if (dst->Data == NULL)
2813089Swyllys 		return (KMF_ERR_MEMORY);
2823089Swyllys 
2833089Swyllys 	dst->Length = src->Length;
2843089Swyllys 	(void) memcpy(dst->Data, src->Data, src->Length);
2853089Swyllys 
2863089Swyllys 	return (ret);
2873089Swyllys }
2883089Swyllys 
2893089Swyllys static KMF_RETURN
2903089Swyllys CreateAVA(KMF_OID *oid, int valueType, char *value,
2913089Swyllys     KMF_X509_TYPE_VALUE_PAIR **newava)
2923089Swyllys {
2933089Swyllys 	int rv = KMF_OK;
2943089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *ava = NULL;
2953089Swyllys 
2963089Swyllys 	*newava = NULL;
2973089Swyllys 	ava = (KMF_X509_TYPE_VALUE_PAIR*) malloc(
2983089Swyllys 	    sizeof (KMF_X509_TYPE_VALUE_PAIR));
2993089Swyllys 	if (ava == NULL) {
3003089Swyllys 		return (KMF_ERR_MEMORY);
3013089Swyllys 	} else {
3023089Swyllys 		(void) memset(ava, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR));
3033089Swyllys 		ava->valueType = valueType;
3043089Swyllys 		ava->value.Data = malloc(strlen(value));
3053089Swyllys 		if (ava->value.Data == NULL) {
3063089Swyllys 			free(ava);
3073089Swyllys 			return (KMF_ERR_MEMORY);
3083089Swyllys 		}
3093089Swyllys 		(void) memcpy(ava->value.Data, value, strlen(value));
3103089Swyllys 		ava->value.Length = strlen(value);
3113089Swyllys 
3123089Swyllys 		rv = copy_oid(&ava->type, oid);
3133089Swyllys 		if (rv != KMF_OK) {
3143089Swyllys 			/* Illegal AVA type */
3153089Swyllys 			free(ava->value.Data);
3163089Swyllys 			free(ava);
3173089Swyllys 			return (rv);
3183089Swyllys 		}
3193089Swyllys 	}
3203089Swyllys 	*newava = ava;
3213089Swyllys 
3223089Swyllys 	return (rv);
3233089Swyllys }
3243089Swyllys 
3253089Swyllys static KMF_RETURN
3263089Swyllys ParseRdnAttribute(char **pbp, char *endptr, boolean_t singleAVA,
3273089Swyllys     KMF_X509_TYPE_VALUE_PAIR **a)
3283089Swyllys {
3293089Swyllys 	KMF_RETURN rv;
3303089Swyllys 	const struct NameToKind *n2k;
3313089Swyllys 	int vt;
3323089Swyllys 	int valLen;
3333089Swyllys 	char *bp;
3343089Swyllys 
3353089Swyllys 	char tagBuf[32];
3363089Swyllys 	char valBuf[384];
3373089Swyllys 
3383089Swyllys 	rv = scanTag(pbp, endptr, tagBuf, sizeof (tagBuf));
3393089Swyllys 	if (rv != KMF_OK)
3403089Swyllys 		return (rv);
3413089Swyllys 	rv = scanVal(pbp, endptr, valBuf, sizeof (valBuf));
3423089Swyllys 	if (rv != KMF_OK)
3433089Swyllys 		return (rv);
3443089Swyllys 
3453089Swyllys 	/* insist that if we haven't finished we've stopped on a separator */
3463089Swyllys 	bp = *pbp;
3473089Swyllys 	if (bp < endptr) {
3483089Swyllys 		if (singleAVA || (*bp != ',' && *bp != ';')) {
3493089Swyllys 			*pbp = bp;
3503089Swyllys 			return (KMF_ERR_RDN_ATTR);
3513089Swyllys 		}
3523089Swyllys 		/* ok, skip over separator */
3533089Swyllys 		bp++;
3543089Swyllys 	}
3553089Swyllys 	*pbp = bp;
3563089Swyllys 
3573089Swyllys 	for (n2k = name2kinds; n2k->name; n2k++) {
3583089Swyllys 		if (strcasecmp(n2k->name, tagBuf) == 0) {
3593089Swyllys 			valLen = strlen(valBuf);
3603089Swyllys 			if (n2k->kind == OID_AVA_COUNTRY_NAME) {
3613089Swyllys 				vt = BER_PRINTABLE_STRING;
3623089Swyllys 				if (valLen != 2) {
3633089Swyllys 					return (KMF_ERR_RDN_ATTR);
3643089Swyllys 				}
3653089Swyllys 				if (!IsPrintable((unsigned char *) valBuf, 2)) {
3663089Swyllys 					return (KMF_ERR_RDN_ATTR);
3673089Swyllys 				}
3683089Swyllys 			} else if ((n2k->kind == OID_PKCS9_EMAIL_ADDRESS) ||
369*5051Swyllys 			    (n2k->kind == OID_RFC1274_MAIL)) {
3703089Swyllys 				vt = BER_IA5STRING;
3713089Swyllys 			} else {
3723089Swyllys 				/*
3733089Swyllys 				 * Hack -- for rationale see X.520
3743089Swyllys 				 * DirectoryString defn
3753089Swyllys 				 */
3763089Swyllys 				if (IsPrintable((unsigned char *)valBuf,
3773089Swyllys 				    valLen)) {
3783089Swyllys 					vt = BER_PRINTABLE_STRING;
3793089Swyllys 				} else if (Is7Bit((unsigned char *)valBuf,
3803089Swyllys 				    valLen)) {
3813089Swyllys 					vt = BER_T61STRING;
3823089Swyllys 				}
3833089Swyllys 			}
384*5051Swyllys 			rv = CreateAVA(n2k->OID, vt, (char *)valBuf, a);
3853089Swyllys 			return (rv);
3863089Swyllys 		}
3873089Swyllys 	}
3883089Swyllys 	/* matched no kind -- invalid tag */
3893089Swyllys 	return (KMF_ERR_RDN_ATTR);
3903089Swyllys }
3913089Swyllys 
3923089Swyllys static int
3933089Swyllys rdnavcompare(const void *a, const void *b)
3943089Swyllys {
3953089Swyllys 	KMF_X509_RDN *r1, *r2;
3963089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *av1, *av2;
3973089Swyllys 	int i, p1, p2;
3983089Swyllys 	const struct NameToKind *n2k;
3993089Swyllys 	KMF_OID *oidrec;
4003089Swyllys 
4013089Swyllys 	r1 = (KMF_X509_RDN *)a;
4023089Swyllys 	r2 = (KMF_X509_RDN *)b;
4033089Swyllys 
4043089Swyllys 	av1 = r1->AttributeTypeAndValue;
4053089Swyllys 	av2 = r2->AttributeTypeAndValue;
4063089Swyllys 
4073089Swyllys 	p1 = p2 = MAXINT;
4083089Swyllys 	/*
4093089Swyllys 	 * The "Name2Kinds" list is ordered by significance.
4103089Swyllys 	 * Compare the "ranking" of each of the OIDs to determine
4113089Swyllys 	 * the result.
4123089Swyllys 	 */
4133089Swyllys 	for (n2k = name2kinds, i = 0;
414*5051Swyllys 	    n2k->name && (p1 == MAXINT || p2 == MAXINT);
415*5051Swyllys 	    n2k++, i++) {
4163089Swyllys 		oidrec = n2k->OID;
4173089Swyllys 		if (oidrec != NULL) {
4183089Swyllys 			if (IsEqualOid(&av1->type, oidrec))
4193089Swyllys 				p1 = i;
4203089Swyllys 			if (IsEqualOid(&av2->type, oidrec))
4213089Swyllys 				p2 = i;
4223089Swyllys 		}
4233089Swyllys 	}
4243089Swyllys 
4253089Swyllys 	if (p1 > p2)
4263089Swyllys 		return (-1);
4273089Swyllys 	else if (p1 < p2)
4283089Swyllys 		return (1);
4293089Swyllys 	else  /* If equal, treat as if it is less than */
4303089Swyllys 		return (1);
4313089Swyllys }
4323089Swyllys 
433*5051Swyllys static KMF_RETURN
4343089Swyllys ParseDistinguishedName(char *buf, int len, KMF_X509_NAME *name)
4353089Swyllys {
4363089Swyllys 	KMF_RETURN rv = KMF_OK;
4373089Swyllys 	char *bp, *e;
4383089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *ava = NULL;
4393089Swyllys 	KMF_X509_RDN rdn;
4403089Swyllys 
4413089Swyllys 	(void) memset(name, 0, sizeof (KMF_X509_NAME));
4423089Swyllys 	e = buf + len;
4433089Swyllys 	bp = buf;
4443089Swyllys 	while (bp < e) {
4453089Swyllys 		rv = ParseRdnAttribute(&bp, e, B_FALSE, &ava);
4463089Swyllys 		if (rv != KMF_OK) goto loser;
4473089Swyllys 		rv = CreateRDN(ava, &rdn);
4483089Swyllys 		if (rv != KMF_OK) goto loser;
4493089Swyllys 		if (AddRDN(name, &rdn) != KMF_OK) goto loser;
4503089Swyllys 		skipSpace(&bp, e);
4513089Swyllys 	}
4523089Swyllys 
4533089Swyllys 	/*
4543089Swyllys 	 * Canonicalize the DN by sorting the elements
4553089Swyllys 	 * in little-endian order, as per RFC 1485:
4563089Swyllys 	 * "The name is presented/input in a little-endian
4573089Swyllys 	 * order (most significant component last)."
4583089Swyllys 	 */
4593089Swyllys 	qsort((void *)name->RelativeDistinguishedName,
460*5051Swyllys 	    name->numberOfRDNs, sizeof (KMF_X509_RDN), rdnavcompare);
4613089Swyllys 
4623089Swyllys 	/* return result */
4633089Swyllys 	return (rv);
4643089Swyllys 
4653089Swyllys loser:
466*5051Swyllys 	kmf_free_dn(name);
4673089Swyllys 	return (rv);
4683089Swyllys }
4693089Swyllys 
4703089Swyllys static KMF_BOOL
4713089Swyllys IsEqualData(KMF_DATA *d1, KMF_DATA *d2)
4723089Swyllys {
4733089Swyllys 	return ((d1->Length == d2->Length) &&
4743089Swyllys 	    !memcmp(d1->Data, d2->Data, d1->Length));
4753089Swyllys }
4763089Swyllys 
4773089Swyllys /*
4783089Swyllys  * Generic routine to compare 2 RDN structures.
4793089Swyllys  *
4803089Swyllys  * Because the ordering of the AV pairs may not be
4813089Swyllys  * the same, we must compare each AV pair individually
4823089Swyllys  *
4833089Swyllys  * Return 0 if equal, 1 if not.
4843089Swyllys  */
4853089Swyllys int
486*5051Swyllys kmf_compare_rdns(KMF_X509_NAME *name1, KMF_X509_NAME *name2)
4873089Swyllys {
4883089Swyllys 	int i, j;
4893089Swyllys 	boolean_t avfound;
4903089Swyllys 	KMF_X509_RDN *r1, *r2;
4913089Swyllys 	KMF_X509_TYPE_VALUE_PAIR *av1, *av2;
4923089Swyllys 
4933089Swyllys 	if (name1 == NULL || name2 == NULL)
4943089Swyllys 		return (1);
4953089Swyllys 
4963089Swyllys 	if (name1->numberOfRDNs != name2->numberOfRDNs)
4973089Swyllys 		return (1);
4983089Swyllys 
4993089Swyllys 	for (i = 0; i < name1->numberOfRDNs; i++) {
5003089Swyllys 		r1 = (KMF_X509_RDN *)&name1->RelativeDistinguishedName[i];
5013089Swyllys 		av1 = (KMF_X509_TYPE_VALUE_PAIR *)r1->AttributeTypeAndValue;
5023089Swyllys 
5033089Swyllys 		avfound = FALSE;
5043089Swyllys 		for (j = 0; j < name2->numberOfRDNs && !avfound; j++) {
5053089Swyllys 			r2 = (KMF_X509_RDN *)
506*5051Swyllys 			    &name2->RelativeDistinguishedName[j];
5073089Swyllys 			av2 = (KMF_X509_TYPE_VALUE_PAIR *)
508*5051Swyllys 			    r2->AttributeTypeAndValue;
5093089Swyllys 
5103089Swyllys 			avfound = (IsEqualOid(&av1->type, &av2->type) &&
511*5051Swyllys 			    IsEqualData(&av1->value, &av2->value));
5123089Swyllys 		}
5133089Swyllys 		/*
5143089Swyllys 		 * If the current AV from name1 was not found in name2,
5153089Swyllys 		 * we are done.
5163089Swyllys 		 */
5173089Swyllys 		if (!avfound)
5183089Swyllys 			return (1);
5193089Swyllys 	}
5203089Swyllys 
5213089Swyllys 	/* If we got this far, it must be a match */
5223089Swyllys 	return (0);
5233089Swyllys }
524*5051Swyllys 
525*5051Swyllys /*
526*5051Swyllys  * kmf_dn_parser
527*5051Swyllys  *
528*5051Swyllys  * Public interface for parsing a Distinguished name in
529*5051Swyllys  * human-readable format into a binary KMF_X509_NAME.
530*5051Swyllys  */
531*5051Swyllys KMF_RETURN
532*5051Swyllys kmf_dn_parser(char *string, KMF_X509_NAME *name)
533*5051Swyllys {
534*5051Swyllys 	KMF_RETURN err;
535*5051Swyllys 
536*5051Swyllys 	if (string == NULL || name == NULL)
537*5051Swyllys 		return (KMF_ERR_BAD_PARAMETER);
538*5051Swyllys 
539*5051Swyllys 	err = ParseDistinguishedName(string, (int)strlen(string), name);
540*5051Swyllys 	return (err);
541*5051Swyllys }
542*5051Swyllys 
543*5051Swyllys KMF_RETURN
544*5051Swyllys KMF_DNParser(char *string, KMF_X509_NAME *name)
545*5051Swyllys {
546*5051Swyllys 	return (kmf_dn_parser(string, name));
547*5051Swyllys }
548