diff options
author | Jean-Paul Calderone <exarkun@divmod.com> | 2011-05-17 15:45:21 -0400 |
---|---|---|
committer | Jean-Paul Calderone <exarkun@divmod.com> | 2011-05-17 15:45:21 -0400 |
commit | 95b92c7888b4acce21e87ec975cac31661469e8a (patch) | |
tree | a264dc0f39919ecaaa151fce272eeee689f8d541 /OpenSSL | |
parent | 9eff5699339c34439d7085e937abd0f3b9235afe (diff) | |
download | pyopenssl-95b92c7888b4acce21e87ec975cac31661469e8a.tar.gz |
Apply the get_peer_cert_chain parts of okuda's patch
Diffstat (limited to 'OpenSSL')
-rwxr-xr-x | OpenSSL/ssl/connection.c | 38 | ||||
-rw-r--r-- | OpenSSL/test/test_ssl.py | 31 | ||||
-rw-r--r-- | OpenSSL/tsafe.py | 2 |
3 files changed, 70 insertions, 1 deletions
diff --git a/OpenSSL/ssl/connection.c b/OpenSSL/ssl/connection.c index 5b304b1..09e2607 100755 --- a/OpenSSL/ssl/connection.c +++ b/OpenSSL/ssl/connection.c @@ -1098,6 +1098,43 @@ ssl_Connection_get_peer_certificate(ssl_ConnectionObj *self, PyObject *args) } } +static char ssl_Connection_get_peer_cert_chain_doc[] = "\n\ +Retrieve the other side's certificate (if any)\n\ +\n\ +Arguments: self - The Connection object\n\ + args - The Python argument tuple, should be empty\n\ +Returns: The peer's certificates chain tuple\n\ +"; +static PyObject * +ssl_Connection_get_peer_cert_chain(ssl_ConnectionObj *self, PyObject *args) +{ + STACK_OF(X509) *sk; + PyObject *tpl, *item; + Py_ssize_t i; + + if (!PyArg_ParseTuple(args, ":get_peer_cert_chain")) + return NULL; + + sk = SSL_get_peer_cert_chain(self->ssl); + if (sk != NULL) + { + tpl = PyTuple_New(sk_X509_num(sk)); + for (i=0; i<sk_X509_num(sk); i++) + { + item = (PyObject *)crypto_X509_New(sk_X509_value(sk,i), 1); + Py_INCREF(item); + PyTuple_SET_ITEM(tpl, i, item); + } + return tpl; + } + else + { + Py_INCREF(Py_None); + return Py_None; + } + +} + static char ssl_Connection_want_read_doc[] = "\n\ Checks if more data has to be read from the transport layer to complete an\n\ operation.\n\ @@ -1175,6 +1212,7 @@ static PyMethodDef ssl_Connection_methods[] = ADD_METHOD(master_key), ADD_METHOD(sock_shutdown), ADD_METHOD(get_peer_certificate), + ADD_METHOD(get_peer_cert_chain), ADD_METHOD(want_read), ADD_METHOD(want_write), ADD_METHOD(set_accept_state), diff --git a/OpenSSL/test/test_ssl.py b/OpenSSL/test/test_ssl.py index ff2e725..5752d13 100644 --- a/OpenSSL/test/test_ssl.py +++ b/OpenSSL/test/test_ssl.py @@ -307,6 +307,37 @@ class ContextTests(TestCase, _LoopbackMixin): context = Context(TLSv1_METHOD) self.assertRaises(TypeError, context.get_timeout, None) + def test_get_peer_cert_chain(self): + """ + L{Connection.get_peer_cert_chain} returns the tuple of certificates + which the connected server returned for the certification verification. + """ + # Testing this requires a server with a certificate signed by one of + # the CAs in the platform CA location. Getting one of those costs + # money. Fortunately (or unfortunately, depending on your + # perspective), it's easy to think of a public server on the + # internet which has such a certificate. Connecting to the network + # in a unit test is bad, but it's the only way I can think of to + # really test this. -exarkun + + # Arg, verisign.com doesn't speak TLSv1 + context = Context(SSLv3_METHOD) + + client = socket() + client.connect(('verisign.com', 443)) + clientSSL = Connection(context, client) + clientSSL.set_connect_state() + clientSSL.do_handshake() + cert = clientSSL.get_peer_certificate() + certs = clientSSL.get_peer_cert_chain() + self.assertEqual(dump_certificate(FILETYPE_PEM, cert), + dump_certificate(FILETYPE_PEM, certs[0])) + self.assertEqual(certs[0].get_subject().CN, 'www.verisign.com') + self.assertEqual(certs[1].get_subject().CN, + 'VeriSign Class 3 Extended Validation SSL SGC CA') + self.assertEqual(certs[2].get_subject().CN, + 'VeriSign Class 3 Public Primary Certification Authority - G5') + def test_timeout(self): """ diff --git a/OpenSSL/tsafe.py b/OpenSSL/tsafe.py index fe4b75f..9d7ad2f 100644 --- a/OpenSSL/tsafe.py +++ b/OpenSSL/tsafe.py @@ -16,7 +16,7 @@ class Connection: 'setblocking', 'fileno', 'shutdown', 'close', 'get_cipher_list', 'getpeername', 'getsockname', 'getsockopt', 'setsockopt', 'makefile', 'get_app_data', 'set_app_data', 'state_string', - 'sock_shutdown', 'get_peer_certificate', 'want_read', + 'sock_shutdown', 'get_peer_certificate', 'get_peer_cert_chain', 'want_read', 'want_write', 'set_connect_state', 'set_accept_state', 'connect_ex', 'sendall'): exec("""def %s(self, *args): |