diff --git a/security/nss/lib/certdb/alg1485.c b/security/nss/lib/certdb/alg1485.c index fe1b4913ea3f..30b41d196a3a 100644 --- a/security/nss/lib/certdb/alg1485.c +++ b/security/nss/lib/certdb/alg1485.c @@ -912,6 +912,147 @@ finish: return(rawEmailAddr); } +static char * +appendStringToBuf(char *dest, char *src, PRUint32 *pRemaining) +{ + PRUint32 len; + if (dest && src && src[0] && *pRemaining > (len = PL_strlen(src))) { + PRUint32 i; + for (i = 0; i < len; ++i) + dest[i] = tolower(src[i]); + dest[len] = 0; + dest += len + 1; + *pRemaining -= len + 1; + } + return dest; +} + +static char * +appendItemToBuf(char *dest, SECItem *src, PRUint32 *pRemaining) +{ + if (dest && src && src->data && src->len && src->data[0] && + *pRemaining > src->len + 1 ) { + PRUint32 len = src->len; + PRUint32 i; + for (i = 0; i < len && src->data[i] ; ++i) + dest[i] = tolower(src->data[i]); + dest[len] = 0; + dest += len + 1; + *pRemaining -= len + 1; + } + return dest; +} + +/* Returns a pointer to an environment-like string, a series of +** null-terminated strings, terminated by a zero-length string. +** This function is intended to be internal to NSS. +*/ +char * +cert_GetCertificateEmailAddresses(CERTCertificate *cert) +{ + char * rawEmailAddr = NULL; + char * addrBuf = NULL; + char * pBuf = NULL; + PRArenaPool * tmpArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + PRUint32 maxLen = 0; + PRInt32 finalLen = 0; + SECStatus rv; + SECItem subAltName; + + if (!tmpArena) + return addrBuf; + + subAltName.data = NULL; + maxLen = cert->derCert.len; + PORT_Assert(maxLen); + if (!maxLen) + maxLen = 2000; /* a guess, should never happen */ + + pBuf = addrBuf = (char *)PORT_ArenaZAlloc(tmpArena, maxLen + 1); + if (!addrBuf) + goto loser; + + rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject, + SEC_OID_PKCS9_EMAIL_ADDRESS); + pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); + + rawEmailAddr = CERT_GetNameElement(tmpArena, &cert->subject, + SEC_OID_RFC1274_MAIL); + pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); + + rv = CERT_FindCertExtension(cert, SEC_OID_X509_SUBJECT_ALT_NAME, + &subAltName); + if (rv == SECSuccess && subAltName.data) { + CERTGeneralName *nameList = NULL; + + if (!!(nameList = CERT_DecodeAltNameExtension(tmpArena, &subAltName))) { + CERTGeneralName *current = nameList; + do { + if (current->type == certDirectoryName) { + rawEmailAddr = CERT_GetNameElement(tmpArena, + ¤t->name.directoryName, + SEC_OID_PKCS9_EMAIL_ADDRESS); + pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); + + rawEmailAddr = CERT_GetNameElement(tmpArena, + ¤t->name.directoryName, + SEC_OID_RFC1274_MAIL); + pBuf = appendStringToBuf(pBuf, rawEmailAddr, &maxLen); + } else if (current->type == certRFC822Name) { + pBuf = appendItemToBuf(pBuf, ¤t->name.other, &maxLen); + } + current = cert_get_next_general_name(current); + } while (current != nameList); + } + SECITEM_FreeItem(&subAltName, PR_FALSE); + /* Don't free nameList, it's part of the tmpArena. */ + } + /* now copy superstring to cert's arena */ + finalLen = (pBuf - addrBuf) + 1; + pBuf = PORT_ArenaAlloc(cert->arena, finalLen); + if (pBuf) { + PORT_Memcpy(pBuf, addrBuf, finalLen); + } + +loser: + if (tmpArena) + PORT_FreeArena(tmpArena, PR_FALSE); + + return pBuf; +} + +/* returns pointer to storage in cert's arena. Storage remains valid +** as long as cert's reference count doesn't go to zero. +** Caller should strdup or otherwise copy. +*/ +const char * /* const so caller won't muck with it. */ +CERT_GetFirstEmailAddress(CERTCertificate * cert) +{ + if (cert && cert->emailAddr && cert->emailAddr[0]) + return (const char *)cert->emailAddr; + return NULL; +} + +/* returns pointer to storage in cert's arena. Storage remains valid +** as long as cert's reference count doesn't go to zero. +** Caller should strdup or otherwise copy. +*/ +const char * /* const so caller won't muck with it. */ +CERT_GetNextEmailAddress(CERTCertificate * cert, const char * prev) +{ + if (cert && prev && prev[0]) { + PRUint32 len = PL_strlen(prev); + prev += len + 1; + if (prev && prev[0]) + return prev; + } + return NULL; +} + +/* This is seriously bogus, now that certs store their email addresses in +** subject Alternative Name extensions. +** Returns a string allocated by PORT_StrDup, which the caller must free. +*/ char * CERT_GetCertEmailAddress(CERTName *name) { diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h index 7a78ec607f5a..3e68b57e02dd 100644 --- a/security/nss/lib/certdb/cert.h +++ b/security/nss/lib/certdb/cert.h @@ -34,7 +34,7 @@ /* * cert.h - public data structures and prototypes for the certificate library * - * $Id: cert.h,v 1.26 2002/10/18 21:58:18 nelsonb%netscape.com Exp $ + * $Id: cert.h,v 1.27 2002/10/23 20:50:51 nelsonb%netscape.com Exp $ */ #ifndef _CERT_H_ @@ -706,6 +706,11 @@ extern char *CERT_GetCertificateEmailAddress(CERTCertificate *cert); extern char *CERT_GetCertEmailAddress(CERTName *name); +extern const char * CERT_GetFirstEmailAddress(CERTCertificate * cert); + +extern const char * CERT_GetNextEmailAddress(CERTCertificate * cert, + const char * prev); + extern char *CERT_GetCommonName(CERTName *name); extern char *CERT_GetCountryName(CERTName *name); diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c index 18918563c1f1..9a82d63bc77f 100644 --- a/security/nss/lib/certdb/certdb.c +++ b/security/nss/lib/certdb/certdb.c @@ -34,7 +34,7 @@ /* * Certificate handling code * - * $Id: certdb.c,v 1.44 2002/10/03 03:34:36 jpierre%netscape.com Exp $ + * $Id: certdb.c,v 1.45 2002/10/23 20:50:51 nelsonb%netscape.com Exp $ */ #include "nssilock.h" @@ -862,7 +862,7 @@ CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, } /* set the email address */ - cert->emailAddr = CERT_GetCertificateEmailAddress(cert); + cert->emailAddr = cert_GetCertificateEmailAddresses(cert); /* initialize the subjectKeyID */ rv = cert_GetKeyID(cert); diff --git a/security/nss/lib/certdb/certi.h b/security/nss/lib/certdb/certi.h index 7a74144fcb29..ec69fd2e1dff 100644 --- a/security/nss/lib/certdb/certi.h +++ b/security/nss/lib/certdb/certi.h @@ -33,7 +33,7 @@ /* * certi.h - private data structures for the certificate library * - * $Id: certi.h,v 1.7 2002/10/05 02:24:23 jpierre%netscape.com Exp $ + * $Id: certi.h,v 1.8 2002/10/23 20:50:51 nelsonb%netscape.com Exp $ */ #ifndef _CERTI_H_ #define _CERTI_H_ @@ -182,5 +182,11 @@ struct CRLCacheStr { SECStatus InitCRLCache(void); SECStatus ShutdownCRLCache(void); +/* Returns a pointer to an environment-like string, a series of +** null-terminated strings, terminated by a zero-length string. +** This function is intended to be internal to NSS. +*/ +extern char * cert_GetCertificateEmailAddresses(CERTCertificate *cert); + #endif /* _CERTI_H_ */ diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index 416e0c77d571..f95c40c949a5 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -716,6 +716,8 @@ SECKEY_CopyPublicKey; ;+}; ;+NSS_3.7 { # NSS 3.7 release ;+ global: +CERT_GetFirstEmailAddress; +CERT_GetNextEmailAddress; CERT_VerifySignedDataWithPubKeyInfo; ;+ local: ;+ *;