1*3089Swyllys /* 2*3089Swyllys * CDDL HEADER START 3*3089Swyllys * 4*3089Swyllys * The contents of this file are subject to the terms of the 5*3089Swyllys * Common Development and Distribution License (the "License"). 6*3089Swyllys * You may not use this file except in compliance with the License. 7*3089Swyllys * 8*3089Swyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3089Swyllys * or http://www.opensolaris.org/os/licensing. 10*3089Swyllys * See the License for the specific language governing permissions 11*3089Swyllys * and limitations under the License. 12*3089Swyllys * 13*3089Swyllys * When distributing Covered Code, include this CDDL HEADER in each 14*3089Swyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3089Swyllys * If applicable, add the following below this CDDL HEADER, with the 16*3089Swyllys * fields enclosed by brackets "[]" replaced with your own identifying 17*3089Swyllys * information: Portions Copyright [yyyy] [name of copyright owner] 18*3089Swyllys * 19*3089Swyllys * CDDL HEADER END 20*3089Swyllys */ 21*3089Swyllys /* 22*3089Swyllys * The contents of this file are subject to the Mozilla Public 23*3089Swyllys * License Version 1.1 (the "License"); you may not use this file 24*3089Swyllys * except in compliance with the License. You may obtain a copy of 25*3089Swyllys * the License at http://www.mozilla.org/MPL/ 26*3089Swyllys * 27*3089Swyllys * Software distributed under the License is distributed on an "AS 28*3089Swyllys * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 29*3089Swyllys * implied. See the License for the specific language governing 30*3089Swyllys * rights and limitations under the License. 31*3089Swyllys * 32*3089Swyllys * The Original Code is the Netscape security libraries. 33*3089Swyllys * 34*3089Swyllys * The Initial Developer of the Original Code is Netscape 35*3089Swyllys * Communications Corporation. Portions created by Netscape are 36*3089Swyllys * Copyright (C) 1994-2000 Netscape Communications Corporation. All 37*3089Swyllys * Rights Reserved. 38*3089Swyllys * 39*3089Swyllys * Contributor(s): 40*3089Swyllys * 41*3089Swyllys * Alternatively, the contents of this file may be used under the 42*3089Swyllys * terms of the GNU General Public License Version 2 or later (the 43*3089Swyllys * "GPL"), in which case the provisions of the GPL are applicable 44*3089Swyllys * instead of those above. If you wish to allow use of your 45*3089Swyllys * version of this file only under the terms of the GPL and not to 46*3089Swyllys * allow others to use your version of this file under the MPL, 47*3089Swyllys * indicate your decision by deleting the provisions above and 48*3089Swyllys * replace them with the notice and other provisions required by 49*3089Swyllys * the GPL. If you do not delete the provisions above, a recipient 50*3089Swyllys * may use your version of this file under either the MPL or the 51*3089Swyllys * GPL. 52*3089Swyllys */ 53*3089Swyllys /* 54*3089Swyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 55*3089Swyllys * Use is subject to license terms. 56*3089Swyllys * 57*3089Swyllys * File: rdn_parser.c 58*3089Swyllys */ 59*3089Swyllys 60*3089Swyllys #pragma ident "%Z%%M% %I% %E% SMI" 61*3089Swyllys 62*3089Swyllys 63*3089Swyllys #include <strings.h> 64*3089Swyllys #include <stdlib.h> 65*3089Swyllys #include <kmfapi.h> 66*3089Swyllys #include <kmfapiP.h> 67*3089Swyllys #include <ber_der.h> 68*3089Swyllys #include <rdn_parser.h> 69*3089Swyllys #include <stdio.h> 70*3089Swyllys #include <values.h> 71*3089Swyllys 72*3089Swyllys /* 73*3089Swyllys * The order here is important. The OIDs are arranged in order of 74*3089Swyllys * significance. The CN is the most specific value, the C (country) 75*3089Swyllys * is less specific, etc. Add to this list with care. 76*3089Swyllys */ 77*3089Swyllys static const struct NameToKind name2kinds[] = { 78*3089Swyllys { "CN", OID_AVA_COMMON_NAME, (KMF_OID *)&KMFOID_CommonName}, 79*3089Swyllys { "SN", OID_AVA_SURNAME, (KMF_OID *)&KMFOID_Surname}, 80*3089Swyllys { "GN", OID_AVA_GIVEN_NAME, (KMF_OID *)&KMFOID_GivenName}, 81*3089Swyllys { "emailAddress", OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress}, 82*3089Swyllys { "E", OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress}, 83*3089Swyllys { "MAIL", OID_RFC1274_MAIL, (KMF_OID *)&KMFOID_RFC822mailbox}, 84*3089Swyllys { "STREET", OID_AVA_STREET_ADDRESS, (KMF_OID *)&KMFOID_StreetAddress}, 85*3089Swyllys { "UID", OID_RFC1274_UID, (KMF_OID *)&KMFOID_userid}, 86*3089Swyllys { "OU", OID_AVA_ORGANIZATIONAL_UNIT_NAME, 87*3089Swyllys (KMF_OID *)&KMFOID_OrganizationalUnitName}, 88*3089Swyllys { "O", OID_AVA_ORGANIZATION_NAME, (KMF_OID *)&KMFOID_OrganizationName}, 89*3089Swyllys { "L", OID_AVA_LOCALITY, (KMF_OID *)&KMFOID_LocalityName}, 90*3089Swyllys { "ST", OID_AVA_STATE_OR_PROVINCE, 91*3089Swyllys (KMF_OID *)&KMFOID_StateProvinceName}, 92*3089Swyllys { "C", OID_AVA_COUNTRY_NAME, (KMF_OID *)&KMFOID_CountryName}, 93*3089Swyllys { "DC", OID_AVA_DC, (KMF_OID *)&KMFOID_domainComponent}, 94*3089Swyllys { 0, OID_UNKNOWN, NULL} 95*3089Swyllys }; 96*3089Swyllys 97*3089Swyllys static KMF_BOOL 98*3089Swyllys IsPrintable(unsigned char *data, unsigned len) 99*3089Swyllys { 100*3089Swyllys unsigned char ch, *end; 101*3089Swyllys 102*3089Swyllys end = data + len; 103*3089Swyllys while (data < end) { 104*3089Swyllys ch = *data++; 105*3089Swyllys if (!IS_PRINTABLE(ch)) { 106*3089Swyllys return (B_FALSE); 107*3089Swyllys } 108*3089Swyllys } 109*3089Swyllys return (B_TRUE); 110*3089Swyllys } 111*3089Swyllys 112*3089Swyllys static KMF_BOOL 113*3089Swyllys Is7Bit(unsigned char *data, unsigned len) 114*3089Swyllys { 115*3089Swyllys unsigned char ch, *end; 116*3089Swyllys 117*3089Swyllys end = data + len; 118*3089Swyllys while (data < end) { 119*3089Swyllys ch = *data++; 120*3089Swyllys if ((ch & 0x80)) { 121*3089Swyllys return (B_FALSE); 122*3089Swyllys } 123*3089Swyllys } 124*3089Swyllys return (B_TRUE); 125*3089Swyllys } 126*3089Swyllys 127*3089Swyllys static void 128*3089Swyllys skipSpace(char **pbp, char *endptr) 129*3089Swyllys { 130*3089Swyllys char *bp = *pbp; 131*3089Swyllys while (bp < endptr && OPTIONAL_SPACE(*bp)) { 132*3089Swyllys bp++; 133*3089Swyllys } 134*3089Swyllys *pbp = bp; 135*3089Swyllys } 136*3089Swyllys 137*3089Swyllys static KMF_RETURN 138*3089Swyllys scanTag(char **pbp, char *endptr, char *tagBuf, int tagBufSize) 139*3089Swyllys { 140*3089Swyllys char *bp, *tagBufp; 141*3089Swyllys int taglen; 142*3089Swyllys 143*3089Swyllys if (tagBufSize <= 0) 144*3089Swyllys return (KMF_ERR_INTERNAL); 145*3089Swyllys 146*3089Swyllys /* skip optional leading space */ 147*3089Swyllys skipSpace(pbp, endptr); 148*3089Swyllys if (*pbp == endptr) { 149*3089Swyllys /* nothing left */ 150*3089Swyllys return (KMF_ERR_RDN_PARSER); 151*3089Swyllys } 152*3089Swyllys 153*3089Swyllys /* fill tagBuf */ 154*3089Swyllys taglen = 0; 155*3089Swyllys bp = *pbp; 156*3089Swyllys tagBufp = tagBuf; 157*3089Swyllys while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) { 158*3089Swyllys if (++taglen >= tagBufSize) { 159*3089Swyllys *pbp = bp; 160*3089Swyllys return (KMF_ERR_RDN_PARSER); 161*3089Swyllys } 162*3089Swyllys *tagBufp++ = *bp++; 163*3089Swyllys } 164*3089Swyllys /* null-terminate tagBuf -- guaranteed at least one space left */ 165*3089Swyllys *tagBufp++ = 0; 166*3089Swyllys *pbp = bp; 167*3089Swyllys 168*3089Swyllys /* 169*3089Swyllys * skip trailing spaces till we hit something - should be 170*3089Swyllys * an equal sign 171*3089Swyllys */ 172*3089Swyllys skipSpace(pbp, endptr); 173*3089Swyllys if (*pbp == endptr) { 174*3089Swyllys /* nothing left */ 175*3089Swyllys return (KMF_ERR_RDN_PARSER); 176*3089Swyllys } 177*3089Swyllys if (**pbp != C_EQUAL) { 178*3089Swyllys /* should be an equal sign */ 179*3089Swyllys return (KMF_ERR_RDN_PARSER); 180*3089Swyllys } 181*3089Swyllys /* skip over the equal sign */ 182*3089Swyllys (*pbp)++; 183*3089Swyllys 184*3089Swyllys return (KMF_OK); 185*3089Swyllys } 186*3089Swyllys 187*3089Swyllys static KMF_RETURN 188*3089Swyllys scanVal(char **pbp, char *endptr, char *valBuf, int valBufSize) 189*3089Swyllys { 190*3089Swyllys char *bp, *valBufp; 191*3089Swyllys int vallen; 192*3089Swyllys boolean_t isQuoted; 193*3089Swyllys 194*3089Swyllys if (valBufSize <= 0) 195*3089Swyllys return (KMF_ERR_INTERNAL); 196*3089Swyllys 197*3089Swyllys /* skip optional leading space */ 198*3089Swyllys skipSpace(pbp, endptr); 199*3089Swyllys if (*pbp == endptr) { 200*3089Swyllys /* nothing left */ 201*3089Swyllys return (KMF_ERR_RDN_PARSER); 202*3089Swyllys } 203*3089Swyllys 204*3089Swyllys bp = *pbp; 205*3089Swyllys 206*3089Swyllys /* quoted? */ 207*3089Swyllys if (*bp == C_DOUBLE_QUOTE) { 208*3089Swyllys isQuoted = B_TRUE; 209*3089Swyllys /* skip over it */ 210*3089Swyllys bp++; 211*3089Swyllys } else { 212*3089Swyllys isQuoted = B_FALSE; 213*3089Swyllys } 214*3089Swyllys 215*3089Swyllys valBufp = valBuf; 216*3089Swyllys vallen = 0; 217*3089Swyllys while (bp < endptr) { 218*3089Swyllys char c = *bp; 219*3089Swyllys if (c == C_BACKSLASH) { 220*3089Swyllys /* escape character */ 221*3089Swyllys bp++; 222*3089Swyllys if (bp >= endptr) { 223*3089Swyllys /* 224*3089Swyllys * escape charater must appear with paired char 225*3089Swyllys */ 226*3089Swyllys *pbp = bp; 227*3089Swyllys return (KMF_ERR_RDN_PARSER); 228*3089Swyllys } 229*3089Swyllys } else if (!isQuoted && SPECIAL_CHAR(c)) { 230*3089Swyllys /* unescaped special and not within quoted value */ 231*3089Swyllys break; 232*3089Swyllys } else if (c == C_DOUBLE_QUOTE) { 233*3089Swyllys /* reached unescaped double quote */ 234*3089Swyllys break; 235*3089Swyllys } 236*3089Swyllys /* append character */ 237*3089Swyllys vallen++; 238*3089Swyllys if (vallen >= valBufSize) { 239*3089Swyllys *pbp = bp; 240*3089Swyllys return (KMF_ERR_RDN_PARSER); 241*3089Swyllys } 242*3089Swyllys *valBufp++ = *bp++; 243*3089Swyllys } 244*3089Swyllys 245*3089Swyllys /* stip trailing spaces from unquoted values */ 246*3089Swyllys if (!isQuoted) { 247*3089Swyllys if (valBufp > valBuf) { 248*3089Swyllys valBufp--; 249*3089Swyllys while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) { 250*3089Swyllys valBufp--; 251*3089Swyllys } 252*3089Swyllys valBufp++; 253*3089Swyllys } 254*3089Swyllys } 255*3089Swyllys 256*3089Swyllys if (isQuoted) { 257*3089Swyllys /* insist that we stopped on a double quote */ 258*3089Swyllys if (*bp != C_DOUBLE_QUOTE) { 259*3089Swyllys *pbp = bp; 260*3089Swyllys return (KMF_ERR_RDN_PARSER); 261*3089Swyllys } 262*3089Swyllys /* skip over the quote and skip optional space */ 263*3089Swyllys bp++; 264*3089Swyllys skipSpace(&bp, endptr); 265*3089Swyllys } 266*3089Swyllys 267*3089Swyllys *pbp = bp; 268*3089Swyllys 269*3089Swyllys if (valBufp == valBuf) { 270*3089Swyllys /* empty value -- not allowed */ 271*3089Swyllys return (KMF_ERR_RDN_PARSER); 272*3089Swyllys } 273*3089Swyllys 274*3089Swyllys /* null-terminate valBuf -- guaranteed at least one space left */ 275*3089Swyllys *valBufp++ = 0; 276*3089Swyllys 277*3089Swyllys return (KMF_OK); 278*3089Swyllys } 279*3089Swyllys 280*3089Swyllys static KMF_RETURN 281*3089Swyllys CreateRDN(KMF_X509_TYPE_VALUE_PAIR *ava, KMF_X509_RDN *newrdn) 282*3089Swyllys { 283*3089Swyllys /* Each RDN has 1 AttrTypeAndValue */ 284*3089Swyllys (void) memset(newrdn, 0, sizeof (KMF_X509_RDN)); 285*3089Swyllys newrdn->numberOfPairs = 1; 286*3089Swyllys newrdn->AttributeTypeAndValue = ava; 287*3089Swyllys 288*3089Swyllys return (KMF_OK); 289*3089Swyllys } 290*3089Swyllys 291*3089Swyllys static KMF_RETURN 292*3089Swyllys copy_oid(KMF_OID *dst, KMF_OID *src) 293*3089Swyllys { 294*3089Swyllys KMF_RETURN ret = KMF_OK; 295*3089Swyllys 296*3089Swyllys if (dst == NULL || src == NULL) 297*3089Swyllys return (KMF_ERR_BAD_PARAMETER); 298*3089Swyllys 299*3089Swyllys dst->Data = malloc(src->Length); 300*3089Swyllys if (dst->Data == NULL) 301*3089Swyllys return (KMF_ERR_MEMORY); 302*3089Swyllys 303*3089Swyllys dst->Length = src->Length; 304*3089Swyllys (void) memcpy(dst->Data, src->Data, src->Length); 305*3089Swyllys 306*3089Swyllys return (ret); 307*3089Swyllys } 308*3089Swyllys 309*3089Swyllys static KMF_RETURN 310*3089Swyllys CreateAVA(KMF_OID *oid, int valueType, char *value, 311*3089Swyllys KMF_X509_TYPE_VALUE_PAIR **newava) 312*3089Swyllys { 313*3089Swyllys int rv = KMF_OK; 314*3089Swyllys KMF_X509_TYPE_VALUE_PAIR *ava = NULL; 315*3089Swyllys 316*3089Swyllys *newava = NULL; 317*3089Swyllys ava = (KMF_X509_TYPE_VALUE_PAIR*) malloc( 318*3089Swyllys sizeof (KMF_X509_TYPE_VALUE_PAIR)); 319*3089Swyllys if (ava == NULL) { 320*3089Swyllys return (KMF_ERR_MEMORY); 321*3089Swyllys } else { 322*3089Swyllys (void) memset(ava, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR)); 323*3089Swyllys ava->valueType = valueType; 324*3089Swyllys ava->value.Data = malloc(strlen(value)); 325*3089Swyllys if (ava->value.Data == NULL) { 326*3089Swyllys free(ava); 327*3089Swyllys return (KMF_ERR_MEMORY); 328*3089Swyllys } 329*3089Swyllys (void) memcpy(ava->value.Data, value, strlen(value)); 330*3089Swyllys ava->value.Length = strlen(value); 331*3089Swyllys 332*3089Swyllys rv = copy_oid(&ava->type, oid); 333*3089Swyllys if (rv != KMF_OK) { 334*3089Swyllys /* Illegal AVA type */ 335*3089Swyllys free(ava->value.Data); 336*3089Swyllys free(ava); 337*3089Swyllys return (rv); 338*3089Swyllys } 339*3089Swyllys } 340*3089Swyllys *newava = ava; 341*3089Swyllys 342*3089Swyllys return (rv); 343*3089Swyllys } 344*3089Swyllys 345*3089Swyllys static KMF_RETURN 346*3089Swyllys ParseRdnAttribute(char **pbp, char *endptr, boolean_t singleAVA, 347*3089Swyllys KMF_X509_TYPE_VALUE_PAIR **a) 348*3089Swyllys { 349*3089Swyllys KMF_RETURN rv; 350*3089Swyllys const struct NameToKind *n2k; 351*3089Swyllys int vt; 352*3089Swyllys int valLen; 353*3089Swyllys char *bp; 354*3089Swyllys 355*3089Swyllys char tagBuf[32]; 356*3089Swyllys char valBuf[384]; 357*3089Swyllys 358*3089Swyllys rv = scanTag(pbp, endptr, tagBuf, sizeof (tagBuf)); 359*3089Swyllys if (rv != KMF_OK) 360*3089Swyllys return (rv); 361*3089Swyllys rv = scanVal(pbp, endptr, valBuf, sizeof (valBuf)); 362*3089Swyllys if (rv != KMF_OK) 363*3089Swyllys return (rv); 364*3089Swyllys 365*3089Swyllys /* insist that if we haven't finished we've stopped on a separator */ 366*3089Swyllys bp = *pbp; 367*3089Swyllys if (bp < endptr) { 368*3089Swyllys if (singleAVA || (*bp != ',' && *bp != ';')) { 369*3089Swyllys *pbp = bp; 370*3089Swyllys return (KMF_ERR_RDN_ATTR); 371*3089Swyllys } 372*3089Swyllys /* ok, skip over separator */ 373*3089Swyllys bp++; 374*3089Swyllys } 375*3089Swyllys *pbp = bp; 376*3089Swyllys 377*3089Swyllys for (n2k = name2kinds; n2k->name; n2k++) { 378*3089Swyllys if (strcasecmp(n2k->name, tagBuf) == 0) { 379*3089Swyllys valLen = strlen(valBuf); 380*3089Swyllys if (n2k->kind == OID_AVA_COUNTRY_NAME) { 381*3089Swyllys vt = BER_PRINTABLE_STRING; 382*3089Swyllys if (valLen != 2) { 383*3089Swyllys return (KMF_ERR_RDN_ATTR); 384*3089Swyllys } 385*3089Swyllys if (!IsPrintable((unsigned char *) valBuf, 2)) { 386*3089Swyllys return (KMF_ERR_RDN_ATTR); 387*3089Swyllys } 388*3089Swyllys } else if ((n2k->kind == OID_PKCS9_EMAIL_ADDRESS) || 389*3089Swyllys (n2k->kind == OID_RFC1274_MAIL)) { 390*3089Swyllys vt = BER_IA5STRING; 391*3089Swyllys } else { 392*3089Swyllys /* 393*3089Swyllys * Hack -- for rationale see X.520 394*3089Swyllys * DirectoryString defn 395*3089Swyllys */ 396*3089Swyllys if (IsPrintable((unsigned char *)valBuf, 397*3089Swyllys valLen)) { 398*3089Swyllys vt = BER_PRINTABLE_STRING; 399*3089Swyllys } else if (Is7Bit((unsigned char *)valBuf, 400*3089Swyllys valLen)) { 401*3089Swyllys vt = BER_T61STRING; 402*3089Swyllys } 403*3089Swyllys } 404*3089Swyllys rv = CreateAVA(n2k->OID, 405*3089Swyllys vt, (char *)valBuf, a); 406*3089Swyllys return (rv); 407*3089Swyllys } 408*3089Swyllys } 409*3089Swyllys /* matched no kind -- invalid tag */ 410*3089Swyllys return (KMF_ERR_RDN_ATTR); 411*3089Swyllys } 412*3089Swyllys 413*3089Swyllys static int 414*3089Swyllys rdnavcompare(const void *a, const void *b) 415*3089Swyllys { 416*3089Swyllys KMF_X509_RDN *r1, *r2; 417*3089Swyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2; 418*3089Swyllys int i, p1, p2; 419*3089Swyllys const struct NameToKind *n2k; 420*3089Swyllys KMF_OID *oidrec; 421*3089Swyllys 422*3089Swyllys r1 = (KMF_X509_RDN *)a; 423*3089Swyllys r2 = (KMF_X509_RDN *)b; 424*3089Swyllys 425*3089Swyllys av1 = r1->AttributeTypeAndValue; 426*3089Swyllys av2 = r2->AttributeTypeAndValue; 427*3089Swyllys 428*3089Swyllys p1 = p2 = MAXINT; 429*3089Swyllys /* 430*3089Swyllys * The "Name2Kinds" list is ordered by significance. 431*3089Swyllys * Compare the "ranking" of each of the OIDs to determine 432*3089Swyllys * the result. 433*3089Swyllys */ 434*3089Swyllys for (n2k = name2kinds, i = 0; 435*3089Swyllys n2k->name && (p1 == MAXINT || p2 == MAXINT); 436*3089Swyllys n2k++, i++) { 437*3089Swyllys oidrec = n2k->OID; 438*3089Swyllys if (oidrec != NULL) { 439*3089Swyllys if (IsEqualOid(&av1->type, oidrec)) 440*3089Swyllys p1 = i; 441*3089Swyllys if (IsEqualOid(&av2->type, oidrec)) 442*3089Swyllys p2 = i; 443*3089Swyllys } 444*3089Swyllys } 445*3089Swyllys 446*3089Swyllys if (p1 > p2) 447*3089Swyllys return (-1); 448*3089Swyllys else if (p1 < p2) 449*3089Swyllys return (1); 450*3089Swyllys else /* If equal, treat as if it is less than */ 451*3089Swyllys return (1); 452*3089Swyllys } 453*3089Swyllys 454*3089Swyllys KMF_RETURN 455*3089Swyllys ParseDistinguishedName(char *buf, int len, KMF_X509_NAME *name) 456*3089Swyllys { 457*3089Swyllys KMF_RETURN rv = KMF_OK; 458*3089Swyllys char *bp, *e; 459*3089Swyllys KMF_X509_TYPE_VALUE_PAIR *ava = NULL; 460*3089Swyllys KMF_X509_RDN rdn; 461*3089Swyllys 462*3089Swyllys (void) memset(name, 0, sizeof (KMF_X509_NAME)); 463*3089Swyllys e = buf + len; 464*3089Swyllys bp = buf; 465*3089Swyllys while (bp < e) { 466*3089Swyllys rv = ParseRdnAttribute(&bp, e, B_FALSE, &ava); 467*3089Swyllys if (rv != KMF_OK) goto loser; 468*3089Swyllys rv = CreateRDN(ava, &rdn); 469*3089Swyllys if (rv != KMF_OK) goto loser; 470*3089Swyllys if (AddRDN(name, &rdn) != KMF_OK) goto loser; 471*3089Swyllys skipSpace(&bp, e); 472*3089Swyllys } 473*3089Swyllys 474*3089Swyllys /* 475*3089Swyllys * Canonicalize the DN by sorting the elements 476*3089Swyllys * in little-endian order, as per RFC 1485: 477*3089Swyllys * "The name is presented/input in a little-endian 478*3089Swyllys * order (most significant component last)." 479*3089Swyllys */ 480*3089Swyllys qsort((void *)name->RelativeDistinguishedName, 481*3089Swyllys name->numberOfRDNs, 482*3089Swyllys sizeof (KMF_X509_RDN), 483*3089Swyllys rdnavcompare); 484*3089Swyllys 485*3089Swyllys /* return result */ 486*3089Swyllys return (rv); 487*3089Swyllys 488*3089Swyllys loser: 489*3089Swyllys KMF_FreeDN(name); 490*3089Swyllys return (rv); 491*3089Swyllys } 492*3089Swyllys 493*3089Swyllys static KMF_BOOL 494*3089Swyllys IsEqualData(KMF_DATA *d1, KMF_DATA *d2) 495*3089Swyllys { 496*3089Swyllys return ((d1->Length == d2->Length) && 497*3089Swyllys !memcmp(d1->Data, d2->Data, d1->Length)); 498*3089Swyllys } 499*3089Swyllys 500*3089Swyllys /* 501*3089Swyllys * Generic routine to compare 2 RDN structures. 502*3089Swyllys * 503*3089Swyllys * Because the ordering of the AV pairs may not be 504*3089Swyllys * the same, we must compare each AV pair individually 505*3089Swyllys * 506*3089Swyllys * Return 0 if equal, 1 if not. 507*3089Swyllys */ 508*3089Swyllys int 509*3089Swyllys KMF_CompareRDNs(KMF_X509_NAME *name1, KMF_X509_NAME *name2) 510*3089Swyllys { 511*3089Swyllys int i, j; 512*3089Swyllys boolean_t avfound; 513*3089Swyllys KMF_X509_RDN *r1, *r2; 514*3089Swyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2; 515*3089Swyllys 516*3089Swyllys if (name1 == NULL || name2 == NULL) 517*3089Swyllys return (1); 518*3089Swyllys 519*3089Swyllys if (name1->numberOfRDNs != name2->numberOfRDNs) 520*3089Swyllys return (1); 521*3089Swyllys 522*3089Swyllys for (i = 0; i < name1->numberOfRDNs; i++) { 523*3089Swyllys r1 = (KMF_X509_RDN *)&name1->RelativeDistinguishedName[i]; 524*3089Swyllys av1 = (KMF_X509_TYPE_VALUE_PAIR *)r1->AttributeTypeAndValue; 525*3089Swyllys 526*3089Swyllys avfound = FALSE; 527*3089Swyllys for (j = 0; j < name2->numberOfRDNs && !avfound; j++) { 528*3089Swyllys r2 = (KMF_X509_RDN *) 529*3089Swyllys &name2->RelativeDistinguishedName[j]; 530*3089Swyllys av2 = (KMF_X509_TYPE_VALUE_PAIR *) 531*3089Swyllys r2->AttributeTypeAndValue; 532*3089Swyllys 533*3089Swyllys avfound = (IsEqualOid(&av1->type, &av2->type) && 534*3089Swyllys IsEqualData(&av1->value, &av2->value)); 535*3089Swyllys } 536*3089Swyllys /* 537*3089Swyllys * If the current AV from name1 was not found in name2, 538*3089Swyllys * we are done. 539*3089Swyllys */ 540*3089Swyllys if (!avfound) 541*3089Swyllys return (1); 542*3089Swyllys } 543*3089Swyllys 544*3089Swyllys /* If we got this far, it must be a match */ 545*3089Swyllys return (0); 546*3089Swyllys } 547