473,586 Members | 2,472 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Obtaining SSL certificate info from SSL object - BUG?

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.c om"

So, no problem; just split on "/", right?

Unfortunately, "/" is a legal character in certificate values.

Worse, this isn't just a theoretical problem. Verisign's issuer
information reads:

"/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International
Server CA - Class 3/OU=www.verisign .com/CPS Incorp.by Ref. LIABILITY LTD.(c)97
VeriSign".

Note that

"OU=Terms of use at www.verisign.com/rpa (c)00"

with a "/" in the middle of the value field. So you hit this
problem on every cert issued by Verisign. Oops.

Nor does there seem to be a way to get at the certificate itself
from within Python. There was some discussion of this in 2002 at

http://groups.google.com/group/comp....c124c606f56c0b

when someone wrote: "Furthermor e, while the server and issuer are exposed
through undocumented attributes, the server_cert is not. So there is no way to
validate the cert manually, short of rewriting socketmodule.c. This is one case
where the batteries included have been sitting on the shelf too long."

Clearly, "server()" and "issuer()" should return lists, not strings. That
would resolve the ambiguity. ASN.1 is a representation for lists, and
hammering those lists into strings loses information.

Is there a workaround for this? Without rebuilding Python
and becoming incompatible?

John Nagle
Animats
Oct 24 '06 #1
11 4049
John Nagle <na***@animats. comwrites:
Is there a workaround for this? Without rebuilding Python
and becoming incompatible?
I've parsed certs by calling openssl in a subprocess. Maybe that's
not what you wanted to hear. If you're really industrious you might
be able to extend the tlslite cert parsing code (written in pure
Python) to get those fields out.
Oct 24 '06 #2
In article <45************ **@animats.com> ,
John Nagle <na***@animats. comwrote:
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.
....
"/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International
Server CA - Class 3/OU=www.verisign .com/CPS Incorp.by Ref. LIABILITY
LTD.(c)97
VeriSign".

Note that

"OU=Terms of use at www.verisign.com/rpa (c)00"

with a "/" in the middle of the value field.
....
Is there a workaround for this? Without rebuilding Python
and becoming incompatible?
As a practical matter, I think it's fairly safe to assume
there will be no values that include / in a context like
really looks like that X.500 style distinguished name.

So if you parse out that string in those terms, and require
each of those key = value pairs to have reasonable values -
key has no embedded spaces, value has non-zero length - then
you should be OK. Re-join any invalid component to its
predecessor's value.

Donn Cave, do**@u.washingt on.edu
Oct 24 '06 #3
Donn Cave wrote:
In article <45************ **@animats.com> ,
John Nagle <na***@animats. comwrote:

> 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
documentati on at "http://docs.python.org/lib/ssl-objects.html"
says "Returns a string containing the ASN.1 distinguished name identifying
the
server's certificate.

...
>>"/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International
Server CA - Class 3/OU=www.verisign .com/CPS Incorp.by Ref. LIABILITY
LTD.(c)97
VeriSign".

Note that

"OU=Terms of use at www.verisign.com/rpa (c)00"

with a "/" in the middle of the value field.

...
>>Is there a workaround for this? Without rebuilding Python
and becoming incompatible?


As a practical matter, I think it's fairly safe to assume
there will be no values that include / in a context like
really looks like that X.500 style distinguished name.
Actually, we've just discovered an exploit. By
ordering a low-level certificate with a "/" in the right
place, you can create the illusion (at least for flawed
implementations like this one) that the certificate
belongs to someone else. Just order a certificate from
GoDaddy, enter something like this in the "Name" field

"Myphonynam e/C=US/ST=California/L=San Jose/O=eBay Inc./OU=Site
Operations/CN=signin.ebay. com"

and Python code will be spoofed into thinking you're eBay.

Fortunately, browsers don't use Python code.

The actual bug is in

python/trunk/Modules/_ssl.c

at

