aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--netlib/certutils.py6
-rw-r--r--netlib/tcp.py10
-rw-r--r--test/data/clientcert/.gitignore3
-rw-r--r--test/data/clientcert/client.cnf5
-rw-r--r--test/data/clientcert/client.pem42
-rwxr-xr-xtest/data/clientcert/make8
-rw-r--r--test/test_tcp.py22
7 files changed, 92 insertions, 4 deletions
diff --git a/netlib/certutils.py b/netlib/certutils.py
index 3fd57b2b..e1407936 100644
--- a/netlib/certutils.py
+++ b/netlib/certutils.py
@@ -256,11 +256,11 @@ class SSLCert:
@property
def cn(self):
- cn = None
+ c = None
for i in self.subject:
if i[0] == "CN":
- cn = i[1]
- return cn
+ c = i[1]
+ return c
@property
def altnames(self):
diff --git a/netlib/tcp.py b/netlib/tcp.py
index afb7e059..4b547d1f 100644
--- a/netlib/tcp.py
+++ b/netlib/tcp.py
@@ -173,10 +173,14 @@ class TCPClient:
self.ssl_established = False
def convert_to_ssl(self, clientcert=None, sni=None, method=TLSv1_METHOD, options=None):
+ """
+ clientcert: Path to a file containing both client cert and private key.
+ """
context = SSL.Context(method)
if not options is None:
ctx.set_options(options)
if clientcert:
+ context.use_privatekey_file(clientcert)
context.use_certificate_file(clientcert)
self.connection = SSL.Connection(context, self.connection)
self.ssl_established = True
@@ -238,6 +242,7 @@ class BaseHandler:
self.server = server
self.finished = False
self.ssl_established = False
+ self.clientcert = None
def convert_to_ssl(self, cert, key, method=SSLv23_METHOD, options=None):
"""
@@ -246,13 +251,16 @@ class BaseHandler:
ctx = SSL.Context(method)
if not options is None:
ctx.set_options(options)
+ # SNI callback happens during do_handshake()
ctx.set_tlsext_servername_callback(self.handle_sni)
ctx.use_privatekey_file(key)
ctx.use_certificate_file(cert)
+ def ver(*args):
+ self.clientcert = certutils.SSLCert(args[1])
+ ctx.set_verify(SSL.VERIFY_PEER, ver)
self.connection = SSL.Connection(ctx, self.connection)
self.ssl_established = True
self.connection.set_accept_state()
- # SNI callback happens during do_handshake()
try:
self.connection.do_handshake()
except SSL.Error, v:
diff --git a/test/data/clientcert/.gitignore b/test/data/clientcert/.gitignore
new file mode 100644
index 00000000..07bc53d2
--- /dev/null
+++ b/test/data/clientcert/.gitignore
@@ -0,0 +1,3 @@
+client.crt
+client.key
+client.req
diff --git a/test/data/clientcert/client.cnf b/test/data/clientcert/client.cnf
new file mode 100644
index 00000000..5046a944
--- /dev/null
+++ b/test/data/clientcert/client.cnf
@@ -0,0 +1,5 @@
+[ ssl_client ]
+basicConstraints = CA:FALSE
+nsCertType = client
+keyUsage = digitalSignature, keyEncipherment
+extendedKeyUsage = clientAuth
diff --git a/test/data/clientcert/client.pem b/test/data/clientcert/client.pem
new file mode 100644
index 00000000..4927bca2
--- /dev/null
+++ b/test/data/clientcert/client.pem
@@ -0,0 +1,42 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAzCpoRjSTfIN24kkNap/GYmP9zVWj0Gk8R5BB/PvvN0OB1Zk0
+EEYPsWCcuhEdK0ehiDZX030doF0DOncKKa6mop/d0x2o+ts42peDhZM6JNUrm6d+
+ZWQVtio33mpp77UMhR093vaA+ExDnmE26kBTVijJ1+fRAVDXG/cmQINEri91Kk/G
+3YJ5e45UrohGI5seBZ4vV0xbHtmczFRhYFlGOvYsoIe4Lvz/eFS2pIrTIpYQ2VM/
+SQQl+JFy+NlQRsWG2NrxtKOzMnnDE7YN4I3z5D5eZFo1EtwZ48LNCeSwrEOdfuzP
+G5q5qbs5KpE/x85H9umuRwSCIArbMwBYV8a8JwIDAQABAoIBAFE3FV/IDltbmHEP
+iky93hbJm+6QgKepFReKpRVTyqb7LaygUvueQyPWQMIriKTsy675nxo8DQr7tQsO
+y3YlSZgra/xNMikIB6e82c7K8DgyrDQw/rCqjZB3Xt4VCqsWJDLXnQMSn98lx0g7
+d7Lbf8soUpKWXqfdVpSDTi4fibSX6kshXyfSTpcz4AdoncEpViUfU1xkEEmZrjT8
+1GcCsDC41xdNmzCpqRuZX7DKSFRoB+0hUzsC1oiqM7FD5kixonRd4F5PbRXImIzt
+6YCsT2okxTA04jX7yByis7LlOLTlkmLtKQYuc3erOFvwx89s4vW+AeFei+GGNitn
+tHfSwbECgYEA7SzV+nN62hAERHlg8cEQT4TxnsWvbronYWcc/ev44eHSPDWL5tPi
+GHfSbW6YAq5Wa0I9jMWfXyhOYEC3MZTC5EEeLOB71qVrTwcy/sY66rOrcgjFI76Q
+5JFHQ4wy3SWU50KxE0oWJO9LIowprG+pW1vzqC3VF0T7q0FqESrY4LUCgYEA3F7Z
+80ndnCUlooJAb+Hfotv7peFf1o6+m1PTRcz1lLnVt5R5lXj86kn+tXEpYZo1RiGR
+2rE2N0seeznWCooakHcsBN7/qmFIhhooJNF7yW+JP2I4P2UV5+tJ+8bcs/voUkQD
+1x+rGOuMn8nvHBd2+Vharft8eGL2mgooPVI2XusCgYEAlMZpO3+w8pTVeHaDP2MR
+7i/AuQ3cbCLNjSX3Y7jgGCFllWspZRRIYXzYPNkA9b2SbBnTLjjRLgnEkFBIGgvs
+7O2EFjaCuDRvydUEQhjq4ErwIsopj7B8h0QyZcbOKTbn3uFQ3n68wVJx2Sv/ADHT
+FIHrp/WIE96r19Niy34LKXkCgYB2W59VsuOKnMz01l5DeR5C+0HSWxS9SReIl2IO
+yEFSKullWyJeLIgyUaGy0990430feKI8whcrZXYumuah7IDN/KOwzhCk8vEfzWao
+N7bzfqtJVrh9HA7C7DVlO+6H4JFrtcoWPZUIomJ549w/yz6EN3ckoMC+a/Ck1TW9
+ka1QFwKBgQCywG6TrZz0UmOjyLQZ+8Q4uvZklSW5NAKBkNnyuQ2kd5rzyYgMPE8C
+Er8T88fdVIKvkhDyHhwcI7n58xE5Gr7wkwsrk/Hbd9/ZB2GgAPY3cATskK1v1McU
+YeX38CU0fUS4aoy26hWQXkViB47IGQ3jWo3ZCtzIJl8DI9/RsBWTnw==
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIICYDCCAckCAQEwDQYJKoZIhvcNAQEFBQAwKDESMBAGA1UEAxMJbWl0bXByb3h5
+MRIwEAYDVQQKEwltaXRtcHJveHkwHhcNMTMwMTIwMDEwODEzWhcNMTUxMDE3MDEw
+ODEzWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UE
+ChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAzCpoRjSTfIN24kkNap/GYmP9zVWj0Gk8R5BB/PvvN0OB1Zk0
+EEYPsWCcuhEdK0ehiDZX030doF0DOncKKa6mop/d0x2o+ts42peDhZM6JNUrm6d+
+ZWQVtio33mpp77UMhR093vaA+ExDnmE26kBTVijJ1+fRAVDXG/cmQINEri91Kk/G
+3YJ5e45UrohGI5seBZ4vV0xbHtmczFRhYFlGOvYsoIe4Lvz/eFS2pIrTIpYQ2VM/
+SQQl+JFy+NlQRsWG2NrxtKOzMnnDE7YN4I3z5D5eZFo1EtwZ48LNCeSwrEOdfuzP
+G5q5qbs5KpE/x85H9umuRwSCIArbMwBYV8a8JwIDAQABMA0GCSqGSIb3DQEBBQUA
+A4GBAFvI+cd47B85PQ970n2dU/PlA2/Hb1ldrrXh2guR4hX6vYx/uuk5yRI/n0Rd
+KOXJ3czO0bd2Fpe3ZoNpkW0pOSDej/Q+58ScuJd0gWCT/Sh1eRk6ZdC0kusOuWoY
+bPOPMkG45LPgUMFOnZEsfJP6P5mZIxlbCvSMFC25nPHWlct7
+-----END CERTIFICATE-----
diff --git a/test/data/clientcert/make b/test/data/clientcert/make
new file mode 100755
index 00000000..d1caea81
--- /dev/null
+++ b/test/data/clientcert/make
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+openssl genrsa -out client.key 2048
+openssl req -key client.key -new -out client.req
+openssl x509 -req -days 365 -in client.req -signkey client.key -out client.crt -extfile client.cnf -extensions ssl_client
+openssl x509 -req -days 1000 -in client.req -CA ~/.mitmproxy/mitmproxy-ca.pem -CAkey ~/.mitmproxy/mitmproxy-ca.pem -set_serial 00001 -out client.crt -extensions ssl_client
+cat client.key client.crt > client.pem
+openssl x509 -text -noout -in client.pem
diff --git a/test/test_tcp.py b/test/test_tcp.py
index d27a678a..034e43b9 100644
--- a/test/test_tcp.py
+++ b/test/test_tcp.py
@@ -57,6 +57,16 @@ class EchoHandler(tcp.BaseHandler):
self.wfile.flush()
+class CertHandler(tcp.BaseHandler):
+ sni = None
+ def handle_sni(self, connection):
+ self.sni = connection.get_servername()
+
+ def handle(self):
+ self.wfile.write("%s\n"%self.clientcert.serial)
+ self.wfile.flush()
+
+
class DisconnectHandler(tcp.BaseHandler):
def handle(self):
self.close()
@@ -168,6 +178,18 @@ class TestSSLv3Only(ServerTestBase):
tutils.raises(tcp.NetLibError, c.convert_to_ssl, sni="foo.com", method=tcp.TLSv1_METHOD)
+class TestSSLClientCert(ServerTestBase):
+ @classmethod
+ def makeserver(cls):
+ return TServer(("127.0.0.1", 0), True, cls.q, CertHandler)
+
+ def test_clientcert(self):
+ c = tcp.TCPClient("127.0.0.1", self.port)
+ c.connect()
+ c.convert_to_ssl(clientcert=tutils.test_data.path("data/clientcert/client.pem"))
+ assert c.rfile.readline().strip() == "1"
+
+
class TestSNI(ServerTestBase):
@classmethod
def makeserver(cls):