mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-22 15:37:45 +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.
|
||||
__name__ = "MasterSecretLogger"
|
||||
|
||||
def __call__(self, connection, where, ret):
|
||||
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:
|
||||
if not self.f:
|
||||
d = os.path.dirname(self.filename)
|
||||
if not os.path.isdir(d):
|
||||
os.makedirs(d)
|
||||
self.f = open(self.filename, "ab")
|
||||
self.f.write(b"\r\n")
|
||||
try:
|
||||
client_random = binascii.hexlify(connection.client_random())
|
||||
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()
|
||||
if hasattr(connection, "_still_needs_masterkey"):
|
||||
delattr(connection, "_still_needs_masterkey")
|
||||
def __call__(self, connection, keymaterial):
|
||||
with self.lock:
|
||||
if not self.f:
|
||||
d = os.path.dirname(self.filename)
|
||||
if not os.path.isdir(d):
|
||||
os.makedirs(d)
|
||||
self.f = open(self.filename, "ab")
|
||||
self.f.write(b"\n")
|
||||
self.f.write(keymaterial)
|
||||
self.f.write(b"\n")
|
||||
self.f.flush()
|
||||
|
||||
def close(self):
|
||||
with self.lock:
|
||||
@ -203,7 +184,7 @@ def _create_ssl_context(
|
||||
|
||||
# SSLKEYLOGFILE
|
||||
if log_master_secret:
|
||||
context.set_info_callback(log_master_secret)
|
||||
context.set_keylog_callback(log_master_secret)
|
||||
|
||||
if alpn_protos is not None:
|
||||
# advertise application layer protocols
|
||||
|
@ -43,7 +43,7 @@ class TestMasterSecretLogger(tservers.ServerTestBase):
|
||||
|
||||
tls.log_master_secret.close()
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user