if ((self->server_cert = SSL_get_peer_ce rtificate(self->ssl))) {
X509_NAME_oneli ne(X509_get_sub ject_name(self->server_cert) ,
self->server, X509_NAME_MAXLE N);
X509_NAME_oneli ne(X509_get_iss uer_name(self->server_cert) ,
self->issuer, X509_NAME_MAXLE N);

The "X509_name_onel ine" function takes an X509_NAME structure, which is
the certificate system's representation of a list, and flattens it
into a printable string. This is a debug function, not one for use in
production code. The SSL documentation for "X509_name_onel ine" says:

"The functions X509_NAME_oneli ne() and X509_NAME_print () are legacy
functions which produce a non standard output form, they don't handle
multi character fields and have various quirks and inconsistencies .
Their use is strongly discouraged in new applications."

What OpenSSL callers are supposed to do is call X509_NAME_entry _count()
to get the number of entries in an X509_NAME structure, then get each
entry with X509_NAME_get_e ntry(). A few more calls will obtain
the name/value pair from the entry, as UTF8 strings, which should
be converted to Python UNICODE strings.

X509_NAME_oneli ne() doesn't handle Unicode; it converts non-ASCII
values to "\xnn" format. Again, it's for debug output only.

So what's needed are two new functions for Python's SSL sockets to
replace "issuer" and "server". The new functions should return
lists of Unicode strings representing the key/value pairs.
(A list is needed, not a dictionary; two strings with the same key
are both possible and common.)

The reason this now matters is that new "high assurance" certs,
the ones that tell you how much a site can be trusted, are now being
deployed, and to use them effectively, you need that info. Support for
them is in Internet Explorer 7, so they're going to be widespread soon.
Python needs to catch up.

I'll submit a bug report.

John Nagle
Animats
Oct 24 '06 #4
John Nagle <na***@animats. comwrites:
The reason this now matters is that new "high assurance" certs,
the ones that tell you how much a site can be trusted, are now being
deployed,
Oh my, I hadn't heard about this. They come up with new scams all the
time. I guess I'll check for info. It sounds sort of like the terror
alert system, which tells us how scared to be on any particular day ;-)
Oct 24 '06 #5
Paul Rubin wrote:
John Nagle <na***@animats. comwrites:
>>The reason this now matters is that new "high assurance" certs,
the ones that tell you how much a site can be trusted, are now being
deployed,


Oh my, I hadn't heard about this. They come up with new scams all the
time. I guess I'll check for info. It sounds sort of like the terror
alert system, which tells us how scared to be on any particular day ;-)
Anyway, I've submitted it as a Python bug report:

[1583946] SSL "issuer" and "server" functions problems - security

And for the record, here's a workaround: do a split with this
regular expression:

pparsecertstrin gre = re.compile(
r"""(?:/)(\w(?:\w|))(?: =)""")

You'll get lists of the form

['', key1, value1, key2, value2 ...]

This isn't totally unspoofable, and won't work for Unicode certs,
but it works for the few dozen common certs I've run through it.

