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 /* 34*3433Shaimay * 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) || 3693089Swyllys (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 } 3843089Swyllys rv = CreateAVA(n2k->OID, 3853089Swyllys vt, (char *)valBuf, a); 3863089Swyllys return (rv); 3873089Swyllys } 3883089Swyllys } 3893089Swyllys /* matched no kind -- invalid tag */ 3903089Swyllys return (KMF_ERR_RDN_ATTR); 3913089Swyllys } 3923089Swyllys 3933089Swyllys static int 3943089Swyllys rdnavcompare(const void *a, const void *b) 3953089Swyllys { 3963089Swyllys KMF_X509_RDN *r1, *r2; 3973089Swyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2; 3983089Swyllys int i, p1, p2; 3993089Swyllys const struct NameToKind *n2k; 4003089Swyllys KMF_OID *oidrec; 4013089Swyllys 4023089Swyllys r1 = (KMF_X509_RDN *)a; 4033089Swyllys r2 = (KMF_X509_RDN *)b; 4043089Swyllys 4053089Swyllys av1 = r1->AttributeTypeAndValue; 4063089Swyllys av2 = r2->AttributeTypeAndValue; 4073089Swyllys 4083089Swyllys p1 = p2 = MAXINT; 4093089Swyllys /* 4103089Swyllys * The "Name2Kinds" list is ordered by significance. 4113089Swyllys * Compare the "ranking" of each of the OIDs to determine 4123089Swyllys * the result. 4133089Swyllys */ 4143089Swyllys for (n2k = name2kinds, i = 0; 4153089Swyllys n2k->name && (p1 == MAXINT || p2 == MAXINT); 4163089Swyllys n2k++, i++) { 4173089Swyllys oidrec = n2k->OID; 4183089Swyllys if (oidrec != NULL) { 4193089Swyllys if (IsEqualOid(&av1->type, oidrec)) 4203089Swyllys p1 = i; 4213089Swyllys if (IsEqualOid(&av2->type, oidrec)) 4223089Swyllys p2 = i; 4233089Swyllys } 4243089Swyllys } 4253089Swyllys 4263089Swyllys if (p1 > p2) 4273089Swyllys return (-1); 4283089Swyllys else if (p1 < p2) 4293089Swyllys return (1); 4303089Swyllys else /* If equal, treat as if it is less than */ 4313089Swyllys return (1); 4323089Swyllys } 4333089Swyllys 4343089Swyllys KMF_RETURN 4353089Swyllys ParseDistinguishedName(char *buf, int len, KMF_X509_NAME *name) 4363089Swyllys { 4373089Swyllys KMF_RETURN rv = KMF_OK; 4383089Swyllys char *bp, *e; 4393089Swyllys KMF_X509_TYPE_VALUE_PAIR *ava = NULL; 4403089Swyllys KMF_X509_RDN rdn; 4413089Swyllys 4423089Swyllys (void) memset(name, 0, sizeof (KMF_X509_NAME)); 4433089Swyllys e = buf + len; 4443089Swyllys bp = buf; 4453089Swyllys while (bp < e) { 4463089Swyllys rv = ParseRdnAttribute(&bp, e, B_FALSE, &ava); 4473089Swyllys if (rv != KMF_OK) goto loser; 4483089Swyllys rv = CreateRDN(ava, &rdn); 4493089Swyllys if (rv != KMF_OK) goto loser; 4503089Swyllys if (AddRDN(name, &rdn) != KMF_OK) goto loser; 4513089Swyllys skipSpace(&bp, e); 4523089Swyllys } 4533089Swyllys 4543089Swyllys /* 4553089Swyllys * Canonicalize the DN by sorting the elements 4563089Swyllys * in little-endian order, as per RFC 1485: 4573089Swyllys * "The name is presented/input in a little-endian 4583089Swyllys * order (most significant component last)." 4593089Swyllys */ 4603089Swyllys qsort((void *)name->RelativeDistinguishedName, 4613089Swyllys name->numberOfRDNs, 4623089Swyllys sizeof (KMF_X509_RDN), 4633089Swyllys rdnavcompare); 4643089Swyllys 4653089Swyllys /* return result */ 4663089Swyllys return (rv); 4673089Swyllys 4683089Swyllys loser: 4693089Swyllys KMF_FreeDN(name); 4703089Swyllys return (rv); 4713089Swyllys } 4723089Swyllys 4733089Swyllys static KMF_BOOL 4743089Swyllys IsEqualData(KMF_DATA *d1, KMF_DATA *d2) 4753089Swyllys { 4763089Swyllys return ((d1->Length == d2->Length) && 4773089Swyllys !memcmp(d1->Data, d2->Data, d1->Length)); 4783089Swyllys } 4793089Swyllys 4803089Swyllys /* 4813089Swyllys * Generic routine to compare 2 RDN structures. 4823089Swyllys * 4833089Swyllys * Because the ordering of the AV pairs may not be 4843089Swyllys * the same, we must compare each AV pair individually 4853089Swyllys * 4863089Swyllys * Return 0 if equal, 1 if not. 4873089Swyllys */ 4883089Swyllys int 4893089Swyllys KMF_CompareRDNs(KMF_X509_NAME *name1, KMF_X509_NAME *name2) 4903089Swyllys { 4913089Swyllys int i, j; 4923089Swyllys boolean_t avfound; 4933089Swyllys KMF_X509_RDN *r1, *r2; 4943089Swyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2; 4953089Swyllys 4963089Swyllys if (name1 == NULL || name2 == NULL) 4973089Swyllys return (1); 4983089Swyllys 4993089Swyllys if (name1->numberOfRDNs != name2->numberOfRDNs) 5003089Swyllys return (1); 5013089Swyllys 5023089Swyllys for (i = 0; i < name1->numberOfRDNs; i++) { 5033089Swyllys r1 = (KMF_X509_RDN *)&name1->RelativeDistinguishedName[i]; 5043089Swyllys av1 = (KMF_X509_TYPE_VALUE_PAIR *)r1->AttributeTypeAndValue; 5053089Swyllys 5063089Swyllys avfound = FALSE; 5073089Swyllys for (j = 0; j < name2->numberOfRDNs && !avfound; j++) { 5083089Swyllys r2 = (KMF_X509_RDN *) 5093089Swyllys &name2->RelativeDistinguishedName[j]; 5103089Swyllys av2 = (KMF_X509_TYPE_VALUE_PAIR *) 5113089Swyllys r2->AttributeTypeAndValue; 5123089Swyllys 5133089Swyllys avfound = (IsEqualOid(&av1->type, &av2->type) && 5143089Swyllys IsEqualData(&av1->value, &av2->value)); 5153089Swyllys } 5163089Swyllys /* 5173089Swyllys * If the current AV from name1 was not found in name2, 5183089Swyllys * we are done. 5193089Swyllys */ 5203089Swyllys if (!avfound) 5213089Swyllys return (1); 5223089Swyllys } 5233089Swyllys 5243089Swyllys /* If we got this far, it must be a match */ 5253089Swyllys return (0); 5263089Swyllys } 527