diff --git a/lib/softoken/legacydb/pcertdb.c b/lib/softoken/legacydb/pcertdb.c --- a/lib/softoken/legacydb/pcertdb.c +++ b/lib/softoken/legacydb/pcertdb.c @@ -4272,16 +4272,17 @@ CreateTrust(void) { NSSLOWCERTTrust *trust = NULL; nsslowcert_LockFreeList(); trust = trustListHead; if (trust) { trustListCount--; trustListHead = trust->next; + trust->next = NULL; } PORT_Assert(trustListCount >= 0); nsslowcert_UnlockFreeList(); if (trust) { return trust; } return PORT_ZNew(NSSLOWCERTTrust); @@ -5155,19 +5156,21 @@ done: } PRBool nsslowcert_hasTrust(NSSLOWCERTCertTrust *trust) { if (trust == NULL) { return PR_FALSE; } - return !((trust->sslFlags & CERTDB_TRUSTED_UNKNOWN) && - (trust->emailFlags & CERTDB_TRUSTED_UNKNOWN) && - (trust->objectSigningFlags & CERTDB_TRUSTED_UNKNOWN)); + /* if we only have CERTDB__USER and CERTDB_TRUSTED_UNKNOWN bits, then + * we don't have a trust record. */ + return !(((trust->sslFlags & ~(CERTDB_USER|CERTDB_TRUSTED_UNKNOWN)) == 0) && + ((trust->emailFlags & ~(CERTDB_USER|CERTDB_TRUSTED_UNKNOWN)) == 0) && + ((trust->objectSigningFlags & ~(CERTDB_USER|CERTDB_TRUSTED_UNKNOWN)) == 0)); } /* * This function has the logic that decides if another person's cert and * email profile from an S/MIME message should be saved. It can deal with * the case when there is no profile. */ static SECStatus diff --git a/lib/softoken/sftkdb.c b/lib/softoken/sftkdb.c --- a/lib/softoken/sftkdb.c +++ b/lib/softoken/sftkdb.c @@ -119,47 +119,79 @@ sftkdb_isAuthenticatedAttribute(CK_ATTRI case CKA_TRUST_STEP_UP_APPROVED: case CKA_NSS_OVERRIDE_EXTENSIONS: return PR_TRUE; default: break; } return PR_FALSE; } - /* * convert a native ULONG to a database ulong. Database ulong's * are all 4 byte big endian values. */ void sftk_ULong2SDBULong(unsigned char *data, CK_ULONG value) { int i; for (i = 0; i < SDB_ULONG_SIZE; i++) { data[i] = (value >> (SDB_ULONG_SIZE - 1 - i) * BBP) & 0xff; } } /* * convert a database ulong back to a native ULONG. (reverse of the above - * function. + * function). */ static CK_ULONG sftk_SDBULong2ULong(unsigned char *data) { int i; CK_ULONG value = 0; for (i = 0; i < SDB_ULONG_SIZE; i++) { value |= (((CK_ULONG)data[i]) << (SDB_ULONG_SIZE - 1 - i) * BBP); } return value; } +/* certain trust records are default values, which are the values + * returned if the signature check fails anyway. + * In those cases, we can skip the signature check. */ +PRBool +sftkdb_isNullTrust(const CK_ATTRIBUTE *template) +{ + switch (template->type) { + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_CODE_SIGNING: + if (template->ulValueLen != SDB_ULONG_SIZE) { + break; + } + if (sftk_SDBULong2ULong(template->pValue) == + CKT_NSS_TRUST_UNKNOWN) { + return PR_TRUE; + } + break; + case CKA_TRUST_STEP_UP_APPROVED: + if (template->ulValueLen != 1) { + break; + } + if (*((unsigned char *)(template->pValue)) == 0) { + return PR_TRUE; + } + break; + default: + break; + } + return PR_FALSE; +} + /* * fix up the input templates. Our fixed up ints are stored in data and must * be freed by the caller. The new template must also be freed. If there are no * CK_ULONG attributes, the orignal template is passed in as is. */ static CK_ATTRIBUTE * sftkdb_fixupTemplateIn(const CK_ATTRIBUTE *template, int count, unsigned char **dataOut, int *dataOutSize) @@ -410,17 +442,18 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *te } /* copy the plain text back into the template */ PORT_Memcpy(template[i].pValue, plainText->data, plainText->len); template[i].ulValueLen = plainText->len; SECITEM_ZfreeItem(plainText, PR_TRUE); } /* make sure signed attributes are valid */ - if (checkSig && sftkdb_isAuthenticatedAttribute(ntemplate[i].type)) { + if (checkSig && sftkdb_isAuthenticatedAttribute(ntemplate[i].type) + && !sftkdb_isNullTrust(&ntemplate[i])) { SECStatus rv; CK_RV local_crv; SECItem signText; SECItem plainText; unsigned char signData[SDB_MAX_META_DATA_LEN]; signText.data = signData; signText.len = sizeof(signData); @@ -2387,16 +2420,18 @@ sftkdb_mergeObject(SFTKDBHandle *handle, crv = (*source->sdb_GetAttributeValue)(source, id, ptemplate, max_attributes); if (crv != CKR_OK) { goto loser; } objectType = sftkdb_getULongFromTemplate(CKA_CLASS, ptemplate, max_attributes); +/*printf(" - merging object Type 0x%08lx id=0x%08lx updateID=%s\n", objectType, id, + handle->updateID?handle->updateID: "");*/ /* * Update Object updates the object template if necessary then returns * whether or not we need to actually write the object out to our target * database. */ if (!handle->updateID) { crv = sftkdb_CreateObject(arena, handle, target, &newID,