classification
Title: Python does not read Alternative Subject Names from some SSL certificates
Type: behavior Stage: resolved
Components: Extension Modules Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: pitrou Nosy List: achipa, atrasatti, janssen, pitrou, python-dev
Priority: normal Keywords:

Created on 2011-09-23 11:53 by atrasatti, last changed 2011-10-01 17:35 by pitrou. This issue is now closed.

Messages (7)
msg144441 - (view) Author: Andrea Trasatti (atrasatti) Date: 2011-09-23 11:53
We found a problem with SSL certificates, when they are larger than 1024 bits and you need to check Alternative Subject Names.
In our case we have a 2048 bit certificate, issued by Verisign for the domain developer.nokia.com. The certificate also covers other sub-domains, once of which is projects.developer.nokia.com. We found the issue using the mercurial client, but we dug down to SSLSocket.getpeercert. It looks like when the openSSL library reads the certificate it does not return any Alternative Subject Name, even though they are there. Using the standard openssl binary we could read the certificate with no problems and the alternative domain names are all there, including the one we need.

See below two examples, the first is our 2048 bit certificate and what Python returns. Then there is Google's code.google.com SSL certificate, 1024 bits and as you can see Python returns the other names correctly.

This was tested with Python 2.7.2.

Binary for projects.developer.nokia.com
'0\x82\x06\xb10\x82\x05\x99\xa0\x03\x02\x01\x02\x02\x10\x0e\xf6_f@\xe4\xd1gtU\x9e39Rn80\r\x06\t*\x86H\x86\xf7\r\x01\x01\x05\x05\x000\x81\xbc1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x170\x15\x06\x03U\x04\n\x13\x0eVeriSign,
Inc.1\x1f0\x1d\x06\x03U\x04\x0b\x13\x16VeriSign Trust Network1;09\x06\x03U\x04\x0b\x132Terms of use at https://www.verisign.com/rpa (c)101604\x06\x03U\x04\x03\x13-VeriSign Class 3 International Server CA - G30\x1e\x17\r110608000000Z\x17\r120607235959Z0h1\x0b0\t\x06\x03U\x04\x06\x13\x02FI1\x0e0\x0c\x06\x03U\x04\x08\x13\x05Espoo1\x0e0\x0c\x06\x03U\x04\x07\x14\x05Espoo1\x0e0\x0c\x06\x03U\x04\n\x14\x05Nokia1\x0b0\t\x06\x03U\x04\x0b\x14\x02IT1\x1c0\x1a\x06\x03U\x04\x03\x14\x13developer.nokia.com0\x82\x01"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\xf8\xdeL"\x8az\xbb\xa6\xddj\x14\x89X\xeeh\x87\x07\xbd\xb3\xc5=!
\xb9\x80\xe8\xe6v"*\xec6w\x82\r\xb6b\x10\xb8\xe5\x06\x88w\xfd\x03\xa9\x82\x9d\xdf\xdb\xbft\xdb\x06\xc5\'\xdd\x83\x0e\
xf1GdM\x9a\x14\xefyO\x8e\x9dO,
\x92\xf8\xcf\xd3\xb3\xa8m\xc3@^\xa5\x0e\xfb$ddn\xc0\x1cV\xe4\xeaE\xce\x1eoG\xca\xf3\x01\xab\x08V\xd2<\x91\x7f7\xbc\x90\x16\xd6b\xdb\x83(ySA\xccH\x1b\x80"7)^\xe9\x1c\xcaZ&r-\xc6\xf0\xe0\xb6\xde\x16c
W\x0b\xf4\xd24ei[E\xbaY\xc9[;
\xbbs\nQ\xfc\x1b_TiM\x8e\xb6\x9c9\x7f}\xa3\xfe\x96\xab\xa9\xb4\x8dn\\S\xfc\x08\xd5\x1a71
\xd3\x14\xaaF\xd0\xe4\xcf\x0f-\xf9\x10\xa7U\xf6\x92\xafQa\x8b\x02x\xc7V;
\xe2F\xf5 L\xe4\xc1\r\x1f\xec|
\x02\xee\xda\x9ej\xb3\xda\xda\x9b\xf8\xaf\xb5\xa2=\x1e\n\x14qf\xe7\xef\xbd\x8av\xe7l\x9d7\x93\xea\x11\x02\x03\x01\x00\x01\xa3\x82\x03\x000\x82\x02\xfc0\x82\x01I\x06\x03U\x1d\x11\x04\x82\x01@0\x82\x01<\x82\x13developer.nokia.com\x82\x17www.developer.nokia.com\x82\x17aux.developer.nokia.com\x82\x16cc.developer.nokia.com\x82\x1cprojects.developer.nokia.com\x82\x17sso.developer.nokia.com\x82\x19stage.developer.nokia.com\x82\x17ejb.developer.nokia.com\x82\x16cm.developer.nokia.com\x82\x17dav.developer.nokia.com\x82\x1fdav.sandbox.developer.nokia.com\x
82\x1ect.sandbox.developer.nokia.com0\t\x06\x03U\x1d\x13\x04\x020\x000\x0b\x06\x03U\x1d\x0f\x04\x04\x03\x02\x05\xa00A\x06\x03U\x1d\x1f\x04:0806\xa04\xa02\x860http://SVRIntl-
G3-crl.verisign.com/SVRIntlG3.crl0D\x06\x03U\x1d
\x04=0;09\x06\x0b`\x86H\x01\x86\xf8E\x01\x07\x17\x030*0(\x06\x08+\x06\x01\x05\x05\x07\x02\x01\x16\x1chttps://www.verisign.com/rpa0(\x06\x03U\x1d%\x04!
0\x1f\x06\t`\x86H\x01\x86\xf8B\x04\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x020r\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04f0d0$\x06\x08+\x06\x01\x05\x05\x070\x01\x86\x18http://ocsp.verisign.com0<\x06\x08+\x06\x01\x05\x05\x070\x02\x860http://SVRIntl-
G3-
aia.verisign.com/SVRIntlG3.cer0n\x06\x08+\x06\x01\x05\x05\x07\x01\x0c\x04b0`\xa1^\xa0\\0Z0X0V\x16\timage/gif0!
0\x1f0\x07\x06\x05+\x0e\x03\x02\x1a\x04\x14Kk\xb9(\x96\x06\x0c\xbb\xd0R8\x9b)\xacK\x07\x8b!
\x05\x180&\x16$http://logo.verisign.com/vslogo1.gif0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x05\x05\x00\x03\x82\x01\x01\x006N\x97\x1e\xba\x85\xcb\x1e
\xddO6\xf9\xf3\x16-\xb6\x05\x13"\xec*\x00\x0f\xde\x89\xc1\xb7\xc1^\xf0\x8b0=C\x87\xf3|
zI\xe4\r\xedmD1\xc1\x06[GqMuV\xd9\x03\xdd\xa6\xbd2Z!
\x0c\xdf\x93\x9c\xc6\xba\x12\xd1\xaa\xd08\x1c\x82\x02\xd1\xb3\xeeK\xca\xcaEK\x07\xffR\xcfW\xae\xa0\x85\xeb\xc1h\xeb\r\xad\xd5\x92d\x82\xac\x03(\x07\xa1F\x82\x93\xdep\xe9\x9a\xf8O\xb1\xfc\xe0&\xfat\xf4d\xa3q&`\x05J\xb9\xdb\x9a\xb5o;
\xb7O\xaa/\xac\xba\xab\xc9\xd9)m\xf2c\xe8=\xc4\x95\xef\xe9\x92\xee\tlx\xe2\xfc>\x87\xab\xbe\xde\xd4[\xc3\x85>X\x8f\xf3\xe3\x89\xc9,
\\\xb2:\x9f\xf3\xe2\xf3\x81;
\xdbk\x9f\x1e\xbc\x00\xc7\x87@\xb3\xac\xdf\xe09\xfe:
\xef\n\xcf\xdaCZ\xc7\x07X\xd0\x0f\xf2nBKe\x1f\xd8\xcc\xb4\xa2%\x01<\x0eE\nt{G\r\x9a\xfd\xaf\x97\xaf\xba\xb8\x983\xc5~\xd2\x1d\xdd\x04\x13*\xd3\xf3VK:'

Python dictionary extracted
{'notAfter': 'Jun  7 23:59:59 2012 GMT', 'subject': ((('countryName', u'FI'),), (('stateOrProvinceName', u'Espoo'),), (('localityName', u'Espoo'),), (('organizationName', u'Nokia'),), (('organizationalUnitName', u'IT'),), (('commonName', u'developer.nokia.com'),))}





Binary for code.google.com
'0\x82\x05\x080\x82\x04q\xa0\x03\x02\x01\x02\x02\nk\xf3\xf0+\x00\x03\x00\x00/\xf60\r\x06\t*\x86H\x86\xf7\r\x01\x01\x05\x05\x000F1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x130\x11\x06\x03U\x04\n\x13\nGoogle
Inc1"0 \x06\x03U\x04\x03\x13\x19Google Internet Authority0\x1e\x17\r110905060549Z\x17\r120905061549Z0f1\x0b0\t\x06\x03U\x04\x06\x13\x02US1\x130\x11\x06\x03U\x04\x08\x13\nCalifornia1\x160\x14\x06\x03U\x04\x07\x13\rMountain
View1\x130\x11\x06\x03U\x04\n\x13\nGoogle
Inc1\x150\x13\x06\x03U\x04\x03\x14\x0c*.google.com0\x81\x9f0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x81\x8d\x000\x81\x89\x02\x81\x81\x00\xbd\x7f49\x0c\xbdg\x962\xd4\x18\x8d#\x16\x91[\xbcH\x8f\xac+\x8a=\xd0\x1cW\x8bRVIh\x89\xf4\x85\xe0\x12\xe1\xfaG\x1a\xf9\x0bQ\xc2\\b;
\x0f$)c\xb9\xc7\xc45\xb90dK1\xf9\xcd\x111\x15]\xac\xb4\xfd\xa7>\x85\x16a\x15\xd3\x870\x82\xf4\xee^\x86\xbb\xd1\xf6\x81\x9a\x06\x07\xbe\xb7\xebx*\x9a\tX\x03;
\x9bE\xad\x02\xeb`(:\xa3k|
\xca"\xca&\xd4\x98\x03I\\\x81\xc1\xb3\xf7\xf2\x95\xc9;\x02\x03\x01\x00\x01\x
a3\x82\x02\xdb0\x82\x02\xd70\x1d\x06\x03U\x1d\x0e\x04\x16\x04\x140\xf5l\xa9\xb8\xd6\xe2\xc7\xcdy\x7fF\xf5)t%\xe4\x9f\x16U0\x1f\x06\x03U\x1d#\x04\x180\x16\x80\x14\xbf\xc00\xeb\xf5C\x11>g\xba\x9e\x91\xfb\xfcj\xda\xe3k\x12$0[\x06\x03U\x1d\x1f\x04T0R0P\xa0N\xa0L\x86Jhttp://www.gstatic.com/GoogleInternetAuthority/GoogleInternetAuthority.crl0f\x06\x08+\x06\x01\x05\x05\x07\x01\x01\x04Z0X0V\x06\x08+\x06\x01\x05\x05\x070\x02\x86Jhttp://www.gstatic.com/GoogleInternetAuthority/GoogleInternetAuthority.crt0!
\x06\t+\x06\x01\x04\x01\x827\x14\x02\x04\x14\x1e\x12\x00W\x00e\x00b\x00S\x00e\x00r\x00v\x00e\x00r0\x82\x01\xab\x06\x03U\x1d\x11\x04\x82\x01\xa20\x82\x01\x9e\x82\x0c*.google.com\x82\ngoogle.com\x82\x0b*.atggl.com\x82\r*.youtube.com\x82\x0byoutube.com\x82\x0b*.ytimg.com\x82\x0f*.google.com.br\x82\x0e*.google.co.in\x82\x0b*.google.es\x82\x0e*.google.co.uk\x82\x0b*.google.ca\x82\x0b*.google.fr\x82\x0b*.google.pt\x82\x0b*.google.it\x82\x0b*.google.de\x82\x0b*.google.cl\x82\x0b*.google.pl\x82\x0b*.goo
gle.nl\x82\x0f*.google.com.au\x82\x0e*.google.co.jp\x82\x0b*.google.hu\x82\x0f*.google.com.mx\x82\x0f*.google.com.ar\x82\x0f*.google.com.co\x82\x0f*.google.com.vn\x82\x0f*.google.com.tr\x82\r*.android.com\x82\x14*.googlecommerce.com0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x05\x05\x00\x03\x81\x81\x00Mfgo\xae\xd5}\xcb\xf7\xca\x82\xed\xcerGvl`\'F0\x0e?
\x8c0\xbc\x7f\xc6\x0c:\x98\xe0\x02\xe4
J\x10\x9d\xe3\xe5p\xd6\xfam\xe0\x91wY\xdb\xf0-\xefV\xfc\xaeVJ!\x0eL_\xf4|
\xff\xb3q\xf4h%\xcc\xf1\xfe
\xfe\xe4\xa57\xb5\x8d\xeeT\xf3-\x04\x01\xfdB`P\xfb\x82\xf3w\xce\x93\x8e+q\x9b\x03\xc9\xcf[Y\xc0\x0f\xf5,V\xb0$\xe6\x1f9qi\xef\xf1\xb3\xda\xba\xc9\xc0\xbb\x84\x1a\x9f\x89'

Python dictionary
{'notAfter': 'Sep  5 06:15:49 2012 GMT', 'subjectAltName': (('DNS', '*.google.com'), ('DNS', 'google.com'), ('DNS', '*.atggl.com'), ('DNS', '*.youtube.com'), ('DNS', 'youtube.com'), ('DNS', '*.ytimg.com'), ('DNS', '*.google.com.br'), ('DNS', '*.google.co.in'), ('DNS', '*.google.es'), ('DNS', '*.google.co.uk'), ('DNS', '*.google.ca'), ('DNS', '*.google.fr'), ('DNS', '*.google.pt'), ('DNS', '*.google.it'), ('DNS', '*.google.de'), ('DNS', '*.google.cl'), ('DNS', '*.google.pl'), ('DNS', '*.google.nl'), ('DNS', '*.google.com.au'), ('DNS', '*.google.co.jp'), ('DNS', '*.google.hu'), ('DNS', '*.google.com.mx'), ('DNS', '*.google.com.ar'), ('DNS', '*.google.com.co'), ('DNS', '*.google.com.vn'), ('DNS', '*.google.com.tr'), ('DNS', '*.android.com'), ('DNS', '*.googlecommerce.com')), 'subject': 
((('countryName', u'US'),), (('stateOrProvinceName', u'California'),), (('localityName', u'Mountain View'),), (('organizationName', u'Google Inc'),), (('commonName', u'*.google.com'),))}
>>>
msg144449 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-09-23 16:23
Thanks for reporting. This trivial patch seems to fix it (still needs a test):

diff -r 1b4fae183da3 Modules/_ssl.c
--- a/Modules/_ssl.c	Tue Aug 09 18:48:02 2011 -0500
+++ b/Modules/_ssl.c	Fri Sep 23 18:16:04 2011 +0200
@@ -590,7 +590,7 @@ _get_peer_alt_names (X509 *certificate) 
     /* get a memory buffer */
     biobuf = BIO_new(BIO_s_mem());
 
-    i = 0;
+    i = -1;
     while ((i = X509_get_ext_by_NID(
                     certificate, NID_subject_alt_name, i)) >= 0) {
 

Yay for undocumented OpenSSL APIs with weird semantics.
msg144451 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-09-23 16:34
For the record, curl uses the (also undocumented) X509_get_ext_d2i() function instead.
msg144740 - (view) Author: Roundup Robot (python-dev) Date: 2011-10-01 17:26
New changeset 65e7f40fefd4 by Antoine Pitrou in branch '3.2':
Issue #13034: When decoding some SSL certificates, the subjectAltName extension could be unreported.
http://hg.python.org/cpython/rev/65e7f40fefd4

New changeset 90a06fbb1f85 by Antoine Pitrou in branch 'default':
Issue #13034: When decoding some SSL certificates, the subjectAltName extension could be unreported.
http://hg.python.org/cpython/rev/90a06fbb1f85
msg144741 - (view) Author: Roundup Robot (python-dev) Date: 2011-10-01 17:34
New changeset 8e6694387c98 by Antoine Pitrou in branch '2.7':
Issue #13034: When decoding some SSL certificates, the subjectAltName extension could be unreported.
http://hg.python.org/cpython/rev/8e6694387c98
msg144742 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-10-01 17:35
This should be fixed now.
msg144743 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2011-10-01 17:35
(fixing the title)
History
Date User Action Args
2011-10-01 17:35:45pitrousetmessages: + msg144743
title: Python does not read Alternative Subject Names from SSL certificates larger than 1024 bits -> Python does not read Alternative Subject Names from some SSL certificates
2011-10-01 17:35:20pitrousetstatus: open -> closed
resolution: fixed
messages: + msg144742

stage: resolved
2011-10-01 17:34:39python-devsetmessages: + msg144741
2011-10-01 17:26:03python-devsetnosy: + python-dev
messages: + msg144740
2011-09-23 16:36:56giampaolo.rodolasetnosy: - giampaolo.rodola
2011-09-23 16:34:19pitrousetmessages: + msg144451
2011-09-23 16:23:11pitrousetassignee: pitrou
messages: + msg144449
versions: + Python 3.2, Python 3.3
2011-09-23 12:14:22achipasetnosy: + achipa
2011-09-23 12:00:43ezio.melottisetnosy: + janssen, pitrou, giampaolo.rodola
components: + Extension Modules
2011-09-23 11:53:12atrasatticreate