Bug 486304: cert8.db "corruption" when importing a large certificate (>64K)

Patch, part 2, r=rrelyea,


git-svn-id: svn://10.0.0.236/trunk@256862 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
nelson%bolyard.com 2009-04-09 02:00:33 +00:00
parent 18113d7a39
commit 1feb852d58

View File

@ -37,7 +37,7 @@
/*
* Permanent Certificate database handling code
*
* $Id: pcertdb.c,v 1.8 2009-04-08 04:35:29 nelson%bolyard.com Exp $
* $Id: pcertdb.c,v 1.9 2009-04-09 02:00:33 nelson%bolyard.com Exp $
*/
#include "lowkeyti.h"
#include "pcert.h"
@ -1178,8 +1178,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);
@ -1188,20 +1189,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 ) {
@ -1213,15 +1213,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);
@ -1503,6 +1503,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);
@ -1511,12 +1513,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,
@ -1831,6 +1838,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);
@ -1838,15 +1847,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,