📄 dbck.c
字号:
if (outfile) { PR_fprintf(outfile, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n"); PR_fprintf(outfile, "Deleting redundant certificate:\n"); dumpCertificate(cert, -1, outfile); } CERT_TraverseCertsForSubject(handle, cert->subjectList, deleteit, NULL);#if 0 CERT_LockDB(handle); subjectEntry = ReadDBSubjectEntry(handle, &cert->derSubject); /* It had better be there, or created a bad db. */ PORT_Assert(subjectEntry); for (i=0; i<subjectEntry->ncerts; i++) { DeleteDBCertEntry(handle, &subjectEntry->certKeys[i]); } DeleteDBSubjectEntry(handle, &cert->derSubject); if (subjectEntry->emailAddr) { smimeEntry = ReadDBSMimeEntry(handle, subjectEntry->emailAddr); if (smimeEntry) { if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject, &smimeEntry->subjectName)) /* Only delete it if it's for this subject! */ DeleteDBSMimeEntry(handle, subjectEntry->emailAddr); SEC_DestroyDBEntry((certDBEntry*)smimeEntry); } } if (subjectEntry->nickname) { nicknameEntry = ReadDBNicknameEntry(handle, subjectEntry->nickname); if (nicknameEntry) { if (SECITEM_ItemsAreEqual(&subjectEntry->derSubject, &nicknameEntry->subjectName)) /* Only delete it if it's for this subject! */ DeleteDBNicknameEntry(handle, subjectEntry->nickname); SEC_DestroyDBEntry((certDBEntry*)nicknameEntry); } } SEC_DestroyDBEntry((certDBEntry*)subjectEntry); CERT_UnlockDB(handle);#endif return SECSuccess;}voidgetCertsToDelete(char *numlist, int len, int *certNums, int nCerts){ int j, num; char *numstr, *numend, *end; numstr = numlist; end = numstr + len - 1; while (numstr != end) { numend = strpbrk(numstr, ", \n"); *numend = '\0'; if (PORT_Strlen(numstr) == 0) return; num = PORT_Atoi(numstr); if (numstr == numlist) certNums[0] = num; for (j=1; j<nCerts+1; j++) { if (num == certNums[j]) { certNums[j] = -1; break; } } if (numend == end) break; numstr = strpbrk(numend+1, "0123456789"); }}PRBooluserSaysDeleteCert(CERTCertificate **certs, int nCerts, int errtype, dbRestoreInfo *info, int *certNums){ char response[32]; int32 nb; int i; /* User wants to remove cert without prompting. */ if (info->promptUser[errtype] == PR_FALSE) return (info->removeType[errtype]); switch (errtype) { case dbInvalidCert: PR_fprintf(PR_STDOUT, "******** Expired ********\n"); PR_fprintf(PR_STDOUT, "Cert has expired.\n\n"); dumpCertificate(certs[0], -1, PR_STDOUT); PR_fprintf(PR_STDOUT, "Keep it? (y/n - this one, Y/N - all expired certs) [n] "); break; case dbNoSMimeProfile: PR_fprintf(PR_STDOUT, "******** No Profile ********\n"); PR_fprintf(PR_STDOUT, "S/MIME cert has no profile.\n\n"); dumpCertificate(certs[0], -1, PR_STDOUT); PR_fprintf(PR_STDOUT, "Keep it? (y/n - this one, Y/N - all S/MIME w/o profile) [n] "); break; case dbOlderCert: PR_fprintf(PR_STDOUT, "******* Redundant nickname/email *******\n\n"); PR_fprintf(PR_STDOUT, "These certs have the same nickname/email:\n"); for (i=0; i<nCerts; i++) dumpCertificate(certs[i], i, PR_STDOUT); PR_fprintf(PR_STDOUT, "Enter the certs you would like to keep from those listed above.\n"); PR_fprintf(PR_STDOUT, "Use a comma-separated list of the cert numbers (ex. 0, 8, 12).\n"); PR_fprintf(PR_STDOUT, "The first cert in the list will be the primary cert\n"); PR_fprintf(PR_STDOUT, " accessed by the nickname/email handle.\n"); PR_fprintf(PR_STDOUT, "List cert numbers to keep here, or hit enter\n"); PR_fprintf(PR_STDOUT, " to always keep only the newest cert: "); break; default: } nb = PR_Read(PR_STDIN, response, sizeof(response)); PR_fprintf(PR_STDOUT, "\n\n"); if (errtype == dbOlderCert) { if (!isdigit(response[0])) { info->promptUser[errtype] = PR_FALSE; info->removeType[errtype] = PR_TRUE; return PR_TRUE; } getCertsToDelete(response, nb, certNums, nCerts); return PR_TRUE; } /* User doesn't want to be prompted for this type anymore. */ if (response[0] == 'Y') { info->promptUser[errtype] = PR_FALSE; info->removeType[errtype] = PR_FALSE; return PR_FALSE; } else if (response[0] == 'N') { info->promptUser[errtype] = PR_FALSE; info->removeType[errtype] = PR_TRUE; return PR_TRUE; } return (response[0] != 'y') ? PR_TRUE : PR_FALSE;}SECStatusaddCertToDB(certDBEntryCert *certEntry, dbRestoreInfo *info, CERTCertDBHandle *oldhandle){ SECStatus rv = SECSuccess; PRBool allowOverride; PRBool userCert; SECCertTimeValidity validity; CERTCertificate *oldCert = NULL; CERTCertificate *dbCert = NULL; CERTCertificate *newCert = NULL; CERTCertTrust *trust; certDBEntrySMime *smimeEntry = NULL; char *email = NULL; char *nickname = NULL; int nCertsForSubject = 1; oldCert = CERT_DecodeDERCertificate(&certEntry->derCert, PR_FALSE, certEntry->nickname); if (!oldCert) { info->dbErrors[dbBadCertificate]++; SEC_DestroyDBEntry((certDBEntry*)certEntry); return SECSuccess; } oldCert->dbEntry = certEntry; oldCert->trust = &certEntry->trust; oldCert->dbhandle = oldhandle; trust = oldCert->trust; info->nOldCerts++; if (info->verbose) PR_fprintf(info->out, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n"); if (oldCert->nickname) nickname = PORT_Strdup(oldCert->nickname); /* Always keep user certs. Skip ahead. */ /* XXX if someone sends themselves a signed message, it is possible for their cert to be imported as an "other" cert, not a user cert. this mucks with smime entries... */ userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) || (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) || (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER); if (userCert) goto createcert; /* If user chooses so, ignore expired certificates. */ allowOverride = (PRBool)((oldCert->keyUsage == certUsageSSLServer) || (oldCert->keyUsage == certUsageSSLServerWithStepUp)); validity = CERT_CheckCertValidTimes(oldCert, PR_Now(), allowOverride); /* If cert expired and user wants to delete it, ignore it. */ if ((validity != secCertTimeValid) && userSaysDeleteCert(&oldCert, 1, dbInvalidCert, info, 0)) { info->dbErrors[dbInvalidCert]++; if (info->verbose) { PR_fprintf(info->out, "Deleting expired certificate:\n"); dumpCertificate(oldCert, -1, info->out); } goto cleanup; } /* New database will already have default certs, don't attempt to overwrite them. */ dbCert = CERT_FindCertByDERCert(info->handle, &oldCert->derCert); if (dbCert) { info->nCerts++; if (info->verbose) { PR_fprintf(info->out, "Added certificate to database:\n"); dumpCertificate(oldCert, -1, info->out); } goto cleanup; } /* Determine if cert is S/MIME and get its email if so. */ email = IsEmailCert(oldCert); /* XXX Just create empty profiles? if (email) { SECItem *profile = CERT_FindSMimeProfile(oldCert); if (!profile && userSaysDeleteCert(&oldCert, 1, dbNoSMimeProfile, info, 0)) { info->dbErrors[dbNoSMimeProfile]++; if (info->verbose) { PR_fprintf(info->out, "Deleted cert missing S/MIME profile.\n"); dumpCertificate(oldCert, -1, info->out); } goto cleanup; } else { SECITEM_FreeItem(profile); } } */createcert: /* Sometimes happens... */ if (!nickname && userCert) nickname = PORT_Strdup(oldCert->subjectName); /* Create a new certificate, copy of the old one. */ newCert = CERT_NewTempCertificate(info->handle, &oldCert->derCert, nickname, PR_FALSE, PR_TRUE); if (!newCert) { PR_fprintf(PR_STDERR, "Unable to create new certificate.\n"); dumpCertificate(oldCert, -1, PR_STDERR); info->dbErrors[dbBadCertificate]++; goto cleanup; } /* Add the cert to the new database. */ rv = CERT_AddTempCertToPerm(newCert, nickname, oldCert->trust); if (rv) { PR_fprintf(PR_STDERR, "Failed to write temp cert to perm database.\n"); dumpCertificate(oldCert, -1, PR_STDERR); info->dbErrors[dbCertNotWrittenToDB]++; goto cleanup; } if (info->verbose) { PR_fprintf(info->out, "Added certificate to database:\n"); dumpCertificate(oldCert, -1, info->out); } /* If the cert is an S/MIME cert, and the first with it's subject, * modify the subject entry to include the email address, * CERT_AddTempCertToPerm does not do email addresses and S/MIME entries. */ if (smimeEntry) { /*&& !userCert && nCertsForSubject == 1) { */#if 0 UpdateSubjectWithEmailAddr(newCert, email);#endif SECItem emailProfile, profileTime; rv = CERT_FindFullSMimeProfile(oldCert, &emailProfile, &profileTime); /* calls UpdateSubjectWithEmailAddr */ if (rv == SECSuccess) rv = CERT_SaveSMimeProfile(newCert, &emailProfile, &profileTime); } info->nCerts++;cleanup: if (nickname) PORT_Free(nickname); if (email) PORT_Free(email); if (oldCert) CERT_DestroyCertificate(oldCert); if (dbCert) CERT_DestroyCertificate(dbCert); if (newCert) CERT_DestroyCertificate(newCert); if (smimeEntry) SEC_DestroyDBEntry((certDBEntry*)smimeEntry); return SECSuccess;}#if 0SECStatuscopyDBEntry(SECItem *data, SECItem *key, certDBEntryType type, void *pdata){ SECStatus rv; CERTCertDBHandle *newdb = (CERTCertDBHandle *)pdata; certDBEntryCommon common; SECItem dbkey; common.type = type; common.version = CERT_DB_FILE_VERSION; common.flags = data->data[2]; common.arena = NULL; dbkey.len = key->len + SEC_DB_KEY_HEADER_LEN; dbkey.data = (unsigned char *)PORT_Alloc(dbkey.len*sizeof(unsigned char)); PORT_Memcpy(&dbkey.data[SEC_DB_KEY_HEADER_LEN], key->data, key->len); dbkey.data[0] = type; rv = WriteDBEntry(newdb, &common, &dbkey, data); PORT_Free(dbkey.data); return rv;}#endifintcertIsOlder(CERTCertificate **cert1, CERTCertificate** cert2){ return !CERT_IsNewer(*cert1, *cert2);}intfindNewestSubjectForEmail(CERTCertDBHandle *handle, int subjectNum, certDBArray *dbArray, dbRestoreInfo *info, int *subjectWithSMime, int *smimeForSubject){ int newestSubject; int subjectsForEmail[50]; int i, j, ns, sNum; certDBEntryListNode *subjects = &dbArray->subjects; certDBEntryListNode *smime = &dbArray->smime; certDBEntrySubject *subjectEntry1, *subjectEntry2; certDBEntrySMime *smimeEntry; CERTCertificate **certs; CERTCertificate *cert; CERTCertTrust *trust; PRBool userCert; int *certNums; ns = 0; subjectEntry1 = (certDBEntrySubject*)&subjects.entries[subjectNum]; subjectsForEmail[ns++] = subjectNum; *subjectWithSMime = -1; *smimeForSubject = -1; newestSubject = subjectNum; cert = CERT_FindCertByKey(handle, &subjectEntry1->certKeys[0]); if (cert) { trust = cert->trust; userCert = (SEC_GET_TRUST_FLAGS(trust, trustSSL) & CERTDB_USER) || (SEC_GET_TRUST_FLAGS(trust, trustEmail) & CERTDB_USER) || (SEC_GET_TRUST_FLAGS(trust, trustObjectSigning) & CERTDB_USER); CERT_DestroyCertificate(cert); } /* Loop over the remaining subjects. */ for (i=subjectNum+1; i<subjects.numEntries; i++) { subjectEntry2 = (certDBEntrySubject*)&subjects.entries[i]; if (!subjectEntry2) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -