Revert the cert8 upgrade code - the changes don't affect any other fixes NSS_3_3_4_1_BRANCH
authorsaul.edwards%sun.com
Thu, 11 Dec 2003 18:41:45 +0000
branchNSS_3_3_4_1_BRANCH
changeset 4924 1f9c1e921e3c5f3ab1612bdb42e6a1b6cc059f6e
parent 4923 6c9ab3e3b8583cd0211713806a62fab55318c089
child 4927 b98f290747fd7168edd0b4e9a75fba99c4d7c7d0
push idunknown
push userunknown
push dateunknown
Revert the cert8 upgrade code - the changes don't affect any other fixes between 3.3.4 and 3.3.7.
security/nss/lib/certdb/certdb.h
security/nss/lib/certdb/pcertdb.c
--- a/security/nss/lib/certdb/certdb.h
+++ b/security/nss/lib/certdb/certdb.h
@@ -36,18 +36,17 @@
 
 #include "plarena.h"
 #include "prlong.h"
 /*
  * Certificate Database related definitions and data structures
  */
 
 /* version number of certificate database */
-#define CERT_DB_FILE_VERSION		8
-#define CERT_DB_V7_FILE_VERSION		7
+#define CERT_DB_FILE_VERSION		7
 #ifdef USE_NS_ROOTS
 #define CERT_DB_CONTENT_VERSION		28
 #else
 #define CERT_DB_CONTENT_VERSION		2
 #endif
 
 #define SEC_DB_ENTRY_HEADER_LEN		3
 #define SEC_DB_KEY_HEADER_LEN		1
@@ -65,18 +64,17 @@
 typedef enum {
     certDBEntryTypeVersion = 0,
     certDBEntryTypeCert = 1,
     certDBEntryTypeNickname = 2,
     certDBEntryTypeSubject = 3,
     certDBEntryTypeRevocation = 4,
     certDBEntryTypeKeyRevocation = 5,
     certDBEntryTypeSMimeProfile = 6,
-    certDBEntryTypeContentVersion = 7,
-    certDBEntryTypeBlob = 8
+    certDBEntryTypeContentVersion = 7
 } certDBEntryType;
 
 typedef struct {
     certDBEntryType type;
     unsigned int version;
     unsigned int flags;
     PRArenaPool *arena;
 } certDBEntryCommon;
--- a/security/nss/lib/certdb/pcertdb.c
+++ b/security/nss/lib/certdb/pcertdb.c
@@ -233,21 +233,17 @@ ReadDBEntry(CERTCertDBHandle *handle, ce
     }
     
     /* validate the entry */
     if ( data.size < SEC_DB_ENTRY_HEADER_LEN ) {
 	PORT_SetError(SEC_ERROR_BAD_DATABASE);
 	goto loser;
     }
     buf = (unsigned char *)data.data;
-    /* version 7 uses the shame scheme, we may be using a v7 db if we
-     * opened the dbs readonly
-     */
-    if ( !((buf[0] == (unsigned char)CERT_DB_FILE_VERSION) ||
-           (buf[0] == (unsigned char)CERT_DB_V7_FILE_VERSION)) ) {
+    if ( buf[0] != (unsigned char)CERT_DB_FILE_VERSION ) {
 	PORT_SetError(SEC_ERROR_BAD_DATABASE);
 	goto loser;
     }
     if ( buf[1] != (unsigned char)entry->type ) {
 	PORT_SetError(SEC_ERROR_BAD_DATABASE);
 	goto loser;
     }
 
@@ -444,17 +440,16 @@ DecodeDBCertEntry(certDBEntryCert *entry
 	break;
       case 6:
 	/* should not get here */
 	PORT_Assert(0);
 	headerlen = DB_CERT_V6_ENTRY_HEADER_LEN;
 	lenoff = 3;
 	break;
       case 7:
-      case 8:
 	headerlen = DB_CERT_ENTRY_HEADER_LEN;
 	lenoff = 6;
 	break;
       default:
 	/* better not get here */
 	PORT_Assert(0);
 	headerlen = DB_CERT_V5_ENTRY_HEADER_LEN;
 	lenoff = 3;
@@ -3200,19 +3195,16 @@ RemovePermSubjectNode(CERTCertificate *c
 	    }
 	}
     } else {
 	/* no entries left, delete the perm entry in the DB */
 	if ( subjectList->entry->emailAddr ) {
 	    /* if the subject had an email record, then delete it too */
 	    DeleteDBSMimeEntry(cert->dbhandle, subjectList->entry->emailAddr);
 	}
-	if ( subjectList->entry->nickname ) {
-	    DeleteDBNicknameEntry(cert->dbhandle, subjectList->entry->nickname);
-	}
 	
 	DestroyDBEntry((certDBEntry *)subjectList->entry);
 	subjectList->entry = NULL;
 	DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject);
     }
 
     return(rv);
 }
