summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornelson%bolyard.com <devnull@localhost>2009-04-15 08:36:58 +0000
committernelson%bolyard.com <devnull@localhost>2009-04-15 08:36:58 +0000
commitce2943e83c291d50e9a2acc3f14e80dd8ab27d2c (patch)
treecd86356859b09c0bd1ed7c63423dc23c95fcd3c9
parent74b5a7db0369b3c5f221308eae71f190bb97f37d (diff)
downloadnss-hg-NSS_3_11_BRANCH.tar.gz
Bug 488241: Fix cert7/cert8.db issues with large issuer names in NSS_3_11_BRANCH as wellNSS_3_11_BRANCH
Patch contributed by Kaspar Brand <mozbugzilla@velox.ch>
-rw-r--r--security/nss/lib/softoken/lowcert.c4
-rw-r--r--security/nss/lib/softoken/pcertdb.c335
-rw-r--r--security/nss/lib/softoken/pcertt.h2
3 files changed, 185 insertions, 156 deletions
diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c
index 008687e52..629cfe3ce 100644
--- a/security/nss/lib/softoken/lowcert.c
+++ b/security/nss/lib/softoken/lowcert.c
@@ -369,6 +369,10 @@ nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena,
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto loser;
}
+ if (len > NSS_MAX_LEGACY_DB_KEY_SIZE) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ goto loser;
+ }
key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
if ( !key->data ) {
goto loser;
diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c
index 6630b6134..ad8fd0b23 100644
--- a/security/nss/lib/softoken/pcertdb.c
+++ b/security/nss/lib/softoken/pcertdb.c
@@ -649,16 +649,16 @@ EncodeDBCertEntry(certDBEntryCert *entry, PRArenaPool *arena, SECItem *dbitem)
/* fill in database record */
buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
- buf[0] = ( entry->trust.sslFlags >> 8 ) & 0xff;
- buf[1] = entry->trust.sslFlags & 0xff;
- buf[2] = ( entry->trust.emailFlags >> 8 ) & 0xff;
- buf[3] = entry->trust.emailFlags & 0xff;
- buf[4] = ( entry->trust.objectSigningFlags >> 8 ) & 0xff;
- buf[5] = entry->trust.objectSigningFlags & 0xff;
- buf[6] = ( entry->derCert.len >> 8 ) & 0xff;
- buf[7] = entry->derCert.len & 0xff;
- buf[8] = ( nnlen >> 8 ) & 0xff;
- buf[9] = nnlen & 0xff;
+ buf[0] = (PRUint8)( entry->trust.sslFlags >> 8 );
+ buf[1] = (PRUint8)( entry->trust.sslFlags );
+ buf[2] = (PRUint8)( entry->trust.emailFlags >> 8 );
+ buf[3] = (PRUint8)( entry->trust.emailFlags );
+ buf[4] = (PRUint8)( entry->trust.objectSigningFlags >> 8 );
+ buf[5] = (PRUint8)( entry->trust.objectSigningFlags );
+ buf[6] = (PRUint8)( entry->derCert.len >> 8 );
+ buf[7] = (PRUint8)( entry->derCert.len );
+ buf[8] = (PRUint8)( nnlen >> 8 );
+ buf[9] = (PRUint8)( nnlen );
PORT_Memcpy(&buf[DB_CERT_ENTRY_HEADER_LEN], entry->derCert.data,
entry->derCert.len);
@@ -679,6 +679,8 @@ static SECStatus
EncodeDBCertKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey)
{
unsigned int len = certKey->len + SEC_DB_KEY_HEADER_LEN;
+ if (len > NSS_MAX_LEGACY_DB_KEY_SIZE)
+ goto loser;
if (arena) {
dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
} else {
@@ -718,12 +720,14 @@ EncodeDBGenericKey(SECItem *certKey, PRArenaPool *arena, SECItem *dbkey,
dbkey->len = certKey->len + SEC_DB_KEY_HEADER_LEN;
+ if (dbkey->len > NSS_MAX_LEGACY_DB_KEY_SIZE)
+ goto loser;
dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
if ( dbkey->data == NULL ) {
goto loser;
}
PORT_Memcpy(&dbkey->data[SEC_DB_KEY_HEADER_LEN],
- certKey->data, certKey->len);
+ certKey->data, certKey->len);
dbkey->data[0] = (unsigned char) entryType;
return(SECSuccess);
@@ -773,14 +777,17 @@ DecodeDBCertEntry(certDBEntryCert *entry, SECItem *dbentry)
entry->derCert.len = ( ( dbentry->data[lenoff] << 8 ) |
dbentry->data[lenoff+1] );
nnlen = ( ( dbentry->data[lenoff+2] << 8 ) | dbentry->data[lenoff+3] );
- if ( ( entry->derCert.len + nnlen + headerlen )
- != dbentry->len) {
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- goto loser;
+ lenoff = dbentry->len - ( entry->derCert.len + nnlen + headerlen );
+ if ( lenoff ) {
+ if ( lenoff < 0 || (lenoff & 0xffff) != 0 ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+ /* The cert size exceeded 64KB. Reconstruct the correct length. */
+ entry->derCert.len += lenoff;
}
/* copy the dercert */
-
entry->derCert.data = pkcs11_copyStaticData(&dbentry->data[headerlen],
entry->derCert.len,entry->derCertSpace,sizeof(entry->derCertSpace));
if ( entry->derCert.data == NULL ) {
@@ -1165,10 +1172,10 @@ EncodeDBCrlEntry(certDBEntryRevocation *entry, PRArenaPool *arena, SECItem *dbit
/* fill in database record */
buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
- buf[0] = ( entry->derCrl.len >> 8 ) & 0xff;
- buf[1] = entry->derCrl.len & 0xff;
- buf[2] = ( nnlen >> 8 ) & 0xff;
- buf[3] = nnlen & 0xff;
+ buf[0] = (PRUint8)( entry->derCrl.len >> 8 );
+ buf[1] = (PRUint8)( entry->derCrl.len );
+ buf[2] = (PRUint8)( nnlen >> 8 );
+ buf[3] = (PRUint8)( nnlen );
PORT_Memcpy(&buf[DB_CRL_ENTRY_HEADER_LEN], entry->derCrl.data,
entry->derCrl.len);
@@ -1187,8 +1194,9 @@ loser:
static SECStatus
DecodeDBCrlEntry(certDBEntryRevocation *entry, SECItem *dbentry)
{
- unsigned int nnlen;
-
+ unsigned int urlLen;
+ int lenDiff;
+
/* is record long enough for header? */
if ( dbentry->len < DB_CRL_ENTRY_HEADER_LEN ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
@@ -1197,20 +1205,19 @@ DecodeDBCrlEntry(certDBEntryRevocation *entry, SECItem *dbentry)
/* is database entry correct length? */
entry->derCrl.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
- nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );
- if ( ( entry->derCrl.len + nnlen + DB_CRL_ENTRY_HEADER_LEN )
- != dbentry->len) {
- /* CRL entry is greater than 64 K. Hack to make this continue to work */
- if (dbentry->len >= (0xffff - DB_CRL_ENTRY_HEADER_LEN) - nnlen) {
- entry->derCrl.len =
- (dbentry->len - DB_CRL_ENTRY_HEADER_LEN) - nnlen;
- } else {
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- goto loser;
- }
+ urlLen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );
+ lenDiff = dbentry->len -
+ (entry->derCrl.len + urlLen + DB_CRL_ENTRY_HEADER_LEN);
+ if (lenDiff) {
+ if (lenDiff < 0 || (lenDiff & 0xffff) != 0) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+ /* CRL entry is greater than 64 K. Hack to make this continue to work */
+ entry->derCrl.len += lenDiff;
}
- /* copy the dercert */
+ /* copy the der CRL */
entry->derCrl.data = (unsigned char *)PORT_ArenaAlloc(entry->common.arena,
entry->derCrl.len);
if ( entry->derCrl.data == NULL ) {
@@ -1222,15 +1229,15 @@ DecodeDBCrlEntry(certDBEntryRevocation *entry, SECItem *dbentry)
/* copy the url */
entry->url = NULL;
- if (nnlen != 0) {
- entry->url = (char *)PORT_ArenaAlloc(entry->common.arena, nnlen);
+ if (urlLen != 0) {
+ entry->url = (char *)PORT_ArenaAlloc(entry->common.arena, urlLen);
if ( entry->url == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
PORT_Memcpy(entry->url,
&dbentry->data[DB_CRL_ENTRY_HEADER_LEN + entry->derCrl.len],
- nnlen);
+ urlLen);
}
return(SECSuccess);
@@ -1461,7 +1468,6 @@ EncodeDBNicknameEntry(certDBEntryNickname *entry, PRArenaPool *arena,
*/
dbitem->len = entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN +
SEC_DB_ENTRY_HEADER_LEN;
-
dbitem->data = (unsigned char *)PORT_ArenaAlloc(arena, dbitem->len);
if ( dbitem->data == NULL) {
goto loser;
@@ -1469,10 +1475,8 @@ EncodeDBNicknameEntry(certDBEntryNickname *entry, PRArenaPool *arena,
/* fill in database record */
buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
-
- buf[0] = ( entry->subjectName.len >> 8 ) & 0xff;
- buf[1] = entry->subjectName.len & 0xff;
-
+ buf[0] = (PRUint8)( entry->subjectName.len >> 8 );
+ buf[1] = (PRUint8)( entry->subjectName.len );
PORT_Memcpy(&buf[DB_NICKNAME_ENTRY_HEADER_LEN], entry->subjectName.data,
entry->subjectName.len);
@@ -1495,6 +1499,8 @@ EncodeDBNicknameKey(char *nickname, PRArenaPool *arena,
/* now get the database key and format it */
dbkey->len = nnlen + SEC_DB_KEY_HEADER_LEN;
+ if (dbkey->len > NSS_MAX_LEGACY_DB_KEY_SIZE)
+ goto loser;
dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
if ( dbkey->data == NULL ) {
goto loser;
@@ -1512,6 +1518,8 @@ static SECStatus
DecodeDBNicknameEntry(certDBEntryNickname *entry, SECItem *dbentry,
char *nickname)
{
+ int lenDiff;
+
/* is record long enough for header? */
if ( dbentry->len < DB_NICKNAME_ENTRY_HEADER_LEN ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
@@ -1520,12 +1528,17 @@ DecodeDBNicknameEntry(certDBEntryNickname *entry, SECItem *dbentry,
/* is database entry correct length? */
entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
- if (( entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN ) !=
- dbentry->len ){
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- goto loser;
+ lenDiff = dbentry->len -
+ (entry->subjectName.len + DB_NICKNAME_ENTRY_HEADER_LEN);
+ if (lenDiff) {
+ if (lenDiff < 0 || (lenDiff & 0xffff) != 0 ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+ /* The entry size exceeded 64KB. Reconstruct the correct length. */
+ entry->subjectName.len += lenDiff;
}
-
+
/* copy the certkey */
entry->subjectName.data =
(unsigned char *)PORT_ArenaAlloc(entry->common.arena,
@@ -1779,12 +1792,12 @@ EncodeDBSMimeEntry(certDBEntrySMime *entry, PRArenaPool *arena,
/* fill in database record */
buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
- buf[0] = ( entry->subjectName.len >> 8 ) & 0xff;
- buf[1] = entry->subjectName.len & 0xff;
- buf[2] = ( entry->smimeOptions.len >> 8 ) & 0xff;
- buf[3] = entry->smimeOptions.len & 0xff;
- buf[4] = ( entry->optionsDate.len >> 8 ) & 0xff;
- buf[5] = entry->optionsDate.len & 0xff;
+ buf[0] = (PRUint8)( entry->subjectName.len >> 8 );
+ buf[1] = (PRUint8)( entry->subjectName.len );
+ buf[2] = (PRUint8)( entry->smimeOptions.len >> 8 );
+ buf[3] = (PRUint8)( entry->smimeOptions.len );
+ buf[4] = (PRUint8)( entry->optionsDate.len >> 8 );
+ buf[5] = (PRUint8)( entry->optionsDate.len );
/* if no smime options, then there should not be an options date either */
PORT_Assert( ! ( ( entry->smimeOptions.len == 0 ) &&
@@ -1821,6 +1834,8 @@ EncodeDBSMimeKey(char *emailAddr, PRArenaPool *arena,
/* now get the database key and format it */
dbkey->len = addrlen + SEC_DB_KEY_HEADER_LEN;
+ if (dbkey->len > NSS_MAX_LEGACY_DB_KEY_SIZE)
+ goto loser;
dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
if ( dbkey->data == NULL ) {
goto loser;
@@ -1840,6 +1855,8 @@ loser:
static SECStatus
DecodeDBSMimeEntry(certDBEntrySMime *entry, SECItem *dbentry, char *emailAddr)
{
+ int lenDiff;
+
/* is record long enough for header? */
if ( dbentry->len < DB_SMIME_ENTRY_HEADER_LEN ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
@@ -1847,15 +1864,22 @@ DecodeDBSMimeEntry(certDBEntrySMime *entry, SECItem *dbentry, char *emailAddr)
}
/* is database entry correct length? */
- entry->subjectName.len = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
- entry->smimeOptions.len = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );
- entry->optionsDate.len = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] );
- if (( entry->subjectName.len + entry->smimeOptions.len +
- entry->optionsDate.len + DB_SMIME_ENTRY_HEADER_LEN ) != dbentry->len){
- PORT_SetError(SEC_ERROR_BAD_DATABASE);
- goto loser;
+ entry->subjectName.len = (( dbentry->data[0] << 8 ) | dbentry->data[1] );
+ entry->smimeOptions.len = (( dbentry->data[2] << 8 ) | dbentry->data[3] );
+ entry->optionsDate.len = (( dbentry->data[4] << 8 ) | dbentry->data[5] );
+ lenDiff = dbentry->len - (entry->subjectName.len +
+ entry->smimeOptions.len +
+ entry->optionsDate.len +
+ DB_SMIME_ENTRY_HEADER_LEN);
+ if (lenDiff) {
+ if (lenDiff < 0 || (lenDiff & 0xffff) != 0 ) {
+ PORT_SetError(SEC_ERROR_BAD_DATABASE);
+ goto loser;
+ }
+ /* The entry size exceeded 64KB. Reconstruct the correct length. */
+ entry->subjectName.len += lenDiff;
}
-
+
/* copy the subject name */
entry->subjectName.data =
(unsigned char *)PORT_ArenaAlloc(entry->common.arena,
@@ -2160,8 +2184,8 @@ EncodeDBSubjectEntry(certDBEntrySubject *entry, PRArenaPool *arena,
unsigned int nnlen = 0;
unsigned int eaddrslen = 0;
int keyidoff;
- SECItem *certKeys;
- SECItem *keyIDs;
+ SECItem *certKeys = entry->certKeys;
+ SECItem *keyIDs = entry->keyIDs;;
if ( entry->nickname ) {
nnlen = PORT_Strlen(entry->nickname) + 1;
@@ -2177,10 +2201,15 @@ EncodeDBSubjectEntry(certDBEntrySubject *entry, PRArenaPool *arena,
/* compute the length of the entry */
keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen ;
- len = keyidoff + 4 * ncerts + eaddrslen;
+ len = keyidoff + (4 * ncerts) + eaddrslen;
for ( i = 0; i < ncerts; i++ ) {
- len += entry->certKeys[i].len;
- len += entry->keyIDs[i].len;
+ if (keyIDs[i].len > 0xffff ||
+ (certKeys[i].len > 0xffff)) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ goto loser;
+ }
+ len += certKeys[i].len;
+ len += keyIDs[i].len;
}
/* allocate space for encoded database record, including space
@@ -2197,50 +2226,44 @@ EncodeDBSubjectEntry(certDBEntrySubject *entry, PRArenaPool *arena,
/* fill in database record */
buf = &dbitem->data[SEC_DB_ENTRY_HEADER_LEN];
- buf[0] = ( ncerts >> 8 ) & 0xff;
- buf[1] = ncerts & 0xff;
- buf[2] = ( nnlen >> 8 ) & 0xff;
- buf[3] = nnlen & 0xff;
+ buf[0] = (PRUint8)( ncerts >> 8 );
+ buf[1] = (PRUint8)( ncerts );
+ buf[2] = (PRUint8)( nnlen >> 8 );
+ buf[3] = (PRUint8)( nnlen );
/* v7 email field is NULL in v8 */
buf[4] = 0;
buf[5] = 0;
PORT_Memcpy(&buf[DB_SUBJECT_ENTRY_HEADER_LEN], entry->nickname, nnlen);
-
+ tmpbuf = &buf[keyidoff];
for ( i = 0; i < ncerts; i++ ) {
-
- certKeys = entry->certKeys;
- keyIDs = entry->keyIDs;
-
- buf[keyidoff+i*2] = ( certKeys[i].len >> 8 ) & 0xff;
- buf[keyidoff+1+i*2] = certKeys[i].len & 0xff;
- buf[keyidoff+ncerts*2+i*2] = ( keyIDs[i].len >> 8 ) & 0xff;
- buf[keyidoff+1+ncerts*2+i*2] = keyIDs[i].len & 0xff;
+ tmpbuf[0] = (PRUint8)( certKeys[i].len >> 8 );
+ tmpbuf[1] = (PRUint8)( certKeys[i].len );
+ tmpbuf += 2;
+ }
+ for ( i = 0; i < ncerts; i++ ) {
+ tmpbuf[0] = (PRUint8)( keyIDs[i].len >> 8 );
+ tmpbuf[1] = (PRUint8)( keyIDs[i].len );
+ tmpbuf += 2;
}
- /* temp pointer used to stuff certkeys and keyids into the buffer */
- tmpbuf = &buf[keyidoff+ncerts*4];
-
for ( i = 0; i < ncerts; i++ ) {
- certKeys = entry->certKeys;
PORT_Memcpy(tmpbuf, certKeys[i].data, certKeys[i].len);
- tmpbuf = tmpbuf + certKeys[i].len;
+ tmpbuf += certKeys[i].len;
}
-
for ( i = 0; i < ncerts; i++ ) {
- keyIDs = entry->keyIDs;
PORT_Memcpy(tmpbuf, keyIDs[i].data, keyIDs[i].len);
- tmpbuf = tmpbuf + keyIDs[i].len;
+ tmpbuf += keyIDs[i].len;
}
if (entry->emailAddrs) {
- tmpbuf[0] = (entry->nemailAddrs >> 8) & 0xff;
- tmpbuf[1] = entry->nemailAddrs & 0xff;
+ tmpbuf[0] = (PRUint8)( entry->nemailAddrs >> 8 );
+ tmpbuf[1] = (PRUint8)( entry->nemailAddrs );
tmpbuf += 2;
for (i=0; i < entry->nemailAddrs; i++) {
int nameLen = PORT_Strlen(entry->emailAddrs[i]) + 1;
- tmpbuf[0] = (nameLen >> 8) & 0xff;
- tmpbuf[1] = nameLen & 0xff;
+ tmpbuf[0] = (PRUint8)( nameLen >> 8 );
+ tmpbuf[1] = (PRUint8)( nameLen );
tmpbuf += 2;
PORT_Memcpy(tmpbuf,entry->emailAddrs[i],nameLen);
tmpbuf +=nameLen;
@@ -2263,6 +2286,8 @@ EncodeDBSubjectKey(SECItem *derSubject, PRArenaPool *arena,
SECItem *dbkey)
{
dbkey->len = derSubject->len + SEC_DB_KEY_HEADER_LEN;
+ if (dbkey->len > NSS_MAX_LEGACY_DB_KEY_SIZE)
+ goto loser;
dbkey->data = (unsigned char *)PORT_ArenaAlloc(arena, dbkey->len);
if ( dbkey->data == NULL ) {
goto loser;
@@ -2281,18 +2306,17 @@ static SECStatus
DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry,
SECItem *derSubject)
{
- unsigned int ncerts;
- PRArenaPool *arena;
- unsigned int len, itemlen;
+ PRArenaPool *arena = entry->common.arena;
unsigned char *tmpbuf;
unsigned char *end;
+ void *mark = PORT_ArenaMark(arena);
+ unsigned int eaddrlen;
unsigned int i;
- SECStatus rv;
unsigned int keyidoff;
- unsigned int nnlen, eaddrlen;
- unsigned int stdlen;
-
- arena = entry->common.arena;
+ unsigned int len;
+ unsigned int ncerts = 0;
+ unsigned int nnlen;
+ SECStatus rv;
rv = SECITEM_CopyItem(arena, &entry->derSubject, derSubject);
if ( rv != SECSuccess ) {
@@ -2305,20 +2329,18 @@ DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry,
goto loser;
}
- entry->ncerts = ncerts = ( ( dbentry->data[0] << 8 ) | dbentry->data[1] );
- nnlen = ( ( dbentry->data[2] << 8 ) | dbentry->data[3] );
- eaddrlen = ( ( dbentry->data[4] << 8 ) | dbentry->data[5] );
- stdlen = ncerts * 4 + DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen;
- if ( dbentry->len < stdlen) {
+ entry->ncerts = ncerts = (( dbentry->data[0] << 8 ) | dbentry->data[1] );
+ nnlen = (( dbentry->data[2] << 8 ) | dbentry->data[3] );
+ eaddrlen = (( dbentry->data[4] << 8 ) | dbentry->data[5] );
+ keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen;
+ len = keyidoff + (4 * ncerts);
+ if ( dbentry->len < len) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
goto loser;
}
- entry->certKeys = (SECItem *)PORT_ArenaAlloc(arena,
- sizeof(SECItem) * ncerts);
- entry->keyIDs = (SECItem *)PORT_ArenaAlloc(arena,
- sizeof(SECItem) * ncerts);
-
+ entry->certKeys = PORT_ArenaNewArray(arena, SECItem, ncerts);
+ entry->keyIDs = PORT_ArenaNewArray(arena, SECItem, ncerts);
if ( ( entry->certKeys == NULL ) || ( entry->keyIDs == NULL ) ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
@@ -2340,7 +2362,7 @@ DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry,
/* if we have an old style email entry, there is only one */
entry->nemailAddrs = 0;
if ( eaddrlen > 1 ) { /* null terminator is stored */
- entry->emailAddrs = (char **)PORT_ArenaAlloc(arena, sizeof(char *));
+ entry->emailAddrs = PORT_ArenaNewArray(arena, char *, 2);
if ( entry->emailAddrs == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
@@ -2361,87 +2383,85 @@ DecodeDBSubjectEntry(certDBEntrySubject *entry, SECItem *dbentry,
/* collect the lengths of the certKeys and keyIDs, and total the
* overall length.
*/
- keyidoff = DB_SUBJECT_ENTRY_HEADER_LEN + nnlen + eaddrlen;
- len = keyidoff + 4 * ncerts;
-
- tmpbuf = &dbentry->data[0];
-
+ tmpbuf = &dbentry->data[keyidoff];
for ( i = 0; i < ncerts; i++ ) {
-
- itemlen = ( tmpbuf[keyidoff + 2*i] << 8 ) | tmpbuf[keyidoff + 1 + 2*i] ;
- len += itemlen;
- entry->certKeys[i].len = itemlen;
-
- itemlen = ( tmpbuf[keyidoff + 2*ncerts + 2*i] << 8 ) |
- tmpbuf[keyidoff + 1 + 2*ncerts + 2*i] ;
- len += itemlen;
- entry->keyIDs[i].len = itemlen;
+ unsigned int itemlen = ( tmpbuf[0] << 8 ) | tmpbuf[1];
+ entry->certKeys[i].len = itemlen;
+ len += itemlen;
+ tmpbuf += 2;
}
-
- /* is database entry correct length? */
+ for ( i = 0; i < ncerts; i++ ) {
+ unsigned int itemlen = ( tmpbuf[0] << 8 ) | tmpbuf[1] ;
+ entry->keyIDs[i].len = itemlen;
+ len += itemlen;
+ tmpbuf += 2;
+ }
+
+ /* is encoded entry large enough ? */
if ( len > dbentry->len ){
PORT_SetError(SEC_ERROR_BAD_DATABASE);
goto loser;
}
-
- tmpbuf = &tmpbuf[keyidoff + 4*ncerts];
+
for ( i = 0; i < ncerts; i++ ) {
- entry->certKeys[i].data =
- (unsigned char *)PORT_ArenaAlloc(arena, entry->certKeys[i].len);
+ unsigned int kLen = entry->certKeys[i].len;
+ entry->certKeys[i].data = (unsigned char *)PORT_ArenaAlloc(arena, kLen);
if ( entry->certKeys[i].data == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
- PORT_Memcpy(entry->certKeys[i].data, tmpbuf, entry->certKeys[i].len);
- tmpbuf = &tmpbuf[entry->certKeys[i].len];
+ PORT_Memcpy(entry->certKeys[i].data, tmpbuf, kLen);
+ tmpbuf += kLen;
}
-
for ( i = 0; i < ncerts; i++ ) {
- entry->keyIDs[i].data =
- (unsigned char *)PORT_ArenaAlloc(arena, entry->keyIDs[i].len);
+ unsigned int iLen = entry->keyIDs[i].len;
+ entry->keyIDs[i].data = (unsigned char *)PORT_ArenaAlloc(arena, iLen);
if ( entry->keyIDs[i].data == NULL ) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
- PORT_Memcpy(entry->keyIDs[i].data, tmpbuf, entry->keyIDs[i].len);
- tmpbuf = &tmpbuf[entry->keyIDs[i].len];
+ PORT_Memcpy(entry->keyIDs[i].data, tmpbuf, iLen);
+ tmpbuf += iLen;
}
- end = &dbentry->data[dbentry->len];
- if ((eaddrlen == 0) && (tmpbuf+1 < end)) {
+ end = dbentry->data + dbentry->len;
+ if ((eaddrlen == 0) && (end - tmpbuf > 1)) {
/* read in the additional email addresses */
- entry->nemailAddrs = tmpbuf[0] << 8 | tmpbuf[1];
+ entry->nemailAddrs = (((unsigned int)tmpbuf[0]) << 8) | tmpbuf[1];
tmpbuf += 2;
- entry->emailAddrs = (char **)
- PORT_ArenaAlloc(arena, entry->nemailAddrs * sizeof(char *));
+ if (end - tmpbuf < 2 * (int)entry->nemailAddrs)
+ goto loser;
+ entry->emailAddrs = PORT_ArenaNewArray(arena, char *, entry->nemailAddrs);
if (entry->emailAddrs == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
for (i=0; i < entry->nemailAddrs; i++) {
int nameLen;
- if (tmpbuf + 2 > end) {
+ if (end - tmpbuf < 2) {
+ goto loser;
+ }
+ nameLen = (((int)tmpbuf[0]) << 8) | tmpbuf[1];
+ tmpbuf += 2;
+ if (end - tmpbuf < nameLen) {
goto loser;
}
-
- nameLen = tmpbuf[0] << 8 | tmpbuf[1];
entry->emailAddrs[i] = PORT_ArenaAlloc(arena,nameLen);
if (entry->emailAddrs == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
- if (tmpbuf + (nameLen+2) > end) {
- goto loser;
- }
- PORT_Memcpy(entry->emailAddrs[i],&tmpbuf[2],nameLen);
- tmpbuf += 2 + nameLen;
+ PORT_Memcpy(entry->emailAddrs[i], tmpbuf, nameLen);
+ tmpbuf += nameLen;
}
+ if (tmpbuf != end)
+ goto loser;
}
-
-
+ PORT_ArenaUnmark(arena, mark);
return(SECSuccess);
loser:
+ PORT_ArenaRelease(arena, mark); /* discard above allocations */
return(SECFailure);
}
@@ -4277,7 +4297,7 @@ nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle,
{
DBT data;
DBT key;
- SECStatus rv;
+ SECStatus rv = SECSuccess;
int ret;
SECItem dataitem;
SECItem keyitem;
@@ -4304,13 +4324,16 @@ nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle,
/* type should equal keybuf[0]. */
rv = (* callback)(&dataitem, &keyitem, type, udata);
- if ( rv != SECSuccess ) {
- return(rv);
+ if ( rv == SECSuccess ) {
+ ++ret;
}
}
} while ( certdb_Seq(handle->permCertDB, &key, &data, R_NEXT) == 0 );
- return(SECSuccess);
+ /* If any callbacks succeeded, or no calls to callbacks were made,
+ * then report success. Otherwise, report failure.
+ */
+ return (ret ? SECSuccess : rv);
}
/*
* Decode a certificate and enter it into the temporary certificate database.
diff --git a/security/nss/lib/softoken/pcertt.h b/security/nss/lib/softoken/pcertt.h
index 848fe69e9..38a152414 100644
--- a/security/nss/lib/softoken/pcertt.h
+++ b/security/nss/lib/softoken/pcertt.h
@@ -166,6 +166,8 @@ struct NSSLOWCERTCertificateStr {
#define SEC_CRL_VERSION_1 0 /* default */
#define SEC_CRL_VERSION_2 1 /* v2 extensions */
+#define NSS_MAX_LEGACY_DB_KEY_SIZE (60 * 1024)
+
struct NSSLOWCERTIssuerAndSNStr {
SECItem derIssuer;
SECItem serialNumber;