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.
32*11462Swyllys.ingersoll@sun.com *
33*11462Swyllys.ingersoll@sun.com * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
343089Swyllys * Use is subject to license terms.
353089Swyllys *
363089Swyllys * File: rdn_parser.c
373089Swyllys */
383089Swyllys
393089Swyllys #include <strings.h>
403089Swyllys #include <stdlib.h>
413089Swyllys #include <kmfapi.h>
423089Swyllys #include <kmfapiP.h>
433089Swyllys #include <ber_der.h>
443089Swyllys #include <rdn_parser.h>
453089Swyllys #include <stdio.h>
463089Swyllys #include <values.h>
473089Swyllys
483089Swyllys /*
493089Swyllys * The order here is important. The OIDs are arranged in order of
503089Swyllys * significance. The CN is the most specific value, the C (country)
513089Swyllys * is less specific, etc. Add to this list with care.
523089Swyllys */
533089Swyllys static const struct NameToKind name2kinds[] = {
543089Swyllys { "CN", OID_AVA_COMMON_NAME, (KMF_OID *)&KMFOID_CommonName},
553089Swyllys { "SN", OID_AVA_SURNAME, (KMF_OID *)&KMFOID_Surname},
563089Swyllys { "GN", OID_AVA_GIVEN_NAME, (KMF_OID *)&KMFOID_GivenName},
573089Swyllys { "emailAddress", OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress},
583089Swyllys { "E", OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress},
593089Swyllys { "MAIL", OID_RFC1274_MAIL, (KMF_OID *)&KMFOID_RFC822mailbox},
603089Swyllys { "STREET", OID_AVA_STREET_ADDRESS, (KMF_OID *)&KMFOID_StreetAddress},
613089Swyllys { "UID", OID_RFC1274_UID, (KMF_OID *)&KMFOID_userid},
623089Swyllys { "OU", OID_AVA_ORGANIZATIONAL_UNIT_NAME,
633089Swyllys (KMF_OID *)&KMFOID_OrganizationalUnitName},
643089Swyllys { "O", OID_AVA_ORGANIZATION_NAME, (KMF_OID *)&KMFOID_OrganizationName},
653089Swyllys { "L", OID_AVA_LOCALITY, (KMF_OID *)&KMFOID_LocalityName},
663089Swyllys { "ST", OID_AVA_STATE_OR_PROVINCE,
673089Swyllys (KMF_OID *)&KMFOID_StateProvinceName},
683089Swyllys { "C", OID_AVA_COUNTRY_NAME, (KMF_OID *)&KMFOID_CountryName},
693089Swyllys { "DC", OID_AVA_DC, (KMF_OID *)&KMFOID_domainComponent},
703089Swyllys { 0, OID_UNKNOWN, NULL}
713089Swyllys };
723089Swyllys
733089Swyllys static KMF_BOOL
IsPrintable(unsigned char * data,unsigned len)743089Swyllys IsPrintable(unsigned char *data, unsigned len)
753089Swyllys {
763089Swyllys unsigned char ch, *end;
773089Swyllys
783089Swyllys end = data + len;
793089Swyllys while (data < end) {
803089Swyllys ch = *data++;
813089Swyllys if (!IS_PRINTABLE(ch)) {
823089Swyllys return (B_FALSE);
833089Swyllys }
843089Swyllys }
853089Swyllys return (B_TRUE);
863089Swyllys }
873089Swyllys
883089Swyllys static KMF_BOOL
Is7Bit(unsigned char * data,unsigned len)893089Swyllys Is7Bit(unsigned char *data, unsigned len)
903089Swyllys {
913089Swyllys unsigned char ch, *end;
923089Swyllys
933089Swyllys end = data + len;
943089Swyllys while (data < end) {
953089Swyllys ch = *data++;
963089Swyllys if ((ch & 0x80)) {
973089Swyllys return (B_FALSE);
983089Swyllys }
993089Swyllys }
1003089Swyllys return (B_TRUE);
1013089Swyllys }
1023089Swyllys
1033089Swyllys static void
skipSpace(char ** pbp,char * endptr)1043089Swyllys skipSpace(char **pbp, char *endptr)
1053089Swyllys {
1063089Swyllys char *bp = *pbp;
1073089Swyllys while (bp < endptr && OPTIONAL_SPACE(*bp)) {
1083089Swyllys bp++;
1093089Swyllys }
1103089Swyllys *pbp = bp;
1113089Swyllys }
1123089Swyllys
1133089Swyllys static KMF_RETURN
scanTag(char ** pbp,char * endptr,char * tagBuf,int tagBufSize)1143089Swyllys scanTag(char **pbp, char *endptr, char *tagBuf, int tagBufSize)
1153089Swyllys {
1163089Swyllys char *bp, *tagBufp;
1173089Swyllys int taglen;
1183089Swyllys
1193089Swyllys if (tagBufSize <= 0)
1203089Swyllys return (KMF_ERR_INTERNAL);
1213089Swyllys
1223089Swyllys /* skip optional leading space */
1233089Swyllys skipSpace(pbp, endptr);
1243089Swyllys if (*pbp == endptr) {
1253089Swyllys /* nothing left */
1263089Swyllys return (KMF_ERR_RDN_PARSER);
1273089Swyllys }
1283089Swyllys
1293089Swyllys /* fill tagBuf */
1303089Swyllys taglen = 0;
1313089Swyllys bp = *pbp;
1323089Swyllys tagBufp = tagBuf;
1333089Swyllys while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) {
1343089Swyllys if (++taglen >= tagBufSize) {
1353089Swyllys *pbp = bp;
1363089Swyllys return (KMF_ERR_RDN_PARSER);
1373089Swyllys }
1383089Swyllys *tagBufp++ = *bp++;
1393089Swyllys }
1403089Swyllys /* null-terminate tagBuf -- guaranteed at least one space left */
1413089Swyllys *tagBufp++ = 0;
1423089Swyllys *pbp = bp;
1433089Swyllys
1443089Swyllys /*
1453089Swyllys * skip trailing spaces till we hit something - should be
1463089Swyllys * an equal sign
1473089Swyllys */
1483089Swyllys skipSpace(pbp, endptr);
1493089Swyllys if (*pbp == endptr) {
1503089Swyllys /* nothing left */
1513089Swyllys return (KMF_ERR_RDN_PARSER);
1523089Swyllys }
1533089Swyllys if (**pbp != C_EQUAL) {
1543089Swyllys /* should be an equal sign */
1553089Swyllys return (KMF_ERR_RDN_PARSER);
1563089Swyllys }
1573089Swyllys /* skip over the equal sign */
1583089Swyllys (*pbp)++;
1593089Swyllys
1603089Swyllys return (KMF_OK);
1613089Swyllys }
1623089Swyllys
1633089Swyllys static KMF_RETURN
scanVal(char ** pbp,char * endptr,char * valBuf,int valBufSize)1643089Swyllys scanVal(char **pbp, char *endptr, char *valBuf, int valBufSize)
1653089Swyllys {
1663089Swyllys char *bp, *valBufp;
1673089Swyllys int vallen;
1683089Swyllys boolean_t isQuoted;
1693089Swyllys
1703089Swyllys if (valBufSize <= 0)
1713089Swyllys return (KMF_ERR_INTERNAL);
1723089Swyllys
1733089Swyllys /* skip optional leading space */
1743089Swyllys skipSpace(pbp, endptr);
1753089Swyllys if (*pbp == endptr) {
1763089Swyllys /* nothing left */
1773089Swyllys return (KMF_ERR_RDN_PARSER);
1783089Swyllys }
1793089Swyllys
1803089Swyllys bp = *pbp;
1813089Swyllys
1823089Swyllys /* quoted? */
1833089Swyllys if (*bp == C_DOUBLE_QUOTE) {
1843089Swyllys isQuoted = B_TRUE;
1853089Swyllys /* skip over it */
1863089Swyllys bp++;
1873089Swyllys } else {
1883089Swyllys isQuoted = B_FALSE;
1893089Swyllys }
1903089Swyllys
1913089Swyllys valBufp = valBuf;
1923089Swyllys vallen = 0;
1933089Swyllys while (bp < endptr) {
1943089Swyllys char c = *bp;
1953089Swyllys if (c == C_BACKSLASH) {
1963089Swyllys /* escape character */
1973089Swyllys bp++;
1983089Swyllys if (bp >= endptr) {
1993089Swyllys /*
2003089Swyllys * escape charater must appear with paired char
2013089Swyllys */
2023089Swyllys *pbp = bp;
2033089Swyllys return (KMF_ERR_RDN_PARSER);
2043089Swyllys }
2053089Swyllys } else if (!isQuoted && SPECIAL_CHAR(c)) {
2063089Swyllys /* unescaped special and not within quoted value */
2073089Swyllys break;
2083089Swyllys } else if (c == C_DOUBLE_QUOTE) {
2093089Swyllys /* reached unescaped double quote */
2103089Swyllys break;
2113089Swyllys }
2123089Swyllys /* append character */
2133089Swyllys vallen++;
2143089Swyllys if (vallen >= valBufSize) {
2153089Swyllys *pbp = bp;
2163089Swyllys return (KMF_ERR_RDN_PARSER);
2173089Swyllys }
2183089Swyllys *valBufp++ = *bp++;
2193089Swyllys }
2203089Swyllys
2213089Swyllys /* stip trailing spaces from unquoted values */
2223089Swyllys if (!isQuoted) {
2233089Swyllys if (valBufp > valBuf) {
2243089Swyllys valBufp--;
2253089Swyllys while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) {
2263089Swyllys valBufp--;
2273089Swyllys }
2283089Swyllys valBufp++;
2293089Swyllys }
2303089Swyllys }
2313089Swyllys
2323089Swyllys if (isQuoted) {
2333089Swyllys /* insist that we stopped on a double quote */
2343089Swyllys if (*bp != C_DOUBLE_QUOTE) {
2353089Swyllys *pbp = bp;
2363089Swyllys return (KMF_ERR_RDN_PARSER);
2373089Swyllys }
2383089Swyllys /* skip over the quote and skip optional space */
2393089Swyllys bp++;
2403089Swyllys skipSpace(&bp, endptr);
2413089Swyllys }
2423089Swyllys
2433089Swyllys *pbp = bp;
2443089Swyllys
2453089Swyllys if (valBufp == valBuf) {
2463089Swyllys /* empty value -- not allowed */
2473089Swyllys return (KMF_ERR_RDN_PARSER);
2483089Swyllys }
2493089Swyllys
2503089Swyllys /* null-terminate valBuf -- guaranteed at least one space left */
2513089Swyllys *valBufp++ = 0;
2523089Swyllys
2533089Swyllys return (KMF_OK);
2543089Swyllys }
2553089Swyllys
2563089Swyllys static KMF_RETURN
CreateRDN(KMF_X509_TYPE_VALUE_PAIR * ava,KMF_X509_RDN * newrdn)2573089Swyllys CreateRDN(KMF_X509_TYPE_VALUE_PAIR *ava, KMF_X509_RDN *newrdn)
2583089Swyllys {
2593089Swyllys /* Each RDN has 1 AttrTypeAndValue */
2603089Swyllys (void) memset(newrdn, 0, sizeof (KMF_X509_RDN));
2613089Swyllys newrdn->numberOfPairs = 1;
2623089Swyllys newrdn->AttributeTypeAndValue = ava;
2633089Swyllys
2643089Swyllys return (KMF_OK);
2653089Swyllys }
2663089Swyllys
2673089Swyllys static KMF_RETURN
copy_oid(KMF_OID * dst,KMF_OID * src)2683089Swyllys copy_oid(KMF_OID *dst, KMF_OID *src)
2693089Swyllys {
2703089Swyllys KMF_RETURN ret = KMF_OK;
2713089Swyllys
2723089Swyllys if (dst == NULL || src == NULL)
2733089Swyllys return (KMF_ERR_BAD_PARAMETER);
2743089Swyllys
2753089Swyllys dst->Data = malloc(src->Length);
2763089Swyllys if (dst->Data == NULL)
2773089Swyllys return (KMF_ERR_MEMORY);
2783089Swyllys
2793089Swyllys dst->Length = src->Length;
2803089Swyllys (void) memcpy(dst->Data, src->Data, src->Length);
2813089Swyllys
2823089Swyllys return (ret);
2833089Swyllys }
2843089Swyllys
2853089Swyllys static KMF_RETURN
CreateAVA(KMF_OID * oid,int valueType,char * value,KMF_X509_TYPE_VALUE_PAIR ** newava)2863089Swyllys CreateAVA(KMF_OID *oid, int valueType, char *value,
2873089Swyllys KMF_X509_TYPE_VALUE_PAIR **newava)
2883089Swyllys {
2893089Swyllys int rv = KMF_OK;
2903089Swyllys KMF_X509_TYPE_VALUE_PAIR *ava = NULL;
2913089Swyllys
2923089Swyllys *newava = NULL;
2933089Swyllys ava = (KMF_X509_TYPE_VALUE_PAIR*) malloc(
2943089Swyllys sizeof (KMF_X509_TYPE_VALUE_PAIR));
2953089Swyllys if (ava == NULL) {
2963089Swyllys return (KMF_ERR_MEMORY);
2973089Swyllys } else {
2983089Swyllys (void) memset(ava, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR));
2993089Swyllys ava->valueType = valueType;
3003089Swyllys ava->value.Data = malloc(strlen(value));
3013089Swyllys if (ava->value.Data == NULL) {
3023089Swyllys free(ava);
3033089Swyllys return (KMF_ERR_MEMORY);
3043089Swyllys }
3053089Swyllys (void) memcpy(ava->value.Data, value, strlen(value));
3063089Swyllys ava->value.Length = strlen(value);
3073089Swyllys
3083089Swyllys rv = copy_oid(&ava->type, oid);
3093089Swyllys if (rv != KMF_OK) {
3103089Swyllys /* Illegal AVA type */
3113089Swyllys free(ava->value.Data);
3123089Swyllys free(ava);
3133089Swyllys return (rv);
3143089Swyllys }
3153089Swyllys }
3163089Swyllys *newava = ava;
3173089Swyllys
3183089Swyllys return (rv);
3193089Swyllys }
3203089Swyllys
3213089Swyllys static KMF_RETURN
ParseRdnAttribute(char ** pbp,char * endptr,boolean_t singleAVA,KMF_X509_TYPE_VALUE_PAIR ** a)3223089Swyllys ParseRdnAttribute(char **pbp, char *endptr, boolean_t singleAVA,
3233089Swyllys KMF_X509_TYPE_VALUE_PAIR **a)
3243089Swyllys {
3253089Swyllys KMF_RETURN rv;
3263089Swyllys const struct NameToKind *n2k;
3273089Swyllys int vt;
3283089Swyllys int valLen;
3293089Swyllys char *bp;
3303089Swyllys
3313089Swyllys char tagBuf[32];
3323089Swyllys char valBuf[384];
3333089Swyllys
3343089Swyllys rv = scanTag(pbp, endptr, tagBuf, sizeof (tagBuf));
3353089Swyllys if (rv != KMF_OK)
3363089Swyllys return (rv);
3373089Swyllys rv = scanVal(pbp, endptr, valBuf, sizeof (valBuf));
3383089Swyllys if (rv != KMF_OK)
3393089Swyllys return (rv);
3403089Swyllys
3413089Swyllys /* insist that if we haven't finished we've stopped on a separator */
3423089Swyllys bp = *pbp;
3433089Swyllys if (bp < endptr) {
3443089Swyllys if (singleAVA || (*bp != ',' && *bp != ';')) {
3453089Swyllys *pbp = bp;
3463089Swyllys return (KMF_ERR_RDN_ATTR);
3473089Swyllys }
3483089Swyllys /* ok, skip over separator */
3493089Swyllys bp++;
3503089Swyllys }
3513089Swyllys *pbp = bp;
3523089Swyllys
3533089Swyllys for (n2k = name2kinds; n2k->name; n2k++) {
3543089Swyllys if (strcasecmp(n2k->name, tagBuf) == 0) {
3553089Swyllys valLen = strlen(valBuf);
3563089Swyllys if (n2k->kind == OID_AVA_COUNTRY_NAME) {
3573089Swyllys vt = BER_PRINTABLE_STRING;
3583089Swyllys if (valLen != 2) {
3593089Swyllys return (KMF_ERR_RDN_ATTR);
3603089Swyllys }
3613089Swyllys if (!IsPrintable((unsigned char *) valBuf, 2)) {
3623089Swyllys return (KMF_ERR_RDN_ATTR);
3633089Swyllys }
3643089Swyllys } else if ((n2k->kind == OID_PKCS9_EMAIL_ADDRESS) ||
3655051Swyllys (n2k->kind == OID_RFC1274_MAIL)) {
3663089Swyllys vt = BER_IA5STRING;
3673089Swyllys } else {
3683089Swyllys /*
3693089Swyllys * Hack -- for rationale see X.520
3703089Swyllys * DirectoryString defn
3713089Swyllys */
3723089Swyllys if (IsPrintable((unsigned char *)valBuf,
3733089Swyllys valLen)) {
3743089Swyllys vt = BER_PRINTABLE_STRING;
3753089Swyllys } else if (Is7Bit((unsigned char *)valBuf,
3763089Swyllys valLen)) {
3773089Swyllys vt = BER_T61STRING;
3783089Swyllys }
3793089Swyllys }
3805051Swyllys rv = CreateAVA(n2k->OID, vt, (char *)valBuf, a);
3813089Swyllys return (rv);
3823089Swyllys }
3833089Swyllys }
3843089Swyllys /* matched no kind -- invalid tag */
3853089Swyllys return (KMF_ERR_RDN_ATTR);
3863089Swyllys }
3873089Swyllys
3883089Swyllys static int
rdnavcompare(const void * a,const void * b)3893089Swyllys rdnavcompare(const void *a, const void *b)
3903089Swyllys {
3913089Swyllys KMF_X509_RDN *r1, *r2;
3923089Swyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2;
3933089Swyllys int i, p1, p2;
3943089Swyllys const struct NameToKind *n2k;
3953089Swyllys KMF_OID *oidrec;
3963089Swyllys
3973089Swyllys r1 = (KMF_X509_RDN *)a;
3983089Swyllys r2 = (KMF_X509_RDN *)b;
3993089Swyllys
4003089Swyllys av1 = r1->AttributeTypeAndValue;
4013089Swyllys av2 = r2->AttributeTypeAndValue;
4023089Swyllys
4033089Swyllys p1 = p2 = MAXINT;
4043089Swyllys /*
4053089Swyllys * The "Name2Kinds" list is ordered by significance.
4063089Swyllys * Compare the "ranking" of each of the OIDs to determine
4073089Swyllys * the result.
4083089Swyllys */
4093089Swyllys for (n2k = name2kinds, i = 0;
4105051Swyllys n2k->name && (p1 == MAXINT || p2 == MAXINT);
4115051Swyllys n2k++, i++) {
4123089Swyllys oidrec = n2k->OID;
4133089Swyllys if (oidrec != NULL) {
4143089Swyllys if (IsEqualOid(&av1->type, oidrec))
4153089Swyllys p1 = i;
4163089Swyllys if (IsEqualOid(&av2->type, oidrec))
4173089Swyllys p2 = i;
4183089Swyllys }
4193089Swyllys }
4203089Swyllys
4213089Swyllys if (p1 > p2)
4223089Swyllys return (-1);
4233089Swyllys else if (p1 < p2)
4243089Swyllys return (1);
4253089Swyllys else /* If equal, treat as if it is less than */
4263089Swyllys return (1);
4273089Swyllys }
4283089Swyllys
4295051Swyllys static KMF_RETURN
ParseDistinguishedName(char * buf,int len,KMF_X509_NAME * name)4303089Swyllys ParseDistinguishedName(char *buf, int len, KMF_X509_NAME *name)
4313089Swyllys {
4323089Swyllys KMF_RETURN rv = KMF_OK;
4333089Swyllys char *bp, *e;
4343089Swyllys KMF_X509_TYPE_VALUE_PAIR *ava = NULL;
4353089Swyllys KMF_X509_RDN rdn;
4363089Swyllys
4373089Swyllys (void) memset(name, 0, sizeof (KMF_X509_NAME));
4383089Swyllys e = buf + len;
4393089Swyllys bp = buf;
4403089Swyllys while (bp < e) {
4413089Swyllys rv = ParseRdnAttribute(&bp, e, B_FALSE, &ava);
4423089Swyllys if (rv != KMF_OK) goto loser;
4433089Swyllys rv = CreateRDN(ava, &rdn);
4443089Swyllys if (rv != KMF_OK) goto loser;
4453089Swyllys if (AddRDN(name, &rdn) != KMF_OK) goto loser;
4463089Swyllys skipSpace(&bp, e);
4473089Swyllys }
4483089Swyllys
4493089Swyllys /*
4503089Swyllys * Canonicalize the DN by sorting the elements
4513089Swyllys * in little-endian order, as per RFC 1485:
4523089Swyllys * "The name is presented/input in a little-endian
4533089Swyllys * order (most significant component last)."
4543089Swyllys */
4553089Swyllys qsort((void *)name->RelativeDistinguishedName,
4565051Swyllys name->numberOfRDNs, sizeof (KMF_X509_RDN), rdnavcompare);
4573089Swyllys
4583089Swyllys /* return result */
4593089Swyllys return (rv);
4603089Swyllys
4613089Swyllys loser:
4625051Swyllys kmf_free_dn(name);
4633089Swyllys return (rv);
4643089Swyllys }
4653089Swyllys
4663089Swyllys static KMF_BOOL
IsEqualData(KMF_DATA * d1,KMF_DATA * d2)4673089Swyllys IsEqualData(KMF_DATA *d1, KMF_DATA *d2)
4683089Swyllys {
4693089Swyllys return ((d1->Length == d2->Length) &&
4703089Swyllys !memcmp(d1->Data, d2->Data, d1->Length));
4713089Swyllys }
4723089Swyllys
4733089Swyllys /*
4743089Swyllys * Generic routine to compare 2 RDN structures.
4753089Swyllys *
4763089Swyllys * Because the ordering of the AV pairs may not be
4773089Swyllys * the same, we must compare each AV pair individually
4783089Swyllys *
4793089Swyllys * Return 0 if equal, 1 if not.
4803089Swyllys */
4813089Swyllys int
kmf_compare_rdns(KMF_X509_NAME * name1,KMF_X509_NAME * name2)4825051Swyllys kmf_compare_rdns(KMF_X509_NAME *name1, KMF_X509_NAME *name2)
4833089Swyllys {
4843089Swyllys int i, j;
4853089Swyllys boolean_t avfound;
4863089Swyllys KMF_X509_RDN *r1, *r2;
4873089Swyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2;
4883089Swyllys
4893089Swyllys if (name1 == NULL || name2 == NULL)
4903089Swyllys return (1);
4913089Swyllys
4923089Swyllys if (name1->numberOfRDNs != name2->numberOfRDNs)
4933089Swyllys return (1);
4943089Swyllys
4953089Swyllys for (i = 0; i < name1->numberOfRDNs; i++) {
4963089Swyllys r1 = (KMF_X509_RDN *)&name1->RelativeDistinguishedName[i];
4973089Swyllys av1 = (KMF_X509_TYPE_VALUE_PAIR *)r1->AttributeTypeAndValue;
4983089Swyllys
4993089Swyllys avfound = FALSE;
5003089Swyllys for (j = 0; j < name2->numberOfRDNs && !avfound; j++) {
5013089Swyllys r2 = (KMF_X509_RDN *)
5025051Swyllys &name2->RelativeDistinguishedName[j];
5033089Swyllys av2 = (KMF_X509_TYPE_VALUE_PAIR *)
5045051Swyllys r2->AttributeTypeAndValue;
5053089Swyllys
5063089Swyllys avfound = (IsEqualOid(&av1->type, &av2->type) &&
5075051Swyllys IsEqualData(&av1->value, &av2->value));
5083089Swyllys }
5093089Swyllys /*
5103089Swyllys * If the current AV from name1 was not found in name2,
5113089Swyllys * we are done.
5123089Swyllys */
5133089Swyllys if (!avfound)
5143089Swyllys return (1);
5153089Swyllys }
5163089Swyllys
5173089Swyllys /* If we got this far, it must be a match */
5183089Swyllys return (0);
5193089Swyllys }
5205051Swyllys
5215051Swyllys /*
5225051Swyllys * kmf_dn_parser
5235051Swyllys *
5245051Swyllys * Public interface for parsing a Distinguished name in
5255051Swyllys * human-readable format into a binary KMF_X509_NAME.
5265051Swyllys */
5275051Swyllys KMF_RETURN
kmf_dn_parser(char * string,KMF_X509_NAME * name)5285051Swyllys kmf_dn_parser(char *string, KMF_X509_NAME *name)
5295051Swyllys {
5305051Swyllys KMF_RETURN err;
5315051Swyllys
5325051Swyllys if (string == NULL || name == NULL)
5335051Swyllys return (KMF_ERR_BAD_PARAMETER);
5345051Swyllys
5355051Swyllys err = ParseDistinguishedName(string, (int)strlen(string), name);
5365051Swyllys return (err);
5375051Swyllys }
538