@@ -3221,22 +3213,21 @@ RemovePermSubjectNode(CERTCertificate *c
  * add a cert to the perm subject list
  */
 static SECStatus
 AddPermSubjectNode(CERTCertificate *cert, char *nickname)
 {
     CERTSubjectList *subjectList;
     certDBEntrySubject *entry;
     SECItem *newCertKeys, *newKeyIDs;
-    int i, new_i;
+    int i;
     SECStatus rv;
     CERTCertificate *cmpcert;
     unsigned int nnlen;
     int ncerts;
-    PRBool added = PR_FALSE;
     
     subjectList = cert->subjectList;
     
     PORT_Assert(subjectList);
     if ( subjectList == NULL ) {
 	return(SECFailure);
     }
 
@@ -3268,79 +3259,71 @@ AddPermSubjectNode(CERTCertificate *cert
 	newKeyIDs = (SECItem *)PORT_ArenaAlloc(entry->common.arena,
 					       sizeof(SECItem) *
 					       ( ncerts + 1 ) );
 
 	if ( ( newCertKeys == NULL ) || ( newKeyIDs == NULL ) ) {
 	    return(SECFailure);
 	}
 
-	for ( i = 0, new_i = 0; i < ncerts; i++ ) {
+	for ( i = 0; i < ncerts; i++ ) {
 	    cmpcert = CERT_FindCertByKeyNoLocking(cert->dbhandle,
 						  &entry->certKeys[i]);
 	    PORT_Assert(cmpcert);
-	    /* The entry has been corrupted, remove it from the list */
-	    if (!cmpcert) {
-		continue;
-	    }
 	    
 	    if ( CERT_IsNewer(cert, cmpcert) ) {
 		/* insert before cmpcert */
-		rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[new_i],
+		rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[i],
 				      &cert->certKey);
 		if ( rv != SECSuccess ) {
 		    return(SECFailure);
 		}
-		rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[new_i],
+		rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[i],
 				      &cert->subjectKeyID);
 		if ( rv != SECSuccess ) {
 		    return(SECFailure);
 		}
-		new_i++;
-		/* copy the rest of the entries */
-		for ( ; i < ncerts; i++, new_i++ ) {
-		    newCertKeys[new_i] = entry->certKeys[i];
-		    newKeyIDs[new_i] = entry->keyIDs[i];
+		/* copy the rest of the entry */
+		for ( ; i < ncerts; i++ ) {
+		    newCertKeys[i+1] = entry->certKeys[i];
+		    newKeyIDs[i+1] = entry->keyIDs[i];
 		}
 
 		/* update certKeys and keyIDs */
 		entry->certKeys = newCertKeys;
 		entry->keyIDs = newKeyIDs;
 		
 		/* increment count */
-		entry->ncerts = new_i;
-		added = PR_TRUE;
+		entry->ncerts++;
 		break;
 	    }
 	    /* copy this cert entry */
-	    newCertKeys[new_i] = entry->certKeys[i];
-	    newKeyIDs[new_i] = entry->keyIDs[i];
-	    new_i++;
+	    newCertKeys[i] = entry->certKeys[i];
+	    newKeyIDs[i] = entry->keyIDs[i];
 	}
 
-	if ( !added ) {
+	if ( entry->ncerts == ncerts ) {
 	    /* insert new one at end */
-	    rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[new_i],
+	    rv = SECITEM_CopyItem(entry->common.arena, &newCertKeys[ncerts],
 				  &cert->certKey);
 	    if ( rv != SECSuccess ) {
 		return(SECFailure);
 	    }
-	    rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[new_i],
+	    rv = SECITEM_CopyItem(entry->common.arena, &newKeyIDs[ncerts],
 				  &cert->subjectKeyID);
 	    if ( rv != SECSuccess ) {
 		return(SECFailure);
 	    }
-	    new_i++;
 
 	    /* update certKeys and keyIDs */
 	    entry->certKeys = newCertKeys;
 	    entry->keyIDs = newKeyIDs;
 		
 	    /* increment count */
-	    entry->ncerts = new_i;
+	    entry->ncerts++;
 	}
     } else {
 	/* need to make a new DB entry */
 	entry = NewDBSubjectEntry(&cert->derSubject, &cert->certKey,
 				  &cert->subjectKeyID, nickname,
 				  NULL, 0);
 	cert->subjectList->entry = entry;
     }
@@ -3369,17 +3352,16 @@ SECStatus
     entry = ReadDBSubjectEntry(handle, derSubject);
 
     if ( entry == NULL ) {
 	return(SECFailure);
     }
     
     for( i = 0; i < entry->ncerts; i++ ) {
 	cert = CERT_FindCertByKey(handle, &entry->certKeys[i]);
-	if (!cert) continue;
 	rv = (* cb)(cert, cbarg);
 	CERT_DestroyCertificate(cert);
 	if ( rv == SECFailure ) {
 	    break;
 	}
     }
 
     DestroyDBEntry((certDBEntry *)entry);
@@ -3618,19 +3600,24 @@ loser:
  */
 SECStatus
 CERT_AddPermNickname(CERTCertificate *cert, char *nickname)
 {
     SECStatus rv;
     
     CERT_LockDB(cert->dbhandle);
     
+    PORT_Assert(cert->nickname == NULL);
     PORT_Assert(cert->isperm);
     PORT_Assert(cert->subjectList != NULL);
     PORT_Assert(cert->subjectList->entry != NULL);
+    
+    if ( cert->nickname != NULL ) {
+	goto done;
+    }
 
     if ( cert->subjectList == NULL ) {
 	goto loser;
     }
     
     if ( cert->subjectList->entry == NULL ) {
 	goto loser;
     }
@@ -3654,16 +3641,17 @@ CERT_AddPermNickname(CERTCertificate *ce
     } else {
 	/* subject already has a nickname */
 	rv = AddNicknameToPermCert(cert, cert->subjectList->entry->nickname);
 	if ( rv != SECSuccess ) {
 	    goto loser;
 	}
     }
 
+done:
     CERT_UnlockDB(cert->dbhandle);
     return(SECSuccess);
 loser:
     CERT_UnlockDB(cert->dbhandle);
     return(SECFailure);
 }
 
 static certDBEntryCert *
@@ -3774,154 +3762,16 @@ loser:
     }
     if ( subjectEntry ) {
 	DestroyDBEntry((certDBEntry *)subjectEntry);
     }
 
     return(NULL);
 }
 
-/* forward declaration */
-static SECStatus
-UpdateV7DB(CERTCertDBHandle *handle, DB *updatedb);
-
-/*
- * version 8 uses the same schema as version 7. The only differences are
- * 1) version 8 db uses the blob shim to store data entries > 32k.
- * 2) version 8 db sets the db block size to 32k.
- * both of these are dealt with by the handle.
- */
-
-static SECStatus
-UpdateV8DB(CERTCertDBHandle *handle, DB *updatedb)
-{
-    return UpdateV7DB(handle,updatedb);
-}
-
-
-/*
- * we could just blindly sequence through reading key data pairs and writing
- * them back out, but some cert.db's have gotten quite large and may have some
- * subtle corruption problems, so instead we cycle through the certs and
- * CRL's and S/MIME profiles and rebuild our subject lists from those records.
- */
-static SECStatus
-UpdateV7DB(CERTCertDBHandle *handle, DB *updatedb)
-{
-    DBT key, data;
-    int ret;
-    CERTCertificate *cert;
-    PRBool isKRL = PR_FALSE;
-    certDBEntryType entryType;
-    SECItem dbEntry, dbKey;
-    certDBEntryRevocation crlEntry;
-    certDBEntryCert certEntry;
-    certDBEntrySMime smimeEntry;
-    SECStatus rv;
-
-    ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST);
-
-    if ( ret ) {
-	return(SECFailure);
-    }
-    
-    do {
-	unsigned char *dataBuf = (unsigned char *)data.data;
-	unsigned char *keyBuf = (unsigned char *)key.data;
-	dbEntry.data = &dataBuf[SEC_DB_ENTRY_HEADER_LEN];
-	dbEntry.len = data.size - SEC_DB_ENTRY_HEADER_LEN;
- 	entryType = (certDBEntryType) keyBuf[0];
-	dbKey.data = &keyBuf[SEC_DB_KEY_HEADER_LEN];
-	dbKey.len = key.size - SEC_DB_KEY_HEADER_LEN;
-	if ((dbEntry.len <= 0) || (dbKey.len <= 0)) {
-	    continue;
-	}
-
-	switch (entryType) {
-	/* these entries will get regenerated as we read the 
-	 * rest of the data from the database */
-	case certDBEntryTypeVersion:
-	case certDBEntryTypeSubject:
-	case certDBEntryTypeContentVersion:
-	case certDBEntryTypeNickname:
-	/*default: */
-	    break;
-
-	case certDBEntryTypeCert:
-	    /* decode Entry */
-    	    certEntry.common.version = (unsigned int)dataBuf[0];
-	    certEntry.common.type = entryType;
-	    certEntry.common.flags = (unsigned int)dataBuf[2];
-	    certEntry.common.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-	    if (certEntry.common.arena == NULL) {
-		break;
-	    }
-	    rv = DecodeDBCertEntry(&certEntry,&dbEntry);
-	    if (rv != SECSuccess) {
-		break;
-	    }
-	    /* should we check for existing duplicates? */
-	    cert = CERT_DecodeDERCertificate(&certEntry.derCert, PR_FALSE,
-	                                     certEntry.nickname);
-	    if (cert) {
-		AddCertToPermDB(handle, cert, certEntry.nickname,
-		                &certEntry.trust);
-		CERT_DestroyCertificate(cert);
-	    }
-	    /* free data allocated by the decode */
-	    PORT_FreeArena(certEntry.common.arena, PR_FALSE);
-	    certEntry.common.arena = NULL;
-	    break;
-
-	case certDBEntryTypeKeyRevocation:
-	    isKRL = PR_TRUE;
-	    /* fall through */
-	case certDBEntryTypeRevocation:
-    	    crlEntry.common.version = (unsigned int)dataBuf[0];
-	    crlEntry.common.type = entryType;
-	    crlEntry.common.flags = (unsigned int)dataBuf[2];
-	    crlEntry.common.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-	    if (crlEntry.common.arena == NULL) {
-		break;
-	    }
-	    rv = DecodeDBCrlEntry(&crlEntry,&dbEntry);
-	    if (rv != SECSuccess) {
-		break;
-	    }
-
-	    rv = WriteDBCrlEntry(handle, &crlEntry);
-	    if (rv != SECSuccess) {
-		break;
-	    }
-	    /* free data allocated by the decode */
-	    PORT_FreeArena(crlEntry.common.arena, PR_FALSE);
-	    crlEntry.common.arena = NULL;
-	    break;
-
-	case certDBEntryTypeSMimeProfile:
-    	    smimeEntry.common.version = (unsigned int)dataBuf[0];
-	    smimeEntry.common.type = entryType;
-	    smimeEntry.common.flags = (unsigned int)dataBuf[2];
-	    smimeEntry.common.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-	    rv = DecodeDBSMimeEntry(&smimeEntry,&dbEntry,(char *)dbKey.data);
-	    /* decode entry */
-	    WriteDBSMimeEntry(handle, &smimeEntry);
-	    PORT_FreeArena(smimeEntry.common.arena, PR_FALSE);
-	    smimeEntry.common.arena = NULL;
-	    break;
-	}
-    } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 );
-
-    (* updatedb->close)(updatedb);
-
-    /* a database update is a good time to go back and verify the integrity of
-     * the keys and certs */
-    return(SECSuccess);
-}
-
 /*
  * NOTE - Version 6 DB did not go out to the real world in a release,
  * so we can remove this function in a later release.
  */
 static SECStatus
 UpdateV6DB(CERTCertDBHandle *handle, DB *updatedb)
 {
     int ret;
@@ -4399,17 +4249,17 @@ SEC_OpenPermCertDB(CERTCertDBHandle *han
 	openflags = O_RDONLY;
     } else {
 	openflags = O_RDWR;
     }
     
     /*
      * first open the permanent file based database.
      */
-    handle->permCertDB = dbsopen( certdbname, openflags, 0600, DB_HASH, 0 );
+    handle->permCertDB = dbopen( certdbname, openflags, 0600, DB_HASH, 0 );
 
     /* check for correct version number */
     if ( handle->permCertDB ) {
 	versionEntry = ReadDBVersionEntry(handle);
 
 	if ( versionEntry == NULL ) {
 	    /* no version number */
 	    certdb_Close(handle->permCertDB);
@@ -4422,44 +4272,24 @@ SEC_OpenPermCertDB(CERTCertDBHandle *han
 	}
 
     }
 
 
     /* if first open fails, try to create a new DB */
     if ( handle->permCertDB == NULL ) {
 
+	/* don't create if readonly */
 	if ( readOnly ) {
-	    /* if opening read-only and cert8.db does not exist, 
-	     * use cert7.db
-	     */
-	    tmpname = (* namecb)(cbarg, 7); /* get v7 db name */
-	    if (!tmpname) {
-		goto loser;
-	    }
-	    handle->permCertDB = dbopen(tmpname, O_RDONLY, 0600, DB_HASH, 0);
-	    PORT_Free(tmpname);
-	    if (!handle->permCertDB) {
-		goto loser;
-	    }
-	    versionEntry = ReadDBVersionEntry(handle);
-	    if ( versionEntry == NULL ) {
-		/* no version number */
-		goto loser;
-	    } else if ( versionEntry->common.version != 7 ) {
-		DestroyDBEntry((certDBEntry *)versionEntry);
-		goto loser;
-	    }
-	    PORT_Free(certdbname);
-	    return SECSuccess;
+	    goto loser;
 	}
-	/* create a new database */
-	handle->permCertDB = dbsopen(certdbname,
-                                     O_RDWR | O_CREAT | O_TRUNC,
-                                     0600, DB_HASH, 0);
+	
+	handle->permCertDB = dbopen(certdbname,
+				    O_RDWR | O_CREAT | O_TRUNC,
+				    0600, DB_HASH, 0);
 
 	/* if create fails then we lose */
 	if ( handle->permCertDB == 0 ) {
 	    goto loser;
 	}
 
 	versionEntry = NewDBVersionEntry(0);
 	if ( versionEntry == NULL ) {
@@ -4468,32 +4298,17 @@ SEC_OpenPermCertDB(CERTCertDBHandle *han
 	
 	rv = WriteDBVersionEntry(handle, versionEntry);
 
 	DestroyDBEntry((certDBEntry *)versionEntry);
 
 	if ( rv != SECSuccess ) {
 	    goto loser;
 	}
-#if 0 /* in this 3.3.4.x version, we want to avoid upgrading 7 to 8 */
-	/* try to upgrade old db here */
-	tmpname = (* namecb)(cbarg, 7);	/* get v7 db name */
-	if ( tmpname ) {
-	    updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 );
-	    PORT_Free(tmpname);
-	    if ( updatedb ) {
-		rv = UpdateV7DB(handle, updatedb);
-		if ( rv != SECSuccess ) {
-		    goto loser;
-		}
-		updated = PR_TRUE;
-		goto update_finished;
-	    }
-	}
-#endif
+
 	/* try to upgrade old db here */
 	tmpname = (* namecb)(cbarg, 6);	/* get v6 db name */
 	if ( tmpname ) {
 	    updatedb = dbopen( tmpname, O_RDONLY, 0600, DB_HASH, 0 );
 	    PORT_Free(tmpname);
 	    if ( updatedb ) {
 		rv = UpdateV6DB(handle, updatedb);
 		if ( rv != SECSuccess ) {
@@ -4531,17 +4346,16 @@ SEC_OpenPermCertDB(CERTCertDBHandle *han
 				forceUpdate = PR_TRUE;
 				updated = PR_TRUE;
 			    }
 			}
 		    }
 		}
 	    }
 	}
-update_finished:
 
 	/* initialize the database with our well known certificates
 	 * or in the case of update, just fall down to CERT_AddNewCerts()
 	 * below.
 	 * Note - if we are updating a really old database, then we try
 	 * to push all of the certs into it.
 	 */
 	if ( ( !updated ) || forceUpdate ) {
@@ -4582,17 +4396,24 @@ DeletePermCert(CERTCertificate *cert)
     SECStatus ret;
 
     ret = SECSuccess;
     
     rv = DeleteDBCertEntry(cert->dbhandle, &cert->certKey);
     if ( rv != SECSuccess ) {
 	ret = SECFailure;
     }
-
+    
+    if ( cert->nickname ) {
+	rv = DeleteDBNicknameEntry(cert->dbhandle, cert->nickname);
+	if ( rv != SECSuccess ) {
+	    ret = SECFailure;
+	}
+    }
+    
     rv = RemovePermSubjectNode(cert);
 
     return(ret);
 }
 
 /*
  * Delete a certificate from the permanent database.
  */
@@ -4860,20 +4681,16 @@ void
 		PORT_Assert(handle->statusConfig->statusDestroy != NULL);
 		(void) (* handle->statusConfig->statusDestroy)(handle->statusConfig);
 		handle->statusConfig = NULL; /* Destroy frees the structure */
 		PORT_Assert(handle->statusConfig == NULL);
 	    }
 	    certdb_Close( handle->permCertDB );
 	    handle->permCertDB = 0;
 	}
-	if (handle->dbMon) {
-	    PZ_DestroyMonitor(handle->dbMon);
-	    handle->dbMon = NULL;
-	}
     }
     return;
 }
 
 void
 CERT_ClosePermCertDB(CERTCertDBHandle *handle)
 {
     __CERT_ClosePermCertDB(handle);