John Nagle
Animats
Oct 25 '06 #6
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
Is it an option for you to use 3rd party libraries (please note that the
Python stdlib SSL library does not do certificate validation etc. which
you'd typically want in a production application)?

With M2Crypto you could do something like this:

from M2Crypto import SSL

ctx = SSL.Context()
conn = SSL.Connection( ctx)
conn.connect((' www.verisign.co m', 443))
cert = conn.get_peer_c ert()
print cert.get_issuer ().as_text()
print cert.get_subjec t().as_text()
try:
print cert.get_ext('s ubjectAltName') .get_value()
except LookupError:
print 'no subjectAltName'
try:
print cert.get_subjec t().CN
except AttributeError:
print 'no commonName'

Please note, however, that if you need the server name because you want
to validate that you connected to the server you intended to, it would
be better to let M2Crypto do it for you or use the M2Crypto SSL.Checker
class explicitly yourself.

Other Python crypto libraries probably have equivalent APIs.

--
Heikki Toivonen
Oct 25 '06 #7
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.c om"

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.

Play around with OpenSSL's command-line option 'nameopt':
openssl x509 -inform der -in VSIGN1.CER -subject -issuer -noout
subject= /C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification
Authority
issuer= /C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification
Authority
openssl x509 -inform der -in VSIGN1.CER -subject -issuer -noout
-nameopt rfc2253
subject= OU=Class 1 Public Primary Certification Authority,O=Ver iSign\,
Inc.,C=US
issuer= OU=Class 1 Public Primary Certification Authority,O=Ver iSign\,
Inc.,C=US

Guess the second is what Python SSL object also should return. No idea
whether this is available at OpenSSL's API level.

Ciao, Michael.
Oct 26 '06 #8
Donn Cave wrote:
In article <45************ **@animats.com> ,
John Nagle <na***@animats. comwrote:
>>
Note that

"OU=Terms of use at www.verisign.com/rpa (c)00"

with a "/" in the middle of the value field.

...
>>Is there a workaround for this? Without rebuilding Python
and becoming incompatible?

As a practical matter, I think it's fairly safe to assume
there will be no values that include / in a context like
really looks like that X.500 style distinguished name.

So if you parse out that string in those terms, and require
each of those key = value pairs to have reasonable values -
key has no embedded spaces, value has non-zero length - then
you should be OK. Re-join any invalid component to its
predecessor's value.
Don't make such assumptions when parsing DNs!
It's a major PITA in the long run.

Ciao, Michael.
Oct 26 '06 #9
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
documentati on 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.c om"

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_onel ine()" which is deprecated, which Python
is using, and which uses "/" as a delimiter without escaping "/" in
content.

OpenSSL also has "X509_NAME_prin t_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_prin t_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_oneli ne(), 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_...l.gmail.com%3E

And it had to be fixed in OpenCA. See

http://www.mail-archive.com/op******.../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
Oct 27 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
5702
by: Martin | last post by:
Dear Group Sorry for posting this here. I'm desperate for a solution to this problem and thought some of you might have come across it with .NET and SQL Server. Let's assume I've the following code: Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
1
12943
by: Gustavo Quinteros | last post by:
I'm trying to sign a XML with a X509 Certificate (Like an email), and store it in a database. I want to include the certificate in the XML in order to display the certificate properties (like click in the red insignia in a signed email message) for this purpose I'm using Visual Basic .Net 2003 with WSE 2.0 preview edition I succefully...
4
11315
by: Matt Frame | last post by:
I am working on a special ASP.Net application that receives files from customers. The connection is made via HTTPS and the client sends the file as a POST to my ASP.Net listener. All of this works fine. Now I am looking at how to validate the clients certificate programmatically. The client application sends to me with something like:...
1
1167
by: Nelson R. | last post by:
Hi, i need to get some info from a website page that requires an certificate. Ive got the provided certificate installed in IE, and when accessing the website page, it shows a window to select the client certificate and then shows the page correctly. Im trying to do this by code (vs2003 C# aspnet), using webrequest.
0
1155
by: Sa¹o Zagoranski | last post by:
Hi, My task is to create a website in asp.net 2.0 that is secured with a digital signature. The default page should be accessible by all (greeting page with a asp.net 2.0 login control) and when the user would press OK on the login form, he would be redirected to page where only people with a valid username, password and digital...
1
2385
by: Rymfax | last post by:
Hello, I'm hoping you guys can help me out. I'm trying to extract the certificate info from a digitally signed .cat file for a driver and then add that certificated as a trusted publisher. I'm having no real luck figuring out how to do this. I have an example of how to make a self-signed certificate and add it to a certificate store, but...
1
3598
by: vaibhavchavan | last post by:
Hi I am doing application for signing of soap message with digital certificate . I am using WSE 2.0 I worte the the simple webservice & deployed it on in our server machine . To make it secured i added the certificate to IIS . My web service code like this.
3
6473
by: Fredrik Lundh | last post by:
Ghirai wrote: you can get some info via (undocumented?) attributes on the file handle: <httplib.SSLFile instance at 0x00CE2508> '/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA' '/C=US/ST=California/L=Mountain View/O=Google Inc/CN=mail.google.com'
0
3150
by: AK | last post by:
Hello, I'm new to cryptography and I would just like to check that I'm doing the right thing when signing an XML file. I've got a PKCS#12 certificate (created using OpenSSL) which I'm loading into a X509Certificate2 object. I get the private key out of that object to sign with, and I include the certificate in the KeyInfo object. However,...
0
7915
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7841
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8339
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7965
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
1
5712
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5392
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3869
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1452
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1184
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.