Improve UX when users specify invalid certs (#7073)
* improve UX when users specify invalid certs if we don't do this ourselves, OpenSSL will greet users with the ever-fascinating 'no shared ciphers' error during the first handshake. * fixup test * fix: include intermediate certs for QUIC * [autofix.ci] apply automated fixes * warn if `certs` has a certificate that's a CA * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
0ff08f975e
commit
aa73608ef6
|
@ -7,6 +7,10 @@
|
|||
|
||||
## Unreleased: mitmproxy next
|
||||
|
||||
- Improve the error message when users specify the `certs` option without a matching private key.
|
||||
([#7073](https://github.com/mitmproxy/mitmproxy/pull/7073), @mhils)
|
||||
- Fix a bug where intermediate certificates would not be transmitted when using QUIC.
|
||||
([#7073](https://github.com/mitmproxy/mitmproxy/pull/7073), @mhils)
|
||||
|
||||
## 02 August 2024: mitmproxy 10.4.2
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import contextlib
|
||||
import datetime
|
||||
import ipaddress
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
@ -19,12 +20,15 @@ from cryptography.hazmat.primitives import serialization
|
|||
from cryptography.hazmat.primitives.asymmetric import dsa
|
||||
from cryptography.hazmat.primitives.asymmetric import ec
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||||
from cryptography.hazmat.primitives.asymmetric.types import CertificatePublicKeyTypes
|
||||
from cryptography.hazmat.primitives.serialization import pkcs12
|
||||
from cryptography.x509 import ExtendedKeyUsageOID
|
||||
from cryptography.x509 import NameOID
|
||||
|
||||
from mitmproxy.coretypes import serializable
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Default expiry must not be too long: https://github.com/mitmproxy/mitmproxy/issues/815
|
||||
CA_EXPIRY = datetime.timedelta(days=10 * 365)
|
||||
CERT_EXPIRY = datetime.timedelta(days=365)
|
||||
|
@ -91,6 +95,9 @@ class Cert(serializable.Serializable):
|
|||
def to_pyopenssl(self) -> OpenSSL.crypto.X509:
|
||||
return OpenSSL.crypto.X509.from_cryptography(self._cert)
|
||||
|
||||
def public_key(self) -> CertificatePublicKeyTypes:
|
||||
return self._cert.public_key()
|
||||
|
||||
def fingerprint(self) -> bytes:
|
||||
return self._cert.fingerprint(hashes.SHA256())
|
||||
|
||||
|
@ -127,6 +134,17 @@ class Cert(serializable.Serializable):
|
|||
def serial(self) -> int:
|
||||
return self._cert.serial_number
|
||||
|
||||
@property
|
||||
def is_ca(self) -> bool:
|
||||
constraints: x509.BasicConstraints
|
||||
try:
|
||||
constraints = self._cert.extensions.get_extension_for_class(
|
||||
x509.BasicConstraints
|
||||
).value
|
||||
return constraints.ca
|
||||
except x509.ExtensionNotFound:
|
||||
return False
|
||||
|
||||
@property
|
||||
def keyinfo(self) -> tuple[str, int]:
|
||||
public_key = self._cert.public_key()
|
||||
|
@ -502,11 +520,34 @@ class CertStore:
|
|||
raw = path.read_bytes()
|
||||
cert = Cert.from_pem(raw)
|
||||
try:
|
||||
key = load_pem_private_key(raw, password=passphrase)
|
||||
except ValueError:
|
||||
key = self.default_privatekey
|
||||
private_key = load_pem_private_key(raw, password=passphrase)
|
||||
except ValueError as e:
|
||||
private_key = self.default_privatekey
|
||||
if cert.public_key() != private_key.public_key():
|
||||
raise ValueError(
|
||||
f'Unable to find private key in "{path.absolute()}": {e}'
|
||||
) from e
|
||||
else:
|
||||
if cert.public_key() != private_key.public_key():
|
||||
raise ValueError(
|
||||
f'Private and public keys in "{path.absolute()}" do not match:\n'
|
||||
f"{cert.public_key()=}\n"
|
||||
f"{private_key.public_key()=}"
|
||||
)
|
||||
|
||||
self.add_cert(CertStoreEntry(cert, key, path, [cert]), spec)
|
||||
try:
|
||||
chain = [Cert(x) for x in x509.load_pem_x509_certificates(raw)]
|
||||
except ValueError as e:
|
||||
logger.warning(f"Failed to read certificate chain: {e}")
|
||||
chain = [cert]
|
||||
|
||||
if cert.is_ca:
|
||||
logger.warning(
|
||||
f'"{path.absolute()}" is a certificate authority and not a leaf certificate. '
|
||||
f"This indicates a misconfiguration, see https://docs.mitmproxy.org/stable/concepts-certificates/."
|
||||
)
|
||||
|
||||
self.add_cert(CertStoreEntry(cert, private_key, path, chain), spec)
|
||||
|
||||
def add_cert(self, entry: CertStoreEntry, *names: str) -> None:
|
||||
"""
|
||||
|
|
|
@ -92,3 +92,22 @@ for x in ["self-signed", "trusted-leaf", "trusted-leaf-ip", "trusted-root"]:
|
|||
pem.write(key.read())
|
||||
|
||||
shutil.copyfile("trusted-leaf.pem", "example.mitmproxy.org.pem")
|
||||
with (
|
||||
open(f"trusted-leaf.crt") as crt,
|
||||
open(f"self-signed.key") as key,
|
||||
open(f"private-public-mismatch.pem", "w") as pem,
|
||||
):
|
||||
pem.write(crt.read())
|
||||
pem.write(key.read())
|
||||
|
||||
with (
|
||||
open(f"trusted-leaf.pem") as crt1,
|
||||
open(f"trusted-root.crt") as crt2,
|
||||
open(f"trusted-chain.pem", "w") as pem,
|
||||
):
|
||||
pem.write(crt1.read())
|
||||
pem.write(crt2.read())
|
||||
|
||||
with open(f"trusted-leaf.pem") as crt1, open(f"trusted-chain-invalid.pem", "w") as pem:
|
||||
pem.write(crt1.read())
|
||||
pem.write("-----BEGIN CERTIFICATE-----\nnotacert\n-----END CERTIFICATE-----\n")
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDZDCCAkygAwIBAgIUSWoLwl7Rc//TKPwKwv25Vhb6uFAwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDExMDMwNzAzMjZaFw00MDEw
|
||||
MjkwNzAzMjZaMDQxHjAcBgNVBAMMFWV4YW1wbGUubWl0bXByb3h5Lm9yZzESMBAG
|
||||
A1UECgwJbWl0bXByb3h5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
qcEdB7TZD7DxJlJH/ZTyrovP0din2vLCRZRZ07ix48arITGWj8wFJ/XpZsFmAWlH
|
||||
2LriXGC8BB54EJt8Epix5tcdKvCZ/7vTgaBQ+DQVdCNiscaKwvDbigy037OY97sT
|
||||
6Ou9xYjjgg0cb+WTkQGMOTMbCW2e5iuSvyMPdZ2+2RzbTcNV1/6O/5cQ7TOW2E83
|
||||
xeaN4stBMfRmsQRoHXBri0tqtQ3bHd3V4H9iai7HFBOcB/nsJUwLliZpz3j/dUD0
|
||||
yZAgdgB9XBlGvs/e746bGctyvl2QZu2JeACEVPmVrAUhqe2TVMVLDT17uzNeH1x5
|
||||
UXxdB4cexTOm4amvWSwvTQIDAQABo10wWzAfBgNVHSMEGDAWgBTkDj66Wmaf9YP0
|
||||
YMqGKG51PejxWzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDAgBgNVHREEGTAXghVl
|
||||
eGFtcGxlLm1pdG1wcm94eS5vcmcwDQYJKoZIhvcNAQELBQADggEBABwKrf+Gy1I5
|
||||
BnfhAqbDUYj8OVcjbB5esbvVYAADNNNQ10RREyz5OTTo2dSKy2hIVQeGxaBy5W6d
|
||||
cNk0CoLzOgpgkwQPQ351+Y0C5yQztXIg/JM5aSeFuAbQg+NtzOQISrcDB390Xr2f
|
||||
7YhyYL0XLX4NCP7ek7+lAClrf+lL9MysHTTP0pmFWLPP6AIR8JIsLpNpTDV10c8p
|
||||
QcnJ8+5q6oLHNKN+M/HRcdKzj/XyJ538UzSOlmU+izhNT1j7mbszS0tc9yh0dmpP
|
||||
9uuBY0wcD/NAHBpSX9v9ZJcOuWntsAxTbMXj1eWNRyt0QJLURlkqeVn6ZrE1/BDS
|
||||
BqDdOKYJbkw=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAw1IZNjnWZOU8jJqlHVK45PLOpr+y8U0ks52OT6pDhTBWGFkn
|
||||
hEffHAey/kSwSoszdb7e19VF0SLj4wXr36X7CKkJfFhzHrFOjg16ciNo0GRic82K
|
||||
4VvlC0qRJVXakTVhN/Tm/zNL90GJLTBMti47jmDup52I8j39/PSb8n/6IWMfNMqt
|
||||
6fqSDYfeATgzeK0jxG+SEpCm+iqeAdzLE3ZotZJMtZ3CTiQfZ5eJamHSJ8pURlZD
|
||||
fha8JyS+DzeeIZEvA2QGWgDRigS4n20p7ykrwUxaUbLh2RV2n+kVy+CwgdsgFfE1
|
||||
40HI5MJ3WU7/TfoxcKUJF5gB3zmkhwD+s22i5QIDAQABAoIBADK7Gi1JbHQcTlO+
|
||||
vvAU0k00+5O36sRd4xB79cCfWpY3bcU5Mthayoo/PbBpKtjRuvX0M3EfxdiCFWqb
|
||||
2R3nwIIJVZtkZdIs/1hKC+mlZM3rpN6rHk1WTvFV1sk5uWFJ2gxsoarbKfn4naaN
|
||||
Cv+ulm1uo84JTs6MZ3HSHscnklIlNnDG3piC8JnzXVgS7kzbJPXTccZJI1Mwgyho
|
||||
D1HoWatIep5XAp3OZePlApfRpKn/+2Hg6USkbcHYzX/XpA3b3/YEBqsXVUFxAs5m
|
||||
nChdLpKUCIjcARInAXoULh0AQHGcH9dfJk1QF1Lw6nCoY12P1sZfdGU5trcslA1O
|
||||
W28syoECgYEA6GjaqFYffceJHlODukHgpLNfa1EUy49ZWjmdmXTYXJpufzjD4n4H
|
||||
sUkEnJ00ssaCVdd0XClbN/l/QvIAz3W8ZXXQWtZJHV2wAIyjWpqiOwaiXQFZIZ67
|
||||
kxGsLVjkuiST33CX6yl8IKAD+8B67uZhmWTnYBmxGnIZODqUatpqW3ECgYEA1yV+
|
||||
CGoNp6VQqej0t0y8C8pXiMGe2DGj5p1WFn00cn/fC1E2Yc0HG+E62OB7tgUFI180
|
||||
/nArOQHnTZCzAQAc44M63gesRMeu+0cxuTUqOUCn1lGD+4K/3IA59Rgzfvvnq6xu
|
||||
tn2jidfqaDPfKavqtCqRbs8wJYaGEhgcb8pUvLUCgYEA4pjpKFvgFGip/lF7C+0T
|
||||
NEJXdHD3j4lSmy+1w1szYQaJWa1k/73VjjsdLf3w1aXKihuprfn8oFS4ifMeayfl
|
||||
6h62aPqpCuK/qal10+8U4ewT/g5Ecw0q4bfHYedcC0mCi8ZhuL0X809Q0vLWaXti
|
||||
CYdiOEaUcK5yfGpRLuWJ8WECgYAWWXa2OQ4iFDJE9EY3pGkEcIiXVEXD/6QfGMkQ
|
||||
nQENw+rPqigUENBkPQl37hnr1qmp+wHuTIiw61mz3Qw7Vl+p4sACwJlMq9GpmMO5
|
||||
kaRJPkYxJVaokfSMW2Wp6FGxJ0nxs3/sxTBv6VYYbQsJsSo4fROOh0dhHpBe4NJT
|
||||
aplS4QKBgQCaMUN88HNaVr0+DPQKeFoflqwCCYsdK43QTWEirrFDWDliJ0k81DZJ
|
||||
k7N3oR5UujsTMgfYDJ6Cp3enZVYyuoFnOlVT8v4XzvzAGTehyo4rMiE2TbMir7Xn
|
||||
agPTZYSuQc4Iy7BPwh/PMlX6bDOTeq/ftyWrDuF9+pC5w3v4SkuMew==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -0,0 +1,51 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDZDCCAkygAwIBAgIUSWoLwl7Rc//TKPwKwv25Vhb6uFAwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDExMDMwNzAzMjZaFw00MDEw
|
||||
MjkwNzAzMjZaMDQxHjAcBgNVBAMMFWV4YW1wbGUubWl0bXByb3h5Lm9yZzESMBAG
|
||||
A1UECgwJbWl0bXByb3h5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
qcEdB7TZD7DxJlJH/ZTyrovP0din2vLCRZRZ07ix48arITGWj8wFJ/XpZsFmAWlH
|
||||
2LriXGC8BB54EJt8Epix5tcdKvCZ/7vTgaBQ+DQVdCNiscaKwvDbigy037OY97sT
|
||||
6Ou9xYjjgg0cb+WTkQGMOTMbCW2e5iuSvyMPdZ2+2RzbTcNV1/6O/5cQ7TOW2E83
|
||||
xeaN4stBMfRmsQRoHXBri0tqtQ3bHd3V4H9iai7HFBOcB/nsJUwLliZpz3j/dUD0
|
||||
yZAgdgB9XBlGvs/e746bGctyvl2QZu2JeACEVPmVrAUhqe2TVMVLDT17uzNeH1x5
|
||||
UXxdB4cexTOm4amvWSwvTQIDAQABo10wWzAfBgNVHSMEGDAWgBTkDj66Wmaf9YP0
|
||||
YMqGKG51PejxWzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDAgBgNVHREEGTAXghVl
|
||||
eGFtcGxlLm1pdG1wcm94eS5vcmcwDQYJKoZIhvcNAQELBQADggEBABwKrf+Gy1I5
|
||||
BnfhAqbDUYj8OVcjbB5esbvVYAADNNNQ10RREyz5OTTo2dSKy2hIVQeGxaBy5W6d
|
||||
cNk0CoLzOgpgkwQPQ351+Y0C5yQztXIg/JM5aSeFuAbQg+NtzOQISrcDB390Xr2f
|
||||
7YhyYL0XLX4NCP7ek7+lAClrf+lL9MysHTTP0pmFWLPP6AIR8JIsLpNpTDV10c8p
|
||||
QcnJ8+5q6oLHNKN+M/HRcdKzj/XyJ538UzSOlmU+izhNT1j7mbszS0tc9yh0dmpP
|
||||
9uuBY0wcD/NAHBpSX9v9ZJcOuWntsAxTbMXj1eWNRyt0QJLURlkqeVn6ZrE1/BDS
|
||||
BqDdOKYJbkw=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAqcEdB7TZD7DxJlJH/ZTyrovP0din2vLCRZRZ07ix48arITGW
|
||||
j8wFJ/XpZsFmAWlH2LriXGC8BB54EJt8Epix5tcdKvCZ/7vTgaBQ+DQVdCNiscaK
|
||||
wvDbigy037OY97sT6Ou9xYjjgg0cb+WTkQGMOTMbCW2e5iuSvyMPdZ2+2RzbTcNV
|
||||
1/6O/5cQ7TOW2E83xeaN4stBMfRmsQRoHXBri0tqtQ3bHd3V4H9iai7HFBOcB/ns
|
||||
JUwLliZpz3j/dUD0yZAgdgB9XBlGvs/e746bGctyvl2QZu2JeACEVPmVrAUhqe2T
|
||||
VMVLDT17uzNeH1x5UXxdB4cexTOm4amvWSwvTQIDAQABAoIBAEb3arF8E3qR2F7S
|
||||
6zHCASqjXIA3+QR5lGoOOPdgMU4uEgDQgEchXc506dyBYamZX+XlSxifgDqgmkUn
|
||||
G1mS6Fy+9XysFVVqKmP4p6D79TQWTv5PKFeS5dTytvMGXB7E4O/xDeb08Ve/L3JA
|
||||
Ic7vPLX0/YqVf2ZuNO0fNSlQhyawUVlSS6yq/B1GUo44PX/PXrWYZd66mc29g+KF
|
||||
7D0nnbloLY+5QmOEVYbf99RHJ64Cwxzwxi4ic9AxLaNMfkrydjbGQ0VhJq14WEux
|
||||
/TJLvinzIDyslnx4aYstno3ryoxLtR/9ALysrdQ8vVMaVCdbf0aMu832R2dI4s9K
|
||||
ixQlgmkCgYEA0Ho0a4qzwk9oLWYk1x16kOCqmfuenlEz3Tv8uBB/jdz7UM63sS3h
|
||||
OUQYKhhtzOGf6CDA3CE11ie6SX7zHrowPLJBSpacJZJcrHPGZxdBZ/As/QpGnZll
|
||||
1eTMlVRXk06k/fEYplU1dS5IDbsvUIaaF9CF9Qd3MkDRglhbM19Iy+sCgYEA0HM1
|
||||
d7OBsjSi09zFDE+Joq6Gih8LqqFLtMsIHEKAJ0gJgmt6MTfjtdPo55ZKVLCR2pbP
|
||||
yRHagK4LRUFY9Pl5eGlEUF9cKEKKtZOURUFVz3yBMYPBje/B1o/UCCj+nr2reWgx
|
||||
qj/jwZrph6QKCkEsnQXi98tE7XSgihUh6UEQO6cCgYASVe0uWDCfMmSzOXyb/te8
|
||||
zkWy7VJyEipBlvkPJ0RQsdLYtJWrW6Gna7nEWgmuL1nlDJxpv/IAN9ZGiIfReAau
|
||||
D+92I/DvzQOhlz0n6/+wqIsMZk73pXozacAkkhpxtkUEoKPOXUgqWju0GXZ72prK
|
||||
5WgiuNle7hx/Hk5HImZAqQKBgQCK7W4iRGpZeklXiNlvtgcWfNlAbyaYZ34MlhDm
|
||||
vM+q3pEv8i/zY7uJcR3WU81gmnnrRP5hlVuazeTHGKGQTEFQJmCYbKYAUzEdiamV
|
||||
atElQ2bbuGOlFLmNJjj7406oP+NsPCx1urUyUOv6MjNa2EtCsCywWDKtTEC/Jwx9
|
||||
6JZIGwKBgDa4Ephl+lcyGC8D9Tdc4Nme6n/10pIN53ZCplqVSuma+kOOQX7ZXpJb
|
||||
0csHR9KODcpQuo2yOnUfZ1z4+tsjms2Uv97GgcZ9sO84I/3RGJCvxmzAEiRmJMfH
|
||||
y38GtEYCnat5VOKdo//eIYtiu9YSXuuS1ENSWUPZ9YInrkUk0j8S
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
notacert
|
||||
-----END CERTIFICATE-----
|
|
@ -0,0 +1,69 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDZDCCAkygAwIBAgIUSWoLwl7Rc//TKPwKwv25Vhb6uFAwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDExMDMwNzAzMjZaFw00MDEw
|
||||
MjkwNzAzMjZaMDQxHjAcBgNVBAMMFWV4YW1wbGUubWl0bXByb3h5Lm9yZzESMBAG
|
||||
A1UECgwJbWl0bXByb3h5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
qcEdB7TZD7DxJlJH/ZTyrovP0din2vLCRZRZ07ix48arITGWj8wFJ/XpZsFmAWlH
|
||||
2LriXGC8BB54EJt8Epix5tcdKvCZ/7vTgaBQ+DQVdCNiscaKwvDbigy037OY97sT
|
||||
6Ou9xYjjgg0cb+WTkQGMOTMbCW2e5iuSvyMPdZ2+2RzbTcNV1/6O/5cQ7TOW2E83
|
||||
xeaN4stBMfRmsQRoHXBri0tqtQ3bHd3V4H9iai7HFBOcB/nsJUwLliZpz3j/dUD0
|
||||
yZAgdgB9XBlGvs/e746bGctyvl2QZu2JeACEVPmVrAUhqe2TVMVLDT17uzNeH1x5
|
||||
UXxdB4cexTOm4amvWSwvTQIDAQABo10wWzAfBgNVHSMEGDAWgBTkDj66Wmaf9YP0
|
||||
YMqGKG51PejxWzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDAgBgNVHREEGTAXghVl
|
||||
eGFtcGxlLm1pdG1wcm94eS5vcmcwDQYJKoZIhvcNAQELBQADggEBABwKrf+Gy1I5
|
||||
BnfhAqbDUYj8OVcjbB5esbvVYAADNNNQ10RREyz5OTTo2dSKy2hIVQeGxaBy5W6d
|
||||
cNk0CoLzOgpgkwQPQ351+Y0C5yQztXIg/JM5aSeFuAbQg+NtzOQISrcDB390Xr2f
|
||||
7YhyYL0XLX4NCP7ek7+lAClrf+lL9MysHTTP0pmFWLPP6AIR8JIsLpNpTDV10c8p
|
||||
QcnJ8+5q6oLHNKN+M/HRcdKzj/XyJ538UzSOlmU+izhNT1j7mbszS0tc9yh0dmpP
|
||||
9uuBY0wcD/NAHBpSX9v9ZJcOuWntsAxTbMXj1eWNRyt0QJLURlkqeVn6ZrE1/BDS
|
||||
BqDdOKYJbkw=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAqcEdB7TZD7DxJlJH/ZTyrovP0din2vLCRZRZ07ix48arITGW
|
||||
j8wFJ/XpZsFmAWlH2LriXGC8BB54EJt8Epix5tcdKvCZ/7vTgaBQ+DQVdCNiscaK
|
||||
wvDbigy037OY97sT6Ou9xYjjgg0cb+WTkQGMOTMbCW2e5iuSvyMPdZ2+2RzbTcNV
|
||||
1/6O/5cQ7TOW2E83xeaN4stBMfRmsQRoHXBri0tqtQ3bHd3V4H9iai7HFBOcB/ns
|
||||
JUwLliZpz3j/dUD0yZAgdgB9XBlGvs/e746bGctyvl2QZu2JeACEVPmVrAUhqe2T
|
||||
VMVLDT17uzNeH1x5UXxdB4cexTOm4amvWSwvTQIDAQABAoIBAEb3arF8E3qR2F7S
|
||||
6zHCASqjXIA3+QR5lGoOOPdgMU4uEgDQgEchXc506dyBYamZX+XlSxifgDqgmkUn
|
||||
G1mS6Fy+9XysFVVqKmP4p6D79TQWTv5PKFeS5dTytvMGXB7E4O/xDeb08Ve/L3JA
|
||||
Ic7vPLX0/YqVf2ZuNO0fNSlQhyawUVlSS6yq/B1GUo44PX/PXrWYZd66mc29g+KF
|
||||
7D0nnbloLY+5QmOEVYbf99RHJ64Cwxzwxi4ic9AxLaNMfkrydjbGQ0VhJq14WEux
|
||||
/TJLvinzIDyslnx4aYstno3ryoxLtR/9ALysrdQ8vVMaVCdbf0aMu832R2dI4s9K
|
||||
ixQlgmkCgYEA0Ho0a4qzwk9oLWYk1x16kOCqmfuenlEz3Tv8uBB/jdz7UM63sS3h
|
||||
OUQYKhhtzOGf6CDA3CE11ie6SX7zHrowPLJBSpacJZJcrHPGZxdBZ/As/QpGnZll
|
||||
1eTMlVRXk06k/fEYplU1dS5IDbsvUIaaF9CF9Qd3MkDRglhbM19Iy+sCgYEA0HM1
|
||||
d7OBsjSi09zFDE+Joq6Gih8LqqFLtMsIHEKAJ0gJgmt6MTfjtdPo55ZKVLCR2pbP
|
||||
yRHagK4LRUFY9Pl5eGlEUF9cKEKKtZOURUFVz3yBMYPBje/B1o/UCCj+nr2reWgx
|
||||
qj/jwZrph6QKCkEsnQXi98tE7XSgihUh6UEQO6cCgYASVe0uWDCfMmSzOXyb/te8
|
||||
zkWy7VJyEipBlvkPJ0RQsdLYtJWrW6Gna7nEWgmuL1nlDJxpv/IAN9ZGiIfReAau
|
||||
D+92I/DvzQOhlz0n6/+wqIsMZk73pXozacAkkhpxtkUEoKPOXUgqWju0GXZ72prK
|
||||
5WgiuNle7hx/Hk5HImZAqQKBgQCK7W4iRGpZeklXiNlvtgcWfNlAbyaYZ34MlhDm
|
||||
vM+q3pEv8i/zY7uJcR3WU81gmnnrRP5hlVuazeTHGKGQTEFQJmCYbKYAUzEdiamV
|
||||
atElQ2bbuGOlFLmNJjj7406oP+NsPCx1urUyUOv6MjNa2EtCsCywWDKtTEC/Jwx9
|
||||
6JZIGwKBgDa4Ephl+lcyGC8D9Tdc4Nme6n/10pIN53ZCplqVSuma+kOOQX7ZXpJb
|
||||
0csHR9KODcpQuo2yOnUfZ1z4+tsjms2Uv97GgcZ9sO84I/3RGJCvxmzAEiRmJMfH
|
||||
y38GtEYCnat5VOKdo//eIYtiu9YSXuuS1ENSWUPZ9YInrkUk0j8S
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDazCCAlOgAwIBAgIUB5WLNdtHRvciUwDfySAEHYVSNe0wDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDExMDMwNzAzMjZaFw00MDEw
|
||||
MjkwNzAzMjZaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
||||
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
|
||||
AQUAA4IBDwAwggEKAoIBAQDVWUg2YdsztWIZpsWdbIB6Aewa1Igt7mNkKMQ1NJ6v
|
||||
priVlzWhZr0FfSVTid2m3Od2f5A751Q+IXLkNJ8d6Y4qVirAstEM57sCH/Hmt1E3
|
||||
cZOAzLQY2xCIrKPmbu6d8eSGO1q+Y8KstCK/V94/QRahjjoHxkLcSAmdg6PAkbhB
|
||||
7MwOxiJslIbsBY4UCXP0l4kUUIuMi8W2Y4M1VgvLRpUjaKVo1NQ0hLi4XBnU7Bsq
|
||||
A8/PZDuVeP0NcJtAxRicqqLX/MjgkTrA2tPnSj9m60lO79S40GSzB238o2zJQ5ON
|
||||
jHJdAhLlrsrkxZmDmKM59IdmV2OhN7O844ktbXDOqvq5AgMBAAGjUzBRMB0GA1Ud
|
||||
DgQWBBTkDj66Wmaf9YP0YMqGKG51PejxWzAfBgNVHSMEGDAWgBTkDj66Wmaf9YP0
|
||||
YMqGKG51PejxWzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAo
|
||||
9FwbGob1WRAo7ORShaDhopIDAYMCL1oc9YZ2ZQK8aDuZbqIZ/7+1LbWCeMAV4PTH
|
||||
Tcx+n9Zg/g/RkoSNu8KqFoQGFmdBZnKOMU4vlITu/ORpDu1sjSA+Eo9YbipemX+n
|
||||
jv+YHI4STFAWnyext3IUZVkT6wpU3pwUjX0fbk4LJfVLR41y4iD11XGergxAcpjj
|
||||
T03txkJcrTiX65SnB041Y4exUMLOUn5lTs/q2rBNkiLNljXQ6l+8L1rdQEN/j0Mx
|
||||
OYdc6FIUIESC1mMOf80+YOwxPJ862SyTv/cJB3npwTj/DdQu7blf/z2hMP7a7w+X
|
||||
l5d31XzcDOrCf/bTthvb
|
||||
-----END CERTIFICATE-----
|
|
@ -108,19 +108,6 @@ class TestCertStore:
|
|||
assert ("three.com", x509.GeneralNames([])) in tstore.certs
|
||||
assert ("four.com", x509.GeneralNames([])) in tstore.certs
|
||||
|
||||
def test_overrides(self, tmp_path):
|
||||
ca1 = certs.CertStore.from_store(tmp_path / "ca1", "test", 2048)
|
||||
ca2 = certs.CertStore.from_store(tmp_path / "ca2", "test", 2048)
|
||||
assert not ca1.default_ca.serial == ca2.default_ca.serial
|
||||
|
||||
dc = ca2.get_cert("foo.com", [x509.DNSName("sans.example.com")])
|
||||
dcp = tmp_path / "dc"
|
||||
dcp.write_bytes(dc.cert.to_pem())
|
||||
ca1.add_cert_file("foo.com", dcp)
|
||||
|
||||
ret = ca1.get_cert("foo.com", [])
|
||||
assert ret.cert.serial == dc.cert.serial
|
||||
|
||||
def test_create_dhparams(self, tmp_path):
|
||||
filename = tmp_path / "dhparam.pem"
|
||||
certs.CertStore.load_dhparam(filename)
|
||||
|
@ -203,6 +190,7 @@ class TestCert:
|
|||
assert c2.cn == "www.inode.co.nz"
|
||||
assert len(c2.altnames) == 2
|
||||
assert c2.fingerprint()
|
||||
assert c2.public_key()
|
||||
assert c2.notbefore == datetime(
|
||||
year=2010,
|
||||
month=1,
|
||||
|
@ -257,6 +245,19 @@ class TestCert:
|
|||
c = certs.Cert.from_pem(d)
|
||||
assert c.keyinfo == (name, bits)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"filename,is_ca",
|
||||
[
|
||||
("mitmproxy/net/data/verificationcerts/trusted-leaf.crt", False),
|
||||
("mitmproxy/net/data/verificationcerts/trusted-root.crt", True),
|
||||
("mitmproxy/data/invalid-subject.pem", False), # no basic constraints
|
||||
],
|
||||
)
|
||||
def test_is_ca(self, tdata, filename, is_ca):
|
||||
pem = Path(tdata.path(filename)).read_bytes()
|
||||
cert = certs.Cert.from_pem(pem)
|
||||
assert cert.is_ca == is_ca
|
||||
|
||||
def test_err_broken_sans(self, tdata):
|
||||
with open(tdata.path("mitmproxy/net/data/text_cert_weird1"), "rb") as f:
|
||||
d = f.read()
|
||||
|
@ -280,6 +281,14 @@ class TestCert:
|
|||
c2.set_state(a)
|
||||
assert c == c2
|
||||
|
||||
def test_add_cert_overrides(self, tdata, tstore):
|
||||
certfile = Path(
|
||||
tdata.path("mitmproxy/net/data/verificationcerts/trusted-leaf.pem")
|
||||
)
|
||||
cert = certs.Cert.from_pem(certfile.read_bytes())
|
||||
tstore.add_cert_file("example.com", certfile)
|
||||
assert cert == tstore.get_cert("example.com", []).cert
|
||||
|
||||
def test_from_store_with_passphrase(self, tdata, tstore):
|
||||
tstore.add_cert_file(
|
||||
"unencrypted-no-pass", Path(tdata.path("mitmproxy/data/testkey.pem")), None
|
||||
|
@ -302,6 +311,54 @@ class TestCert:
|
|||
None,
|
||||
)
|
||||
|
||||
def test_add_cert_with_no_private_key(self, tdata, tstore):
|
||||
with pytest.raises(ValueError, match="Unable to find private key"):
|
||||
tstore.add_cert_file(
|
||||
"example.com",
|
||||
Path(
|
||||
tdata.path("mitmproxy/net/data/verificationcerts/trusted-leaf.crt")
|
||||
),
|
||||
)
|
||||
|
||||
def test_add_cert_private_public_mismatch(self, tdata, tstore):
|
||||
with pytest.raises(
|
||||
ValueError, match='Private and public keys in ".+" do not match'
|
||||
):
|
||||
tstore.add_cert_file(
|
||||
"example.com",
|
||||
Path(
|
||||
tdata.path(
|
||||
"mitmproxy/net/data/verificationcerts/private-public-mismatch.pem"
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def test_add_cert_chain(self, tdata, tstore):
|
||||
tstore.add_cert_file(
|
||||
"example.com",
|
||||
Path(tdata.path("mitmproxy/net/data/verificationcerts/trusted-chain.pem")),
|
||||
)
|
||||
assert len(tstore.get_cert("example.com", []).chain_certs) == 2
|
||||
|
||||
def test_add_cert_chain_invalid(self, tdata, tstore, caplog):
|
||||
tstore.add_cert_file(
|
||||
"example.com",
|
||||
Path(
|
||||
tdata.path(
|
||||
"mitmproxy/net/data/verificationcerts/trusted-chain-invalid.pem"
|
||||
)
|
||||
),
|
||||
)
|
||||
assert "Failed to read certificate chain" in caplog.text
|
||||
assert len(tstore.get_cert("example.com", []).chain_certs) == 1
|
||||
|
||||
def test_add_cert_is_ca(self, tdata, tstore, caplog):
|
||||
tstore.add_cert_file(
|
||||
"example.com",
|
||||
Path(tdata.path("mitmproxy/net/data/verificationcerts/trusted-root.pem")),
|
||||
)
|
||||
assert "is a certificate authority and not a leaf certificate" in caplog.text
|
||||
|
||||
def test_special_character(self, tdata):
|
||||
with open(tdata.path("mitmproxy/net/data/text_cert_with_comma"), "rb") as f:
|
||||
d = f.read()
|
||||
|
|
Loading…
Reference in New Issue