Obtaining SSL certificate info from SSL object - BUG?

John Nagle nagle at animats.com
Fri Oct 27 02:03:34 EDT 2006


Michael Ströder wrote:
> John Nagle wrote:
> 
>>    The Python SSL object offers two methods from obtaining
>>the info from an SSL certificate, "server()" and "issuer()".
>>The actual values in the certificate are a series of name/value
>>pairs in ASN.1 binary format.  But what "server()" and "issuer()"
>>return are strings, with the pairs separated by "/".  The
>>documentation at "http://docs.python.org/lib/ssl-objects.html"
>>says "Returns a string containing the ASN.1 distinguished name
>>identifying the server's certificate. (See below for an example showing
>>what distinguished names look like.)"  There is, however, no "below".
>>
>>What you actually get back looks like this, which is Google's certificate:
>>
>>"/C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com"
>>
>>So, no problem; just split on "/", right?
>>
>>Unfortunately, "/" is a legal character in certificate values.
> 
> 
> You hit a really serious problem: There's no completely well-defined
> string representation format for distinguished names used in X.509
> certificates. The format above is what OpenSSL used in the beginning.
> Yuck! IMO this is also a security problem in some cases.
> 
> The best thing would be to stick to RFC 4514 (formerly RFC 2253:
> Lightweight Directory Access Protocol (LDAP): String Representation of
> Distinguished Names). It defines a UTF-8-based string representation.
...
> Guess the second is what Python SSL object also should return. No idea
> whether this is available at OpenSSL's API level.
> 
     That's exactly what I suggested in my Python bug report update.

     OpenSSL has all the right functions.  Almost.

     OpenSSL has "X509_NAME_oneline()" which is deprecated, which Python
is using, and which uses "/" as a delimiter without escaping "/" in
content.

     OpenSSL also has "X509_NAME_print_ex", which does the right
thing - outputs a UTF8 string in RFC 2253 format, with all the
right escapes and Unicode compatibility if you ask for Unicode
output.

     Unfortunately, "X509_NAME_print_ex" is set up to output to
an I/O port, not a string.  There's no comparable function in
OpenSSL to edit that info to a string.

     All the right machinery to do the job is in

	openssl/crypto/asn1/a_strex.c

but they ran into a classic C problem.  They have code designed
to output to a stream of infinite length, and don't have a way
to get the target length down to the copy function.  Take look at
"send_mem_chars" in that file, which is turned off.  If it were
used, it would have buffer overflow potential.  This could be
fixed, but it's a pain.  It's local to that file, though;
someone who owns that code could fix it in an hour.

     X509_NAME_oneline(), the deprecated function, is in a
completely separate file and doesn't handle the hard cases at all.

     The same problem was reported in Apache mod_ssl back in 2004.  See

http://mail-archives.apache.org/mod_mbox/httpd-dev/200410.mbox/%3C54f1458d04101510173c5c4e00@mail.gmail.com%3E

     And it had to be fixed in OpenCA.  See

http://www.mail-archive.com/openca-devel@lists.sourceforge.net/msg02672.html

     Also, there may be an exploitable bug in MySQL that depends on this.  See

	http://bugs.mysql.com/bug.php?id=17208

Get the OpenSSL people to fix their API, and the Python fix will
be a one-line change.


				John Nagle



More information about the Python-list mailing list