1
/* alg1485.c - implementation of RFCs 1485, 1779 and 2253.
3
* The contents of this file are subject to the Mozilla Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/MPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is the Netscape security libraries.
15
* The Initial Developer of the Original Code is Netscape
16
* Communications Corporation. Portions created by Netscape are
17
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
22
* Alternatively, the contents of this file may be used under the
23
* terms of the GNU General Public License Version 2 or later (the
24
* "GPL"), in which case the provisions of the GPL are applicable
25
* instead of those above. If you wish to allow use of your
26
* version of this file only under the terms of the GPL and not to
27
* allow others to use your version of this file under the MPL,
28
* indicate your decision by deleting the provisions above and
29
* replace them with the notice and other provisions required by
30
* the GPL. If you do not delete the provisions above, a recipient
31
* may use your version of this file under either the MPL or the
42
/* for better RFC 2253 compliance. */
43
#define NSS_STRICT_RFC_2253_VALUES_ONLY 1
47
unsigned int maxLen; /* max bytes in UTF8 encoded string value */
51
/* Add new entries to this table, and maybe to function CERT_ParseRFC1485AVA */
52
static const struct NameToKind name2kinds[] = {
53
/* keywords given in RFC 2253 */
54
{ "CN", 64, SEC_OID_AVA_COMMON_NAME },
55
{ "L", 128, SEC_OID_AVA_LOCALITY },
56
{ "ST", 128, SEC_OID_AVA_STATE_OR_PROVINCE },
57
{ "O", 64, SEC_OID_AVA_ORGANIZATION_NAME },
58
{ "OU", 64, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME },
59
{ "C", 2, SEC_OID_AVA_COUNTRY_NAME },
60
{ "STREET", 128, SEC_OID_AVA_STREET_ADDRESS },
61
{ "DC", 128, SEC_OID_AVA_DC },
62
{ "UID", 256, SEC_OID_RFC1274_UID },
64
#ifndef NSS_STRICT_RFC_2253_KEYWORDS_ONLY
65
/* NSS legacy keywords */
66
{ "dnQualifier", 32767, SEC_OID_AVA_DN_QUALIFIER },
67
{ "E", 128, SEC_OID_PKCS9_EMAIL_ADDRESS },
68
{ "MAIL", 256, SEC_OID_RFC1274_MAIL },
70
#ifndef NSS_LEGACY_KEYWORDS_ONLY
71
/* values from draft-ietf-ldapbis-user-schema-05 */
72
{ "SN", 64, SEC_OID_AVA_SURNAME },
73
{ "serialNumber", 64, SEC_OID_AVA_SERIAL_NUMBER },
74
{ "title", 64, SEC_OID_AVA_TITLE },
75
{ "postalAddress", 128, SEC_OID_AVA_POSTAL_ADDRESS },
76
{ "postalCode", 40, SEC_OID_AVA_POSTAL_CODE },
77
{ "postOfficeBox", 40, SEC_OID_AVA_POST_OFFICE_BOX },
78
{ "givenName", 64, SEC_OID_AVA_GIVEN_NAME },
79
{ "initials", 64, SEC_OID_AVA_INITIALS },
80
{ "generationQualifier", 64, SEC_OID_AVA_GENERATION_QUALIFIER },
81
{ "houseIdentifier", 64, SEC_OID_AVA_HOUSE_IDENTIFIER },
82
#if 0 /* removed. Not yet in any IETF draft or RFC. */
83
{ "pseudonym", 64, SEC_OID_AVA_PSEUDONYM },
87
{ 0, 256, SEC_OID_UNKNOWN }
90
#define C_DOUBLE_QUOTE '\042'
92
#define C_BACKSLASH '\134'
96
#define OPTIONAL_SPACE(c) \
97
(((c) == ' ') || ((c) == '\r') || ((c) == '\n'))
99
#define SPECIAL_CHAR(c) \
100
(((c) == ',') || ((c) == '=') || ((c) == C_DOUBLE_QUOTE) || \
101
((c) == '\r') || ((c) == '\n') || ((c) == '+') || \
102
((c) == '<') || ((c) == '>') || ((c) == '#') || \
103
((c) == ';') || ((c) == C_BACKSLASH))
106
#define IS_PRINTABLE(c) \
107
((((c) >= 'a') && ((c) <= 'z')) || \
108
(((c) >= 'A') && ((c) <= 'Z')) || \
109
(((c) >= '0') && ((c) <= '9')) || \
112
((c) == '\050') || /* ( */ \
113
((c) == '\051') || /* ) */ \
114
(((c) >= '+') && ((c) <= '/')) || /* + , - . / */ \
120
cert_AVAOidTagToMaxLen(SECOidTag tag)
122
const struct NameToKind *n2k = name2kinds;
124
while (n2k->kind != tag && n2k->kind != SEC_OID_UNKNOWN) {
127
return (n2k->kind != SEC_OID_UNKNOWN) ? n2k->maxLen : -1;
131
IsPrintable(unsigned char *data, unsigned len)
133
unsigned char ch, *end;
138
if (!IS_PRINTABLE(ch)) {
146
Is7Bit(unsigned char *data, unsigned len)
148
unsigned char ch, *end;
161
skipSpace(char **pbp, char *endptr)
164
while (bp < endptr && OPTIONAL_SPACE(*bp)) {
171
scanTag(char **pbp, char *endptr, char *tagBuf, int tagBufSize)
176
PORT_Assert(tagBufSize > 0);
178
/* skip optional leading space */
179
skipSpace(pbp, endptr);
180
if (*pbp == endptr) {
189
while (bp < endptr && !OPTIONAL_SPACE(*bp) && (*bp != C_EQUAL)) {
190
if (++taglen >= tagBufSize) {
196
/* null-terminate tagBuf -- guaranteed at least one space left */
200
/* skip trailing spaces till we hit something - should be an equal sign */
201
skipSpace(pbp, endptr);
202
if (*pbp == endptr) {
206
if (**pbp != C_EQUAL) {
207
/* should be an equal sign */
210
/* skip over the equal sign */
217
scanVal(char **pbp, char *endptr, char *valBuf, int valBufSize)
223
PORT_Assert(valBufSize > 0);
225
/* skip optional leading space */
226
skipSpace(pbp, endptr);
235
if (*bp == C_DOUBLE_QUOTE) {
245
while (bp < endptr) {
247
if (c == C_BACKSLASH) {
248
/* escape character */
251
/* escape charater must appear with paired char */
255
} else if (!isQuoted && SPECIAL_CHAR(c)) {
256
/* unescaped special and not within quoted value */
258
} else if (c == C_DOUBLE_QUOTE) {
259
/* reached unescaped double quote */
262
/* append character */
264
if (vallen >= valBufSize) {
271
/* stip trailing spaces from unquoted values */
273
if (valBufp > valBuf) {
275
while ((valBufp > valBuf) && OPTIONAL_SPACE(*valBufp)) {
283
/* insist that we stopped on a double quote */
284
if (*bp != C_DOUBLE_QUOTE) {
288
/* skip over the quote and skip optional space */
290
skipSpace(&bp, endptr);
295
if (valBufp == valBuf) {
296
/* empty value -- not allowed */
300
/* null-terminate valBuf -- guaranteed at least one space left */
307
CERT_ParseRFC1485AVA(PRArenaPool *arena, char **pbp, char *endptr,
311
const struct NameToKind *n2k;
319
if (scanTag(pbp, endptr, tagBuf, sizeof(tagBuf)) == SECFailure ||
320
scanVal(pbp, endptr, valBuf, sizeof(valBuf)) == SECFailure) {
321
PORT_SetError(SEC_ERROR_INVALID_AVA);
325
/* insist that if we haven't finished we've stopped on a separator */
328
if (singleAVA || (*bp != ',' && *bp != ';')) {
329
PORT_SetError(SEC_ERROR_INVALID_AVA);
333
/* ok, skip over separator */
338
for (n2k = name2kinds; n2k->name; n2k++) {
339
if (PORT_Strcasecmp(n2k->name, tagBuf) == 0) {
340
valLen = PORT_Strlen(valBuf);
341
if (n2k->kind == SEC_OID_AVA_COUNTRY_NAME) {
342
vt = SEC_ASN1_PRINTABLE_STRING;
344
PORT_SetError(SEC_ERROR_INVALID_AVA);
347
if (!IsPrintable((unsigned char*) valBuf, 2)) {
348
PORT_SetError(SEC_ERROR_INVALID_AVA);
351
} else if ((n2k->kind == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
352
(n2k->kind == SEC_OID_RFC1274_MAIL)) {
353
vt = SEC_ASN1_IA5_STRING;
355
/* Hack -- for rationale see X.520 DirectoryString defn */
356
if (IsPrintable((unsigned char*)valBuf, valLen)) {
357
vt = SEC_ASN1_PRINTABLE_STRING;
358
} else if (Is7Bit((unsigned char *)valBuf, valLen)) {
359
vt = SEC_ASN1_T61_STRING;
361
/* according to RFC3280, UTF8String is preferred encoding */
362
vt = SEC_ASN1_UTF8_STRING;
365
a = CERT_CreateAVA(arena, n2k->kind, vt, (char *) valBuf);
369
/* matched no kind -- invalid tag */
370
PORT_SetError(SEC_ERROR_INVALID_AVA);
375
ParseRFC1485Name(char *buf, int len)
383
name = CERT_CreateName(NULL);
391
ava = CERT_ParseRFC1485AVA(name->arena, &bp, e, PR_FALSE);
392
if (ava == 0) goto loser;
393
rdn = CERT_CreateRDN(name->arena, ava, 0);
394
if (rdn == 0) goto loser;
395
rv = CERT_AddRDN(name, rdn);
400
if (name->rdns[0] == 0) {
401
/* empty name -- illegal */
405
/* Reverse order of RDNS to comply with RFC */
412
firstRdn = name->rdns;
415
lastRdn = name->rdns;
416
while (*lastRdn) lastRdn++;
420
for ( ; firstRdn < lastRdn; firstRdn++, lastRdn--) {
422
*firstRdn = *lastRdn;
431
CERT_DestroyName(name);
436
CERT_AsciiToName(char *string)
439
name = ParseRFC1485Name(string, PORT_Strlen(string));
443
/************************************************************************/
445
typedef struct stringBufStr {
451
#define DEFAULT_BUFFER_SIZE 200
454
AppendStr(stringBuf *bufp, char *str)
457
unsigned bufLen, bufSize, len;
460
/* Figure out how much to grow buf by (add in the '\0') */
462
bufLen = bufp->offset;
463
len = PORT_Strlen(str);
464
bufSize = bufLen + len;
467
size = PR_MAX(DEFAULT_BUFFER_SIZE,bufSize*2);
468
buf = (char *) PORT_Alloc(size);
470
} else if (bufp->size < bufSize) {
472
buf =(char *) PORT_Realloc(buf,size);
476
PORT_SetError(SEC_ERROR_NO_MEMORY);
480
bufp->offset = bufSize;
482
/* Concatenate str onto buf */
484
if (bufLen) buf--; /* stomp on old '\0' */
485
PORT_Memcpy(buf, str, len+1); /* put in new null */
490
CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, int srclen)
494
PRBool needsQuoting = PR_FALSE;
497
/* need to make an initial pass to determine if quoting is needed */
498
for (i = 0; i < srclen; i++) {
501
if (!needsQuoting && (SPECIAL_CHAR(c) ||
502
(OPTIONAL_SPACE(c) && OPTIONAL_SPACE(lastC)))) {
503
/* entirety will need quoting */
504
needsQuoting = PR_TRUE;
506
if (c == C_DOUBLE_QUOTE || c == C_BACKSLASH) {
507
/* this char will need escaping */
512
/* if it begins or ends in optional space it needs quoting */
513
if (!needsQuoting && srclen > 0 &&
514
(OPTIONAL_SPACE(src[srclen-1]) || OPTIONAL_SPACE(src[0]))) {
515
needsQuoting = PR_TRUE;
518
if (needsQuoting) reqLen += 2;
520
/* space for terminal null */
523
if (reqLen > dstlen) {
524
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
529
if (needsQuoting) *d++ = C_DOUBLE_QUOTE;
530
for (i = 0; i < srclen; i++) {
532
if (c == C_DOUBLE_QUOTE || c == C_BACKSLASH) {
538
if (needsQuoting) *d++ = C_DOUBLE_QUOTE;
543
/* convert an OID to dotted-decimal representation */
544
/* Returns a string that must be freed with PR_smprintf_free(), */
546
CERT_GetOidString(const SECItem *oid)
554
#define MAX_OID_LEN 1024 /* bytes */
556
if (oid->len > MAX_OID_LEN) {
557
PORT_SetError(SEC_ERROR_INPUT_LEN);
561
/* d will point to the next sequence of bytes to decode */
562
d = (PRUint8 *)oid->data;
563
/* end points to one past the legitimate data */
564
end = &d[ oid->len ];
567
* Check for our pseudo-encoded single-digit OIDs
569
if( (*d == 0x80) && (2 == oid->len) ) {
570
/* Funky encoding. The second byte is the number */
571
a = PR_smprintf("%lu", (PRUint32)d[1]);
572
if( (char *)NULL == a ) {
573
PORT_SetError(SEC_ERROR_NO_MEMORY);
579
for( ; d < end; d = &e[1] ) {
581
for( e = d; e < end; e++ ) {
582
if( 0 == (*e & 0x80) ) {
587
if( ((e-d) > 4) || (((e-d) == 4) && (*d & 0x70)) ) {
588
/* More than a 32-bit number */
594
n |= ((PRUint32)(e[-4] & 0x0f)) << 28;
596
n |= ((PRUint32)(e[-3] & 0x7f)) << 21;
598
n |= ((PRUint32)(e[-2] & 0x7f)) << 14;
600
n |= ((PRUint32)(e[-1] & 0x7f)) << 7;
602
n |= ((PRUint32)(e[-0] & 0x7f)) ;
605
if( (char *)NULL == a ) {
606
/* This is the first number.. decompose it */
607
PRUint32 one = PR_MIN(n/40, 2); /* never > 2 */
608
PRUint32 two = n - one * 40;
610
a = PR_smprintf("OID.%lu.%lu", one, two);
611
if( (char *)NULL == a ) {
612
PORT_SetError(SEC_ERROR_NO_MEMORY);
616
b = PR_smprintf("%s.%lu", a, n);
617
if( (char *)NULL == b ) {
619
PORT_SetError(SEC_ERROR_NO_MEMORY);
632
/* convert DER-encoded hex to a string */
634
get_hex_string(SECItem *data)
638
static const char hex[] = { "0123456789ABCDEF" };
640
/* '#' + 2 chars per octet + terminator */
641
rv = SECITEM_AllocItem(NULL, NULL, data->len*2 + 2);
646
rv->len = 1 + 2 * data->len;
647
for (i=0; i<data->len; i++) {
649
rv->data[2*i+1] = hex[j >> 4];
650
rv->data[2*i+2] = hex[j & 15];
652
rv->data[rv->len] = 0;
657
AppendAVA(stringBuf *bufp, CERTAVA *ava)
659
const struct NameToKind *n2k = name2kinds;
661
unsigned len, maxLen;
664
SECItem *avaValue = NULL;
665
char *unknownTag = NULL;
666
PRBool hexValue = PR_FALSE;
669
tag = CERT_GetAVATag(ava);
670
while (n2k->kind != tag && n2k->kind != SEC_OID_UNKNOWN) {
673
if (n2k->kind != SEC_OID_UNKNOWN) {
676
/* handle unknown attribute types per RFC 2253 */
677
tagName = unknownTag = CERT_GetOidString(&ava->type);
681
maxLen = n2k->maxLen;
683
#ifdef NSS_STRICT_RFC_2253_VALUES_ONLY
686
avaValue = CERT_DecodeAVAValue(&ava->value);
688
/* the attribute value is not recognized, get the hex value */
689
avaValue = get_hex_string(&ava->value);
691
if (unknownTag) PR_smprintf_free(unknownTag);
697
/* Check value length */
698
if (avaValue->len > maxLen + 3) { /* must be room for "..." */
699
/* avaValue is a UTF8 string, freshly allocated and returned to us
700
** by CERT_DecodeAVAValue just above, so we can modify it here.
701
** See if we're in the middle of a multi-byte UTF8 character.
703
while (((avaValue->data[maxLen] & 0xc0) == 0x80) && maxLen > 0) {
706
/* add elipsis to signify truncation. */
707
avaValue->data[maxLen++] = '.';
708
avaValue->data[maxLen++] = '.';
709
avaValue->data[maxLen++] = '.';
710
avaValue->data[maxLen] = 0;
711
avaValue->len = maxLen;
714
len = PORT_Strlen(tagName);
715
if (len+1 > sizeof(tmpBuf)) {
716
if (unknownTag) PR_smprintf_free(unknownTag);
717
SECITEM_FreeItem(avaValue, PR_TRUE);
718
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
721
PORT_Memcpy(tmpBuf, tagName, len);
722
if (unknownTag) PR_smprintf_free(unknownTag);
725
/* escape and quote as necessary - don't quote hex strings */
727
/* appent avaValue to tmpBuf */
728
if (avaValue->len + len + 1 > sizeof tmpBuf) {
729
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
732
PORT_Strncpy(tmpBuf+len, (char *)avaValue->data, avaValue->len + 1);
736
rv = CERT_RFC1485_EscapeAndQuote(tmpBuf+len, sizeof(tmpBuf)-len,
737
(char *)avaValue->data, avaValue->len);
738
SECITEM_FreeItem(avaValue, PR_TRUE);
739
if (rv) return SECFailure;
741
rv = AppendStr(bufp, tmpBuf);
746
CERT_NameToAscii(CERTName *name)
751
PRBool first = PR_TRUE;
752
stringBuf strBuf = { NULL, 0, 0 };
761
while (*lastRdn) lastRdn++;
765
* Loop over name contents in _reverse_ RDN order appending to string
767
for (rdn = lastRdn; rdn >= rdns; rdn--) {
768
CERTAVA** avas = (*rdn)->avas;
770
PRBool newRDN = PR_TRUE;
773
* XXX Do we need to traverse the AVAs in reverse order, too?
775
while (avas && (ava = *avas++) != NULL) {
777
/* Put in comma or plus separator */
779
/* Use of spaces is deprecated in RFC 2253. */
780
rv = AppendStr(&strBuf, newRDN ? "," : "+");
786
/* Add in tag type plus value into buf */
787
rv = AppendAVA(&strBuf, ava);
792
return strBuf.buffer;
795
PORT_Free(strBuf.buffer);
801
* Return the string representation of a DER encoded distinguished name
802
* "dername" - The DER encoded name to convert
805
CERT_DerNameToAscii(SECItem *dername)
808
PRArenaPool *arena = NULL;
812
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
814
if ( arena == NULL) {
818
rv = SEC_QuickDERDecodeItem(arena, &name, CERT_NameTemplate, dername);
820
if ( rv != SECSuccess ) {
824
retstr = CERT_NameToAscii(&name);
827
if ( arena != NULL ) {
828
PORT_FreeArena(arena, PR_FALSE);
835
CERT_GetNameElement(PRArenaPool *arena, CERTName *name, int wantedTag)
842
while (rdns && (rdn = *rdns++) != 0) {
843
CERTAVA** avas = rdn->avas;
845
while (avas && (ava = *avas++) != 0) {
846
int tag = CERT_GetAVATag(ava);
847
if ( tag == wantedTag ) {
848
SECItem *decodeItem = CERT_DecodeAVAValue(&ava->value);
853
buf = (char *)PORT_ArenaZAlloc(arena,decodeItem->len + 1);
855
buf = (char *)PORT_ZAlloc(decodeItem->len + 1);
858
PORT_Memcpy(buf, decodeItem->data, decodeItem->len);
859
buf[decodeItem->len] = 0;
861
SECITEM_FreeItem(decodeItem, PR_TRUE);
872
CERT_GetCertificateEmailAddress(CERTCertificate *cert)
874
char *rawEmailAddr = NULL;
877
CERTGeneralName *nameList = NULL;
878
CERTGeneralName *current;
879
PRArenaPool *arena = NULL;
882
subAltName.data = NULL;
884
rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject),
885
SEC_OID_PKCS9_EMAIL_ADDRESS);
886
if ( rawEmailAddr == NULL ) {
887
rawEmailAddr = CERT_GetNameElement(cert->arena, &(cert->subject),
888
SEC_OID_RFC1274_MAIL);
890
if ( rawEmailAddr == NULL) {
892
rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
894
if (rv != SECSuccess) {
897
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
901
nameList = current = CERT_DecodeAltNameExtension(arena, &subAltName);
905
if (nameList != NULL) {
907
if (current->type == certDirectoryName) {
908
rawEmailAddr = CERT_GetNameElement(cert->arena,
909
&(current->name.directoryName),
910
SEC_OID_PKCS9_EMAIL_ADDRESS);
911
if ( rawEmailAddr == NULL ) {
912
rawEmailAddr = CERT_GetNameElement(cert->arena,
913
&(current->name.directoryName), SEC_OID_RFC1274_MAIL);
915
} else if (current->type == certRFC822Name) {
916
rawEmailAddr = (char*)PORT_ArenaZAlloc(cert->arena,
917
current->name.other.len + 1);
921
PORT_Memcpy(rawEmailAddr, current->name.other.data,
922
current->name.other.len);
923
rawEmailAddr[current->name.other.len] = '\0';
928
current = cert_get_next_general_name(current);
929
} while (current != nameList);
933
for (i = 0; i <= (int) PORT_Strlen(rawEmailAddr); i++) {
934
rawEmailAddr[i] = tolower(rawEmailAddr[i]);
940
/* Don't free nameList, it's part of the arena. */
943
PORT_FreeArena(arena, PR_FALSE);
946
if ( subAltName.data ) {
947
SECITEM_FreeItem(&subAltName, PR_FALSE);
950
return(rawEmailAddr);
954
appendStringToBuf(char *dest, char *src, PRUint32 *pRemaining)
957
if (dest && src && src[0] && *pRemaining > (len = PL_strlen(src))) {
959
for (i = 0; i < len; ++i)
960
dest[i] = tolower(src[i]);
963
*pRemaining -= len + 1;
969
appendItemToBuf(char *dest, SECItem *src, PRUint32 *pRemaining)
971
if (dest && src && src->data && src->len && src->data[0] &&
972
*pRemaining > src->len + 1 ) {
973
PRUint32 len = src->len;
975
for (i = 0; i < len && src->data[i] ; ++i)
976
dest[i] = tolower(src->data[i]);
979
*pRemaining -= len + 1;
984
/* Returns a pointer to an environment-like string, a series of
985
** null-terminated strings, terminated by a zero-length string.
986
** This function is intended to be internal to NSS.
989
cert_GetCertificateEmailAddresses(CERTCertificate *cert)
991
char * rawEmailAddr = NULL;
992
char * addrBuf = NULL;
994
PRArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
996
PRInt32 finalLen = 0;
1003
subAltName.data = NULL;
1004
maxLen = cert->derCert.len;
1005
PORT_Assert(maxLen);
1007
maxLen = 2000; /* a guess, should never happen */
1009
pBuf = addrBuf = (char *)PORT_ArenaZAlloc(tmpArena, maxLen + 1);
1013
rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject,
1014
SEC_OID_PKCS9_EMAIL_ADDRESS);
1015
pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
1017
rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject,
1018
SEC_OID_RFC1274_MAIL);
1019
pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
1021
rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME,
1023
if (rv == SECSuccess && subAltName.data) {
1024
CERTGeneralName *nameList = NULL;
1026
if (!!(nameList = CERT_DecodeAltNameExtension(tmpArena, &subAltName))) {
1027
CERTGeneralName *current = nameList;
1029
if (current->type == certDirectoryName) {
1030
rawEmailAddr = CERT_GetNameElement(tmpArena,
1031
¤t->name.directoryName,
1032
SEC_OID_PKCS9_EMAIL_ADDRESS);
1033
pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
1035
rawEmailAddr = CERT_GetNameElement(tmpArena,
1036
¤t->name.directoryName,
1037
SEC_OID_RFC1274_MAIL);
1038
pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen);
1039
} else if (current->type == certRFC822Name) {
1040
pBuf = appendItemToBuf(pBuf, ¤t->name.other, &maxLen);
1042
current = cert_get_next_general_name(current);
1043
} while (current != nameList);
1045
SECITEM_FreeItem(&subAltName, PR_FALSE);
1046
/* Don't free nameList, it's part of the tmpArena. */
1048
/* now copy superstring to cert's arena */
1049
finalLen = (pBuf - addrBuf) + 1;
1052
pBuf = PORT_ArenaAlloc(cert->arena, finalLen);
1054
PORT_Memcpy(pBuf, addrBuf, finalLen);
1059
PORT_FreeArena(tmpArena, PR_FALSE);
1064
/* returns pointer to storage in cert's arena. Storage remains valid
1065
** as long as cert's reference count doesn't go to zero.
1066
** Caller should strdup or otherwise copy.
1068
const char * /* const so caller won't muck with it. */
1069
CERT_GetFirstEmailAddress(CERTCertificate * cert)
1071
if (cert && cert->emailAddr && cert->emailAddr[0])
1072
return (const char *)cert->emailAddr;
1076
/* returns pointer to storage in cert's arena. Storage remains valid
1077
** as long as cert's reference count doesn't go to zero.
1078
** Caller should strdup or otherwise copy.
1080
const char * /* const so caller won't muck with it. */
1081
CERT_GetNextEmailAddress(CERTCertificate * cert, const char * prev)
1083
if (cert && prev && prev[0]) {
1084
PRUint32 len = PL_strlen(prev);
1086
if (prev && prev[0])
1092
/* This is seriously bogus, now that certs store their email addresses in
1093
** subject Alternative Name extensions.
1094
** Returns a string allocated by PORT_StrDup, which the caller must free.
1097
CERT_GetCertEmailAddress(CERTName *name)
1103
rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_PKCS9_EMAIL_ADDRESS);
1104
if ( rawEmailAddr == NULL ) {
1105
rawEmailAddr = CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_MAIL);
1107
emailAddr = CERT_FixupEmailAddr(rawEmailAddr);
1108
if ( rawEmailAddr ) {
1109
PORT_Free(rawEmailAddr);
1114
/* The return value must be freed with PORT_Free. */
1116
CERT_GetCommonName(CERTName *name)
1118
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_COMMON_NAME));
1122
CERT_GetCountryName(CERTName *name)
1124
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_COUNTRY_NAME));
1128
CERT_GetLocalityName(CERTName *name)
1130
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_LOCALITY));
1134
CERT_GetStateName(CERTName *name)
1136
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_STATE_OR_PROVINCE));
1140
CERT_GetOrgName(CERTName *name)
1142
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATION_NAME));
1146
CERT_GetDomainComponentName(CERTName *name)
1148
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DC));
1152
CERT_GetOrgUnitName(CERTName *name)
1154
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME));
1158
CERT_GetDnQualifier(CERTName *name)
1160
return(CERT_GetNameElement(NULL, name, SEC_OID_AVA_DN_QUALIFIER));
1164
CERT_GetCertUid(CERTName *name)
1166
return(CERT_GetNameElement(NULL, name, SEC_OID_RFC1274_UID));