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