199ebb4caSwyllys /*
299ebb4caSwyllys * The contents of this file are subject to the Mozilla Public
399ebb4caSwyllys * License Version 1.1 (the "License"); you may not use this file
499ebb4caSwyllys * except in compliance with the License. You may obtain a copy of
599ebb4caSwyllys * the License at http://www.mozilla.org/MPL/
699ebb4caSwyllys *
799ebb4caSwyllys * Software distributed under the License is distributed on an "AS
899ebb4caSwyllys * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
999ebb4caSwyllys * implied. See the License for the specific language governing
1099ebb4caSwyllys * rights and limitations under the License.
1199ebb4caSwyllys *
1299ebb4caSwyllys * The Original Code is the Netscape security libraries.
1399ebb4caSwyllys *
1499ebb4caSwyllys * The Initial Developer of the Original Code is Netscape
1599ebb4caSwyllys * Communications Corporation. Portions created by Netscape are
1699ebb4caSwyllys * Copyright (C) 1994-2000 Netscape Communications Corporation. All
1799ebb4caSwyllys * Rights Reserved.
1899ebb4caSwyllys *
1999ebb4caSwyllys * Contributor(s):
2099ebb4caSwyllys *
2199ebb4caSwyllys * Alternatively, the contents of this file may be used under the
2299ebb4caSwyllys * terms of the GNU General Public License Version 2 or later (the
2399ebb4caSwyllys * "GPL"), in which case the provisions of the GPL are applicable
2499ebb4caSwyllys * instead of those above. If you wish to allow use of your
2599ebb4caSwyllys * version of this file only under the terms of the GPL and not to
2699ebb4caSwyllys * allow others to use your version of this file under the MPL,
2799ebb4caSwyllys * indicate your decision by deleting the provisions above and
2899ebb4caSwyllys * replace them with the notice and other provisions required by
2999ebb4caSwyllys * the GPL. If you do not delete the provisions above, a recipient
3099ebb4caSwyllys * may use your version of this file under either the MPL or the
3199ebb4caSwyllys * GPL.
32*9f0bc604SWyllys Ingersoll *
33*9f0bc604SWyllys Ingersoll * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3499ebb4caSwyllys * Use is subject to license terms.
3599ebb4caSwyllys *
3699ebb4caSwyllys * File: rdn_parser.c
3799ebb4caSwyllys */
3899ebb4caSwyllys
3999ebb4caSwyllys #include <strings.h>
4099ebb4caSwyllys #include <stdlib.h>
4199ebb4caSwyllys #include <kmfapi.h>
4299ebb4caSwyllys #include <kmfapiP.h>
4399ebb4caSwyllys #include <ber_der.h>
4499ebb4caSwyllys #include <rdn_parser.h>
4599ebb4caSwyllys #include <stdio.h>
4699ebb4caSwyllys #include <values.h>
4799ebb4caSwyllys
4899ebb4caSwyllys /*
4999ebb4caSwyllys * The order here is important. The OIDs are arranged in order of
5099ebb4caSwyllys * significance. The CN is the most specific value, the C (country)
5199ebb4caSwyllys * is less specific, etc. Add to this list with care.
5299ebb4caSwyllys */
5399ebb4caSwyllys static const struct NameToKind name2kinds[] = {
5499ebb4caSwyllys { "CN", OID_AVA_COMMON_NAME, (KMF_OID *)&KMFOID_CommonName},
5599ebb4caSwyllys { "SN", OID_AVA_SURNAME, (KMF_OID *)&KMFOID_Surname},
5699ebb4caSwyllys { "GN", OID_AVA_GIVEN_NAME, (KMF_OID *)&KMFOID_GivenName},
5799ebb4caSwyllys { "emailAddress", OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress},
5899ebb4caSwyllys { "E", OID_PKCS9_EMAIL_ADDRESS, (KMF_OID *)&KMFOID_EmailAddress},
5999ebb4caSwyllys { "MAIL", OID_RFC1274_MAIL, (KMF_OID *)&KMFOID_RFC822mailbox},
6099ebb4caSwyllys { "STREET", OID_AVA_STREET_ADDRESS, (KMF_OID *)&KMFOID_StreetAddress},
6199ebb4caSwyllys { "UID", OID_RFC1274_UID, (KMF_OID *)&KMFOID_userid},
6299ebb4caSwyllys { "OU", OID_AVA_ORGANIZATIONAL_UNIT_NAME,
6399ebb4caSwyllys (KMF_OID *)&KMFOID_OrganizationalUnitName},
6499ebb4caSwyllys { "O", OID_AVA_ORGANIZATION_NAME, (KMF_OID *)&KMFOID_OrganizationName},
6599ebb4caSwyllys { "L", OID_AVA_LOCALITY, (KMF_OID *)&KMFOID_LocalityName},
6699ebb4caSwyllys { "ST", OID_AVA_STATE_OR_PROVINCE,
6799ebb4caSwyllys (KMF_OID *)&KMFOID_StateProvinceName},
6899ebb4caSwyllys { "C", OID_AVA_COUNTRY_NAME, (KMF_OID *)&KMFOID_CountryName},
6999ebb4caSwyllys { "DC", OID_AVA_DC, (KMF_OID *)&KMFOID_domainComponent},
7099ebb4caSwyllys { 0, OID_UNKNOWN, NULL}
7199ebb4caSwyllys };
7299ebb4caSwyllys
7399ebb4caSwyllys static KMF_BOOL
IsPrintable(unsigned char * data,unsigned len)7499ebb4caSwyllys IsPrintable(unsigned char *data, unsigned len)
7599ebb4caSwyllys {
7699ebb4caSwyllys unsigned char ch, *end;
7799ebb4caSwyllys
7899ebb4caSwyllys end = data + len;
7999ebb4caSwyllys while (data < end) {
8099ebb4caSwyllys ch = *data++;
8199ebb4caSwyllys if (!IS_PRINTABLE(ch)) {
8299ebb4caSwyllys return (B_FALSE);
8399ebb4caSwyllys }
8499ebb4caSwyllys }
8599ebb4caSwyllys return (B_TRUE);
8699ebb4caSwyllys }
8799ebb4caSwyllys
8899ebb4caSwyllys static KMF_BOOL
Is7Bit(unsigned char * data,unsigned len)8999ebb4caSwyllys Is7Bit(unsigned char *data, unsigned len)
9099ebb4caSwyllys {
9199ebb4caSwyllys unsigned char ch, *end;
9299ebb4caSwyllys
9399ebb4caSwyllys end = data + len;
9499ebb4caSwyllys while (data < end) {
9599ebb4caSwyllys ch = *data++;
9699ebb4caSwyllys if ((ch & 0x80)) {
9799ebb4caSwyllys return (B_FALSE);
9899ebb4caSwyllys }
9999ebb4caSwyllys }
10099ebb4caSwyllys return (B_TRUE);
10199ebb4caSwyllys }
10299ebb4caSwyllys
10399ebb4caSwyllys static void
skipSpace(char ** pbp,char * endptr)10499ebb4caSwyllys skipSpace(char **pbp, char *endptr)
10599ebb4caSwyllys {
10699ebb4caSwyllys char *bp = *pbp;
10799ebb4caSwyllys while (bp < endptr && OPTIONAL_SPACE(*bp)) {
10899ebb4caSwyllys bp++;
10999ebb4caSwyllys }
11099ebb4caSwyllys *pbp = bp;
11199ebb4caSwyllys }
11299ebb4caSwyllys
11399ebb4caSwyllys static KMF_RETURN
scanTag(char ** pbp,char * endptr,char * tagBuf,int tagBufSize)11499ebb4caSwyllys scanTag(char **pbp, char *endptr, char *tagBuf, int tagBufSize)
11599ebb4caSwyllys {
11699ebb4caSwyllys char *bp, *tagBufp;
11799ebb4caSwyllys int taglen;
11899ebb4caSwyllys
11999ebb4caSwyllys if (tagBufSize <= 0)
12099ebb4caSwyllys return (KMF_ERR_INTERNAL);
12199ebb4caSwyllys
12299ebb4caSwyllys /* skip optional leading space */
12399ebb4caSwyllys skipSpace(pbp, endptr);
12499ebb4caSwyllys if (*pbp == endptr) {
12599ebb4caSwyllys /* nothing left */
12699ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
12799ebb4caSwyllys }
12899ebb4caSwyllys
12999ebb4caSwyllys /* fill tagBuf */
13099ebb4caSwyllys taglen = 0;
13199ebb4caSwyllys bp = *pbp;
13299ebb4caSwyllys tagBufp = tagBuf;
13399ebb4caSwyllys while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) {
13499ebb4caSwyllys if (++taglen >= tagBufSize) {
13599ebb4caSwyllys *pbp = bp;
13699ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
13799ebb4caSwyllys }
13899ebb4caSwyllys *tagBufp++ = *bp++;
13999ebb4caSwyllys }
14099ebb4caSwyllys /* null-terminate tagBuf -- guaranteed at least one space left */
14199ebb4caSwyllys *tagBufp++ = 0;
14299ebb4caSwyllys *pbp = bp;
14399ebb4caSwyllys
14499ebb4caSwyllys /*
14599ebb4caSwyllys * skip trailing spaces till we hit something - should be
14699ebb4caSwyllys * an equal sign
14799ebb4caSwyllys */
14899ebb4caSwyllys skipSpace(pbp, endptr);
14999ebb4caSwyllys if (*pbp == endptr) {
15099ebb4caSwyllys /* nothing left */
15199ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
15299ebb4caSwyllys }
15399ebb4caSwyllys if (**pbp != C_EQUAL) {
15499ebb4caSwyllys /* should be an equal sign */
15599ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
15699ebb4caSwyllys }
15799ebb4caSwyllys /* skip over the equal sign */
15899ebb4caSwyllys (*pbp)++;
15999ebb4caSwyllys
16099ebb4caSwyllys return (KMF_OK);
16199ebb4caSwyllys }
16299ebb4caSwyllys
16399ebb4caSwyllys static KMF_RETURN
scanVal(char ** pbp,char * endptr,char * valBuf,int valBufSize)16499ebb4caSwyllys scanVal(char **pbp, char *endptr, char *valBuf, int valBufSize)
16599ebb4caSwyllys {
16699ebb4caSwyllys char *bp, *valBufp;
16799ebb4caSwyllys int vallen;
16899ebb4caSwyllys boolean_t isQuoted;
16999ebb4caSwyllys
17099ebb4caSwyllys if (valBufSize <= 0)
17199ebb4caSwyllys return (KMF_ERR_INTERNAL);
17299ebb4caSwyllys
17399ebb4caSwyllys /* skip optional leading space */
17499ebb4caSwyllys skipSpace(pbp, endptr);
17599ebb4caSwyllys if (*pbp == endptr) {
17699ebb4caSwyllys /* nothing left */
17799ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
17899ebb4caSwyllys }
17999ebb4caSwyllys
18099ebb4caSwyllys bp = *pbp;
18199ebb4caSwyllys
18299ebb4caSwyllys /* quoted? */
18399ebb4caSwyllys if (*bp == C_DOUBLE_QUOTE) {
18499ebb4caSwyllys isQuoted = B_TRUE;
18599ebb4caSwyllys /* skip over it */
18699ebb4caSwyllys bp++;
18799ebb4caSwyllys } else {
18899ebb4caSwyllys isQuoted = B_FALSE;
18999ebb4caSwyllys }
19099ebb4caSwyllys
19199ebb4caSwyllys valBufp = valBuf;
19299ebb4caSwyllys vallen = 0;
19399ebb4caSwyllys while (bp < endptr) {
19499ebb4caSwyllys char c = *bp;
19599ebb4caSwyllys if (c == C_BACKSLASH) {
19699ebb4caSwyllys /* escape character */
19799ebb4caSwyllys bp++;
19899ebb4caSwyllys if (bp >= endptr) {
19999ebb4caSwyllys /*
20099ebb4caSwyllys * escape charater must appear with paired char
20199ebb4caSwyllys */
20299ebb4caSwyllys *pbp = bp;
20399ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
20499ebb4caSwyllys }
20599ebb4caSwyllys } else if (!isQuoted && SPECIAL_CHAR(c)) {
20699ebb4caSwyllys /* unescaped special and not within quoted value */
20799ebb4caSwyllys break;
20899ebb4caSwyllys } else if (c == C_DOUBLE_QUOTE) {
20999ebb4caSwyllys /* reached unescaped double quote */
21099ebb4caSwyllys break;
21199ebb4caSwyllys }
21299ebb4caSwyllys /* append character */
21399ebb4caSwyllys vallen++;
21499ebb4caSwyllys if (vallen >= valBufSize) {
21599ebb4caSwyllys *pbp = bp;
21699ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
21799ebb4caSwyllys }
21899ebb4caSwyllys *valBufp++ = *bp++;
21999ebb4caSwyllys }
22099ebb4caSwyllys
22199ebb4caSwyllys /* stip trailing spaces from unquoted values */
22299ebb4caSwyllys if (!isQuoted) {
22399ebb4caSwyllys if (valBufp > valBuf) {
22499ebb4caSwyllys valBufp--;
22599ebb4caSwyllys while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) {
22699ebb4caSwyllys valBufp--;
22799ebb4caSwyllys }
22899ebb4caSwyllys valBufp++;
22999ebb4caSwyllys }
23099ebb4caSwyllys }
23199ebb4caSwyllys
23299ebb4caSwyllys if (isQuoted) {
23399ebb4caSwyllys /* insist that we stopped on a double quote */
23499ebb4caSwyllys if (*bp != C_DOUBLE_QUOTE) {
23599ebb4caSwyllys *pbp = bp;
23699ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
23799ebb4caSwyllys }
23899ebb4caSwyllys /* skip over the quote and skip optional space */
23999ebb4caSwyllys bp++;
24099ebb4caSwyllys skipSpace(&bp, endptr);
24199ebb4caSwyllys }
24299ebb4caSwyllys
24399ebb4caSwyllys *pbp = bp;
24499ebb4caSwyllys
24599ebb4caSwyllys if (valBufp == valBuf) {
24699ebb4caSwyllys /* empty value -- not allowed */
24799ebb4caSwyllys return (KMF_ERR_RDN_PARSER);
24899ebb4caSwyllys }
24999ebb4caSwyllys
25099ebb4caSwyllys /* null-terminate valBuf -- guaranteed at least one space left */
25199ebb4caSwyllys *valBufp++ = 0;
25299ebb4caSwyllys
25399ebb4caSwyllys return (KMF_OK);
25499ebb4caSwyllys }
25599ebb4caSwyllys
25699ebb4caSwyllys static KMF_RETURN
CreateRDN(KMF_X509_TYPE_VALUE_PAIR * ava,KMF_X509_RDN * newrdn)25799ebb4caSwyllys CreateRDN(KMF_X509_TYPE_VALUE_PAIR *ava, KMF_X509_RDN *newrdn)
25899ebb4caSwyllys {
25999ebb4caSwyllys /* Each RDN has 1 AttrTypeAndValue */
26099ebb4caSwyllys (void) memset(newrdn, 0, sizeof (KMF_X509_RDN));
26199ebb4caSwyllys newrdn->numberOfPairs = 1;
26299ebb4caSwyllys newrdn->AttributeTypeAndValue = ava;
26399ebb4caSwyllys
26499ebb4caSwyllys return (KMF_OK);
26599ebb4caSwyllys }
26699ebb4caSwyllys
26799ebb4caSwyllys static KMF_RETURN
copy_oid(KMF_OID * dst,KMF_OID * src)26899ebb4caSwyllys copy_oid(KMF_OID *dst, KMF_OID *src)
26999ebb4caSwyllys {
27099ebb4caSwyllys KMF_RETURN ret = KMF_OK;
27199ebb4caSwyllys
27299ebb4caSwyllys if (dst == NULL || src == NULL)
27399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
27499ebb4caSwyllys
27599ebb4caSwyllys dst->Data = malloc(src->Length);
27699ebb4caSwyllys if (dst->Data == NULL)
27799ebb4caSwyllys return (KMF_ERR_MEMORY);
27899ebb4caSwyllys
27999ebb4caSwyllys dst->Length = src->Length;
28099ebb4caSwyllys (void) memcpy(dst->Data, src->Data, src->Length);
28199ebb4caSwyllys
28299ebb4caSwyllys return (ret);
28399ebb4caSwyllys }
28499ebb4caSwyllys
28599ebb4caSwyllys static KMF_RETURN
CreateAVA(KMF_OID * oid,int valueType,char * value,KMF_X509_TYPE_VALUE_PAIR ** newava)28699ebb4caSwyllys CreateAVA(KMF_OID *oid, int valueType, char *value,
28799ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR **newava)
28899ebb4caSwyllys {
28999ebb4caSwyllys int rv = KMF_OK;
29099ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *ava = NULL;
29199ebb4caSwyllys
29299ebb4caSwyllys *newava = NULL;
29399ebb4caSwyllys ava = (KMF_X509_TYPE_VALUE_PAIR*) malloc(
29499ebb4caSwyllys sizeof (KMF_X509_TYPE_VALUE_PAIR));
29599ebb4caSwyllys if (ava == NULL) {
29699ebb4caSwyllys return (KMF_ERR_MEMORY);
29799ebb4caSwyllys } else {
29899ebb4caSwyllys (void) memset(ava, 0, sizeof (KMF_X509_TYPE_VALUE_PAIR));
29999ebb4caSwyllys ava->valueType = valueType;
30099ebb4caSwyllys ava->value.Data = malloc(strlen(value));
30199ebb4caSwyllys if (ava->value.Data == NULL) {
30299ebb4caSwyllys free(ava);
30399ebb4caSwyllys return (KMF_ERR_MEMORY);
30499ebb4caSwyllys }
30599ebb4caSwyllys (void) memcpy(ava->value.Data, value, strlen(value));
30699ebb4caSwyllys ava->value.Length = strlen(value);
30799ebb4caSwyllys
30899ebb4caSwyllys rv = copy_oid(&ava->type, oid);
30999ebb4caSwyllys if (rv != KMF_OK) {
31099ebb4caSwyllys /* Illegal AVA type */
31199ebb4caSwyllys free(ava->value.Data);
31299ebb4caSwyllys free(ava);
31399ebb4caSwyllys return (rv);
31499ebb4caSwyllys }
31599ebb4caSwyllys }
31699ebb4caSwyllys *newava = ava;
31799ebb4caSwyllys
31899ebb4caSwyllys return (rv);
31999ebb4caSwyllys }
32099ebb4caSwyllys
32199ebb4caSwyllys static KMF_RETURN
ParseRdnAttribute(char ** pbp,char * endptr,boolean_t singleAVA,KMF_X509_TYPE_VALUE_PAIR ** a)32299ebb4caSwyllys ParseRdnAttribute(char **pbp, char *endptr, boolean_t singleAVA,
32399ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR **a)
32499ebb4caSwyllys {
32599ebb4caSwyllys KMF_RETURN rv;
32699ebb4caSwyllys const struct NameToKind *n2k;
32799ebb4caSwyllys int vt;
32899ebb4caSwyllys int valLen;
32999ebb4caSwyllys char *bp;
33099ebb4caSwyllys
33199ebb4caSwyllys char tagBuf[32];
33299ebb4caSwyllys char valBuf[384];
33399ebb4caSwyllys
33499ebb4caSwyllys rv = scanTag(pbp, endptr, tagBuf, sizeof (tagBuf));
33599ebb4caSwyllys if (rv != KMF_OK)
33699ebb4caSwyllys return (rv);
33799ebb4caSwyllys rv = scanVal(pbp, endptr, valBuf, sizeof (valBuf));
33899ebb4caSwyllys if (rv != KMF_OK)
33999ebb4caSwyllys return (rv);
34099ebb4caSwyllys
34199ebb4caSwyllys /* insist that if we haven't finished we've stopped on a separator */
34299ebb4caSwyllys bp = *pbp;
34399ebb4caSwyllys if (bp < endptr) {
34499ebb4caSwyllys if (singleAVA || (*bp != ',' && *bp != ';')) {
34599ebb4caSwyllys *pbp = bp;
34699ebb4caSwyllys return (KMF_ERR_RDN_ATTR);
34799ebb4caSwyllys }
34899ebb4caSwyllys /* ok, skip over separator */
34999ebb4caSwyllys bp++;
35099ebb4caSwyllys }
35199ebb4caSwyllys *pbp = bp;
35299ebb4caSwyllys
35399ebb4caSwyllys for (n2k = name2kinds; n2k->name; n2k++) {
35499ebb4caSwyllys if (strcasecmp(n2k->name, tagBuf) == 0) {
35599ebb4caSwyllys valLen = strlen(valBuf);
35699ebb4caSwyllys if (n2k->kind == OID_AVA_COUNTRY_NAME) {
35799ebb4caSwyllys vt = BER_PRINTABLE_STRING;
35899ebb4caSwyllys if (valLen != 2) {
35999ebb4caSwyllys return (KMF_ERR_RDN_ATTR);
36099ebb4caSwyllys }
36199ebb4caSwyllys if (!IsPrintable((unsigned char *) valBuf, 2)) {
36299ebb4caSwyllys return (KMF_ERR_RDN_ATTR);
36399ebb4caSwyllys }
36499ebb4caSwyllys } else if ((n2k->kind == OID_PKCS9_EMAIL_ADDRESS) ||
36599ebb4caSwyllys (n2k->kind == OID_RFC1274_MAIL)) {
36699ebb4caSwyllys vt = BER_IA5STRING;
36799ebb4caSwyllys } else {
36899ebb4caSwyllys /*
36999ebb4caSwyllys * Hack -- for rationale see X.520
37099ebb4caSwyllys * DirectoryString defn
37199ebb4caSwyllys */
37299ebb4caSwyllys if (IsPrintable((unsigned char *)valBuf,
37399ebb4caSwyllys valLen)) {
37499ebb4caSwyllys vt = BER_PRINTABLE_STRING;
37599ebb4caSwyllys } else if (Is7Bit((unsigned char *)valBuf,
37699ebb4caSwyllys valLen)) {
37799ebb4caSwyllys vt = BER_T61STRING;
37899ebb4caSwyllys }
37999ebb4caSwyllys }
38030a5e8faSwyllys rv = CreateAVA(n2k->OID, vt, (char *)valBuf, a);
38199ebb4caSwyllys return (rv);
38299ebb4caSwyllys }
38399ebb4caSwyllys }
38499ebb4caSwyllys /* matched no kind -- invalid tag */
38599ebb4caSwyllys return (KMF_ERR_RDN_ATTR);
38699ebb4caSwyllys }
38799ebb4caSwyllys
38899ebb4caSwyllys static int
rdnavcompare(const void * a,const void * b)38999ebb4caSwyllys rdnavcompare(const void *a, const void *b)
39099ebb4caSwyllys {
39199ebb4caSwyllys KMF_X509_RDN *r1, *r2;
39299ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2;
39399ebb4caSwyllys int i, p1, p2;
39499ebb4caSwyllys const struct NameToKind *n2k;
39599ebb4caSwyllys KMF_OID *oidrec;
39699ebb4caSwyllys
39799ebb4caSwyllys r1 = (KMF_X509_RDN *)a;
39899ebb4caSwyllys r2 = (KMF_X509_RDN *)b;
39999ebb4caSwyllys
40099ebb4caSwyllys av1 = r1->AttributeTypeAndValue;
40199ebb4caSwyllys av2 = r2->AttributeTypeAndValue;
40299ebb4caSwyllys
40399ebb4caSwyllys p1 = p2 = MAXINT;
40499ebb4caSwyllys /*
40599ebb4caSwyllys * The "Name2Kinds" list is ordered by significance.
40699ebb4caSwyllys * Compare the "ranking" of each of the OIDs to determine
40799ebb4caSwyllys * the result.
40899ebb4caSwyllys */
40999ebb4caSwyllys for (n2k = name2kinds, i = 0;
41099ebb4caSwyllys n2k->name && (p1 == MAXINT || p2 == MAXINT);
41199ebb4caSwyllys n2k++, i++) {
41299ebb4caSwyllys oidrec = n2k->OID;
41399ebb4caSwyllys if (oidrec != NULL) {
41499ebb4caSwyllys if (IsEqualOid(&av1->type, oidrec))
41599ebb4caSwyllys p1 = i;
41699ebb4caSwyllys if (IsEqualOid(&av2->type, oidrec))
41799ebb4caSwyllys p2 = i;
41899ebb4caSwyllys }
41999ebb4caSwyllys }
42099ebb4caSwyllys
42199ebb4caSwyllys if (p1 > p2)
42299ebb4caSwyllys return (-1);
42399ebb4caSwyllys else if (p1 < p2)
42499ebb4caSwyllys return (1);
42599ebb4caSwyllys else /* If equal, treat as if it is less than */
42699ebb4caSwyllys return (1);
42799ebb4caSwyllys }
42899ebb4caSwyllys
42930a5e8faSwyllys static KMF_RETURN
ParseDistinguishedName(char * buf,int len,KMF_X509_NAME * name)43099ebb4caSwyllys ParseDistinguishedName(char *buf, int len, KMF_X509_NAME *name)
43199ebb4caSwyllys {
43299ebb4caSwyllys KMF_RETURN rv = KMF_OK;
43399ebb4caSwyllys char *bp, *e;
43499ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *ava = NULL;
43599ebb4caSwyllys KMF_X509_RDN rdn;
43699ebb4caSwyllys
43799ebb4caSwyllys (void) memset(name, 0, sizeof (KMF_X509_NAME));
43899ebb4caSwyllys e = buf + len;
43999ebb4caSwyllys bp = buf;
44099ebb4caSwyllys while (bp < e) {
44199ebb4caSwyllys rv = ParseRdnAttribute(&bp, e, B_FALSE, &ava);
44299ebb4caSwyllys if (rv != KMF_OK) goto loser;
44399ebb4caSwyllys rv = CreateRDN(ava, &rdn);
44499ebb4caSwyllys if (rv != KMF_OK) goto loser;
44599ebb4caSwyllys if (AddRDN(name, &rdn) != KMF_OK) goto loser;
44699ebb4caSwyllys skipSpace(&bp, e);
44799ebb4caSwyllys }
44899ebb4caSwyllys
44999ebb4caSwyllys /*
45099ebb4caSwyllys * Canonicalize the DN by sorting the elements
45199ebb4caSwyllys * in little-endian order, as per RFC 1485:
45299ebb4caSwyllys * "The name is presented/input in a little-endian
45399ebb4caSwyllys * order (most significant component last)."
45499ebb4caSwyllys */
45599ebb4caSwyllys qsort((void *)name->RelativeDistinguishedName,
45630a5e8faSwyllys name->numberOfRDNs, sizeof (KMF_X509_RDN), rdnavcompare);
45799ebb4caSwyllys
45899ebb4caSwyllys /* return result */
45999ebb4caSwyllys return (rv);
46099ebb4caSwyllys
46199ebb4caSwyllys loser:
46230a5e8faSwyllys kmf_free_dn(name);
46399ebb4caSwyllys return (rv);
46499ebb4caSwyllys }
46599ebb4caSwyllys
46699ebb4caSwyllys static KMF_BOOL
IsEqualData(KMF_DATA * d1,KMF_DATA * d2)46799ebb4caSwyllys IsEqualData(KMF_DATA *d1, KMF_DATA *d2)
46899ebb4caSwyllys {
46999ebb4caSwyllys return ((d1->Length == d2->Length) &&
47099ebb4caSwyllys !memcmp(d1->Data, d2->Data, d1->Length));
47199ebb4caSwyllys }
47299ebb4caSwyllys
47399ebb4caSwyllys /*
47499ebb4caSwyllys * Generic routine to compare 2 RDN structures.
47599ebb4caSwyllys *
47699ebb4caSwyllys * Because the ordering of the AV pairs may not be
47799ebb4caSwyllys * the same, we must compare each AV pair individually
47899ebb4caSwyllys *
47999ebb4caSwyllys * Return 0 if equal, 1 if not.
48099ebb4caSwyllys */
48199ebb4caSwyllys int
kmf_compare_rdns(KMF_X509_NAME * name1,KMF_X509_NAME * name2)48230a5e8faSwyllys kmf_compare_rdns(KMF_X509_NAME *name1, KMF_X509_NAME *name2)
48399ebb4caSwyllys {
48499ebb4caSwyllys int i, j;
48599ebb4caSwyllys boolean_t avfound;
48699ebb4caSwyllys KMF_X509_RDN *r1, *r2;
48799ebb4caSwyllys KMF_X509_TYPE_VALUE_PAIR *av1, *av2;
48899ebb4caSwyllys
48999ebb4caSwyllys if (name1 == NULL || name2 == NULL)
49099ebb4caSwyllys return (1);
49199ebb4caSwyllys
49299ebb4caSwyllys if (name1->numberOfRDNs != name2->numberOfRDNs)
49399ebb4caSwyllys return (1);
49499ebb4caSwyllys
49599ebb4caSwyllys for (i = 0; i < name1->numberOfRDNs; i++) {
49699ebb4caSwyllys r1 = (KMF_X509_RDN *)&name1->RelativeDistinguishedName[i];
49799ebb4caSwyllys av1 = (KMF_X509_TYPE_VALUE_PAIR *)r1->AttributeTypeAndValue;
49899ebb4caSwyllys
49999ebb4caSwyllys avfound = FALSE;
50099ebb4caSwyllys for (j = 0; j < name2->numberOfRDNs && !avfound; j++) {
50199ebb4caSwyllys r2 = (KMF_X509_RDN *)
50299ebb4caSwyllys &name2->RelativeDistinguishedName[j];
50399ebb4caSwyllys av2 = (KMF_X509_TYPE_VALUE_PAIR *)
50499ebb4caSwyllys r2->AttributeTypeAndValue;
50599ebb4caSwyllys
50699ebb4caSwyllys avfound = (IsEqualOid(&av1->type, &av2->type) &&
50799ebb4caSwyllys IsEqualData(&av1->value, &av2->value));
50899ebb4caSwyllys }
50999ebb4caSwyllys /*
51099ebb4caSwyllys * If the current AV from name1 was not found in name2,
51199ebb4caSwyllys * we are done.
51299ebb4caSwyllys */
51399ebb4caSwyllys if (!avfound)
51499ebb4caSwyllys return (1);
51599ebb4caSwyllys }
51699ebb4caSwyllys
51799ebb4caSwyllys /* If we got this far, it must be a match */
51899ebb4caSwyllys return (0);
51999ebb4caSwyllys }
52030a5e8faSwyllys
52130a5e8faSwyllys /*
52230a5e8faSwyllys * kmf_dn_parser
52330a5e8faSwyllys *
52430a5e8faSwyllys * Public interface for parsing a Distinguished name in
52530a5e8faSwyllys * human-readable format into a binary KMF_X509_NAME.
52630a5e8faSwyllys */
52730a5e8faSwyllys KMF_RETURN
kmf_dn_parser(char * string,KMF_X509_NAME * name)52830a5e8faSwyllys kmf_dn_parser(char *string, KMF_X509_NAME *name)
52930a5e8faSwyllys {
53030a5e8faSwyllys KMF_RETURN err;
53130a5e8faSwyllys
53230a5e8faSwyllys if (string == NULL || name == NULL)
53330a5e8faSwyllys return (KMF_ERR_BAD_PARAMETER);
53430a5e8faSwyllys
53530a5e8faSwyllys err = ParseDistinguishedName(string, (int)strlen(string), name);
53630a5e8faSwyllys return (err);
53730a5e8faSwyllys }
538