Skip to content

Commit 21399a0

Browse files
miss-islingtonmatiuszkagpshead
authored
[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 8ef358d) Co-authored-by: Mateusz Nowak <nowak.mateusz@hotmail.com> Co-authored-by: Gregory P. Smith [Google LLC] <greg@krypto.org>
1 parent 0a02026 commit 21399a0

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

Lib/ssl.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -1165,11 +1165,21 @@ def getpeercert(self, binary_form=False):
11651165

11661166
@_sslcopydoc
11671167
def get_verified_chain(self):
1168-
return self._sslobj.get_verified_chain()
1168+
chain = self._sslobj.get_verified_chain()
1169+
1170+
if chain is None:
1171+
return []
1172+
1173+
return [cert.public_bytes(_ssl.ENCODING_DER) for cert in chain]
11691174

11701175
@_sslcopydoc
11711176
def get_unverified_chain(self):
1172-
return self._sslobj.get_unverified_chain()
1177+
chain = self._sslobj.get_unverified_chain()
1178+
1179+
if chain is None:
1180+
return []
1181+
1182+
return [cert.public_bytes(_ssl.ENCODING_DER) for cert in chain]
11731183

11741184
@_sslcopydoc
11751185
def selected_npn_protocol(self):

Lib/test/certdata/cert3.pem

+34
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_ssl.py

+35
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ def data_file(*name):
103103

104104
# Two keys and certs signed by the same CA (for SNI tests)
105105
SIGNED_CERTFILE = data_file("keycert3.pem")
106+
SINGED_CERTFILE_ONLY = data_file("cert3.pem")
106107
SIGNED_CERTFILE_HOSTNAME = 'localhost'
107108

108109
SIGNED_CERTFILE_INFO = {
@@ -4720,6 +4721,40 @@ def test_internal_chain_client(self):
47204721
ssl.PEM_cert_to_DER_cert(pem), der
47214722
)
47224723

4724+
def test_certificate_chain(self):
4725+
client_context, server_context, hostname = testing_context(
4726+
server_chain=False
4727+
)
4728+
server = ThreadedEchoServer(context=server_context, chatty=False)
4729+
4730+
with open(SIGNING_CA) as f:
4731+
expected_ca_cert = ssl.PEM_cert_to_DER_cert(f.read())
4732+
4733+
with open(SINGED_CERTFILE_ONLY) as f:
4734+
expected_ee_cert = ssl.PEM_cert_to_DER_cert(f.read())
4735+
4736+
with server:
4737+
with client_context.wrap_socket(
4738+
socket.socket(),
4739+
server_hostname=hostname
4740+
) as s:
4741+
s.connect((HOST, server.port))
4742+
vc = s.get_verified_chain()
4743+
self.assertEqual(len(vc), 2)
4744+
4745+
ee, ca = vc
4746+
self.assertIsInstance(ee, bytes)
4747+
self.assertIsInstance(ca, bytes)
4748+
self.assertEqual(expected_ca_cert, ca)
4749+
self.assertEqual(expected_ee_cert, ee)
4750+
4751+
uvc = s.get_unverified_chain()
4752+
self.assertEqual(len(uvc), 1)
4753+
self.assertIsInstance(uvc[0], bytes)
4754+
4755+
self.assertEqual(ee, uvc[0])
4756+
self.assertNotEqual(ee, ca)
4757+
47234758
def test_internal_chain_server(self):
47244759
client_context, server_context, hostname = testing_context()
47254760
client_context.load_cert_chain(SIGNED_CERTFILE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
You can now get the raw TLS certificate chains from TLS connections via
2+
:meth:`ssl.SSLSocket.get_verified_chain` and
3+
:meth:`ssl.SSLSocket.get_unverified_chain` methods.
4+
5+
Contributed by Mateusz Nowak.

0 commit comments

Comments
 (0)