[docs/libmproxy/test] Support single client-side cert file as argument to

--client-certs
This commit is contained in:
Michael J. Bazzinotti 2015-12-28 15:20:45 -05:00
parent 6391b05ef1
commit 80690b7906
6 changed files with 42 additions and 13 deletions

View File

@ -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/

View File

@ -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,

View File

@ -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

View File

@ -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:

View File

@ -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")

View File

@ -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"]