How to get a list of SubjectAltNames of a cert in NSS

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

How to get a list of SubjectAltNames of a cert in NSS

Paul Wouters-2

Hi,

I'm looking at the best way to get a list of SubjectAltNames of a CERTCertificate.

Anyone have a pointer (haha) for me ?

Paul
--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto
Reply | Threaded
Open this post in threaded view
|

Re: How to get a list of SubjectAltNames of a cert in NSS

John Dennis
On 02/23/2017 11:04 AM, Paul Wouters wrote:
>
> Hi,
>
> I'm looking at the best way to get a list of SubjectAltNames of a
> CERTCertificate.
>
> Anyone have a pointer (haha) for me ?

CERT_DecodeAltNameExtension

See secu_PrintAltNameExtension() in cmd/lib/secutil.c or
cert_VerifySubjectAltName() in lib/certdb/certdb.c for an examples.


--
John
--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto
Reply | Threaded
Open this post in threaded view
|

Re: How to get a list of SubjectAltNames of a cert in NSS

John Dennis
On 02/23/2017 11:14 AM, John Dennis wrote:

> On 02/23/2017 11:04 AM, Paul Wouters wrote:
>>
>> Hi,
>>
>> I'm looking at the best way to get a list of SubjectAltNames of a
>> CERTCertificate.
>>
>> Anyone have a pointer (haha) for me ?
>
> CERT_DecodeAltNameExtension
>
> See secu_PrintAltNameExtension() in cmd/lib/secutil.c or
> cert_VerifySubjectAltName() in lib/certdb/certdb.c for an examples.
Actually, if all you want to simply grab the names avoiding C code you
can use the nss python binding. Attached is a simple Python script, the
Symantec cert to use as an example, and the output of the script

% python nss_print_subject_alt_names.py symantec.pem




--
John

--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto

output.txt (996 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: How to get a list of SubjectAltNames of a cert in NSS

John Dennis
Argh ... looks like the mailing list scrubbed 2 of my attachments.
Here is the python code (not as an attachment), hope the mailer does not
mangle it.

import sys
import nss.nss as nss
from nss.error import NSPRError

# Perform basic configuration and setup
nss.nss_init_nodb()

# Get the cert filename from command line argument
filename = sys.argv[1]
print "certificate filename: %s" % (filename)

# Read the certificate from the file
si = nss.read_der_from_file(filename, True)

# Parse the DER encoded data returning a Certificate object
cert = nss.Certificate(si)

# Get the SubjectAltName extension from the cert
try:
     extension = cert.get_extension(nss.SEC_OID_X509_SUBJECT_ALT_NAME)
except KeyError:
     print "Certificate does not contain a SubjectAltName extension"
     sys.exit(1)

# Get the names from the extension
names = nss.x509_alt_name(extension.value)

# Print out the names
print 'certificate subject: %s' % cert.subject
print 'has %d alternate names' % len(names)
for name in names:
     print '  %s' % name

# Success
sys.exit(0)



--
John
--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto
Reply | Threaded
Open this post in threaded view
|

Re: How to get a list of SubjectAltNames of a cert in NSS

Paul Wouters-2
On Fri, 3 Mar 2017, Robert Relyea wrote:

>>  [offlist]

redirected back to the list, since the item I was concerned about is not
a concern.

>>  Thanks for the info. I looked at it and have two questions and one
>>  concern (which is why this is offlist)
> I'm not sure what list this was from. I don't remember seeing the thread.

[hidden email]

>>  - Why not export this NSS function for everyone?
>
> Which function?

Sorry, I was referring to:

  cert_VerifySubjectAltName(const CERTCertificate *cert, const char *name);

Basically in IKE you can set an ID different from a DN. So if someone
sets ID_FQDN (eg vpn.example.com) then we want to lookup and ensure that
the certificate is really matching that ID. IKE also allows specifying
email addresses and IP's. So we need to look for:

- email= in the DN
- subjectAltName of type DNSname
- subjectAltName of type IP
- subjectAltName of type email address.

It looks that CERT_GetFirstEmailAddress() and CERT_GetNextEmailAddress()
gets me the email= from the DN and all email address in the first
subjectAltName section, but not in subsequent subjectAltName sections.

The same is true for cert_VerifySubjectAltName() which seems to only
look at the first subjectAltName section as well.

The certificates I use for testing use this openssl/python code:

-               add_ext(cert, 'subjectAltName', False, dnsname)
+               if cnstr == "east.testing.libreswan.org":
+                       dnsname = "%s,%s"%(dnsname , "DNS:east.alias")
+                       add_ext(cert, 'subjectAltName', False, "IP: 192.1.2.23")
+                       add_ext(cert, 'subjectAltName', False, dnsname)
+                       add_ext(cert, 'subjectAltName', False, "email: user1@%s"%cnstr)

So there are 3 subjectAltName sections.

> In general NSS tends to be stingy by default on the functions it exports,

I completely understand that :)

