Open Bug 145376 Opened 23 years ago Updated 3 years ago

there is a unique S/MIME entry for each e-mail address in the certificate db, and it may point to an old expired cert

Categories

(NSS :: Libraries, defect, P2)

Tracking

(Not tracked)

People

(Reporter: julien.pierre, Assigned: rrelyea)

References

(Blocks 1 open bug)

Details

(Whiteboard: certdb)

Attachments

(1 file)

This was discovered with S/MIME support in PSM. The code does : CERT_FindCertByNicknameOrEmailAddr followed by certlist = CERT_CreateSubjectCertList( NULL, CERT_GetDefaultCertDB(), &recipientcerts[i]->derSubject, PR_Now(), PR_TRUE); if (!certlist) goto loser; if (SECSuccess != CERT_FilterCertListByUsage(certlist, certUsageEmailRecipient, PR_FALSE)) goto loser; I have found that if my security databases contain a mix of my old Netscape and AOL expired certs, plus my current one, then I get an empty list returned. Somehow not all the certs are being searched. If I delete all the expired certs from the database, then the current cert is found. This is a regression from NSS 3.4 - it works fine there.
OS: Windows 2000 → All
Priority: -- → P1
Hardware: PC → All
Target Milestone: --- → 3.5
I forgot to roll the patch to cmsutil into my 3.4 tree. After I did that, it also failed to find the recipient cert for jpierre@netscape.com, claiming it was expired, even though I had the latest one. So this is not a regression but an existing problem.
Version: 3.5 → 3.4
I had a talk with Nelson. This function is doing the right thing. My problem is that my old certs and my current cert don't have exactly the same subject, even though they have the same e-mail address. The initial call to CERT_FindCertByNicknameOrEmailAddr returns one cert matching the e-mail property, which has a given subject. But it is returning one of the old certs with a different subject than my current cert. Then CERT_CreateSubjectCertList builds a list of all unexpired certs with that same subject, and there are none. What needs to be fixed is CERT_FindCertByNicknameOrEmailAddr . When there are certs with multiple subjects matching the nickname or e-mail address passed in, it should look among the different subjects and ideally return the most current certificate. Ideally though, I think there should be a new API to return a list containing one cert for each multiple matching subject.
Summary: CERT_CreateSubjectCertList incorrectly returns empty list → CERT_FindCertByNicknameOrEmailAddr API defficiency
The code that picks the subjectname is this one, from softoken/pkcs11.c in pk11_searchCertsAndTrust : entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name); if (entry) { int count; SECItem *subjectName = &entry->subjectName; count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName); pk11_CertSetupData(&certData,count); nsslowcert_TraversePermCertsForSubject(certHandle, subjectName, pk11_cert_collect, &certData); nsslowcert_DestroyDBEntry((certDBEntry *)entry); } The stack at that point is pk11_searchCertsAndTrust(PK11SlotStr * 0x004ae4c0, SECItemStr * 0x0012fc20, SECItemStr * 0x0012fc14, SECItemStr * 0x0012fc2c, NSSLOWCERTIssuerAndSNStr * 0x0012fc48, SECItemStr * 0x0012fc38, unsigned long 1, PK11SearchResultsStr * 0x004d5cf8, CK_ATTRIBUTE * 0x0012fd30, long 3) line 3888 pk11_searchTokenList(PK11SlotStr * 0x004ae4c0, PK11SearchResultsStr * 0x004d5cf8, CK_ATTRIBUTE * 0x0012fd30, long 3, int * 0x0012fcc8, int 1) line 4149 + 45 bytes NSC_FindObjectsInit(unsigned long 16777217, CK_ATTRIBUTE * 0x0012fd30, unsigned long 3) line 4206 + 29 bytes find_objects(NSSTokenStr * 0x004d0308, nssSessionStr * 0x00000000, CK_ATTRIBUTE * 0x0012fd30, unsigned long 3, unsigned int 0, int * 0x0012fd98) line 420 + 21 bytes nssToken_FindCertificatesByEmail(NSSTokenStr * 0x004d0308, nssSessionStr * 0x00000000, char * 0x004861f0, int 2, unsigned int 0, int * 0x0012fd98) line 763 + 29 bytes PK11_FindCertFromNickname(char * 0x004861f0, void * 0x00000000) line 1297 + 25 bytes CERT_FindCertByNicknameOrEmailAddr(NSSTrustDomainStr * 0x004c5388, char * 0x004861f0) line 451 + 11 bytes enveloped_data(envelopeOptionsStr * 0x0012fea4) line 626 + 22 bytes main(int 8, char * * 0x004840b8) line 1365 + 12 bytes CMSUTIL! mainCRTStartup + 227 bytes KERNEL32! 77e97d08() How does the S/MIME entry get created in the db ? I just imported a p12 file into a fresh database. Is that expected to create an S/MIME entry ? Can there be more than one S/MIME entry per e-mail address ? In this case the function is returning the subject of one of the expired certificates. Then there are 5 matching certs for it, but they are all expired. What I want the search to do is to find all 8 certs that match the e-mail address.
Assigned the bug to Julien.
Assignee: wtc → jpierre
The function nssToken_FindCertificatesByEmail should find all certificates with a given email address. PK11_FindCertFromNickname should return the newest of those, so I don't think it's an API deficiency (this would work with other tokens, see below). > Can there be more than one S/MIME entry per e-mail address ? Nope. This is a long existing limitation of cert7.db. NSS ran into this the last time there was widespread use of S/MIME, and it is coming up again. The simple fact is, the design of cert7.db only allows each email address to map to a single subject. The results of trying to have more subjects per email address are undefined, and as you have discovered, usually wrong. A long time ago, in an NSS far far away, Nelson and I tried to come up with a solution that fit within cert7.db. We thought about using characters in the email address that would be ignored by MTA's, like "foo@bar.com <2>". Unfortunately, nothing seemed to promising. Now, the situation is even worse. The ideal workaround would be just above the database. The code would detect an email address conflict, and prefer the subject with the newest certificate for the S/MIME entry (note, this doesn't help you if both are valid, and you want to use both). But this code is now down in the softoken, which isn't supposed to know about the validity period of a cert (but maybe it does?). I believe the only complete solution is a cert8.db. Otherwise, we have to accept some reasonable level of workaround (like the one above, always take the newest), and call it a known bug.
Discussed this with Ian. In order to be able to implement the suggested workaround, which is to pick the subject with the most recent cert (or at least a currently valid one, over a subject with all certs expired), it seems that we would have to enumerate the whole database, decode the certs, and search for a matching e-mail. That seems like a very expensive operation to do for a cert lookup. According to Ian the decoding code required for this is no longer in softoken and putting it back would be a big task. I'm wondering instead if we shouldn't take another route, which is also a workaround. We could update the S/MIME entry in the db every time a cert is added. The import code would check for an existing email entry and update it if the installed cert was newer than the one in the entry. This would not require a new cert8.db format . Comments welcome.
Summary: CERT_FindCertByNicknameOrEmailAddr API defficiency → there is a unique S/MIME entry for each e-mail address in the certificate db
Ian, Bob, Would you mind expanding on the 2 suggestions outlined in comment #8 ?
Julien, Was that comment for a different bug?
Ian, I think the comment is in the right bug. I'm not certain whether there is an associated PSM bug at the moment, but there should be.
Julien, In comment #7, you asked Bob and Ian to expand on comment #8, which did not exist. This is the confusion.
Oops. That was a typo. I meant on comment #6. I'd like to know which workaround we should implement, if any, to avoid having to roll out a new cert db format.
I think the second workaround is sufficient. You have to find the softoken code that creates S/MIME entries upon import. I believe the validity periods should be available for comparison at that point, so you can overwrite the S/MIME entry with the subject of the newer cert. One drawback is that any S/MIME profile data will be lost. But I still think this is the best option.
Stephane, Do we want to resolve this or not ? If we don't - as I suspect at this time - please move the target to NSS 3.6 .
Summary: there is a unique S/MIME entry for each e-mail address in the certificate db → there is a unique S/MIME entry for each e-mail address in the certificate db, and it may point to an old expired cert
Target Milestone: 3.5 → 3.6
You're right it's the right target. I'm still working on a patch, but if you don't mind I'll leave it assigned to you.
This bug affects all S/MIME email certs, not just user certs. It happens when there are multiple certs with different subjects but the same email. The fix would need to be done in PK11_ImportCert. It would check for an existing S/MIME profile for the given email address, compare the validity periods, and update the profile if the imported cert is more recent.
I implemented a fix. I tried it, and it works, but I'm having second thought about it. While this will do the right thing in most cases, updating the S/MIME profile automatically can also exhibit very annoying behavior . In my case, I have a bunch of test certs that have my email address, eg. for accessing various CMS servers. These typically have newer validity dates than my other corporate certs. I think what we really need to do is give the user a choice when a cert is imported with a different subject than the subject of the cert for the existing S/MIME record. The user should be able to select which one becomes the default. This would be an application issue. If we make the patch in NSS and choose a subject (& cert) based on validity date automatically, then the application wouldn't be able to implement the choice logic - ie. the choice would be lost upon a new cert being imported.
Moved to 3.7 to give us more time to think the issues over.
Target Milestone: 3.6 → 3.7
Note that there is still a problem with this patch - it only gets the cert by subject but doesn't create the subject list to get the latest one under that subject. So the comparison that ensues with the newly-imported cert could still be incorrect - comparing it with an old cert of a different subject for which there is a newer cert. I'm not going to fix it for the time being because I don't think the logic implemented in this patch is what we want our solution to be. As discussed in the NSS meeting today, this needs to be the subject of further discussions and most likely a dedicated meeting. The issues are somewhat more complicated than originally thought. The initial scenario I ran into and for which this bug was opened is the following : A user has multiple certs with different subjects, but the same email address. Eg. a Netscape cert and an AOL cert. Only one of them is valid, and the other is expired. However, the S/MIME record is still pointing to the subject of the expired cert. When the user tries to send an S/MIME-encrypted email to himself (eg. as a bcc for POP users), the application does a lookup by email address and finds the subject of the old cert, and since all certs of that subject are expired, the encryption fails. This is a relatively benign case, which got worked around in the following ways in the client : Every time an S/MIME-encrypted e-mail is created, before the recipient cert is looked up, the S/MIME profile of the user is updated with his own certificate, as configured in PSM. This means that a valid cert is found and resolves the issue. However, this workaround only works if you are sending emails to yourself. You could be corresponding with other people who had Netscape certs and are still listed with S/MIME records in your database point to their subjects. Even though you receive new emails from them containing the newer AOL cert with a different subject, that does not cause the S/MIME record to be updated. Therefore, you won't be able to correspond with those people, until you remove the old certs from your database. You then need to reimport the new certs to update the S/MIME profile. The patch I created attepts to fix that case by checking at import time if the cert is more recent than the one configured in the profile, and if so, updates the profile. However, that blind replacement of the S/MIME profile can still cause a problem . The above assumed that the user only had one valid cert at any given time listing his email address. But he may have several. Here are some examples : - One can have both a corporate AOL cert and a Thawte cert with the corporate email address listed in each one. They can both be valid certs at the same time. - One can have certs for different sites, all listing the email address. This could actually be very common if more businesses deployed client auth - you might end up with one cert for each site, instead of one userid/password per site. - You can have multiple certs all listing your email address for different purposes - eg. one for administering a given CMS server, another corporate one. The question then becomes - which subject should the application use for S/MIME, and which subject to write in the profile ? Solely doing it on validity dates is not adequate, as the certs have different purposes. I believe the decision can only be made at the application level, and the single subject record we maintain per e-mail address is insufficient. Currently, the only way the application can even be aware of the conflict of certs listing the same e-mail address is for it to enumerate and decode all certs and sort them by email address. I believe we need to better deal with this case by having an email record pointing to multiple subjects. Then, a new API could be added to return multiple subjects in the lookup, instead of one. At that time, the API that returns a single cert subject for an email address could be updated - it would get the list of all subjects, and then return the subject of the cert of the most recent one. Actually , rereading all this, I think there is another flaw in the API. The function "CERT_FindCertByNicknameOrEmailAddr" should return a SECItem* of a DER subject, rather than a CERTCertificate*. The later is misleading to the application developer, since the returned cert may be any old one and not necessarily the most recent. This would make it clear for the application that the second lookup through a subject list is needed (which is what I forgot to do in the patch). Of course, doing this would involve a prototype change so we can't do it in 3.x.
Moved to target milestone 3.8 because the original NSS 3.7 release has been renamed 3.8.
Target Milestone: 3.7 → 3.8
Based on comment #19 , the only proper fix for this problem requires a database schema change. The email records need to be able to point to more than one subject. This bug is currently targeted for NSS 3.8. Since we are also changing the database format in 3.7, I think it would be a good idea to sneak in the fix to that release, if we can. Otherwise, we will have to rev up the database yet again in the near future.
Julien, please talk with the appropriate people about this issue right away. If necessary call a meeting tomorrow.
Retargeting to stan per Bob Relyea.
Target Milestone: 3.8 → 4.0
It seems to me that there are two separate issues here: 1. Eventually we'd like an email address to be able to map to a set of one or more certs. That part can wait until Stan, I agree. 2. In the mean time, if I get a new cert from my employer (say) and the subject name is different than before, I need to be able to get my smime profile to point to the new cert without deleting the old one. Can I do that now?
For your own cert, yes. There is a kludge in PSM that caues the email profile to automatically updated with the cert you select as signing cert (or is it encrypting) every time you send an email. For other people's certs, no. If the subject of the cert of your correspondents changes, there is no easy fix. You would have to delete both your recipient's certs and reimport only the one you want to use to ensure the profile pointed to it.
> For other people's certs, no. If the subject of the cert of your correspondents < changes, there is no easy fix. You would have to delete both your recipient's > certs and reimport only the one you want to use to ensure the profile pointed to > it. PSM looks up the recipient cert by email address. > 2. In the mean time, if I get a new cert from my employer (say) and the > subject name is different than before, I need to be able to get my smime > profile to point to the new cert without deleting the old one. > Can I do that now? I don't understand completely the relationship between S/Mime usable certs and S/Mime profiles, but I assumed, every cert can have a S/Mime profile or not. You need one assigned to it before you can use it. PSM looks up your own S/Mime profile by selecting it by the subject you had explicitly configured - which is contrary to the automatic decision made in old Communicator. PSM will automatically save an S/Mime profile when you use a certificate as a S/Mime encryption recipient certificate. Oops. Now that we talk about it, I wonder whether we are doing something wrong. We call CERT_SaveSMimeProfile(mCert, nsnull, nsnull); unconditionally for each recipient cert whenever we are sending an encrypted message. By doing that, are we overwriting important recipient S/Mime configuration information stored in the profile, such as the prefered cipher of the other person? Maybe we would do better, by only trying to save the profile, if a check tells us, there is none yet available?
There is currently a 1-1 mapping between email address, S/MIME profile, and cert subject list. S/MIME profiles are indexed by email address. They point to a single subject list. The subject list knows what email address points to it so it can clean up the profile when it is deleted. NSS 3.7 has changes that allows multiple profiles to point to a single subject list. This allows the use of certs with multiple email adddresses in the single cert. The subject list record was modified to add space for multiple email addresses so that all the profiles will get deleted when the subject record is destroyed. The converse (multiple subject lists pointed to by email entries) is a lot harder. There needs to be code to determine which subjectlist to use to select a cert when doing encryption. It also significately changes the API for applications (and potential requiring UI changes as well).
Not a vulnerability or crash, reprioritizing to P2.
Priority: P1 → P2
In the scheme where Stan isn't going to happen, how do we implement this ? This is a cert db format issue, so I'm making this a blocker for 219654.
Blocks: 219654
Whiteboard: certdb
Removing target 4.0, since there is no 4.0 plan .
Target Milestone: 4.0 → ---
QA Contact: bishakhabanerjee → jason.m.reid
I'm reassigning this bug to Bob, since he is already working on the database changes, including the schema, for NSS 3.12, so it would make sense to do this change at the same time . There is no way I will be able to get to this enhancement myself.
Assignee: julien.pierre.bugs → rrelyea
QA Contact: jason.m.reid → libraries
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: