mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-30 03:14:22 +00:00
Merge pull request #870 from bazzinotti/master
[docs/libmproxy/test] Support single client-side cert file
This commit is contained in:
commit
7b093b46b6
@ -175,10 +175,21 @@ no such file exists, it will be generated automatically.
|
|||||||
Using a client side certificate
|
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
|
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
|
directory and uses this as the client cert.
|
||||||
should contain both the unencrypted private key and the certificate.
|
|
||||||
|
|
||||||
|
|
||||||
.. _Certificate Pinning: http://security.stackexchange.com/questions/29988/what-is-certificate-pinning/
|
.. _Certificate Pinning: http://security.stackexchange.com/questions/29988/what-is-certificate-pinning/
|
@ -407,7 +407,7 @@ def proxy_ssl_options(parser):
|
|||||||
group.add_argument(
|
group.add_argument(
|
||||||
"--client-certs", action="store",
|
"--client-certs", action="store",
|
||||||
type=str, dest="clientcerts", default=None,
|
type=str, dest="clientcerts", default=None,
|
||||||
help="Client certificate directory."
|
help="Client certificate file or directory."
|
||||||
)
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
"--no-upstream-cert", default=False,
|
"--no-upstream-cert", default=False,
|
||||||
|
@ -174,6 +174,9 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
|
|||||||
def establish_ssl(self, clientcerts, sni, **kwargs):
|
def establish_ssl(self, clientcerts, sni, **kwargs):
|
||||||
clientcert = None
|
clientcert = None
|
||||||
if clientcerts:
|
if clientcerts:
|
||||||
|
if os.path.isfile(clientcerts):
|
||||||
|
clientcert = clientcerts
|
||||||
|
else:
|
||||||
path = os.path.join(
|
path = os.path.join(
|
||||||
clientcerts,
|
clientcerts,
|
||||||
self.address.host.encode("idna")) + ".pem"
|
self.address.host.encode("idna")) + ".pem"
|
||||||
|
@ -133,10 +133,9 @@ def process_proxy_options(parser, options):
|
|||||||
|
|
||||||
if options.clientcerts:
|
if options.clientcerts:
|
||||||
options.clientcerts = os.path.expanduser(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):
|
||||||
return parser.error(
|
return parser.error(
|
||||||
"Client certificate directory does not exist or is not a directory: %s" %
|
"Client certificate path does not exist: %s" % options.clientcerts
|
||||||
options.clientcerts
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd:
|
if options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd:
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
import mock
|
import mock
|
||||||
from OpenSSL import SSL
|
from OpenSSL import SSL
|
||||||
|
|
||||||
@ -99,8 +100,11 @@ class TestProcessProxyOptions:
|
|||||||
def test_client_certs(self):
|
def test_client_certs(self):
|
||||||
with tutils.tmpdir() as cadir:
|
with tutils.tmpdir() as cadir:
|
||||||
self.assert_noerr("--client-certs", 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(
|
self.assert_err(
|
||||||
"directory does not exist",
|
"path does not exist",
|
||||||
"--client-certs",
|
"--client-certs",
|
||||||
"nonexistent")
|
"nonexistent")
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
from OpenSSL import SSL
|
from OpenSSL import SSL
|
||||||
@ -313,13 +314,24 @@ class TestHTTPAuth(tservers.HTTPProxTest):
|
|||||||
class TestHTTPS(tservers.HTTPProxTest, CommonMixin, TcpMixin):
|
class TestHTTPS(tservers.HTTPProxTest, CommonMixin, TcpMixin):
|
||||||
ssl = True
|
ssl = True
|
||||||
ssloptions = pathod.SSLOptions(request_client_cert=True)
|
ssloptions = pathod.SSLOptions(request_client_cert=True)
|
||||||
clientcerts = True
|
|
||||||
|
|
||||||
def test_clientcert(self):
|
def test_clientcert_file(self):
|
||||||
|
try:
|
||||||
|
self.config.clientcerts = os.path.join(
|
||||||
|
tutils.test_data.path("data/clientcert"), "client.pem")
|
||||||
f = self.pathod("304")
|
f = self.pathod("304")
|
||||||
assert f.status_code == 304
|
assert f.status_code == 304
|
||||||
assert self.server.last_log()["request"]["clientcert"]["keyinfo"]
|
assert self.server.last_log()["request"]["clientcert"]["keyinfo"]
|
||||||
|
finally:
|
||||||
|
self.config.clientcerts = None
|
||||||
|
def test_clientcert_dir(self):
|
||||||
|
try:
|
||||||
|
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"]
|
||||||
|
finally:
|
||||||
|
self.config.clientcerts = None
|
||||||
def test_error_post_connect(self):
|
def test_error_post_connect(self):
|
||||||
p = self.pathoc()
|
p = self.pathoc()
|
||||||
assert p.request("get:/:i0,'invalid\r\n\r\n'").status_code == 400
|
assert p.request("get:/:i0,'invalid\r\n\r\n'").status_code == 400
|
||||||
|
@ -83,7 +83,6 @@ class ProxTestBase(object):
|
|||||||
# Test Configuration
|
# Test Configuration
|
||||||
ssl = None
|
ssl = None
|
||||||
ssloptions = False
|
ssloptions = False
|
||||||
clientcerts = False
|
|
||||||
no_upstream_cert = False
|
no_upstream_cert = False
|
||||||
authenticator = None
|
authenticator = None
|
||||||
masterclass = TestMaster
|
masterclass = TestMaster
|
||||||
@ -130,7 +129,6 @@ class ProxTestBase(object):
|
|||||||
no_upstream_cert = cls.no_upstream_cert,
|
no_upstream_cert = cls.no_upstream_cert,
|
||||||
cadir = cls.cadir,
|
cadir = cls.cadir,
|
||||||
authenticator = cls.authenticator,
|
authenticator = cls.authenticator,
|
||||||
clientcerts = tutils.test_data.path("data/clientcert") if cls.clientcerts else None
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user