1 /* alg1485.c - implementation of RFCs 1485, 1779 and 2253.
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is the Netscape security libraries.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1994-2000
21 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
47 typedef struct NameToKindStr
{
49 unsigned int maxLen
; /* max bytes in UTF8 encoded string value */
54 /* local type for directory string--could be printable_string or utf8 */
55 #define SEC_ASN1_DS SEC_ASN1_HIGH_TAG_NUMBER
57 /* Add new entries to this table, and maybe to function CERT_ParseRFC1485AVA */
58 static const NameToKind name2kinds
[] = {
59 /* IANA registered type names
60 * (See: http://www.iana.org/assignments/ldap-parameters)
62 /* RFC 3280, 4630 MUST SUPPORT */
63 { "CN", 64, SEC_OID_AVA_COMMON_NAME
, SEC_ASN1_DS
},
64 { "ST", 128, SEC_OID_AVA_STATE_OR_PROVINCE
,
66 { "O", 64, SEC_OID_AVA_ORGANIZATION_NAME
,
68 { "OU", 64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME
,
70 { "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER
, SEC_ASN1_PRINTABLE_STRING
},
71 { "C", 2, SEC_OID_AVA_COUNTRY_NAME
, SEC_ASN1_PRINTABLE_STRING
},
72 { "serialNumber", 64, SEC_OID_AVA_SERIAL_NUMBER
,SEC_ASN1_PRINTABLE_STRING
},
74 /* RFC 3280, 4630 SHOULD SUPPORT */
75 { "L", 128, SEC_OID_AVA_LOCALITY
, SEC_ASN1_DS
},
76 { "title", 64, SEC_OID_AVA_TITLE
, SEC_ASN1_DS
},
77 { "SN", 64, SEC_OID_AVA_SURNAME
, SEC_ASN1_DS
},
78 { "givenName", 64, SEC_OID_AVA_GIVEN_NAME
, SEC_ASN1_DS
},
79 { "initials", 64, SEC_OID_AVA_INITIALS
, SEC_ASN1_DS
},
80 { "generationQualifier",
81 64, SEC_OID_AVA_GENERATION_QUALIFIER
,
83 /* RFC 3280, 4630 MAY SUPPORT */
84 { "DC", 128, SEC_OID_AVA_DC
, SEC_ASN1_IA5_STRING
},
85 { "MAIL", 256, SEC_OID_RFC1274_MAIL
, SEC_ASN1_IA5_STRING
},
86 { "UID", 256, SEC_OID_RFC1274_UID
, SEC_ASN1_DS
},
88 /* ------------------ "strict" boundary ---------------------------------
89 * In strict mode, cert_NameToAscii does not encode any of the attributes
90 * below this line. The first SECOidTag below this line must be used to
91 * conditionally define the "endKind" in function AppendAVA() below.
92 * Most new attribute names should be added below this line.
93 * Maybe this line should be up higher? Say, after the 3280 MUSTs and
94 * before the 3280 SHOULDs?
97 /* values from draft-ietf-ldapbis-user-schema-05 (not in RFC 3280) */
98 { "postalAddress", 128, SEC_OID_AVA_POSTAL_ADDRESS
, SEC_ASN1_DS
},
99 { "postalCode", 40, SEC_OID_AVA_POSTAL_CODE
, SEC_ASN1_DS
},
100 { "postOfficeBox", 40, SEC_OID_AVA_POST_OFFICE_BOX
,SEC_ASN1_DS
},
101 { "houseIdentifier",64, SEC_OID_AVA_HOUSE_IDENTIFIER
,SEC_ASN1_DS
},
102 /* end of IANA registered type names */
104 /* legacy keywords */
105 { "E", 128, SEC_OID_PKCS9_EMAIL_ADDRESS
,SEC_ASN1_DS
},
107 #if 0 /* removed. Not yet in any IETF draft or RFC. */
108 { "pseudonym", 64, SEC_OID_AVA_PSEUDONYM
, SEC_ASN1_DS
},
111 { 0, 256, SEC_OID_UNKNOWN
, 0},
114 #define C_DOUBLE_QUOTE '\042'
116 #define C_BACKSLASH '\134'
120 #define OPTIONAL_SPACE(c) \
121 (((c) == ' ') || ((c) == '\r') || ((c) == '\n'))
123 #define SPECIAL_CHAR(c) \
124 (((c) == ',') || ((c) == '=') || ((c) == C_DOUBLE_QUOTE) || \
125 ((c) == '\r') || ((c) == '\n') || ((c) == '+') || \
126 ((c) == '<') || ((c) == '>') || ((c) == '#') || \
127 ((c) == ';') || ((c) == C_BACKSLASH))
130 #define IS_PRINTABLE(c) \
131 ((((c) >= 'a') && ((c) <= 'z')) || \
132 (((c) >= 'A') && ((c) <= 'Z')) || \
133 (((c) >= '0') && ((c) <= '9')) || \
136 ((c) == '\050') || /* ( */ \
137 ((c) == '\051') || /* ) */ \
138 (((c) >= '+') && ((c) <= '/')) || /* + , - . / */ \
144 cert_AVAOidTagToMaxLen(SECOidTag tag
)
146 const NameToKind
*n2k
= name2kinds
;
148 while (n2k
->kind
!= tag
&& n2k
->kind
!= SEC_OID_UNKNOWN
) {
151 return (n2k
->kind
!= SEC_OID_UNKNOWN
) ? n2k
->maxLen
: -1;
155 IsPrintable(unsigned char *data
, unsigned len
)
157 unsigned char ch
, *end
;
162 if (!IS_PRINTABLE(ch
)) {
170 skipSpace(char **pbp
, char *endptr
)
173 while (bp
< endptr
&& OPTIONAL_SPACE(*bp
)) {
180 scanTag(char **pbp
, char *endptr
, char *tagBuf
, int tagBufSize
)
185 PORT_Assert(tagBufSize
> 0);
187 /* skip optional leading space */
188 skipSpace(pbp
, endptr
);
189 if (*pbp
== endptr
) {
198 while (bp
< endptr
&& !OPTIONAL_SPACE(*bp
) && (*bp
!= C_EQUAL
)) {
199 if (++taglen
>= tagBufSize
) {
205 /* null-terminate tagBuf -- guaranteed at least one space left */
209 /* skip trailing spaces till we hit something - should be an equal sign */
210 skipSpace(pbp
, endptr
);
211 if (*pbp
== endptr
) {
215 if (**pbp
!= C_EQUAL
) {
216 /* should be an equal sign */
219 /* skip over the equal sign */
226 scanVal(char **pbp
, char *endptr
, char *valBuf
, int valBufSize
)
232 PORT_Assert(valBufSize
> 0);
234 /* skip optional leading space */
235 skipSpace(pbp
, endptr
);
244 if (*bp
== C_DOUBLE_QUOTE
) {
254 while (bp
< endptr
) {
256 if (c
== C_BACKSLASH
) {
257 /* escape character */
260 /* escape charater must appear with paired char */
264 } else if (c
== '#' && bp
== *pbp
) {
265 /* ignore leading #, quotation not required for it. */
266 } else if (!isQuoted
&& SPECIAL_CHAR(c
)) {
267 /* unescaped special and not within quoted value */
269 } else if (c
== C_DOUBLE_QUOTE
) {
270 /* reached unescaped double quote */
273 /* append character */
275 if (vallen
>= valBufSize
) {
282 /* stip trailing spaces from unquoted values */
284 if (valBufp
> valBuf
) {
286 while ((valBufp
> valBuf
) && OPTIONAL_SPACE(*valBufp
)) {
294 /* insist that we stopped on a double quote */
295 if (*bp
!= C_DOUBLE_QUOTE
) {
299 /* skip over the quote and skip optional space */
301 skipSpace(&bp
, endptr
);
306 if (valBufp
== valBuf
) {
307 /* empty value -- not allowed */
311 /* null-terminate valBuf -- guaranteed at least one space left */
317 static const PRInt16 x2b
[256] =
319 /* #0x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
320 /* #1x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
321 /* #2x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
322 /* #3x */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
323 /* #4x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
324 /* #5x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
325 /* #6x */ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
326 /* #7x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
327 /* #8x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
328 /* #9x */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
329 /* #ax */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
330 /* #bx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
331 /* #cx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
332 /* #dx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
333 /* #ex */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
334 /* #fx */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
337 /* Caller must set error code upon failure */
339 hexToBin(PLArenaPool
*pool
, SECItem
* destItem
, const char * src
, int len
)
343 destItem
->data
= NULL
;
344 if (len
<= 0 || (len
& 1)) {
348 if (!SECITEM_AllocItem(pool
, destItem
, len
))
350 dest
= destItem
->data
;
351 for (; len
> 0; len
--, src
+= 2) {
352 PRInt16 bin
= (x2b
[(PRUint8
)src
[0]] << 4) | x2b
[(PRUint8
)src
[1]];
355 *dest
++ = (PRUint8
)bin
;
360 SECITEM_FreeItem(destItem
, PR_FALSE
);
366 CERT_ParseRFC1485AVA(PRArenaPool
*arena
, char **pbp
, char *endptr
,
370 const NameToKind
*n2k
;
374 SECOidTag kind
= SEC_OID_UNKNOWN
;
375 SECStatus rv
= SECFailure
;
376 SECItem derOid
= { 0, NULL
, 0 };
382 if (scanTag(pbp
, endptr
, tagBuf
, sizeof(tagBuf
)) == SECFailure
||
383 scanVal(pbp
, endptr
, valBuf
, sizeof(valBuf
)) == SECFailure
) {
387 /* insist that if we haven't finished we've stopped on a separator */
390 if (singleAVA
|| (*bp
!= ',' && *bp
!= ';')) {
394 /* ok, skip over separator */
399 /* is this a dotted decimal OID attribute type ? */
400 if (!PL_strncasecmp("oid.", tagBuf
, 4)) {
401 rv
= SEC_StringToOID(arena
, &derOid
, tagBuf
, strlen(tagBuf
));
403 for (n2k
= name2kinds
; n2k
->name
; n2k
++) {
405 if (PORT_Strcasecmp(n2k
->name
, tagBuf
) == 0) {
408 oidrec
= SECOID_FindOIDByTag(kind
);
411 derOid
= oidrec
->oid
;
416 if (kind
== SEC_OID_UNKNOWN
&& rv
!= SECSuccess
)
419 /* Is this a hex encoding of a DER attribute value ? */
420 if ('#' == valBuf
[0]) {
421 /* convert attribute value from hex to binary */
422 SECItem derVal
= { 0, NULL
, 0};
423 valLen
= PORT_Strlen(valBuf
+1);
424 rv
= hexToBin(arena
, &derVal
, valBuf
+ 1, valLen
);
427 a
= CERT_CreateAVAFromRaw(arena
, &derOid
, &derVal
);
429 if (kind
== SEC_OID_UNKNOWN
)
431 valLen
= PORT_Strlen(valBuf
);
432 if (kind
== SEC_OID_AVA_COUNTRY_NAME
&& valLen
!= 2)
434 if (vt
== SEC_ASN1_PRINTABLE_STRING
&&
435 !IsPrintable((unsigned char*) valBuf
, valLen
))
437 if (vt
== SEC_ASN1_DS
) {
438 /* RFC 4630: choose PrintableString or UTF8String */
439 if (IsPrintable((unsigned char*) valBuf
, valLen
))
440 vt
= SEC_ASN1_PRINTABLE_STRING
;
442 vt
= SEC_ASN1_UTF8_STRING
;
445 a
= CERT_CreateAVA(arena
, kind
, vt
, (char *)valBuf
);
450 /* matched no kind -- invalid tag */
451 PORT_SetError(SEC_ERROR_INVALID_AVA
);
456 ParseRFC1485Name(char *buf
, int len
)
464 name
= CERT_CreateName(NULL
);
472 ava
= CERT_ParseRFC1485AVA(name
->arena
, &bp
, e
, PR_FALSE
);
473 if (ava
== 0) goto loser
;
474 rdn
= CERT_CreateRDN(name
->arena
, ava
, (CERTAVA
*)0);
475 if (rdn
== 0) goto loser
;
476 rv
= CERT_AddRDN(name
, rdn
);
481 if (name
->rdns
[0] == 0) {
482 /* empty name -- illegal */
486 /* Reverse order of RDNS to comply with RFC */
493 firstRdn
= name
->rdns
;
496 lastRdn
= name
->rdns
;
497 while (*lastRdn
) lastRdn
++;
501 for ( ; firstRdn
< lastRdn
; firstRdn
++, lastRdn
--) {
503 *firstRdn
= *lastRdn
;
512 CERT_DestroyName(name
);
517 CERT_AsciiToName(char *string
)
520 name
= ParseRFC1485Name(string
, PORT_Strlen(string
));
524 /************************************************************************/
526 typedef struct stringBufStr
{
532 #define DEFAULT_BUFFER_SIZE 200
535 AppendStr(stringBuf
*bufp
, char *str
)
538 unsigned bufLen
, bufSize
, len
;
541 /* Figure out how much to grow buf by (add in the '\0') */
543 bufLen
= bufp
->offset
;
544 len
= PORT_Strlen(str
);
545 bufSize
= bufLen
+ len
;
548 size
= PR_MAX(DEFAULT_BUFFER_SIZE
,bufSize
*2);
549 buf
= (char *) PORT_Alloc(size
);
551 } else if (bufp
->size
< bufSize
) {
553 buf
=(char *) PORT_Realloc(buf
,size
);
557 PORT_SetError(SEC_ERROR_NO_MEMORY
);
561 bufp
->offset
= bufSize
;
563 /* Concatenate str onto buf */
565 if (bufLen
) buf
--; /* stomp on old '\0' */
566 PORT_Memcpy(buf
, str
, len
+1); /* put in new null */
571 cert_RFC1485_GetRequiredLen(const char *src
, int srclen
, PRBool
*pNeedsQuoting
)
574 PRBool needsQuoting
= PR_FALSE
;
577 /* need to make an initial pass to determine if quoting is needed */
578 for (i
= 0; i
< srclen
; i
++) {
581 if (!needsQuoting
&& (SPECIAL_CHAR(c
) ||
582 (OPTIONAL_SPACE(c
) && OPTIONAL_SPACE(lastC
)))) {
583 /* entirety will need quoting */
584 needsQuoting
= PR_TRUE
;
586 if (c
== C_DOUBLE_QUOTE
|| c
== C_BACKSLASH
) {
587 /* this char will need escaping */
592 /* if it begins or ends in optional space it needs quoting */
593 if (!needsQuoting
&& srclen
> 0 &&
594 (OPTIONAL_SPACE(src
[srclen
-1]) || OPTIONAL_SPACE(src
[0]))) {
595 needsQuoting
= PR_TRUE
;
601 *pNeedsQuoting
= needsQuoting
;
607 CERT_RFC1485_EscapeAndQuote(char *dst
, int dstlen
, char *src
, int srclen
)
611 PRBool needsQuoting
= PR_FALSE
;
613 /* space for terminal null */
614 reqLen
= cert_RFC1485_GetRequiredLen(src
, srclen
, &needsQuoting
) + 1;
615 if (reqLen
> dstlen
) {
616 PORT_SetError(SEC_ERROR_OUTPUT_LEN
);
621 if (needsQuoting
) *d
++ = C_DOUBLE_QUOTE
;
622 for (i
= 0; i
< srclen
; i
++) {
624 if (c
== C_DOUBLE_QUOTE
|| c
== C_BACKSLASH
) {
630 if (needsQuoting
) *d
++ = C_DOUBLE_QUOTE
;
635 /* convert an OID to dotted-decimal representation */
636 /* Returns a string that must be freed with PR_smprintf_free(), */
638 CERT_GetOidString(const SECItem
*oid
)
646 #define MAX_OID_LEN 1024 /* bytes */
648 if (oid
->len
> MAX_OID_LEN
) {
649 PORT_SetError(SEC_ERROR_INPUT_LEN
);
653 /* d will point to the next sequence of bytes to decode */
654 d
= (PRUint8
*)oid
->data
;
655 /* end points to one past the legitimate data */
656 end
= &d
[ oid
->len
];
659 * Check for our pseudo-encoded single-digit OIDs
661 if( (*d
== 0x80) && (2 == oid
->len
) ) {
662 /* Funky encoding. The second byte is the number */
663 a
= PR_smprintf("%lu", (PRUint32
)d
[1]);
664 if( (char *)NULL
== a
) {
665 PORT_SetError(SEC_ERROR_NO_MEMORY
);
671 for( ; d
< end
; d
= &e
[1] ) {
673 for( e
= d
; e
< end
; e
++ ) {
674 if( 0 == (*e
& 0x80) ) {
679 if( ((e
-d
) > 4) || (((e
-d
) == 4) && (*d
& 0x70)) ) {
680 /* More than a 32-bit number */
686 n
|= ((PRUint32
)(e
[-4] & 0x0f)) << 28;
688 n
|= ((PRUint32
)(e
[-3] & 0x7f)) << 21;
690 n
|= ((PRUint32
)(e
[-2] & 0x7f)) << 14;
692 n
|= ((PRUint32
)(e
[-1] & 0x7f)) << 7;
694 n
|= ((PRUint32
)(e
[-0] & 0x7f)) ;
697 if( (char *)NULL
== a
) {
698 /* This is the first number.. decompose it */
699 PRUint32 one
= PR_MIN(n
/40, 2); /* never > 2 */
700 PRUint32 two
= n
- one
* 40;
702 a
= PR_smprintf("OID.%lu.%lu", one
, two
);
703 if( (char *)NULL
== a
) {
704 PORT_SetError(SEC_ERROR_NO_MEMORY
);
708 b
= PR_smprintf("%s.%lu", a
, n
);
709 if( (char *)NULL
== b
) {
711 PORT_SetError(SEC_ERROR_NO_MEMORY
);
724 /* convert DER-encoded hex to a string */
726 get_hex_string(SECItem
*data
)
730 static const char hex
[] = { "0123456789ABCDEF" };
732 /* '#' + 2 chars per octet + terminator */
733 rv
= SECITEM_AllocItem(NULL
, NULL
, data
->len
*2 + 2);
738 rv
->len
= 1 + 2 * data
->len
;
739 for (i
=0; i
<data
->len
; i
++) {
741 rv
->data
[2*i
+1] = hex
[j
>> 4];
742 rv
->data
[2*i
+2] = hex
[j
& 15];
744 rv
->data
[rv
->len
] = 0;
748 /* For compliance with RFC 2253, RFC 3280 and RFC 4630, we choose to
749 * use the NAME=STRING form, rather than the OID.N.N=#hexXXXX form,
750 * when both of these conditions are met:
751 * 1) The attribute name OID (kind) has a known name string that is
752 * defined in one of those RFCs, or in RFCs that they cite, AND
753 * 2) The attribute's value encoding is RFC compliant for the kind
754 * (e.g., the value's encoding tag is correct for the kind, and
755 * the value's length is in the range allowed for the kind, and
756 * the value's contents are appropriate for the encoding tag).
757 * Otherwise, we use the OID.N.N=#hexXXXX form.
759 * If the caller prefers maximum human readability to RFC compliance,
761 * - We print the kind in NAME= string form if we know the name
762 * string for the attribute type OID, regardless of whether the
763 * value is correctly encoded or not. else we use the OID.N.N= form.
764 * - We use the non-hex STRING form for the attribute value if the
765 * value can be represented in such a form. Otherwise, we use
766 * the hex string form.
767 * This implies that, for maximum human readability, in addition to
768 * the two forms allowed by the RFC, we allow two other forms of output:
769 * - the OID.N.N=STRING form, and
770 * - the NAME=#hexXXXX form
771 * When the caller prefers maximum human readability, we do not allow
772 * the value of any attribute to exceed the length allowed by the RFC.
773 * If the attribute value exceeds the allowed length, we truncate it to
774 * the allowed length and append "...".
775 * Also in this case, we arbitrarily impose a limit on the length of the
776 * entire AVA encoding, regardless of the form, of 384 bytes per AVA.
777 * This limit includes the trailing NULL character. If the encoded
778 * AVA length exceeds that limit, this function reports failure to encode
781 * An ASCII representation of an AVA is said to be "invertible" if
782 * conversion back to DER reproduces the original DER encoding exactly.
783 * The RFC 2253 rules do not ensure that all ASCII AVAs derived according
784 * to its rules are invertible. That is because the RFCs allow some
785 * attribute values to be encoded in any of a number of encodings,
786 * and the encoding type information is lost in the non-hex STRING form.
787 * This is particularly true of attributes of type DirectoryString.
788 * The encoding type information is always preserved in the hex string
789 * form, because the hex includes the entire DER encoding of the value.
791 * So, when the caller perfers maximum invertibility, we apply the
792 * RFC compliance rules stated above, and add a third required
793 * condition on the use of the NAME=STRING form.
794 * 3) The attribute's kind is not is allowed to be encoded in any of
795 * several different encodings, such as DirectoryStrings.
797 * The chief difference between CERT_N2A_STRICT and CERT_N2A_INVERTIBLE
798 * is that the latter forces DirectoryStrings to be hex encoded.
800 * As a simplification, we assume the value is correctly encoded for
801 * its encoding type. That is, we do not test that all the characters
802 * in a string encoded type are allowed by that type. We assume it.
805 AppendAVA(stringBuf
*bufp
, CERTAVA
*ava
, CertStrictnessLevel strict
)
807 const NameToKind
*pn2k
= name2kinds
;
808 SECItem
*avaValue
= NULL
;
809 char *unknownTag
= NULL
;
810 char *encodedAVA
= NULL
;
811 PRBool useHex
= PR_FALSE
; /* use =#hexXXXX form */
815 int nameLen
, valueLen
;
816 NameToKind n2k
= { NULL
, 32767, SEC_OID_UNKNOWN
, SEC_ASN1_DS
};
819 #define tagName n2k.name /* non-NULL means use NAME= form */
820 #define maxBytes n2k.maxLen
822 #define vt n2k.valueType
824 /* READABLE mode recognizes more names from the name2kinds table
825 * than do STRICT or INVERTIBLE modes. This assignment chooses the
826 * point in the table where the attribute type name scanning stops.
828 endKind
= (strict
== CERT_N2A_READABLE
) ? SEC_OID_UNKNOWN
829 : SEC_OID_AVA_POSTAL_ADDRESS
;
830 tag
= CERT_GetAVATag(ava
);
831 while (pn2k
->kind
!= tag
&& pn2k
->kind
!= endKind
) {
835 if (pn2k
->kind
!= endKind
) {
837 } else if (strict
!= CERT_N2A_READABLE
) {
840 /* For invertable form, force Directory Strings to use hex form. */
841 if (strict
== CERT_N2A_INVERTIBLE
&& vt
== SEC_ASN1_DS
) {
842 tagName
= NULL
; /* must use OID.N form */
843 useHex
= PR_TRUE
; /* must use hex string */
846 avaValue
= CERT_DecodeAVAValue(&ava
->value
);
849 if (strict
!= CERT_N2A_READABLE
) {
850 tagName
= NULL
; /* must use OID.N form */
855 /* handle unknown attribute types per RFC 2253 */
856 tagName
= unknownTag
= CERT_GetOidString(&ava
->type
);
859 SECITEM_FreeItem(avaValue
, PR_TRUE
);
864 avaValue
= get_hex_string(&ava
->value
);
867 PR_smprintf_free(unknownTag
);
872 if (strict
== CERT_N2A_READABLE
) {
873 if (maxBytes
> sizeof(tmpBuf
) - 4)
874 maxBytes
= sizeof(tmpBuf
) - 4;
875 /* Check value length. Must be room for "..." */
876 if (avaValue
->len
> maxBytes
+ 3) {
877 /* avaValue is a UTF8 string, freshly allocated and returned to us
878 ** by CERT_DecodeAVAValue or get_hex_string just above, so we can
879 ** modify it here. See if we're in the middle of a multi-byte
883 while (((avaValue
->data
[len
] & 0xc0) == 0x80) && len
> 0) {
886 /* add elipsis to signify truncation. */
887 avaValue
->data
[len
++] = '.';
888 avaValue
->data
[len
++] = '.';
889 avaValue
->data
[len
++] = '.';
890 avaValue
->data
[len
] = 0;
895 nameLen
= strlen(tagName
);
896 valueLen
= (useHex
? avaValue
->len
:
897 cert_RFC1485_GetRequiredLen(avaValue
->data
, avaValue
->len
, NULL
));
898 len
= nameLen
+ valueLen
+ 2; /* Add 2 for '=' and trailing NUL */
900 if (len
<= sizeof(tmpBuf
)) {
902 } else if (strict
== CERT_N2A_READABLE
) {
903 PORT_SetError(SEC_ERROR_OUTPUT_LEN
);
905 encodedAVA
= PORT_Alloc(len
);
908 SECITEM_FreeItem(avaValue
, PR_TRUE
);
910 PR_smprintf_free(unknownTag
);
913 memcpy(encodedAVA
, tagName
, nameLen
);
915 PR_smprintf_free(unknownTag
);
916 encodedAVA
[nameLen
++] = '=';
918 /* escape and quote as necessary - don't quote hex strings */
920 memcpy(encodedAVA
+ nameLen
, (char *)avaValue
->data
, avaValue
->len
);
921 encodedAVA
[nameLen
+ avaValue
->len
] = '\0';
924 rv
= CERT_RFC1485_EscapeAndQuote(encodedAVA
+ nameLen
, len
- nameLen
,
925 (char *)avaValue
->data
, avaValue
->len
);
926 SECITEM_FreeItem(avaValue
, PR_TRUE
);
927 if (rv
== SECSuccess
)
928 rv
= AppendStr(bufp
, encodedAVA
);
929 if (encodedAVA
!= tmpBuf
)
930 PORT_Free(encodedAVA
);
940 CERT_NameToAsciiInvertible(CERTName
*name
, CertStrictnessLevel strict
)
945 PRBool first
= PR_TRUE
;
946 stringBuf strBuf
= { NULL
, 0, 0 };
955 while (*lastRdn
) lastRdn
++;
959 * Loop over name contents in _reverse_ RDN order appending to string
961 for (rdn
= lastRdn
; rdn
>= rdns
; rdn
--) {
962 CERTAVA
** avas
= (*rdn
)->avas
;
964 PRBool newRDN
= PR_TRUE
;
967 * XXX Do we need to traverse the AVAs in reverse order, too?
969 while (avas
&& (ava
= *avas
++) != NULL
) {
971 /* Put in comma or plus separator */
973 /* Use of spaces is deprecated in RFC 2253. */
974 rv
= AppendStr(&strBuf
, newRDN
? "," : "+");
980 /* Add in tag type plus value into buf */
981 rv
= AppendAVA(&strBuf
, ava
, strict
);
986 return strBuf
.buffer
;
989 PORT_Free(strBuf
.buffer
);
995 CERT_NameToAscii(CERTName
*name
)
997 return CERT_NameToAsciiInvertible(name
, CERT_N2A_READABLE
);
1001 * Return the string representation of a DER encoded distinguished name
1002 * "dername" - The DER encoded name to convert
1005 CERT_DerNameToAscii(SECItem
*dername
)
1008 PRArenaPool
*arena
= NULL
;
1010 char *retstr
= NULL
;
1012 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1014 if ( arena
== NULL
) {
1018 rv
= SEC_QuickDERDecodeItem(arena
, &name
, CERT_NameTemplate
, dername
);
1020 if ( rv
!= SECSuccess
) {
1024 retstr
= CERT_NameToAscii(&name
);
1027 if ( arena
!= NULL
) {
1028 PORT_FreeArena(arena
, PR_FALSE
);
1034 /* RDNs are sorted from most general to most specific.
1035 * This code returns the FIRST one found, the most general one found.
1038 CERT_GetNameElement(PRArenaPool
*arena
, CERTName
*name
, int wantedTag
)
1045 while (rdns
&& (rdn
= *rdns
++) != 0) {
1046 CERTAVA
** avas
= rdn
->avas
;
1048 while (avas
&& (ava
= *avas
++) != 0) {
1049 int tag
= CERT_GetAVATag(ava
);
1050 if ( tag
== wantedTag
) {
1051 SECItem
*decodeItem
= CERT_DecodeAVAValue(&ava
->value
);
1056 buf
= (char *)PORT_ArenaZAlloc(arena
,decodeItem
->len
+ 1);
1058 buf
= (char *)PORT_ZAlloc(decodeItem
->len
+ 1);
1061 PORT_Memcpy(buf
, decodeItem
->data
, decodeItem
->len
);
1062 buf
[decodeItem
->len
] = 0;
1064 SECITEM_FreeItem(decodeItem
, PR_TRUE
);
1074 /* RDNs are sorted from most general to most specific.
1075 * This code returns the LAST one found, the most specific one found.
1076 * This is particularly appropriate for Common Name. See RFC 2818.
1079 CERT_GetLastNameElement(PRArenaPool
*arena
, CERTName
*name
, int wantedTag
)
1083 CERTAVA
* lastAva
= NULL
;
1087 while (rdns
&& (rdn
= *rdns
++) != 0) {
1088 CERTAVA
** avas
= rdn
->avas
;
1090 while (avas
&& (ava
= *avas
++) != 0) {
1091 int tag
= CERT_GetAVATag(ava
);
1092 if ( tag
== wantedTag
) {
1099 SECItem
*decodeItem
= CERT_DecodeAVAValue(&lastAva
->value
);
1104 buf
= (char *)PORT_ArenaZAlloc(arena
,decodeItem
->len
+ 1);
1106 buf
= (char *)PORT_ZAlloc(decodeItem
->len
+ 1);
1109 PORT_Memcpy(buf
, decodeItem
->data
, decodeItem
->len
);
1110 buf
[decodeItem
->len
] = 0;
1112 SECITEM_FreeItem(decodeItem
, PR_TRUE
);
1118 CERT_GetCertificateEmailAddress(CERTCertificate
*cert
)
1120 char *rawEmailAddr
= NULL
;
1123 CERTGeneralName
*nameList
= NULL
;
1124 CERTGeneralName
*current
;
1125 PRArenaPool
*arena
= NULL
;
1128 subAltName
.data
= NULL
;
1130 rawEmailAddr
= CERT_GetNameElement(cert
->arena
, &(cert
->subject
),
1131 SEC_OID_PKCS9_EMAIL_ADDRESS
);
1132 if ( rawEmailAddr
== NULL
) {
1133 rawEmailAddr
= CERT_GetNameElement(cert
->arena
, &(cert
->subject
),
1134 SEC_OID_RFC1274_MAIL
);
1136 if ( rawEmailAddr
== NULL
) {
1138 rv
= CERT_FindCertExtension(cert
, SEC_OID_X509_SUBJECT_ALT_NAME
,
1140 if (rv
!= SECSuccess
) {
1143 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1147 nameList
= current
= CERT_DecodeAltNameExtension(arena
, &subAltName
);
1151 if (nameList
!= NULL
) {
1153 if (current
->type
== certDirectoryName
) {
1154 rawEmailAddr
= CERT_GetNameElement(cert
->arena
,
1155 &(current
->name
.directoryName
),
1156 SEC_OID_PKCS9_EMAIL_ADDRESS
);
1157 if ( rawEmailAddr
== NULL
) {
1158 rawEmailAddr
= CERT_GetNameElement(cert
->arena
,
1159 &(current
->name
.directoryName
), SEC_OID_RFC1274_MAIL
);
1161 } else if (current
->type
== certRFC822Name
) {
1162 rawEmailAddr
= (char*)PORT_ArenaZAlloc(cert
->arena
,
1163 current
->name
.other
.len
+ 1);
1164 if (!rawEmailAddr
) {
1167 PORT_Memcpy(rawEmailAddr
, current
->name
.other
.data
,
1168 current
->name
.other
.len
);
1169 rawEmailAddr
[current
->name
.other
.len
] = '\0';
1174 current
= CERT_GetNextGeneralName(current
);
1175 } while (current
!= nameList
);
1179 for (i
= 0; i
<= (int) PORT_Strlen(rawEmailAddr
); i
++) {
1180 rawEmailAddr
[i
] = tolower(rawEmailAddr
[i
]);
1186 /* Don't free nameList, it's part of the arena. */
1189 PORT_FreeArena(arena
, PR_FALSE
);
1192 if ( subAltName
.data
) {
1193 SECITEM_FreeItem(&subAltName
, PR_FALSE
);
1196 return(rawEmailAddr
);
1200 appendStringToBuf(char *dest
, char *src
, PRUint32
*pRemaining
)
1203 if (dest
&& src
&& src
[0] && *pRemaining
> (len
= PL_strlen(src
))) {
1205 for (i
= 0; i
< len
; ++i
)
1206 dest
[i
] = tolower(src
[i
]);
1209 *pRemaining
-= len
+ 1;
1215 appendItemToBuf(char *dest
, SECItem
*src
, PRUint32
*pRemaining
)
1217 if (dest
&& src
&& src
->data
&& src
->len
&& src
->data
[0] &&
1218 *pRemaining
> src
->len
+ 1 ) {
1219 PRUint32 len
= src
->len
;
1221 for (i
= 0; i
< len
&& src
->data
[i
] ; ++i
)
1222 dest
[i
] = tolower(src
->data
[i
]);
1225 *pRemaining
-= len
+ 1;
1230 /* Returns a pointer to an environment-like string, a series of
1231 ** null-terminated strings, terminated by a zero-length string.
1232 ** This function is intended to be internal to NSS.
1235 cert_GetCertificateEmailAddresses(CERTCertificate
*cert
)
1237 char * rawEmailAddr
= NULL
;
1238 char * addrBuf
= NULL
;
1240 PRArenaPool
* tmpArena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1241 PRUint32 maxLen
= 0;
1242 PRInt32 finalLen
= 0;
1249 subAltName
.data
= NULL
;
1250 maxLen
= cert
->derCert
.len
;
1251 PORT_Assert(maxLen
);
1253 maxLen
= 2000; /* a guess, should never happen */
1255 pBuf
= addrBuf
= (char *)PORT_ArenaZAlloc(tmpArena
, maxLen
+ 1);
1259 rawEmailAddr
= CERT_GetNameElement(tmpArena
, &cert
->subject
,
1260 SEC_OID_PKCS9_EMAIL_ADDRESS
);
1261 pBuf
= appendStringToBuf(pBuf
, rawEmailAddr
, &maxLen
);
1263 rawEmailAddr
= CERT_GetNameElement(tmpArena
, &cert
->subject
,
1264 SEC_OID_RFC1274_MAIL
);
1265 pBuf
= appendStringToBuf(pBuf
, rawEmailAddr
, &maxLen
);
1267 rv
= CERT_FindCertExtension(cert
, SEC_OID_X509_SUBJECT_ALT_NAME
,
1269 if (rv
== SECSuccess
&& subAltName
.data
) {
1270 CERTGeneralName
*nameList
= NULL
;
1272 if (!!(nameList
= CERT_DecodeAltNameExtension(tmpArena
, &subAltName
))) {
1273 CERTGeneralName
*current
= nameList
;
1275 if (current
->type
== certDirectoryName
) {
1276 rawEmailAddr
= CERT_GetNameElement(tmpArena
,
1277 ¤t
->name
.directoryName
,
1278 SEC_OID_PKCS9_EMAIL_ADDRESS
);
1279 pBuf
= appendStringToBuf(pBuf
, rawEmailAddr
, &maxLen
);
1281 rawEmailAddr
= CERT_GetNameElement(tmpArena
,
1282 ¤t
->name
.directoryName
,
1283 SEC_OID_RFC1274_MAIL
);
1284 pBuf
= appendStringToBuf(pBuf
, rawEmailAddr
, &maxLen
);
1285 } else if (current
->type
== certRFC822Name
) {
1286 pBuf
= appendItemToBuf(pBuf
, ¤t
->name
.other
, &maxLen
);
1288 current
= CERT_GetNextGeneralName(current
);
1289 } while (current
!= nameList
);
1291 SECITEM_FreeItem(&subAltName
, PR_FALSE
);
1292 /* Don't free nameList, it's part of the tmpArena. */
1294 /* now copy superstring to cert's arena */
1295 finalLen
= (pBuf
- addrBuf
) + 1;
1298 pBuf
= PORT_ArenaAlloc(cert
->arena
, finalLen
);
1300 PORT_Memcpy(pBuf
, addrBuf
, finalLen
);
1305 PORT_FreeArena(tmpArena
, PR_FALSE
);
1310 /* returns pointer to storage in cert's arena. Storage remains valid
1311 ** as long as cert's reference count doesn't go to zero.
1312 ** Caller should strdup or otherwise copy.
1314 const char * /* const so caller won't muck with it. */
1315 CERT_GetFirstEmailAddress(CERTCertificate
* cert
)
1317 if (cert
&& cert
->emailAddr
&& cert
->emailAddr
[0])
1318 return (const char *)cert
->emailAddr
;
1322 /* returns pointer to storage in cert's arena. Storage remains valid
1323 ** as long as cert's reference count doesn't go to zero.
1324 ** Caller should strdup or otherwise copy.
1326 const char * /* const so caller won't muck with it. */
1327 CERT_GetNextEmailAddress(CERTCertificate
* cert
, const char * prev
)
1329 if (cert
&& prev
&& prev
[0]) {
1330 PRUint32 len
= PL_strlen(prev
);
1332 if (prev
&& prev
[0])
1338 /* This is seriously bogus, now that certs store their email addresses in
1339 ** subject Alternative Name extensions.
1340 ** Returns a string allocated by PORT_StrDup, which the caller must free.
1343 CERT_GetCertEmailAddress(CERTName
*name
)
1349 rawEmailAddr
= CERT_GetNameElement(NULL
, name
, SEC_OID_PKCS9_EMAIL_ADDRESS
);
1350 if ( rawEmailAddr
== NULL
) {
1351 rawEmailAddr
= CERT_GetNameElement(NULL
, name
, SEC_OID_RFC1274_MAIL
);
1353 emailAddr
= CERT_FixupEmailAddr(rawEmailAddr
);
1354 if ( rawEmailAddr
) {
1355 PORT_Free(rawEmailAddr
);
1360 /* The return value must be freed with PORT_Free. */
1362 CERT_GetCommonName(CERTName
*name
)
1364 return(CERT_GetLastNameElement(NULL
, name
, SEC_OID_AVA_COMMON_NAME
));
1368 CERT_GetCountryName(CERTName
*name
)
1370 return(CERT_GetNameElement(NULL
, name
, SEC_OID_AVA_COUNTRY_NAME
));
1374 CERT_GetLocalityName(CERTName
*name
)
1376 return(CERT_GetNameElement(NULL
, name
, SEC_OID_AVA_LOCALITY
));
1380 CERT_GetStateName(CERTName
*name
)
1382 return(CERT_GetNameElement(NULL
, name
, SEC_OID_AVA_STATE_OR_PROVINCE
));
1386 CERT_GetOrgName(CERTName
*name
)
1388 return(CERT_GetNameElement(NULL
, name
, SEC_OID_AVA_ORGANIZATION_NAME
));
1392 CERT_GetDomainComponentName(CERTName
*name
)
1394 return(CERT_GetNameElement(NULL
, name
, SEC_OID_AVA_DC
));
1398 CERT_GetOrgUnitName(CERTName
*name
)
1400 return(CERT_GetNameElement(NULL
, name
, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME
));
1404 CERT_GetDnQualifier(CERTName
*name
)
1406 return(CERT_GetNameElement(NULL
, name
, SEC_OID_AVA_DN_QUALIFIER
));
1410 CERT_GetCertUid(CERTName
*name
)
1412 return(CERT_GetNameElement(NULL
, name
, SEC_OID_RFC1274_UID
));