📄 dbck.c
字号:
if (subjectEntry2->emailAddr && PORT_Strcmp(subjectEntry1->emailAddr, subjectEntry2->emailAddr) == 0) { /* Found a subject using the same email address. */ subjectsForEmail[ns++] = i; } } /* Find the S/MIME entry for this email address. */ for (i=0; i<smime.numEntries; i++) { smimeEntry = (certDBEntrySMime*)&smime.entries[i]; if (smimeEntry->common.arena == NULL) continue; if (PORT_Strcmp(subjectEntry1->emailAddr, smimeEntry->emailAddr) == 0) { /* Find which of the subjects uses this S/MIME entry. */ for (j=0; j<ns && *subjectWithSMime < 0; j++) { sNum = subjectsForEmail[j]; subjectEntry2 = (certDBEntrySubject*)&subjects.entries[sNum]; if (SECITEM_ItemsAreEqual(&smimeEntry->subjectName, &subjectEntry2->derSubject)) { /* Found the subject corresponding to the S/MIME entry. */ *subjectWithSMime = sNum; *smimeForSubject = i; } } SEC_DestroyDBEntry((certDBEntry*)smimeEntry); PORT_Memset(smimeEntry, 0, sizeof(certDBEntry)); break; } } if (ns <= 1) return subjectNum; if (userCert) return *subjectWithSMime; /* Now find which of the subjects has the newest cert. */ certs = (CERTCertificate**)PORT_Alloc(ns*sizeof(CERTCertificate*)); certNums = (int*)PORT_Alloc((ns+1)*sizeof(int)); certNums[0] = 0; for (i=0; i<ns; i++) { sNum = subjectsForEmail[i]; subjectEntry1 = (certDBEntrySubject*)&subjects.entries[sNum]; certs[i] = CERT_FindCertByKey(handle, &subjectEntry1->certKeys[0]); certNums[i+1] = i; } /* Sort the array by validity. */ qsort(certs, ns, sizeof(CERTCertificate*), (int (*)(const void *, const void *))certIsOlder); newestSubject = -1; for (i=0; i<ns; i++) { sNum = subjectsForEmail[i]; subjectEntry1 = (certDBEntrySubject*)&subjects.entries[sNum]; if (SECITEM_ItemsAreEqual(&subjectEntry1->derSubject, &certs[0]->derSubject)) newestSubject = sNum; else SEC_DestroyDBEntry((certDBEntry*)subjectEntry1); } if (info && userSaysDeleteCert(certs, ns, dbOlderCert, info, certNums)) { for (i=1; i<ns+1; i++) { if (certNums[i] >= 0 && certNums[i] != certNums[0]) { deleteAllEntriesForCert(handle, certs[certNums[i]], info->out); info->dbErrors[dbOlderCert]++; } } } CERT_DestroyCertArray(certs, ns); return newestSubject;}CERTCertDBHandle *DBCK_ReconstructDBFromCerts(CERTCertDBHandle *oldhandle, char *newdbname, PRFileDesc *outfile, PRBool removeExpired, PRBool requireProfile, PRBool singleEntry, PRBool promptUser){ SECStatus rv; dbRestoreInfo info; certDBEntryContentVersion *oldContentVersion; certDBArray dbArray; int i; PORT_Memset(&dbArray, 0, sizeof(dbArray)); PORT_Memset(&info, 0, sizeof(info)); info.verbose = (outfile) ? PR_TRUE : PR_FALSE; info.out = (outfile) ? outfile : PR_STDOUT; info.removeType[dbInvalidCert] = removeExpired; info.removeType[dbNoSMimeProfile] = requireProfile; info.removeType[dbOlderCert] = singleEntry; info.promptUser[dbInvalidCert] = promptUser; info.promptUser[dbNoSMimeProfile] = promptUser; info.promptUser[dbOlderCert] = promptUser; /* Allocate a handle to fill with CERT_OpenCertDB below. */ info.handle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle)); if (!info.handle) { fprintf(stderr, "unable to get database handle"); return NULL; } /* Create a certdb with the most recent set of roots. */ rv = CERT_OpenCertDBFilename(info.handle, newdbname, PR_FALSE); if (rv) { fprintf(stderr, "could not open certificate database"); goto loser; } /* Create certificate, subject, nickname, and email records. * mcom_db seems to have a sequential access bug. Though reads and writes * should be allowed during traversal, they seem to screw up the sequence. * So, stuff all the cert entries into an array, and loop over the array * doing read/writes in the db. */ fillDBEntryArray(oldhandle, certDBEntryTypeCert, &dbArray.certs); for (elem = PR_LIST_HEAD(&dbArray->certs.link); elem != &dbArray->certs.link; elem = PR_NEXT_LINK(elem)) { node = LISTNODE_CAST(elem); addCertToDB((certDBEntryCert*)&node->entry, &info, oldhandle); /* entries get destroyed in addCertToDB */ }#if 0 rv = SEC_TraverseDBEntries(oldhandle, certDBEntryTypeSMimeProfile, copyDBEntry, info.handle);#endif /* Fix up the pointers between (nickname|S/MIME) --> (subject). * Create S/MIME entries for S/MIME certs. * Have the S/MIME entry point to the last-expiring cert using * an email address. */#if 0 CERT_RedoHandlesForSubjects(info.handle, singleEntry, &info);#endif freeDBEntryList(&dbArray.certs.link); /* Copy over the version record. */ /* XXX Already exists - and _must_ be correct... */ /* versionEntry = ReadDBVersionEntry(oldhandle); rv = WriteDBVersionEntry(info.handle, versionEntry); */ /* Copy over the content version record. */ /* XXX Can probably get useful info from old content version? * Was this db created before/after this tool? etc. */#if 0 oldContentVersion = ReadDBContentVersionEntry(oldhandle); CERT_SetDBContentVersion(oldContentVersion->contentVersion, info.handle); #endif#if 0 /* Copy over the CRL & KRL records. */ rv = SEC_TraverseDBEntries(oldhandle, certDBEntryTypeRevocation, copyDBEntry, info.handle); /* XXX Only one KRL, just do db->get? */ rv = SEC_TraverseDBEntries(oldhandle, certDBEntryTypeKeyRevocation, copyDBEntry, info.handle);#endif PR_fprintf(info.out, "Database had %d certificates.\n", info.nOldCerts); PR_fprintf(info.out, "Reconstructed %d certificates.\n", info.nCerts); PR_fprintf(info.out, "(ax) Rejected %d expired certificates.\n", info.dbErrors[dbInvalidCert]); PR_fprintf(info.out, "(as) Rejected %d S/MIME certificates missing a profile.\n", info.dbErrors[dbNoSMimeProfile]); PR_fprintf(info.out, "(ar) Rejected %d certificates for which a newer certificate was found.\n", info.dbErrors[dbOlderCert]); PR_fprintf(info.out, " Rejected %d corrupt certificates.\n", info.dbErrors[dbBadCertificate]); PR_fprintf(info.out, " Rejected %d certificates which did not write to the DB.\n", info.dbErrors[dbCertNotWrittenToDB]); if (rv) goto loser; return info.handle;loser: if (info.handle) PORT_Free(info.handle); return NULL;}#endif /* DORECOVER */enum { cmd_Debug = 0, cmd_LongUsage, cmd_Recover};enum { opt_KeepAll = 0, opt_CertDir, opt_Dumpfile, opt_InputDB, opt_OutputDB, opt_Mailfile, opt_Prompt, opt_KeepRedundant, opt_KeepNoSMimeProfile, opt_Verbose, opt_KeepExpired};static secuCommandFlag dbck_commands[] ={ { /* cmd_Debug, */ 'D', PR_FALSE, 0, PR_FALSE }, { /* cmd_LongUsage,*/ 'H', PR_FALSE, 0, PR_FALSE }, { /* cmd_Recover, */ 'R', PR_FALSE, 0, PR_FALSE }};static secuCommandFlag dbck_options[] ={ { /* opt_KeepAll, */ 'a', PR_FALSE, 0, PR_FALSE }, { /* opt_CertDir, */ 'd', PR_TRUE, 0, PR_FALSE }, { /* opt_Dumpfile, */ 'f', PR_TRUE, 0, PR_FALSE }, { /* opt_InputDB, */ 'i', PR_TRUE, 0, PR_FALSE }, { /* opt_OutputDB, */ 'o', PR_TRUE, 0, PR_FALSE }, { /* opt_Mailfile, */ 'm', PR_FALSE, 0, PR_FALSE }, { /* opt_Prompt, */ 'p', PR_FALSE, 0, PR_FALSE }, { /* opt_KeepRedundant, */ 'r', PR_FALSE, 0, PR_FALSE }, { /* opt_KeepNoSMimeProfile,*/ 's', PR_FALSE, 0, PR_FALSE }, { /* opt_Verbose, */ 'v', PR_FALSE, 0, PR_FALSE }, { /* opt_KeepExpired, */ 'x', PR_FALSE, 0, PR_FALSE }};int main(int argc, char **argv){ CERTCertDBHandle *certHandle; PRFileInfo fileInfo; PRFileDesc *mailfile = NULL; PRFileDesc *dumpfile = NULL; char * pathname = 0; char * fullname = 0; char * newdbname = 0; PRBool removeExpired, requireProfile, singleEntry; SECStatus rv; secuCommand dbck; dbck.numCommands = sizeof(dbck_commands) / sizeof(secuCommandFlag); dbck.numOptions = sizeof(dbck_options) / sizeof(secuCommandFlag); dbck.commands = dbck_commands; dbck.options = dbck_options; progName = strrchr(argv[0], '/'); progName = progName ? progName+1 : argv[0]; rv = SECU_ParseCommandLine(argc, argv, progName, &dbck); if (rv != SECSuccess) Usage(progName); if (dbck.commands[cmd_LongUsage].activated) LongUsage(progName); if (!dbck.commands[cmd_Debug].activated && !dbck.commands[cmd_Recover].activated) { PR_fprintf(PR_STDERR, "Please specify -D or -R.\n"); Usage(progName); } removeExpired = !(dbck.options[opt_KeepAll].activated || dbck.options[opt_KeepExpired].activated); requireProfile = !(dbck.options[opt_KeepAll].activated || dbck.options[opt_KeepNoSMimeProfile].activated); singleEntry = !(dbck.options[opt_KeepAll].activated || dbck.options[opt_KeepRedundant].activated); if (dbck.options[opt_OutputDB].activated) { newdbname = PL_strdup(dbck.options[opt_OutputDB].arg); } else { newdbname = PL_strdup("new_cert7.db"); } /* Create a generic graph of the database. */ if (dbck.options[opt_Mailfile].activated) { mailfile = PR_Open("./mailfile", PR_RDWR | PR_CREATE_FILE, 00660); if (!mailfile) { fprintf(stderr, "Unable to create mailfile.\n"); return -1; } } /* Dump all debugging info while running. */ if (dbck.options[opt_Verbose].activated) { if (dbck.options[opt_Dumpfile].activated) { dumpfile = PR_Open(dbck.options[opt_Dumpfile].arg, PR_RDWR | PR_CREATE_FILE, 00660); } if (!dumpfile) { fprintf(stderr, "Unable to create dumpfile.\n"); return -1; } } /* Set the cert database directory. */ if (dbck.options[opt_CertDir].activated) { SECU_ConfigDirectory(dbck.options[opt_CertDir].arg); } PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); SEC_Init(); certHandle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle)); if (!certHandle) { SECU_PrintError(progName, "unable to get database handle"); return -1; } /* Open the possibly corrupt database. */ if (dbck.options[opt_InputDB].activated) { pathname = SECU_ConfigDirectory(NULL); fullname = PR_smprintf("%s/%s", pathname, dbck.options[opt_InputDB].arg); if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) { fprintf(stderr, "Unable to read file \"%s\".\n", fullname); return -1; } rv = CERT_OpenCertDBFilename(certHandle, fullname, PR_TRUE); } else { /* Use the default. */ fullname = SECU_CertDBNameCallback(NULL, CERT_DB_FILE_VERSION); if (PR_GetFileInfo(fullname, &fileInfo) != PR_SUCCESS) { fprintf(stderr, "Unable to read file \"%s\".\n", fullname); return -1; } rv = CERT_OpenCertDB(certHandle, PR_TRUE, SECU_CertDBNameCallback, NULL); } if (rv) { SECU_PrintError(progName, "unable to open cert database"); return -1; } if (dbck.commands[cmd_Debug].activated) { DBCK_DebugDB(certHandle, dumpfile, mailfile); return 0; }#ifdef DORECOVER if (dbck.commands[cmd_Recover].activated) { DBCK_ReconstructDBFromCerts(certHandle, newdbname, dumpfile, removeExpired, requireProfile, singleEntry, dbck.options[opt_Prompt].activated); return 0; }#endif if (mailfile) PR_Close(mailfile); if (dumpfile) PR_Close(dumpfile); if (certHandle) { CERT_ClosePermCertDB(certHandle); PORT_Free(certHandle); } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -