mirror of
https://github.com/mitmproxy/mitmproxy.git
synced 2024-11-24 13:49:40 +00:00
Merge branch 'master' into docs-tutorials
This commit is contained in:
commit
bfa6467e4c
@ -13,6 +13,7 @@ Unreleased: mitmproxy next
|
||||
* Add ASGI support for embedded apps (@mhils)
|
||||
* Updated raw exports to not remove headers (@wchasekelley)
|
||||
* Fix file unlinking before external viewer finishes loading (@wchasekelley)
|
||||
* Add --cert-passphrase command line argument (@mirosyn)
|
||||
* Add interactive tutorials to the documentation (@mplattner)
|
||||
|
||||
* --- TODO: add new PRs above this line ---
|
||||
|
@ -196,7 +196,7 @@ class CertStore:
|
||||
return dh
|
||||
|
||||
@classmethod
|
||||
def from_store(cls, path, basename, key_size):
|
||||
def from_store(cls, path, basename, key_size, passphrase: typing.Optional[bytes] = None):
|
||||
ca_path = os.path.join(path, basename + "-ca.pem")
|
||||
if not os.path.exists(ca_path):
|
||||
key, ca = cls.create_store(path, basename, key_size)
|
||||
@ -208,7 +208,8 @@ class CertStore:
|
||||
raw)
|
||||
key = OpenSSL.crypto.load_privatekey(
|
||||
OpenSSL.crypto.FILETYPE_PEM,
|
||||
raw)
|
||||
raw,
|
||||
passphrase)
|
||||
dh_path = os.path.join(path, basename + "-dhparam.pem")
|
||||
dh = cls.load_dhparam(dh_path)
|
||||
return cls(key, ca, ca_path, dh)
|
||||
@ -280,7 +281,7 @@ class CertStore:
|
||||
|
||||
return key, ca
|
||||
|
||||
def add_cert_file(self, spec: str, path: str) -> None:
|
||||
def add_cert_file(self, spec: str, path: str, passphrase: typing.Optional[bytes] = None) -> None:
|
||||
with open(path, "rb") as f:
|
||||
raw = f.read()
|
||||
cert = Cert(
|
||||
@ -290,7 +291,8 @@ class CertStore:
|
||||
try:
|
||||
privatekey = OpenSSL.crypto.load_privatekey(
|
||||
OpenSSL.crypto.FILETYPE_PEM,
|
||||
raw)
|
||||
raw,
|
||||
passphrase)
|
||||
except Exception:
|
||||
privatekey = self.default_privatekey
|
||||
self.add_cert(
|
||||
|
@ -47,6 +47,10 @@ class Options(optmanager.OptManager):
|
||||
certificate as the first entry.
|
||||
"""
|
||||
)
|
||||
self.add_option(
|
||||
"cert_passphrase", Optional[str], None,
|
||||
"Passphrase for decrypting the private key provided in the --cert option."
|
||||
)
|
||||
self.add_option(
|
||||
"ciphers_client", Optional[str], None,
|
||||
"Set supported ciphers for client connections using OpenSSL syntax."
|
||||
|
@ -62,10 +62,12 @@ class ProxyConfig:
|
||||
os.path.dirname(certstore_path)
|
||||
)
|
||||
key_size = options.key_size
|
||||
passphrase = options.cert_passphrase.encode("utf-8") if options.cert_passphrase else None
|
||||
self.certstore = certs.CertStore.from_store(
|
||||
certstore_path,
|
||||
moptions.CONF_BASENAME,
|
||||
key_size
|
||||
key_size,
|
||||
passphrase
|
||||
)
|
||||
|
||||
for c in options.certs:
|
||||
@ -79,7 +81,7 @@ class ProxyConfig:
|
||||
"Certificate file does not exist: %s" % cert
|
||||
)
|
||||
try:
|
||||
self.certstore.add_cert_file(parts[0], cert)
|
||||
self.certstore.add_cert_file(parts[0], cert, passphrase)
|
||||
except crypto.Error:
|
||||
raise exceptions.OptionsError(
|
||||
"Invalid certificate format: %s" % cert
|
||||
|
@ -67,6 +67,7 @@ def common_options(parser, opts):
|
||||
# Proxy SSL options
|
||||
group = parser.add_argument_group("SSL")
|
||||
opts.make_parser(group, "certs", metavar="SPEC")
|
||||
opts.make_parser(group, "cert_passphrase", metavar="PASS")
|
||||
opts.make_parser(group, "ssl_insecure", short="k")
|
||||
opts.make_parser(group, "key_size", metavar="KEY_SIZE")
|
||||
|
||||
|
51
test/mitmproxy/data/mitmproxy.pem
Normal file
51
test/mitmproxy/data/mitmproxy.pem
Normal file
@ -0,0 +1,51 @@
|
||||
-----BEGIN ENCRYPTED PRIVATE KEY-----
|
||||
MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQI9fSurwMcOA4CAggA
|
||||
MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECKALBF48zvQnBIIEyKDIy72IMJoZ
|
||||
4q7LsG0dCSa8oGI/CtAnC9YqRlDj+paWoGKDUkzxnMloUbJkpQlTEYRHXp0xKtdP
|
||||
IcCjWFqWeQjsaJUlwILNLiliVpbyW/0PLmNQmRSfvLhlZ77rRk08DyLU0mcW2zRX
|
||||
DuKHuxGhdlmte7EKsNf8czch9hDXqrCLqxlzr86K0pwT40W1r32TgQdX68edluoj
|
||||
acggWuEzeTTKy1BKkVtlCq63dflgRfSo0as+dYX38wxzC6O6hxKpax277ijoJZHc
|
||||
QsXxi/zREa+gtVOq9D6Vz5E+MmmIIAzVrXsFe1Uj4wYb3XUSO6WnJ9GlrixqWeu3
|
||||
9lkOZOEKyyDgIY+twn06kyZBspKnXvQMMPjeiSSeaqI9LA0qpvRsxuWCxyTJ2YZI
|
||||
s+xab8j5g5RKOmrt1bGtLl66tcrGNP9jYC5pjMNl6fz3c8+oxC0Bun4q+yOA9QzG
|
||||
4GaiA834x+9wtsEBSjlMB5AMwYH+1ODo6Q+VUAWH1qBvCm/gQT2mvSgcrz6bcGJI
|
||||
gimfzl/IbqVuVkWl7yFqNN/renE47pvy34Dbymb0FBK/5Gb1FImno3CcAkCuaEJ1
|
||||
sWdx2Ej0Ezit8v1iJN2q29xlD7MrxB0uPvklUPRlD9RVcDJ15GwBPA8ugN/Fjj50
|
||||
2BiMJ2/uqBoEnAjMyStINArS5PWL6gthIXenVJ4w0wegBciCsGo4G7UFQ0z/w2Je
|
||||
7NJ8TjwKdTYJdAfgO5Rr8u6j0ybn72T/+QJfjugNLufRx4sakvPZR90/AFb2YX+L
|
||||
kgCVS3ySOfom9p5JcxdnI8omelBIi1Qa9xwPKMPaV6oYkqBVjmcDDZocC6qN15PD
|
||||
jCrgGryV3Fsn5OLYTB+EQDLNqmo+qd1O0pNY2THwD/DGGlx6VhmeQnWdt534g5lo
|
||||
clQOmLXEeUWIb2u5PanakqNpY5mBQcOJ88/RS+oGAjTGU0e3I1zLb6EN/Ftndjv1
|
||||
sfEh+HMwHxIWxdnJb6z6m73XJr4z30VGN8e+f1lC8c9SJ9aTQ/9vH3bsaXLW6GFY
|
||||
DBisBg2/+vMwRSG9PkYrp1p6rGAhwbaofnZE5zApT7PFEX2RVNPU7lgXn84ycRHw
|
||||
gZ89Mpa9zShL4T1PS8BrKwS7AH/se7ofKW/s8Z9SgngTWj0Efd4hZmn/EenVHBWf
|
||||
kjAkvKIgGE8FJF1QlmU5dHDFhRiUGXIaB1rYAcwwuwB06fxRqEL3pU6jkHSru3ry
|
||||
sYaY/cfpd5D5PT+FlxkzAPH1iiC3knXpcotWpJ2iQshsw9ifwg/vVJB0n20+Rxeu
|
||||
XTgwiT+X5mJNAQUCj6aExWUg+D5gPnJPwFmzAWBGKWrvwI+vI6zIv4MJywzU+Ei8
|
||||
1lU5rezPovAbGSTwUBPDydhORua0P8tVT8KPMmPJhza6IORTPpzdEOCXCOH17CWg
|
||||
VWKjYvEul8CdNh4O3CJDU4lN8yn6RXCBPK4NKDea17GCIEBgnOnpFny+jdfNT+Ce
|
||||
9aNh8ah61vbPag9EM2okmBlbnpkhUO+x8K8prZHZE7qRgUbmn1cJwIP6pNN/263q
|
||||
S2uKZMnoaT65BaQh9wpgSvWmDup3/lGG/C2+m0k087QBVHMSfpTK9WcZ94BbzoeR
|
||||
S9rWCU2k/woEUOv3hssY5w==
|
||||
-----END ENCRYPTED PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDdTCCAl2gAwIBAgIURm3Wk48Uc3RtqZ0FFxCaE33TvjcwDQYJKoZIhvcNAQEL
|
||||
BQAwSTELMAkGA1UEBhMCVVMxDTALBgNVBAgMBENhbGkxDTALBgNVBAcMBHRlc3Qx
|
||||
DTALBgNVBAoMBHRlc3QxDTALBgNVBAMMBHRlc3QwIBcNMjAwODI4MTIyNDU4WhgP
|
||||
MjI5NDA2MTIxMjI0NThaMEkxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARDYWxpMQ0w
|
||||
CwYDVQQHDAR0ZXN0MQ0wCwYDVQQKDAR0ZXN0MQ0wCwYDVQQDDAR0ZXN0MIIBIjAN
|
||||
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyrgqfiwRh2EcPYk/GFMgF2k8yJq
|
||||
4mkQcjpWlowp/fL99W/c33ySEtV/LyMJ6LtPAIKN4SambUFcx97pEgJi9YEDLRGW
|
||||
aN9jznss5AAe03uXN2gizpq9LmdPxr/vmH1DnqdI5MKwa8g9phpe9tT6ik3f2qkm
|
||||
1V9Ka38GlkHbB+w743ytz20jM6ifTtrX0SuDqDbAppandv5Ix3CHdlllRS/MKNEw
|
||||
LAs7LVkct0UNTp+soTIhGcASmbf24dvJnO+Msfuqw60mHJpoUP/xDcRGcXnjsgAZ
|
||||
zAi0UXlV9QiItQeOKxLBHIlMSAEd9oEejPCi6uN+zjKb3De7LUD2Vxu7iwIDAQAB
|
||||
o1MwUTAdBgNVHQ4EFgQU6tvbiSgA6pujKJBSFw/j+QRZOiwwHwYDVR0jBBgwFoAU
|
||||
6tvbiSgA6pujKJBSFw/j+QRZOiwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B
|
||||
AQsFAAOCAQEAgVa/jUdGqElv3EzxzSqtYkGxmeY5m2aLPKgsUl2zOPWwgyE1Synu
|
||||
TuFS+B5pyTT1KZ6IDwRQ+hA9jOnEopNK33lVelz7XBuw7485qVidG4o6QH1uo/J9
|
||||
GlxjM5SCY6yQ4frCI8lCY6+LA0NbI05qtVNTS1zgdOBnC/IOlMFpp0oDaf5FZHxc
|
||||
Ci1I/g32ES3rvKiAGBY2m6hy138GzYpZTXnKS03MaTfUCFfsOvqq/z2KBCeCd4mH
|
||||
VDO7adjhw4I7EYYXjmly2um6NaqyXtT6/AARY3JuQgFoW7W3XBV6TCsYmsGSeUTH
|
||||
JrhnGnHiNi06IuBwOXYZDID+orBMr9NDKw==
|
||||
-----END CERTIFICATE-----
|
@ -204,3 +204,9 @@ class TestCert:
|
||||
x = certs.Cert('')
|
||||
x.set_state(a)
|
||||
assert x == c
|
||||
|
||||
def test_from_store_with_passphrase(self, tdata, tmpdir):
|
||||
ca = certs.CertStore.from_store(str(tmpdir), "mitmproxy", 2048, "password")
|
||||
ca.add_cert_file("*", tdata.path("mitmproxy/data/mitmproxy.pem"), "password")
|
||||
|
||||
assert ca.get_cert(b"foo", [])
|
||||
|
@ -42,11 +42,10 @@ class TestProcessProxyOptions:
|
||||
assert self.p()
|
||||
|
||||
def test_certs(self, tdata):
|
||||
self.assert_noerr(
|
||||
"--cert",
|
||||
tdata.path("mitmproxy/data/testkey.pem"))
|
||||
with pytest.raises(Exception, match="does not exist"):
|
||||
self.p("--cert", "nonexistent")
|
||||
with pytest.raises(Exception, match="ambiguous option"):
|
||||
self.assert_noerr(
|
||||
"--cert",
|
||||
tdata.path("mitmproxy/data/testkey.pem"))
|
||||
|
||||
|
||||
class TestProxyServer:
|
||||
|
Loading…
Reference in New Issue
Block a user