On Sun, Dec 29, 2019 at 12:03:55AM +0100, Branko Čibej wrote: > On 28.12.2019 17:49, James McCoy wrote: > > On Wed, Dec 04, 2019 at 10:34:00PM -0500, James McCoy wrote: > >> I use create_certs.py at build time in the Debian packaging to avoid > >> dealing with expired certs. Since Debian is in the process of trying to > >> remove Python 2, I've updated the script to work with Python 3. > >> > >> It would also be useful if 1.4 were released, so I could switch to the > >> CMake build. > > These are both becoming more important issues. As an alternative, is > > current trunk in decent enough shape to be used, even without an > > official release? > > > > I can also look into more of the Python3 issues (like SyntaxErrors in > > SConstruct) if there's a desire to release another 1.3.x version (or to > > carry the patches locally until a new release happens). > > Sorry for not getting back to you sooner.
No worries. I ended up with two patches. One that I've applied to the packaging of 1.3.9, since that was the immediate need. The other is for trunk and only covers a couple of the helper scripts. I got distracted by other priorities and didn't get around to finishing the work, but it should at least be a starting point. Cheers, -- James GPG Key: 4096R/91BF BF4D 6956 BD5D F7B7 2D23 DFE6 91AE 331B A3DB
diff --git i/SConstruct w/SConstruct index 4358a23..7f3cc94 100644 --- i/SConstruct +++ w/SConstruct @@ -20,6 +20,8 @@ # ==================================================================== # +from __future__ import print_function + import sys import os import re @@ -163,9 +165,9 @@ env.Append(BUILDERS = { suffix='.def', src_suffix='.h') }) -match = re.search('SERF_MAJOR_VERSION ([0-9]+).*' - 'SERF_MINOR_VERSION ([0-9]+).*' - 'SERF_PATCH_VERSION ([0-9]+)', +match = re.search(b'SERF_MAJOR_VERSION ([0-9]+).*' + b'SERF_MINOR_VERSION ([0-9]+).*' + b'SERF_PATCH_VERSION ([0-9]+)', env.File('serf.h').get_contents(), re.DOTALL) MAJOR, MINOR, PATCH = [int(x) for x in match.groups()] @@ -183,7 +185,7 @@ CALLOUT_OKAY = not (env.GetOption('clean') or env.GetOption('help')) unknown = opts.UnknownVariables() if unknown: - print 'Warning: Used unknown variables:', ', '.join(unknown.keys()) + print('Warning: Used unknown variables:', ', '.join(unknown.keys())) apr = str(env['APR']) apu = str(env['APU']) diff --git i/build/check.py w/build/check.py index 2dacb4c..76945af 100755 --- i/build/check.py +++ w/build/check.py @@ -22,6 +22,8 @@ # =================================================================== # +from __future__ import print_function + import sys import glob import subprocess @@ -52,16 +54,16 @@ if __name__ == '__main__': # Find test responses and run them one by one for case in glob.glob(testdir + "/testcases/*.response"): - print "== Testing %s ==" % (case) + print("== Testing %s ==" % (case)) try: subprocess.check_call([SERF_RESPONSE_EXE, case]) except subprocess.CalledProcessError: - print "ERROR: test case %s failed" % (case) + print("ERROR: test case %s failed" % (case)) sys.exit(1) - print "== Running the unit tests ==" + print("== Running the unit tests ==") try: subprocess.check_call(TEST_ALL_EXE) except subprocess.CalledProcessError: - print "ERROR: test(s) failed in test_all" + print("ERROR: test(s) failed in test_all") sys.exit(1) diff --git i/build/gen_def.py w/build/gen_def.py index a2222d0..1e006ee 100755 --- i/build/gen_def.py +++ w/build/gen_def.py @@ -52,12 +52,13 @@ _types = re.compile(r'^extern const serf_bucket_type_t (serf_[a-z_]*);', def extract_exports(fname): - content = open(fname).read() exports = [ ] - for name in _funcs.findall(content): - exports.append(name) - for name in _types.findall(content): - exports.append(name) + with open(fname) as fd: + content = fd.read() + for name in _funcs.findall(content): + exports.append(name) + for name in _types.findall(content): + exports.append(name) return exports # Blacklist the serf v2 API for now
Index: buckets/hpack_huffman.py =================================================================== --- buckets/hpack_huffman.py (revision 1875679) +++ buckets/hpack_huffman.py (working copy) @@ -29,6 +29,8 @@ # The following script parses the table to a C struct to be used # by the hpack huffman decoder and encoder in serf. +from __future__ import print_function + import re rfc_text = """ @@ -391,13 +393,13 @@ bits = int(m.group(4)) if len(bitvals) != bits: - print '%d vs %d (%s)' %(len(bitvals), bits, bitvals) + print('{d} vs {d} ({})'.format(len(bitvals), bits, bitvals)) continue shift = hex << (32 - bits) if '{0:032b}'.format(shift)[0:bits] != bitvals: - print '%s vs %s' % ('{0:032b}'.format(shift)[0:bits], bitvals) + print('{} vs {}'.format('{0:032b}'.format(shift)[0:bits], bitvals)) continue mask = 0 @@ -411,19 +413,19 @@ if len(items) != 257: raise Exception('There should be exactly 257 items') -print '/*****************************************************' -print ' * Generated code *' -print ' *****************************************************' -print ' * Please edit hpack_huffman.py instead of this file *' -print ' * to recreate this file *' -print ' *****************************************************/' -print '' -print 'static const struct serf_hpack_huffman_item_t {' -print ' apr_uint32_t hval; /* Huffman code shifted to most left bit */' -print ' apr_uint32_t hmask; /* Mask of bits used in this code */' -print ' apr_int16_t bits; /* Nr of bits used */' -print ' apr_int16_t cval; /* The character value of this code */' -print '} serf_hpack_hm_map[] = {' +print('/*****************************************************') +print(' * Generated code *') +print(' *****************************************************') +print(' * Please edit hpack_huffman.py instead of this file *') +print(' * to recreate this file *') +print(' *****************************************************/') +print() +print('static const struct serf_hpack_huffman_item_t {') +print(' apr_uint32_t hval; /* Huffman code shifted to most left bit */') +print(' apr_uint32_t hmask; /* Mask of bits used in this code */') +print(' apr_int16_t bits; /* Nr of bits used */') +print(' apr_int16_t cval; /* The character value of this code */') +print('} serf_hpack_hm_map[] = {') n = 1 map = {} for i in items: @@ -431,16 +433,16 @@ comma = ',' else: comma = ' ' - print ' { 0x%08x, 0x%08x, %2d, %3d }%s /* %s */' % \ - (i[0], i[1], i[2], i[3], comma, i[4]) + print(' {{ 0x{0:08x}, 0x{1:08x}, {2:2d}, {3:3d} }}{4:s} /* {5:s} */' + .format(i[0], i[1], i[2], i[3], comma, i[4])) map[i[3]] = n-1 n += 1 -print '};' -print '' +print('};') +print() -print '/* Maps chars to records in serf_hpack_hm_map. */' -print 'static const apr_int16_t serf_hpack_hm_rmap[] = {' +print('/* Maps chars to records in serf_hpack_hm_map. */') +print('static const apr_int16_t serf_hpack_hm_rmap[] = {') for i in range(0,257): if i < 256: comma = ',' @@ -447,9 +449,9 @@ else: comma = '' if i % 8 != 7: - print ' %3d%s' % (map[i], comma), + print(' {0:3d}{1:s}'.format(map[i], comma), end='') else: - print ' %3d%s' % (map[i], comma) -print '' -print '};' -print '' + print(' {0:3d}{1:s}'.format(map[i], comma)) +print() +print('};') +print() Index: test/certs/create_certs.py =================================================================== --- test/certs/create_certs.py (revision 1875679) +++ test/certs/create_certs.py (working copy) @@ -47,11 +47,11 @@ key = crypto.PKey() key.generate_key(KEY_ALGO, KEY_SIZE) if passphrase: - open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, + open(keyfile, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key, KEY_CIPHER, passphrase)) else: - open(keyfile, "wt").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, + open(keyfile, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, key)) return key @@ -62,7 +62,7 @@ pkcs12.set_certificate(clientcert) pkcs12.set_privatekey(clientkey) pkcs12.set_ca_certificates([issuer]) - open(pkcs12file, "wt").write(pkcs12.export(passphrase=passphrase, + open(pkcs12file, "wb").write(pkcs12.export(passphrase=passphrase, iter=2048, maciter=2048)) def create_crl(revokedcert, cakey, cacert, crlfile, next_crl_days=VALID_DAYS): @@ -69,12 +69,12 @@ crl = crypto.CRL() revoked = crypto.Revoked() - serial_number = "%x" % revokedcert.get_serial_number() + serial_number = b"%x" % revokedcert.get_serial_number() now = datetime.utcnow() - now_str = now.strftime('%Y%m%d%H%M%SZ') + now_str = now.strftime('%Y%m%d%H%M%SZ').encode('utf-8') revoked.set_serial(serial_number) - revoked.set_reason('unspecified') + revoked.set_reason(b'unspecified') revoked.set_rev_date(now_str) # revoked as of now crl.add_revoked(revoked) @@ -84,7 +84,7 @@ # Some very old versions of pyopenssl (such as the one on macOS) # do not support the 'digest' keyword argument. exported = crl.export(cacert, cakey, days=next_crl_days) - open(crlfile, "wt").write(exported) + open(crlfile, "wb").write(exported) # subjectAltName def create_cert(subjectkey, certfile, issuer=None, issuerkey=None, country='', @@ -96,7 +96,7 @@ subjectAltName Array of fully qualified subject alternative names (use OpenSSL syntax): - For a DNS entry, use: ['DNS:localhost']. Other options are 'email', 'URI', 'IP'. + For a DNS entry, use: [b'DNS:localhost']. Other options are b'email', b'URI', b'IP'. ''' cert = crypto.X509() @@ -122,34 +122,34 @@ if ca: cert.add_extensions([ - crypto.X509Extension("basicConstraints", False, - "CA:TRUE"), - crypto.X509Extension("subjectKeyIdentifier", False, "hash", + crypto.X509Extension(b"basicConstraints", False, + b"CA:TRUE"), + crypto.X509Extension(b"subjectKeyIdentifier", False, b"hash", subject=cert) ]) cert.add_extensions([ - crypto.X509Extension("authorityKeyIdentifier", False, - "keyid:always", issuer=issuer) + crypto.X509Extension(b"authorityKeyIdentifier", False, + b"keyid:always", issuer=issuer) ]) - if subjectAltName: + if subjectAltName is not None: critical = True if not cn else False cert.add_extensions([ - crypto.X509Extension('subjectAltName', critical, ", ".join(subjectAltName))]) + crypto.X509Extension(b'subjectAltName', critical, ", ".join(subjectAltName).encode('utf-8'))]) - if ocsp_responder_url: + if ocsp_responder_url is not None: cert.add_extensions([ - crypto.X509Extension('authorityInfoAccess', False, - 'OCSP;URI:' + ocsp_responder_url)]) + crypto.X509Extension(b'authorityInfoAccess', False, + 'OCSP;URI:{}'.format(ocsp_responder_url).encode('utf-8'))]) if ocsp_signer: cert.add_extensions([ - crypto.X509Extension('extendedKeyUsage', True, 'OCSPSigning') + crypto.X509Extension(b'extendedKeyUsage', True, b'OCSPSigning') ]) cert.sign(issuerkey, SIGN_ALGO) - open(certfile, "wt").write(crypto.dump_certificate(crypto.FILETYPE_PEM, + open(certfile, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) return cert @@ -156,7 +156,7 @@ if __name__ == '__main__': # root CA key pair and certificate. # This key will be used to sign the intermediate CA certificate - rootcakey = create_key('private/serfrootcakey.pem', 'serftest') + rootcakey = create_key('private/serfrootcakey.pem', b'serftest') rootcacert = create_cert(subjectkey=rootcakey, certfile='serfrootcacert.pem', @@ -167,7 +167,7 @@ # intermediate CA key pair and certificate # This key will be used to sign all server certificates - cakey = create_key('private/serfcakey.pem', 'serftest') + cakey = create_key('private/serfcakey.pem', b'serftest') cacert = create_cert(subjectkey=cakey, certfile='serfcacert.pem', issuer=rootcacert, issuerkey=rootcakey, @@ -178,7 +178,7 @@ # server key pair # server certificate, no errors - serverkey = create_key('private/serfserverkey.pem', 'serftest') + serverkey = create_key('private/serfserverkey.pem', b'serftest') servercert = create_cert(subjectkey=serverkey, certfile='serfservercert.pem', @@ -247,7 +247,7 @@ ocsp_signer=True) # client key pair and certificate - clientkey = create_key('private/serfclientkey.pem', 'serftest') + clientkey = create_key('private/serfclientkey.pem', b'serftest') clientcert = create_cert(subjectkey=clientkey, certfile='serfclientcert.pem', @@ -258,10 +258,10 @@ email='serfcli...@example.com') clientpkcs12 = create_pkcs12(clientkey, clientcert, cacert, - 'serfclientcert.p12', 'serftest') + 'serfclientcert.p12', b'serftest') # Note that this creates a v1 CRL file without extensions set, and with # MD5 hash. Not ideal, but pyOpenSSL doesn't support more than this. # # crl - crl = create_crl(servercert, cakey, cacert, 'serfservercrl.pem') + crl = create_crl(servercert, cakey, cacert, b'serfservercrl.pem')