aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael J. Bazzinotti <mbazzinotti@gmail.com>2015-12-28 15:20:45 -0500
committerMichael J. Bazzinotti <mbazzinotti@gmail.com>2015-12-28 15:20:45 -0500
commit80690b79062c739fc8adfc725d39a68d4b65b43a (patch)
treee80e05eff05a690a0c7d76ba36b46cb4329c631f
parent6391b05ef1b92585765eb77e352921ec61b65020 (diff)
downloadmitmproxy-80690b79062c739fc8adfc725d39a68d4b65b43a.tar.gz
mitmproxy-80690b79062c739fc8adfc725d39a68d4b65b43a.tar.bz2
mitmproxy-80690b79062c739fc8adfc725d39a68d4b65b43a.zip
[docs/libmproxy/test] Support single client-side cert file as argument to
--client-certs
-rw-r--r--docs/certinstall.rst17
-rw-r--r--libmproxy/cmdline.py2
-rw-r--r--libmproxy/models/connections.py13
-rw-r--r--libmproxy/proxy/config.py8
-rw-r--r--test/test_proxy.py6
-rw-r--r--test/test_server.py9
6 files changed, 42 insertions, 13 deletions
diff --git a/docs/certinstall.rst b/docs/certinstall.rst
index 5ec7b7ce..5a8cce64 100644
--- a/docs/certinstall.rst
+++ b/docs/certinstall.rst
@@ -175,10 +175,21 @@ no such file exists, it will be generated automatically.
Using a client side certificate
-------------------------------
-You can use a client certificate by passing the ``--client-certs DIRECTORY`` option to mitmproxy.
+You can use a client certificate by passing the ``--client-certs DIRECTORY|FILE``
+option to mitmproxy. Using a directory allows certs to be selected based on
+hostname, while using a filename allows a single specific certificate to be used for
+all SSL connections. Certificate files must be in the PEM format and should
+contain both the unencrypted private key and the certificate.
+
+Multiple certs by Hostname
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you've specified a directory to ``--client-certs``, then the following
+behavior will be taken:
+
If you visit example.org, mitmproxy looks for a file named ``example.org.pem`` in the specified
-directory and uses this as the client cert. The certificate file needs to be in the PEM format and
-should contain both the unencrypted private key and the certificate.
+directory and uses this as the client cert.
+
.. _Certificate Pinning: http://security.stackexchange.com/questions/29988/what-is-certificate-pinning/ \ No newline at end of file
diff --git a/libmproxy/cmdline.py b/libmproxy/cmdline.py
index 16678486..99b76e68 100644
--- a/libmproxy/cmdline.py
+++ b/libmproxy/cmdline.py
@@ -407,7 +407,7 @@ def proxy_ssl_options(parser):
group.add_argument(
"--client-certs", action="store",
type=str, dest="clientcerts", default=None,
- help="Client certificate directory."
+ help="Client certificate file or directory."
)
group.add_argument(
"--no-upstream-cert", default=False,
diff --git a/libmproxy/models/connections.py b/libmproxy/models/connections.py
index 3aa522ea..0991955d 100644
--- a/libmproxy/models/connections.py
+++ b/libmproxy/models/connections.py
@@ -174,11 +174,14 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
def establish_ssl(self, clientcerts, sni, **kwargs):
clientcert = None
if clientcerts:
- path = os.path.join(
- clientcerts,
- self.address.host.encode("idna")) + ".pem"
- if os.path.exists(path):
- clientcert = path
+ if os.path.isfile(clientcerts):
+ clientcert = clientcerts
+ else:
+ path = os.path.join(
+ clientcerts,
+ self.address.host.encode("idna")) + ".pem"
+ if os.path.exists(path):
+ clientcert = path
self.convert_to_ssl(cert=clientcert, sni=sni, **kwargs)
self.sni = sni
diff --git a/libmproxy/proxy/config.py b/libmproxy/proxy/config.py
index c7b51311..f06e55ca 100644
--- a/libmproxy/proxy/config.py
+++ b/libmproxy/proxy/config.py
@@ -133,10 +133,12 @@ def process_proxy_options(parser, options):
if options.clientcerts:
options.clientcerts = os.path.expanduser(options.clientcerts)
- if not os.path.exists(options.clientcerts) or not os.path.isdir(options.clientcerts):
+ if not (os.path.exists(options.clientcerts) or
+ os.path.isdir(options.clientcerts) or
+ os.path.isfile(options.clientcerts)):
return parser.error(
- "Client certificate directory does not exist or is not a directory: %s" %
- options.clientcerts
+ "Client certificate argument is not a file or directory, "
+ "or does not exist: %s" % options.clientcerts
)
if options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd:
diff --git a/test/test_proxy.py b/test/test_proxy.py
index b3e7258a..a0530c79 100644
--- a/test/test_proxy.py
+++ b/test/test_proxy.py
@@ -1,3 +1,4 @@
+import os
import mock
from OpenSSL import SSL
@@ -99,8 +100,11 @@ class TestProcessProxyOptions:
def test_client_certs(self):
with tutils.tmpdir() as cadir:
self.assert_noerr("--client-certs", cadir)
+ self.assert_noerr(
+ "--client-certs",
+ os.path.join(tutils.test_data.path("data/clientcert"), "client.pem"))
self.assert_err(
- "directory does not exist",
+ "not a file or directory",
"--client-certs",
"nonexistent")
diff --git a/test/test_server.py b/test/test_server.py
index e48e46fe..09cfa381 100644
--- a/test/test_server.py
+++ b/test/test_server.py
@@ -1,3 +1,4 @@
+import os
import socket
import time
from OpenSSL import SSL
@@ -316,6 +317,14 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin, TcpMixin):
clientcerts = True
def test_clientcert(self):
+ self.config.clientcerts = os.path.join(
+ tutils.test_data.path("data/clientcert"), "client.pem")
+ f = self.pathod("304")
+ assert f.status_code == 304
+ assert self.server.last_log()["request"]["clientcert"]["keyinfo"]
+
+ def test_clientcerts(self):
+ self.config.clientcerts = tutils.test_data.path("data/clientcert")
f = self.pathod("304")
assert f.status_code == 304
assert self.server.last_log()["request"]["clientcert"]["keyinfo"]