Commit ffe576dc authored by Bill Janssen's avatar Bill Janssen

SSL certificate distinguished names should be represented by tuples

parent 38336406
...@@ -173,6 +173,8 @@ use the first chain it finds in the file which matches. ...@@ -173,6 +173,8 @@ use the first chain it finds in the file which matches.
Some "standard" root certificates are available at Some "standard" root certificates are available at
http://www.thawte.com/roots/ (for Thawte roots) and http://www.thawte.com/roots/ (for Thawte roots) and
http://www.verisign.com/support/roots.html (for Verisign roots). http://www.verisign.com/support/roots.html (for Verisign roots).
See also :rfc:`4158` for more discussion of the way in which
certification chains can be built.
sslsocket Objects sslsocket Objects
...@@ -242,23 +244,23 @@ sslsocket Objects ...@@ -242,23 +244,23 @@ sslsocket Objects
the certificate), ``notBefore`` (the time before which the certificate should not be trusted), the certificate), ``notBefore`` (the time before which the certificate should not be trusted),
and ``notAfter`` (the time after which the certificate should not be trusted) filled in. and ``notAfter`` (the time after which the certificate should not be trusted) filled in.
The "subject" and "issuer" fields are themselves dictionaries containing the fields given The "subject" and "issuer" fields are tuples containing the name-value fields
in the certificate's data structure for each principal:: given in the certificate's data structure for each principal::
{'issuer': {'commonName': u'somemachine.python.org', {'issuer': (('countryName', u'US'),
'countryName': u'US', ('stateOrProvinceName', u'Delaware'),
'localityName': u'Wilmington', ('localityName', u'Wilmington'),
'organizationName': u'Python Software Foundation', ('organizationName', u'Python Software Foundation'),
'organizationalUnitName': u'SSL', ('organizationalUnitName', u'SSL'),
'stateOrProvinceName': u'Delaware'}, ('commonName', u'somemachine.python.org')),
'subject': {'commonName': u'somemachine.python.org', 'notAfter': 'Feb 16 16:54:50 2013 GMT',
'countryName': u'US', 'notBefore': 'Aug 27 16:54:50 2007 GMT',
'localityName': u'Wilmington', 'subject': (('countryName', u'US'),
'organizationName': u'Python Software Foundation', ('stateOrProvinceName', u'Delaware'),
'organizationalUnitName': u'SSL', ('localityName', u'Wilmington'),
'stateOrProvinceName': u'Delaware'}, ('organizationName', u'Python Software Foundation'),
'notAfter': 'Sep 4 21:54:26 2007 GMT', ('organizationalUnitName', u'SSL'),
'notBefore': 'Aug 25 21:54:26 2007 GMT', ('commonName', u'somemachine.python.org')),
'version': 2} 'version': 2}
This certificate is said to be *self-signed*, because the subject This certificate is said to be *self-signed*, because the subject
...@@ -314,27 +316,32 @@ sends some bytes, and reads part of the response:: ...@@ -314,27 +316,32 @@ sends some bytes, and reads part of the response::
# note that closing the sslsocket will also close the underlying socket # note that closing the sslsocket will also close the underlying socket
ssl_sock.close() ssl_sock.close()
As of August 25, 2007, the certificate printed by this program As of September 4, 2007, the certificate printed by this program
looked like this:: looked like this::
{'issuer': {'commonName': u'VeriSign Class 3 Extended Validation SSL SGC CA', {'issuer': (('countryName', u'US'),
'countryName': u'US', ('organizationName', u'VeriSign, Inc.'),
'organizationName': u'VeriSign, Inc.', ('organizationalUnitName', u'VeriSign Trust Network'),
'organizationalUnitName': u'Terms of use at https://www.verisign.com/rpa (c)06'}, ('organizationalUnitName',
'subject': {'1.3.6.1.4.1.311.60.2.1.2': u'Delaware', u'Terms of use at https://www.verisign.com/rpa (c)06'),
'1.3.6.1.4.1.311.60.2.1.3': u'US', ('commonName',
'commonName': u'www.verisign.com', u'VeriSign Class 3 Extended Validation SSL SGC CA')),
'countryName': u'US', 'notAfter': 'May 8 23:59:59 2009 GMT',
'localityName': u'Mountain View', 'notBefore': 'May 9 00:00:00 2007 GMT',
'organizationName': u'VeriSign, Inc.', 'subject': (('serialNumber', u'2497886'),
'organizationalUnitName': u'Terms of use at www.verisign.com/rpa (c)06', ('1.3.6.1.4.1.311.60.2.1.3', u'US'),
'postalCode': u'94043', ('1.3.6.1.4.1.311.60.2.1.2', u'Delaware'),
'serialNumber': u'2497886', ('countryName', u'US'),
'stateOrProvinceName': u'California', ('postalCode', u'94043'),
'streetAddress': u'487 East Middlefield Road'}, ('stateOrProvinceName', u'California'),
'notAfter': 'May 8 23:59:59 2009 GMT', ('localityName', u'Mountain View'),
'notBefore': 'May 9 00:00:00 2007 GMT', ('streetAddress', u'487 East Middlefield Road'),
'version': 2} ('organizationName', u'VeriSign, Inc.'),
('organizationalUnitName', u'Production Security Services'),
('organizationalUnitName',
u'Terms of use at www.verisign.com/rpa (c)06'),
('commonName', u'www.verisign.com')),
'version': 2}
Server-side operation Server-side operation
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
...@@ -386,3 +393,5 @@ Class :class:`socket.socket` ...@@ -386,3 +393,5 @@ Class :class:`socket.socket`
`Introducing SSL and Certificates using OpenSSL <http://old.pseudonym.org/ssl/wwwj-index.html>`_, by Frederick J. Hirsch `Introducing SSL and Certificates using OpenSSL <http://old.pseudonym.org/ssl/wwwj-index.html>`_, by Frederick J. Hirsch
`Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management`, :rfc:`1422`, by Steve Kent `Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management`, :rfc:`1422`, by Steve Kent
`Internet X.509 Public Key Infrastructure Certificate and CRL Profile`, :rfc:`3280`, Housley et. al.
...@@ -137,18 +137,15 @@ class ConnectedTests(unittest.TestCase): ...@@ -137,18 +137,15 @@ class ConnectedTests(unittest.TestCase):
cert = c2.getpeercert() cert = c2.getpeercert()
if not cert: if not cert:
raise test_support.TestFailed("Can't get peer certificate.") raise test_support.TestFailed("Can't get peer certificate.")
if test_support.verbose:
sys.stdout.write(pprint.pformat(cert) + '\n')
if not cert.has_key('subject'): if not cert.has_key('subject'):
raise test_support.TestFailed( raise test_support.TestFailed(
"No subject field in certificate: %s." % "No subject field in certificate: %s." %
pprint.pformat(cert)) pprint.pformat(cert))
if not (cert['subject'].has_key('organizationName')): if not ('organizationName', 'Python Software Foundation') in cert['subject']:
raise test_support.TestFailed(
"No 'organizationName' field in certificate subject: %s." %
pprint.pformat(cert))
if (cert['subject']['organizationName'] !=
"Python Software Foundation"):
raise test_support.TestFailed( raise test_support.TestFailed(
"Invalid 'organizationName' field in certificate subject; " "Missing or invalid 'organizationName' field in certificate subject; "
"should be 'Python Software Foundation'."); "should be 'Python Software Foundation'.");
c2.close() c2.close()
...@@ -336,7 +333,7 @@ def create_cert_files(hostname=None): ...@@ -336,7 +333,7 @@ def create_cert_files(hostname=None):
def test_main(verbose=False): def test_main(verbose=False):
if skip_expected: if skip_expected:
raise test_support.TestSkipped("socket module has no ssl support") raise test_support.TestSkipped("No SSL support")
global CERTFILE global CERTFILE
CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
......
...@@ -437,12 +437,15 @@ PySSL_issuer(PySSLObject *self) ...@@ -437,12 +437,15 @@ PySSL_issuer(PySSLObject *self)
} }
static PyObject * static PyObject *
_create_dict_for_X509_NAME (X509_NAME *xname) _create_tuple_for_X509_NAME (X509_NAME *xname)
{ {
PyObject *pd = PyDict_New(); PyObject *pt = NULL;
PyObject *entry_tuple = NULL;
int entry_count = X509_NAME_entry_count(xname);
int index_counter; int index_counter;
if (pd == NULL) pt = PyTuple_New(entry_count);
if (pt == NULL)
return NULL; return NULL;
for (index_counter = 0; for (index_counter = 0;
...@@ -480,18 +483,20 @@ _create_dict_for_X509_NAME (X509_NAME *xname) ...@@ -480,18 +483,20 @@ _create_dict_for_X509_NAME (X509_NAME *xname)
Py_DECREF(name_obj); Py_DECREF(name_obj);
goto fail0; goto fail0;
} }
if (PyDict_SetItem(pd, name_obj, value_obj) < 0) { entry_tuple = PyTuple_New(2);
if (entry_tuple == NULL) {
Py_DECREF(name_obj); Py_DECREF(name_obj);
Py_DECREF(value_obj); Py_DECREF(value_obj);
goto fail0; goto fail0;
} }
Py_DECREF(name_obj); PyTuple_SET_ITEM(entry_tuple, 0, name_obj);
Py_DECREF(value_obj); PyTuple_SET_ITEM(entry_tuple, 1, value_obj);
PyTuple_SET_ITEM(pt, index_counter, entry_tuple);
} }
return pd; return pt;
fail0: fail0:
Py_XDECREF(pd); Py_XDECREF(pt);
return NULL; return NULL;
} }
...@@ -520,7 +525,7 @@ PySSL_peercert(PySSLObject *self) ...@@ -520,7 +525,7 @@ PySSL_peercert(PySSLObject *self)
if ((verification & SSL_VERIFY_PEER) == 0) if ((verification & SSL_VERIFY_PEER) == 0)
return retval; return retval;
peer = _create_dict_for_X509_NAME( peer = _create_tuple_for_X509_NAME(
X509_get_subject_name(self->peer_cert)); X509_get_subject_name(self->peer_cert));
if (peer == NULL) if (peer == NULL)
goto fail0; goto fail0;
...@@ -530,7 +535,7 @@ PySSL_peercert(PySSLObject *self) ...@@ -530,7 +535,7 @@ PySSL_peercert(PySSLObject *self)
} }
Py_DECREF(peer); Py_DECREF(peer);
issuer = _create_dict_for_X509_NAME( issuer = _create_tuple_for_X509_NAME(
X509_get_issuer_name(self->peer_cert)); X509_get_issuer_name(self->peer_cert));
if (issuer == NULL) if (issuer == NULL)
goto fail0; goto fail0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment