Skip to content

Commit 609504f

Browse files
committed
python3: add backports from 3.14 to allow Y2038 testing
Signed-off-by: Alexander Kanavin <alex@linutronix.de>
1 parent e3402fe commit 609504f

5 files changed

+3182
-0
lines changed
Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
From 8cae89bd2d496ad44fae8c0a40ca508461806d95 Mon Sep 17 00:00:00 2001
2+
From: Alexander Kanavin <alex.kanavin@gmail.com>
3+
Date: Wed, 25 Sep 2024 23:23:47 +0200
4+
Subject: [PATCH] gh-119400: make_ssl_certs: update reference test data
5+
automatically, pass in expiration dates as parameters #119400 (GH-119401)
6+
7+
* Lib/test/certdata: do not hardcode reference cert data into tests
8+
9+
The script was simply printing the reference data and asking
10+
users to update it by hand into the test suites. This can
11+
be easily improved by writing the data into files and
12+
having the test cases load the files.
13+
14+
* make_ssl_certs: make it possible to pass in expiration dates from command line
15+
16+
Note that in this commit, the defaults are same as they were,
17+
so if nothing is specified the script works as before.
18+
19+
---------
20+
Upstream-Status: Backport
21+
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
22+
---
23+
Lib/test/certdata/keycert.pem.reference | 13 +++++
24+
Lib/test/certdata/keycert3.pem.reference | 15 +++++
25+
Lib/test/certdata/make_ssl_certs.py | 56 +++++++++++--------
26+
Lib/test/test_asyncio/utils.py | 21 +------
27+
Lib/test/test_ssl.py | 36 ++----------
28+
...-05-22-13-18-02.gh-issue-119400.WEt83v.rst | 2 +
29+
6 files changed, 71 insertions(+), 72 deletions(-)
30+
create mode 100644 Lib/test/certdata/keycert.pem.reference
31+
create mode 100644 Lib/test/certdata/keycert3.pem.reference
32+
create mode 100644 Misc/NEWS.d/next/Build/2024-05-22-13-18-02.gh-issue-119400.WEt83v.rst
33+
34+
diff --git a/Lib/test/certdata/keycert.pem.reference b/Lib/test/certdata/keycert.pem.reference
35+
new file mode 100644
36+
index 00000000000..f9a82f35f34
37+
--- /dev/null
38+
+++ b/Lib/test/certdata/keycert.pem.reference
39+
@@ -0,0 +1,13 @@
40+
+{'issuer': ((('countryName', 'XY'),),
41+
+ (('localityName', 'Castle Anthrax'),),
42+
+ (('organizationName', 'Python Software Foundation'),),
43+
+ (('commonName', 'localhost'),)),
44+
+ 'notAfter': 'Jan 24 04:21:36 2043 GMT',
45+
+ 'notBefore': 'Nov 25 04:21:36 2023 GMT',
46+
+ 'serialNumber': '53E14833F7546C29256DD0F034F776C5E983004C',
47+
+ 'subject': ((('countryName', 'XY'),),
48+
+ (('localityName', 'Castle Anthrax'),),
49+
+ (('organizationName', 'Python Software Foundation'),),
50+
+ (('commonName', 'localhost'),)),
51+
+ 'subjectAltName': (('DNS', 'localhost'),),
52+
+ 'version': 3}
53+
diff --git a/Lib/test/certdata/keycert3.pem.reference b/Lib/test/certdata/keycert3.pem.reference
54+
new file mode 100644
55+
index 00000000000..04a749c920b
56+
--- /dev/null
57+
+++ b/Lib/test/certdata/keycert3.pem.reference
58+
@@ -0,0 +1,15 @@
59+
+{'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
60+
+ 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
61+
+ 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
62+
+ 'issuer': ((('countryName', 'XY'),),
63+
+ (('organizationName', 'Python Software Foundation CA'),),
64+
+ (('commonName', 'our-ca-server'),)),
65+
+ 'notAfter': 'Oct 28 14:23:16 2037 GMT',
66+
+ 'notBefore': 'Aug 29 14:23:16 2018 GMT',
67+
+ 'serialNumber': 'CB2D80995A69525C',
68+
+ 'subject': ((('countryName', 'XY'),),
69+
+ (('localityName', 'Castle Anthrax'),),
70+
+ (('organizationName', 'Python Software Foundation'),),
71+
+ (('commonName', 'localhost'),)),
72+
+ 'subjectAltName': (('DNS', 'localhost'),),
73+
+ 'version': 3}
74+
\ No newline at end of file
75+
diff --git a/Lib/test/certdata/make_ssl_certs.py b/Lib/test/certdata/make_ssl_certs.py
76+
index ed2037c1fdf..48f980124e1 100644
77+
--- a/Lib/test/certdata/make_ssl_certs.py
78+
+++ b/Lib/test/certdata/make_ssl_certs.py
79+
@@ -1,6 +1,7 @@
80+
"""Make the custom certificate and private key files used by test_ssl
81+
and friends."""
82+
83+
+import argparse
84+
import os
85+
import pprint
86+
import shutil
87+
@@ -8,7 +9,8 @@
88+
from subprocess import *
89+
90+
startdate = "20180829142316Z"
91+
-enddate = "20371028142316Z"
92+
+enddate_default = "20371028142316Z"
93+
+days_default = "7000"
94+
95+
req_template = """
96+
[ default ]
97+
@@ -79,8 +81,8 @@
98+
default_startdate = {startdate}
99+
enddate = {enddate}
100+
default_enddate = {enddate}
101+
- default_days = 7000
102+
- default_crl_days = 7000
103+
+ default_days = {days}
104+
+ default_crl_days = {days}
105+
certificate = pycacert.pem
106+
private_key = pycakey.pem
107+
serial = $dir/serial
108+
@@ -117,7 +119,7 @@
109+
here = os.path.abspath(os.path.dirname(__file__))
110+
111+
112+
-def make_cert_key(hostname, sign=False, extra_san='',
113+
+def make_cert_key(cmdlineargs, hostname, sign=False, extra_san='',
114+
ext='req_x509_extensions_full', key='rsa:3072'):
115+
print("creating cert for " + hostname)
116+
tempnames = []
117+
@@ -130,11 +132,12 @@ def make_cert_key(hostname, sign=False, extra_san='',
118+
hostname=hostname,
119+
extra_san=extra_san,
120+
startdate=startdate,
121+
- enddate=enddate
122+
+ enddate=cmdlineargs.enddate,
123+
+ days=cmdlineargs.days
124+
)
125+
with open(req_file, 'w') as f:
126+
f.write(req)
127+
- args = ['req', '-new', '-nodes', '-days', '7000',
128+
+ args = ['req', '-new', '-nodes', '-days', cmdlineargs.days,
129+
'-newkey', key, '-keyout', key_file,
130+
'-extensions', ext,
131+
'-config', req_file]
132+
@@ -175,7 +178,7 @@ def make_cert_key(hostname, sign=False, extra_san='',
133+
def unmake_ca():
134+
shutil.rmtree(TMP_CADIR)
135+
136+
-def make_ca():
137+
+def make_ca(cmdlineargs):
138+
os.mkdir(TMP_CADIR)
139+
with open(os.path.join('cadir','index.txt'),'a+') as f:
140+
pass # empty file
141+
@@ -192,7 +195,8 @@ def make_ca():
142+
hostname='our-ca-server',
143+
extra_san='',
144+
startdate=startdate,
145+
- enddate=enddate
146+
+ enddate=cmdlineargs.enddate,
147+
+ days=cmdlineargs.days
148+
)
149+
t.write(req)
150+
t.flush()
151+
@@ -219,14 +223,22 @@ def make_ca():
152+
shutil.copy('capath/ceff1710.0', 'capath/b1930218.0')
153+
154+
155+
-def print_cert(path):
156+
+def write_cert_reference(path):
157+
import _ssl
158+
- pprint.pprint(_ssl._test_decode_cert(path))
159+
+ refdata = pprint.pformat(_ssl._test_decode_cert(path))
160+
+ print(refdata)
161+
+ with open(path + '.reference', 'w') as f:
162+
+ print(refdata, file=f)
163+
164+
165+
if __name__ == '__main__':
166+
+ parser = argparse.ArgumentParser(description='Make the custom certificate and private key files used by test_ssl and friends.')
167+
+ parser.add_argument('--days', default=days_default)
168+
+ parser.add_argument('--enddate', default=enddate_default)
169+
+ cmdlineargs = parser.parse_args()
170+
+
171+
os.chdir(here)
172+
- cert, key = make_cert_key('localhost', ext='req_x509_extensions_simple')
173+
+ cert, key = make_cert_key(cmdlineargs, 'localhost', ext='req_x509_extensions_simple')
174+
with open('ssl_cert.pem', 'w') as f:
175+
f.write(cert)
176+
with open('ssl_key.pem', 'w') as f:
177+
@@ -243,26 +255,26 @@ def print_cert(path):
178+
f.write(cert)
179+
180+
# For certificate matching tests
181+
- make_ca()
182+
- cert, key = make_cert_key('fakehostname', ext='req_x509_extensions_simple')
183+
+ make_ca(cmdlineargs)
184+
+ cert, key = make_cert_key(cmdlineargs, 'fakehostname', ext='req_x509_extensions_simple')
185+
with open('keycert2.pem', 'w') as f:
186+
f.write(key)
187+
f.write(cert)
188+
189+
- cert, key = make_cert_key('localhost', sign=True)
190+
+ cert, key = make_cert_key(cmdlineargs, 'localhost', sign=True)
191+
with open('keycert3.pem', 'w') as f:
192+
f.write(key)
193+
f.write(cert)
194+
195+
check_call(['openssl', 'x509', '-outform', 'pem', '-in', 'keycert3.pem', '-out', 'cert3.pem'])
196+
197+
- cert, key = make_cert_key('fakehostname', sign=True)
198+
+ cert, key = make_cert_key(cmdlineargs, 'fakehostname', sign=True)
199+
with open('keycert4.pem', 'w') as f:
200+
f.write(key)
201+
f.write(cert)
202+
203+
cert, key = make_cert_key(
204+
- 'localhost-ecc', sign=True, key='param:secp384r1.pem'
205+
+ cmdlineargs, 'localhost-ecc', sign=True, key='param:secp384r1.pem'
206+
)
207+
with open('keycertecc.pem', 'w') as f:
208+
f.write(key)
209+
@@ -282,7 +294,7 @@ def print_cert(path):
210+
'RID.1 = 1.2.3.4.5',
211+
]
212+
213+
- cert, key = make_cert_key('allsans', sign=True, extra_san='\n'.join(extra_san))
214+
+ cert, key = make_cert_key(cmdlineargs, 'allsans', sign=True, extra_san='\n'.join(extra_san))
215+
with open('allsans.pem', 'w') as f:
216+
f.write(key)
217+
f.write(cert)
218+
@@ -299,17 +311,17 @@ def print_cert(path):
219+
]
220+
221+
# IDN SANS, signed
222+
- cert, key = make_cert_key('idnsans', sign=True, extra_san='\n'.join(extra_san))
223+
+ cert, key = make_cert_key(cmdlineargs, 'idnsans', sign=True, extra_san='\n'.join(extra_san))
224+
with open('idnsans.pem', 'w') as f:
225+
f.write(key)
226+
f.write(cert)
227+
228+
- cert, key = make_cert_key('nosan', sign=True, ext='req_x509_extensions_nosan')
229+
+ cert, key = make_cert_key(cmdlineargs, 'nosan', sign=True, ext='req_x509_extensions_nosan')
230+
with open('nosan.pem', 'w') as f:
231+
f.write(key)
232+
f.write(cert)
233+
234+
unmake_ca()
235+
- print("update Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py")
236+
- print_cert('keycert.pem')
237+
- print_cert('keycert3.pem')
238+
+ print("Writing out reference data for Lib/test/test_ssl.py and Lib/test/test_asyncio/utils.py")
239+
+ write_cert_reference('keycert.pem')
240+
+ write_cert_reference('keycert3.pem')
241+
diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py
242+
index ce2408fc1aa..cfb5de58902 100644
243+
--- a/Lib/test/test_asyncio/utils.py
244+
+++ b/Lib/test/test_asyncio/utils.py
245+
@@ -15,6 +15,7 @@
246+
import unittest
247+
import weakref
248+
import warnings
249+
+from ast import literal_eval
250+
from unittest import mock
251+
252+
from http.server import HTTPServer
253+
@@ -56,24 +57,8 @@ def data_file(*filename):
254+
ONLYKEY = data_file('certdata', 'ssl_key.pem')
255+
SIGNED_CERTFILE = data_file('certdata', 'keycert3.pem')
256+
SIGNING_CA = data_file('certdata', 'pycacert.pem')
257+
-PEERCERT = {
258+
- 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
259+
- 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
260+
- 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
261+
- 'issuer': ((('countryName', 'XY'),),
262+
- (('organizationName', 'Python Software Foundation CA'),),
263+
- (('commonName', 'our-ca-server'),)),
264+
- 'notAfter': 'Oct 28 14:23:16 2037 GMT',
265+
- 'notBefore': 'Aug 29 14:23:16 2018 GMT',
266+
- 'serialNumber': 'CB2D80995A69525C',
267+
- 'subject': ((('countryName', 'XY'),),
268+
- (('localityName', 'Castle Anthrax'),),
269+
- (('organizationName', 'Python Software Foundation'),),
270+
- (('commonName', 'localhost'),)),
271+
- 'subjectAltName': (('DNS', 'localhost'),),
272+
- 'version': 3
273+
-}
274+
-
275+
+with open(data_file('certdata', 'keycert3.pem.reference')) as file:
276+
+ PEERCERT = literal_eval(file.read())
277+
278+
def simple_server_sslcontext():
279+
server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
280+
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
281+
index 7fdd2be78d5..fb86383d78e 100644
282+
--- a/Lib/test/test_ssl.py
283+
+++ b/Lib/test/test_ssl.py
284+
@@ -84,21 +84,8 @@ def data_file(*name):
285+
CAFILE_NEURONIO = data_file("capath", "4e1295a3.0")
286+
CAFILE_CACERT = data_file("capath", "5ed36f99.0")
287+
288+
-CERTFILE_INFO = {
289+
- 'issuer': ((('countryName', 'XY'),),
290+
- (('localityName', 'Castle Anthrax'),),
291+
- (('organizationName', 'Python Software Foundation'),),
292+
- (('commonName', 'localhost'),)),
293+
- 'notAfter': 'Jan 24 04:21:36 2043 GMT',
294+
- 'notBefore': 'Nov 25 04:21:36 2023 GMT',
295+
- 'serialNumber': '53E14833F7546C29256DD0F034F776C5E983004C',
296+
- 'subject': ((('countryName', 'XY'),),
297+
- (('localityName', 'Castle Anthrax'),),
298+
- (('organizationName', 'Python Software Foundation'),),
299+
- (('commonName', 'localhost'),)),
300+
- 'subjectAltName': (('DNS', 'localhost'),),
301+
- 'version': 3
302+
-}
303+
+with open(data_file('keycert.pem.reference')) as file:
304+
+ CERTFILE_INFO = literal_eval(file.read())
305+
306+
# empty CRL
307+
CRLFILE = data_file("revocation.crl")
308+
@@ -108,23 +95,8 @@ def data_file(*name):
309+
SINGED_CERTFILE_ONLY = data_file("cert3.pem")
310+
SIGNED_CERTFILE_HOSTNAME = 'localhost'
311+
312+
-SIGNED_CERTFILE_INFO = {
313+
- 'OCSP': ('http://testca.pythontest.net/testca/ocsp/',),
314+
- 'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',),
315+
- 'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',),
316+
- 'issuer': ((('countryName', 'XY'),),
317+
- (('organizationName', 'Python Software Foundation CA'),),
318+
- (('commonName', 'our-ca-server'),)),
319+
- 'notAfter': 'Oct 28 14:23:16 2037 GMT',
320+
- 'notBefore': 'Aug 29 14:23:16 2018 GMT',
321+
- 'serialNumber': 'CB2D80995A69525C',
322+
- 'subject': ((('countryName', 'XY'),),
323+
- (('localityName', 'Castle Anthrax'),),
324+
- (('organizationName', 'Python Software Foundation'),),
325+
- (('commonName', 'localhost'),)),
326+
- 'subjectAltName': (('DNS', 'localhost'),),
327+
- 'version': 3
328+
-}
329+
+with open(data_file('keycert3.pem.reference')) as file:
330+
+ SIGNED_CERTFILE_INFO = literal_eval(file.read())
331+
332+
SIGNED_CERTFILE2 = data_file("keycert4.pem")
333+
SIGNED_CERTFILE2_HOSTNAME = 'fakehostname'
334+
diff --git a/Misc/NEWS.d/next/Build/2024-05-22-13-18-02.gh-issue-119400.WEt83v.rst b/Misc/NEWS.d/next/Build/2024-05-22-13-18-02.gh-issue-119400.WEt83v.rst
335+
new file mode 100644
336+
index 00000000000..b4029f20579
337+
--- /dev/null
338+
+++ b/Misc/NEWS.d/next/Build/2024-05-22-13-18-02.gh-issue-119400.WEt83v.rst
339+
@@ -0,0 +1,2 @@
340+
+``make_ssl_certs``, the script that prepares certificate data for the
341+
+test suite, now allows specifying expiration dates.
342+
--
343+
2.39.5
344+

0 commit comments

Comments
 (0)