mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 00:01:36 +00:00
use OpenSSL's keylog callback for SSLKEYLOGFILE, refs #3994
This commit is contained in:
parent
b01d574d8b
commit
4b8fcc8650
@ -86,36 +86,17 @@ class MasterSecretLogger:
|
|||||||
# required for functools.wraps, which pyOpenSSL uses.
|
# required for functools.wraps, which pyOpenSSL uses.
|
||||||
__name__ = "MasterSecretLogger"
|
__name__ = "MasterSecretLogger"
|
||||||
|
|
||||||
def __call__(self, connection, where, ret):
|
def __call__(self, connection, keymaterial):
|
||||||
done_now = (
|
|
||||||
where == SSL.SSL_CB_HANDSHAKE_DONE and ret == 1
|
|
||||||
)
|
|
||||||
# this is a horrendous workaround for https://github.com/mitmproxy/mitmproxy/pull/3692#issuecomment-608454530:
|
|
||||||
# OpenSSL 1.1.1f decided to not make connection.master_key() fail in the SSL_CB_HANDSHAKE_DONE callback.
|
|
||||||
# To support various OpenSSL versions and still log master secrets, we now mark connections where this has
|
|
||||||
# happened and then try again on the next event. This is ugly and shouldn't be done, but eventually we
|
|
||||||
# replace this with context.set_keylog_callback anyways.
|
|
||||||
done_previously_but_not_logged_yet = (
|
|
||||||
hasattr(connection, "_still_needs_masterkey")
|
|
||||||
)
|
|
||||||
if done_now or done_previously_but_not_logged_yet:
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if not self.f:
|
if not self.f:
|
||||||
d = os.path.dirname(self.filename)
|
d = os.path.dirname(self.filename)
|
||||||
if not os.path.isdir(d):
|
if not os.path.isdir(d):
|
||||||
os.makedirs(d)
|
os.makedirs(d)
|
||||||
self.f = open(self.filename, "ab")
|
self.f = open(self.filename, "ab")
|
||||||
self.f.write(b"\r\n")
|
self.f.write(b"\n")
|
||||||
try:
|
self.f.write(keymaterial)
|
||||||
client_random = binascii.hexlify(connection.client_random())
|
self.f.write(b"\n")
|
||||||
masterkey = binascii.hexlify(connection.master_key())
|
|
||||||
except (AssertionError, SSL.Error): # careful: exception type changes between pyOpenSSL versions
|
|
||||||
connection._still_needs_masterkey = True
|
|
||||||
else:
|
|
||||||
self.f.write(b"CLIENT_RANDOM %s %s\r\n" % (client_random, masterkey))
|
|
||||||
self.f.flush()
|
self.f.flush()
|
||||||
if hasattr(connection, "_still_needs_masterkey"):
|
|
||||||
delattr(connection, "_still_needs_masterkey")
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
@ -203,7 +184,7 @@ def _create_ssl_context(
|
|||||||
|
|
||||||
# SSLKEYLOGFILE
|
# SSLKEYLOGFILE
|
||||||
if log_master_secret:
|
if log_master_secret:
|
||||||
context.set_info_callback(log_master_secret)
|
context.set_keylog_callback(log_master_secret)
|
||||||
|
|
||||||
if alpn_protos is not None:
|
if alpn_protos is not None:
|
||||||
# advertise application layer protocols
|
# advertise application layer protocols
|
||||||
|
@ -43,7 +43,7 @@ class TestMasterSecretLogger(tservers.ServerTestBase):
|
|||||||
|
|
||||||
tls.log_master_secret.close()
|
tls.log_master_secret.close()
|
||||||
with open(logfile, "rb") as f:
|
with open(logfile, "rb") as f:
|
||||||
assert f.read().count(b"CLIENT_RANDOM") >= 2
|
assert f.read().count(b"SERVER_HANDSHAKE_TRAFFIC_SECRET") >= 2
|
||||||
|
|
||||||
tls.log_master_secret = _logfun
|
tls.log_master_secret = _logfun
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user