mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
[3.13] gh-118658: Return consistent types from get_un/verified_chain
in SSLObject
and SSLSocket
(GH-118669) (#123082)
gh-118658: Return consistent types from `get_un/verified_chain` in `SSLObject` and `SSLSocket` (GH-118669)
(cherry picked from commit 8ef358dae1
)
Co-authored-by: Mateusz Nowak <nowak.mateusz@hotmail.com>
Co-authored-by: Gregory P. Smith [Google LLC] <greg@krypto.org>
This commit is contained in:
parent
0a02026a08
commit
21399a0963
4 changed files with 86 additions and 2 deletions
14
Lib/ssl.py
14
Lib/ssl.py
|
@ -1165,11 +1165,21 @@ class SSLSocket(socket):
|
||||||
|
|
||||||
@_sslcopydoc
|
@_sslcopydoc
|
||||||
def get_verified_chain(self):
|
def get_verified_chain(self):
|
||||||
return self._sslobj.get_verified_chain()
|
chain = self._sslobj.get_verified_chain()
|
||||||
|
|
||||||
|
if chain is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [cert.public_bytes(_ssl.ENCODING_DER) for cert in chain]
|
||||||
|
|
||||||
@_sslcopydoc
|
@_sslcopydoc
|
||||||
def get_unverified_chain(self):
|
def get_unverified_chain(self):
|
||||||
return self._sslobj.get_unverified_chain()
|
chain = self._sslobj.get_unverified_chain()
|
||||||
|
|
||||||
|
if chain is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [cert.public_bytes(_ssl.ENCODING_DER) for cert in chain]
|
||||||
|
|
||||||
@_sslcopydoc
|
@_sslcopydoc
|
||||||
def selected_npn_protocol(self):
|
def selected_npn_protocol(self):
|
||||||
|
|
34
Lib/test/certdata/cert3.pem
generated
Normal file
34
Lib/test/certdata/cert3.pem
generated
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIF8TCCBFmgAwIBAgIJAMstgJlaaVJcMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV
|
||||||
|
BAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUgRm91bmRhdGlvbiBDQTEW
|
||||||
|
MBQGA1UEAwwNb3VyLWNhLXNlcnZlcjAeFw0xODA4MjkxNDIzMTZaFw0zNzEwMjgx
|
||||||
|
NDIzMTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEj
|
||||||
|
MCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMMCWxv
|
||||||
|
Y2FsaG9zdDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKAqKHEL7aDt
|
||||||
|
3swl8hQF8VaK4zDGDRaF3E/IZTMwCN7FsQ4ejSiOe3E90f0phHCIpEpv2OebNenY
|
||||||
|
IpOGoFgkh62r/cthmnhu8Mn+FUIv17iOq7WX7B30OSqEpnr1voLX93XYkAq8LlMh
|
||||||
|
P79vsSCVhTwow3HZY7krEgl5WlfryOfj1i1TODSFPRCJePh66BsOTUvV/33GC+Qd
|
||||||
|
pVZVDGLowU1Ycmr/FdRvwT+F39Dehp03UFcxaX0/joPhH5gYpBB1kWTAQmxuqKMW
|
||||||
|
9ZZs6hrPtMXF/yfSrrXrzTdpct9paKR8RcufOcS8qju/ISK+1P/LXg2b5KJHedLo
|
||||||
|
TTIO3yCZ4d1odyuZBP7JDrI05gMJx95gz6sG685Qc+52MzLSTwr/Qg+MOjQoBy0o
|
||||||
|
8fRRVvIMEwoN0ZDb4uFEUuwZceUP1vTk/GGpNQt7ct4ropn6K4Zta3BUtovlLjZa
|
||||||
|
IIBhc1KETUqjRDvC6ACKmlcJ/5pY/dbH1lOux+IMFsh+djmaV90b3QIDAQABo4IB
|
||||||
|
wDCCAbwwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA4GA1UdDwEB/wQEAwIFoDAdBgNV
|
||||||
|
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4E
|
||||||
|
FgQUP7HpT6C+MGY+ChjID0caTzRqD0IwfQYDVR0jBHYwdIAU8+yUjvKOMMSOaMK/
|
||||||
|
jmoZwMGfdmWhUaRPME0xCzAJBgNVBAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29m
|
||||||
|
dHdhcmUgRm91bmRhdGlvbiBDQTEWMBQGA1UEAwwNb3VyLWNhLXNlcnZlcoIJAMst
|
||||||
|
gJlaaVJbMIGDBggrBgEFBQcBAQR3MHUwPAYIKwYBBQUHMAKGMGh0dHA6Ly90ZXN0
|
||||||
|
Y2EucHl0aG9udGVzdC5uZXQvdGVzdGNhL3B5Y2FjZXJ0LmNlcjA1BggrBgEFBQcw
|
||||||
|
AYYpaHR0cDovL3Rlc3RjYS5weXRob250ZXN0Lm5ldC90ZXN0Y2Evb2NzcC8wQwYD
|
||||||
|
VR0fBDwwOjA4oDagNIYyaHR0cDovL3Rlc3RjYS5weXRob250ZXN0Lm5ldC90ZXN0
|
||||||
|
Y2EvcmV2b2NhdGlvbi5jcmwwDQYJKoZIhvcNAQELBQADggGBAMo0usXQzycxMtYN
|
||||||
|
JzC42xfftzmnu7E7hsQx/fur22MazJCruU6rNEkMXow+cKOnay+nmiV7AVoYlkh2
|
||||||
|
+DZ4dPq8fWh/5cqmnXvccr2jJVEXaOjp1wKGLH0WfLXcRLIK4/fJM6NRNoO81HDN
|
||||||
|
hJGfBrot0gUKZcPZVQmouAlpu5OGwrfCkHR8v/BdvA5jE4zr+g/x+uUScE0M64wu
|
||||||
|
okJCAAQP/PkfQZxjePBmk7KPLuiTHFDLLX+2uldvUmLXOQsJgqumU03MBT4Z8NTA
|
||||||
|
zqmtEM65ceSP8lo8Zbrcy+AEkCulFaZ92tyjtbe8oN4wTmTLFw06oFLSZzuiOgDV
|
||||||
|
OaphdVKf/pvA6KBpr6izox0KQFIE5z3AAJZfKzMGDDD20xhy7jjQZNMAhjfsT+k4
|
||||||
|
SeYB/6KafNxq08uoulj7w4Z4R/EGpkXnU96ZHYHmvGN0RnxwI1cpYHCazG8AjsK/
|
||||||
|
anN9brBi5twTGrn+D8LRBqF5Yn+2MKkD0EdXJdtIENHP+32sPQ==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -103,6 +103,7 @@ CRLFILE = data_file("revocation.crl")
|
||||||
|
|
||||||
# Two keys and certs signed by the same CA (for SNI tests)
|
# Two keys and certs signed by the same CA (for SNI tests)
|
||||||
SIGNED_CERTFILE = data_file("keycert3.pem")
|
SIGNED_CERTFILE = data_file("keycert3.pem")
|
||||||
|
SINGED_CERTFILE_ONLY = data_file("cert3.pem")
|
||||||
SIGNED_CERTFILE_HOSTNAME = 'localhost'
|
SIGNED_CERTFILE_HOSTNAME = 'localhost'
|
||||||
|
|
||||||
SIGNED_CERTFILE_INFO = {
|
SIGNED_CERTFILE_INFO = {
|
||||||
|
@ -4720,6 +4721,40 @@ class TestPostHandshakeAuth(unittest.TestCase):
|
||||||
ssl.PEM_cert_to_DER_cert(pem), der
|
ssl.PEM_cert_to_DER_cert(pem), der
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_certificate_chain(self):
|
||||||
|
client_context, server_context, hostname = testing_context(
|
||||||
|
server_chain=False
|
||||||
|
)
|
||||||
|
server = ThreadedEchoServer(context=server_context, chatty=False)
|
||||||
|
|
||||||
|
with open(SIGNING_CA) as f:
|
||||||
|
expected_ca_cert = ssl.PEM_cert_to_DER_cert(f.read())
|
||||||
|
|
||||||
|
with open(SINGED_CERTFILE_ONLY) as f:
|
||||||
|
expected_ee_cert = ssl.PEM_cert_to_DER_cert(f.read())
|
||||||
|
|
||||||
|
with server:
|
||||||
|
with client_context.wrap_socket(
|
||||||
|
socket.socket(),
|
||||||
|
server_hostname=hostname
|
||||||
|
) as s:
|
||||||
|
s.connect((HOST, server.port))
|
||||||
|
vc = s.get_verified_chain()
|
||||||
|
self.assertEqual(len(vc), 2)
|
||||||
|
|
||||||
|
ee, ca = vc
|
||||||
|
self.assertIsInstance(ee, bytes)
|
||||||
|
self.assertIsInstance(ca, bytes)
|
||||||
|
self.assertEqual(expected_ca_cert, ca)
|
||||||
|
self.assertEqual(expected_ee_cert, ee)
|
||||||
|
|
||||||
|
uvc = s.get_unverified_chain()
|
||||||
|
self.assertEqual(len(uvc), 1)
|
||||||
|
self.assertIsInstance(uvc[0], bytes)
|
||||||
|
|
||||||
|
self.assertEqual(ee, uvc[0])
|
||||||
|
self.assertNotEqual(ee, ca)
|
||||||
|
|
||||||
def test_internal_chain_server(self):
|
def test_internal_chain_server(self):
|
||||||
client_context, server_context, hostname = testing_context()
|
client_context, server_context, hostname = testing_context()
|
||||||
client_context.load_cert_chain(SIGNED_CERTFILE)
|
client_context.load_cert_chain(SIGNED_CERTFILE)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
You can now get the raw TLS certificate chains from TLS connections via
|
||||||
|
:meth:`ssl.SSLSocket.get_verified_chain` and
|
||||||
|
:meth:`ssl.SSLSocket.get_unverified_chain` methods.
|
||||||
|
|
||||||
|
Contributed by Mateusz Nowak.
|
Loading…
Add table
Add a link
Reference in a new issue