We currenlty can't adhere to the S/MIME standards that specify that a cert can
contain multiple email addresses because the only api in the s/mime libraries is:
char * NSS_CMSSignerInfo_GetSignerEmailAddress()
Note that NSS_CMSSignerInfo_GetSignerEmailAddress returns
CERTCertificate.emailAddr, which is created by a call to
That function seems to be looking at all the right places, but only returns one
The very existence of CERTCErtificate.emailAddr is questionable, since certs can
have more than one.
Maybe we can add a field to CERTCertificate that would contain a list of email
addresses? Maybe we can have a function that computes the list on demand?
What do you think?
The bug doesn't depend on 50823, it blocks it.
*** Bug 124070 has been marked as a duplicate of this bug. ***
*** Bug 152984 has been marked as a duplicate of this bug. ***
It seems that CERTCErtificate.emailAddr is used as the
key to the S/MIME profiles. CERT_GetCertificateEmailAddress
recomputes the email address every time; it does not use
So I think we also need to look at how the S/MIME profiles
are stored to handle the possibility that multiple email
addresses correspond to the same S/MIME profile.
Unfortunately the CERTCertificate datastructure is pretty much locked in place
as long as we are still mantaining binary compatibility (Unfortunately the data
structure was exported when it should have been Opaque).
The underlying NSS database does not handle multiple email address all that
well, since there is a one-for-one index between email address and certificate
Subject. We can, however provide a function which lists all the valid email
addresses for a given certificate. I don't think will give you all you need to
handle the many-to-many email-to-certificate semantic we want to support.
Adding this function is still scheduled for NSS 3.6, P2.
Assigned the bug to Nelson.
Nelson, please investigate how much work it is to
implement a function that takes a cert and an email
address as arguments and returns a Boolean indicating
whether the cert contains that email address.
This Boolean function should meet the immediate need
of the S/MIME code in the Mozilla client. It is not as
general as the function Stephane requested, but avoids the
whole issues of the format of the list of email addresses,
whether the list should be returned or stored in
CERTCertificate, and how to free the list.
Moved to NSS 3.7, priority P1.
NSS_CMSSignerInfo_GetSignerEmailAddress takes this argument:
Another function in that family, NSS_CMSSignerInfo_GetSigningCertificate
also takes a NSSCMSSignerInfo *, and returns a CERTCertificate *.
The CERTCertificate pointer returned by NSS_CMSSignerInfo_GetSigningCertificate
is a new reference to the CERTCertificate, and the reference must be destroyed
with a call to CERT_DestroyCertificate to avoid a leak.
I propose two new functions:
char * CERT_GetFirstEmailAddress(CERTCertificate * cert);
char * CERT_GetNextEmailAddress(char * prevEmailAddress);
These functions will return a pointer to a UTF8 string, or NULL.
The value returned by GetFirst will be passed to GetNext, and each value
returned by GetNext will be passed to the next call to GetNext, until
GetNext returns a NULL.
The char * pointers returned point to storage that is part of the
CERTCertificate's arena. The pointer will remain good as long as the caller
retains a reference to the CERTCertificate. The caller must strdup (or
otherwise copy) the data if he wishes to keep it after releasing the
reference to the CERTCertificate.
How does this sound?
I'm coding it up now.
One minor correction to the proposal:
instead of taking and returning char *, they'll take and return const char *.
That should keep the callers from doing bad things with the data.
Ideally we just need one function:
const char *const* CERT_GetEmailAddresses(CERTCertificate *cert);
char ** CERT_GetEmailAddresses(CERTCertificate *cert, PLArenaPool *arena);
I know why you proposed the CERT_GetFirstEmailAddress and
CERT_GetNextEmailAddress functions -- you want to store the
list of email addresses in CERTCertificate without adding a
new field. They are fine by me although they look
inefficient (we need a strlen call rather than a pointer
increment to get the next email address) to someone who
doesn't know the reason behind them.
Can email addresses be UTF8 strings?
taka, do you know what kind of encoding there can be in an email address?
Let's not get hung up on UTF8.
The scheme I propose will work on any character set that does not use wide
characters, and that has no zero bytes in any of the characters that might
be used in an email address. That includes the following character sets,
and probably others, too:
UTF8, ISO-Latin-1 and its subsets, such as ASCII & IA5 would all work with this
Are you expecting addr-spec (e.g. firstname.lastname@example.org) only?
Or, name-addr (e.g. Takayuki Tei <email@example.com>) ?
I was just wondering whether we need to specify the
character encoding of the strings returned by the
new functions Nelson proposed in comment #9.
In reply to comment 15, Taka, I expect that all the email addresses in
the certificate will be addr-spec only. RFC 3280 says:
When the subjectAltName extension contains an Internet mail address,
the address MUST be included as an rfc822Name. The format of an
rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822]. An
addr-spec has the form "local-part@domain". Note that an addr-spec
has no phrase (such as a common name) before it, has no comment (text
surrounded in parentheses) after it, and is not surrounded by "<" and
">". Note that while upper and lower case letters are allowed in an
RFC 822 addr-spec, no significance is attached to the case.
It also says:
In addition, legacy implementations exist where an RFC 822 name is
embedded in the subject distinguished name as an EmailAddress
attribute. The attribute value for EmailAddress is of type IA5String
to permit inclusion of the character '@', which is not part of the
PrintableString character set. EmailAddress attribute values are not
case sensitive (e.g., "firstname.lastname@example.org" is the same as
IA5String is a subset of ASCII.
In reply to comment 16, Wan-Teh, RFC 822 and its successor RFC 2822 both state
that all the characters in the email headers (including email addresses) must be
ACII characters in the range 1-127. I expect we will see some certificates
with ISO-Latin-1 characters in the email addresses, but these are similar
enough to ASCII for the purposes of string comparison, and for this API.
BTW, to permit alternative implementations in the future, I now propose that
the two functions be:
const char *
const char *
CERT_GetNextEmailAddress(CERTCertificate *cert, const char *prevEmailAddress);
This permits the internal opaque implementation to use either a environment-like
super-string, or an array of pointers to strings, without requiring any
change to the callers.
I'm waiting for feedback from Stephane's team on this proposal.
I recommend the API to do validation so that e-mail addresses are
guranteed to have ASCII characters only. You shouldn't allow
any characters including Latin-1, otherwise it will break things
down the road.
Created attachment 103833 [details] [diff] [review]
One implementation, not most efficient, but should work.
If performance is a problem with this implementation, the API allows us to
change it without making client's change.
Do we have any certs with multiple email addresses in them for testing
this new code? Is so, please email them to me. Thanks.
I'm going to create a Thawte one with both my home and work email address, and
will email you.
I found a cert with 2 email addresses in it. They were the same address.
The address is returned twice, once by GetFirst and again by GetNext.
Patch checked in.
So this is 3.7, correct? Won't make it into Buffy then?
What NSS release will Buffy use?
I've not received any request to do this in any other release than 3.7.
This change adds new API functions to NSS, by which an application could
access this info. We generally don't add new API functions to NSS in
patch releases (such as 3.6.1).
But even if we did add it to 3.6.1, would any new code be written in PSM
to make use of this new feature for Buffy?
We plan to release NSS 3.7 RTM on 3/3/2003 and the
earliest time Mozilla can have to the new NSS 3.7
APIs is the NSS 3.7 Beta release on 2/10/2003.
Kai can pull NSS 3.7 pre-release for his development.
If this is too late for you we can talk about it.
Our schedule is tentative at the moment and there
is some flexibility to adjust it.
There's another issue about this API that needs to be resolved, perhaps
resulting in a change to the code just checked in.
The old CERTCertificate->emailAddr string was downshifted. Every character
in it came from a call to tolower(). Each byte of the original email
address in the cert was passed to tolower, and the result was stored in
the emailAddr string.
So, when I implemented the new functions, I duplicated this behavior.
Perhaps this is not the desired behavior.
If the strings returned by the new API functions are intended for display
purposes, then they should not be downshifted. OTOH, if they are only
intended for comparison purposes, then perhaps downshifting is OK,
although only characters less than 0x80 should be downshifted, IMO.
Stephane, please help me get resolution to this ASAP.
Downshifting is the right thing to do.
These email addresses may end up being displayed in the cert manager, where all
email addresses for the "other people certs" tab are downshifted.