> I believe Kai has already exported several functions upstream for you that
> will go into RHEL 7.

Yes, and we've already updated libreswan to make use of this in upstream
and fedora rawhide! Thanks!

>>  The code I see in NSS seems to assume there is only one SAN section? I
>>  checked and it does not create one big list of all the SAN extensions,
>>  because I don't see my IP address SAN in the above example.
>
> It doesn't. For most of NSS we usually are looking for a specific SAN (like a
> particular DNS name, or an email address.), so it loops through them all.
>
> I'm surprised the SAN processing isn't exported since applications that
> override the SSL name check would need it.

You do export CERT_VerifyCertName() which uses this function. So maybe I
was trying to use the wrong function. But it seems this function also
does not process multiple subjectAltName sections.

>>  - While browsing through some code for this, I noticed:
>>
>>          if (!!(nameList = CERT_DecodeAltNameExtension(tmpArena,
>>  &subAltName))) {
>>              CERTGeneralName *current = nameList;
>>
>>  I'm a little confused about the double exclamation mark? I hope it is
>>  something clever and not a typo?
> It looks correct but funky. The if clearly should trigger if nameList is
> non-zero. It looks to me like a bad attempt to silence a compiler warning (I
> personally prefer coding (xxx = func) != NULL). I suspect the original code
> was:
>    if (nameList = CERT_DecodeAltNameExtension(tmpArea,&subAltName))  {
> Which triggered the normal compiler warning to protect agains things like: if
> (nameList = NULL) instead of if (nameList == NULL).

Okay, that is what i thought, but i just wanted to be sure "!!" was not
a bad typo.

Paul
--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto
Reply | Threaded
Open this post in threaded view
|

Re: How to get a list of SubjectAltNames of a cert in NSS

Robert Relyea
On 03/03/2017 09:42 AM, Paul Wouters wrote:

> On Fri, 3 Mar 2017, Robert Relyea wrote:
>
>>>  [offlist]
>
> redirected back to the list, since the item I was concerned about is not
> a concern.
>
>>>  Thanks for the info. I looked at it and have two questions and one
>>>  concern (which is why this is offlist)
>> I'm not sure what list this was from. I don't remember seeing the
>> thread.
>
> [hidden email]
>
>>>  - Why not export this NSS function for everyone?
>>
>> Which function?
>
> Sorry, I was referring to:
>
>     cert_VerifySubjectAltName(const CERTCertificate *cert, const char
> *name);

Certainly as named, we would export it, but we could wrap the function
as CERT_VerifySubjectAltName()
and export that function.


>
> Basically in IKE you can set an ID different from a DN. So if someone
> sets ID_FQDN (eg vpn.example.com) then we want to lookup and ensure that
> the certificate is really matching that ID. IKE also allows specifying
> email addresses and IP's. So we need to look for:
>
> - email= in the DN
> - subjectAltName of type DNSname
> - subjectAltName of type IP
> - subjectAltName of type email address.
>
> It looks that CERT_GetFirstEmailAddress() and CERT_GetNextEmailAddress()
> gets me the email= from the DN and all email address in the first
> subjectAltName section, but not in subsequent subjectAltName sections.

Yes, NSS only looks at the first subjectAltName section. That section
can and should hold all the alt names (That's certainly the case with
SSL certificates).

I think you may be confused with the openSSL API. When openSSL says:

Please make sure the following details are correct before proceeding any further.

CommonName: server1.example.com
subjectAltName: DNS:server1.example.com
subjectAltName: DNS:mail.example.com
subjectAltName: DNS:www.example.com
subjectAltName: DNS:www.sub.example.com
subjectAltName: DNS:mx.example.com
subjectAltName: DNS:support.example.com
No additional information will be included on certificates because it can not be automatically checked by the system.

It will create a single subjectAltName with all those names in it:

             X509v3 Subject Alternative Name:
                 DNS:server1.example.com, othername:<unsupported>, DNS:mail.example.com, othername:<unsupported>, DNS:www.example.com, othername:<unsupported>, DNS
:www.sub.example.com, othername:<unsupported>, DNS:mx.example.com, othername:<un
supported>, DNS:support.example.com, othername:<unsupported>

Are you sure the certificate you have actually has multiple
subjectAltName sections?

>
> The same is true for cert_VerifySubjectAltName() which seems to only
> look at the first subjectAltName section as well.
>
> The certificates I use for testing use this openssl/python code:
>
> -               add_ext(cert, 'subjectAltName', False, dnsname)
> +               if cnstr == "east.testing.libreswan.org":
> +                       dnsname = "%s,%s"%(dnsname , "DNS:east.alias")
> +                       add_ext(cert, 'subjectAltName', False, "IP:
> 192.1.2.23")
> +                       add_ext(cert, 'subjectAltName', False, dnsname)
> +                       add_ext(cert, 'subjectAltName', False, "email:
> user1@%s"%cnstr)
>
> So there are 3 subjectAltName sections.

Hmm Are you sure these aren't being colapsed into a single
subjectAltName section with multiple subjectAltNames in it?

>
>> In general NSS tends to be stingy by default on the functions it
>> exports,
>
> I completely understand that :)
>
>> I believe Kai has already exported several functions upstream for you
>> that will go into RHEL 7.
>
> Yes, and we've already updated libreswan to make use of this in upstream
> and fedora rawhide! Thanks!
>
>>>  The code I see in NSS seems to assume there is only one SAN section? I
>>>  checked and it does not create one big list of all the SAN extensions,
>>>  because I don't see my IP address SAN in the above example.
>>
>> It doesn't. For most of NSS we usually are looking for a specific SAN
>> (like a particular DNS name, or an email address.), so it loops
>> through them all.
>>
>> I'm surprised the SAN processing isn't exported since applications
>> that override the SSL name check would need it.
>
> You do export CERT_VerifyCertName() which uses this function. So maybe I
> was trying to use the wrong function. But it seems this function also
> does not process multiple subjectAltName sections.

CERT_VerifyCertName() verifies against either the SAN or the CN (SSL
processing). it supports multiple subjectAltNames, but they all are
expected to be in the same section.

bob


--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto
Reply | Threaded
Open this post in threaded view
|

Re: How to get a list of SubjectAltNames of a cert in NSS

Robert Relyea
On 03/03/2017 02:48 PM, Robert Relyea wrote:

> On 03/03/2017 09:42 AM, Paul Wouters wrote:
>> On Fri, 3 Mar 2017, Robert Relyea wrote:
>>
>>>>  [offlist]
>>
>> redirected back to the list, since the item I was concerned about is not
>> a concern.
>>
>>>>  Thanks for the info. I looked at it and have two questions and one
>>>>  concern (which is why this is offlist)
>>> I'm not sure what list this was from. I don't remember seeing the
>>> thread.
>>
>> [hidden email]
>>
>>>>  - Why not export this NSS function for everyone?
>>>
>>> Which function?
>>
>> Sorry, I was referring to:
>>
>>     cert_VerifySubjectAltName(const CERTCertificate *cert, const char
>> *name);
>
> Certainly as named, we would export it, but we could wrap the function
> as CERT_VerifySubjectAltName()
> and export that function.

Arg... typing to fast drops negations. this should read

"Certainly as names we would NOT export it, but we could wrap the
function as CERT_VerifySubjectAltName() and export that function()."

Lower case function names is an indicator the the function is local, at
least to the NSS directory, if not to the .c file itself. Anything
exported even within the NSS shared library (yet alone to the
application) sould have an all cap prefix.

bob

--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto
Reply | Threaded
Open this post in threaded view
|

Re: How to get a list of SubjectAltNames of a cert in NSS

Paul Wouters-2
In reply to this post by Robert Relyea
On Fri, 3 Mar 2017, Robert Relyea wrote:

> Yes, NSS only looks at the first subjectAltName section. That section can and should hold all the alt names (That's certainly the case with SSL
> certificates).

Ok, so maybe we have generated certificates in a bad way :)

See the attached python script that generates these :)

>       So there are 3 subjectAltName sections.
>
> Hmm Are you sure these aren't being colapsed into a single subjectAltName section with multiple subjectAltNames in it?

Yes because I was testing the IP: and DNS: and email= SAN's and my code
showed it only looped over the first one.

> CERT_VerifyCertName() verifies against either the SAN or the CN (SSL processing). it supports multiple subjectAltNames, but they all are expected to
> be in the same section.

So it seems that this function would do everything I need. I'll see
about changing my certificates to have one SAN section and then
confirm if it can pick up the DNS name or email address from CN
and SAN.

Thanks,

Paul
--
dev-tech-crypto mailing list
[hidden email]
https://lists.mozilla.org/listinfo/dev-tech-crypto

dist_certs.py (26K) Download Attachment