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')

Reply via email to