From a6a905cc11da1f13db08e43b17fb32ed5295a23e Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 14 Mar 2012 16:45:38 -0400 Subject: [PATCH] Make get_mozilla_ciphers script a little more regexy and readable --- src/common/get_mozilla_ciphers.py | 121 +++++++++++++++--------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/src/common/get_mozilla_ciphers.py b/src/common/get_mozilla_ciphers.py index 59f8b59891..378ce01e83 100644 --- a/src/common/get_mozilla_ciphers.py +++ b/src/common/get_mozilla_ciphers.py @@ -1,54 +1,64 @@ #!/usr/bin/python +# coding=utf-8 # Copyright 2011, The Tor Project, Inc -# original version by Arturo Filastò +# original version by Arturo Filastò # This script parses Firefox and OpenSSL sources, and uses this information # to generate a ciphers.inc file. -# Read the cpp file to understand what Ciphers map to what name +import re + +##### +# Read the cpp file to understand what Ciphers map to what name : +# Make "ciphers" a map from name used in the javascript to a cipher macro name fileA = open('security/manager/ssl/src/nsNSSComponent.cpp','r') -start = None -lines = fileA.readlines() -for i, line in enumerate(lines): - if line.strip().startswith('static CipherPref CipherPrefs'): - # Get the starting boundary of the Cipher Preferences - start = i +# The input format is a file containing exactly one section of the form: +# static CipherPref CipherPrefs[] = { +# {"name", MACRO_NAME}, // comment +# ... +# {NULL, 0} +# } - if start and line.strip().startswith('{NULL, 0}'): - # Get the ending boundary of the Cipher Prefs - end = i - break +inCipherSection = False +cipherLines = [] +for line in fileA: + if line.startswith('static CipherPref CipherPrefs'): + # Get the starting boundary of the Cipher Preferences + inCipherSection = True + elif inCipherSection: + line = line.strip() + if line.startswith('{NULL, 0}'): + # At the ending boundary of the Cipher Prefs + break + else: + cipherLines.append(line) fileA.close() # Parse the lines and put them into a dict ciphers = {} -for x in lines[start:end]: - line = x.strip() - if line.startswith('{'): - for i, y in enumerate(line): - if y == '}': - parsed = line[1:i] - key, value = parsed.split(',') - ciphers[key.replace("\"","")] = value.strip() +for line in cipherLines: + m = re.search(r'^{\s*\"([^\"]+)\",\s*(\S*)\s*}', line) + if m: + key,value = m.groups() + ciphers[key] = value -# Read the JS file to understand what ciphers are enabled +##### +# Read the JS file to understand what ciphers are enabled. The format is +# pref("name", true/false); +# Build a map enabled_ciphers from javascript name to "true" or "false", +# and an (unordered!) list of the macro names for those ciphers that are +# enabled. fileB = open('netwerk/base/public/security-prefs.js', 'r') enabled_ciphers = {} -for x in fileB.readlines(): - start = None - line = x.strip() - for i, y in enumerate(line): - if y == "(": - start = i - if start and y == ")": - end = i - if start: - inner = line[start+1:end] - key, value = inner.replace("\"","").split(",") - if key.startswith('security.ssl3'): - enabled_ciphers[key.strip()] = value.strip() +for line in fileB: + m = re.match(r'pref\(\"([^\"]+)\"\s*,\s*(\S*)\s*\)', line) + if not m: + continue + key, val = m.groups() + if key.startswith("security.ssl3"): + enabled_ciphers[key] = val fileB.close() used_ciphers = [] @@ -56,27 +66,21 @@ for k, v in enabled_ciphers.items(): if v == "true": used_ciphers.append(ciphers[k]) - oSSLinclude = ('/usr/include/openssl/ssl3.h', '/usr/include/openssl/ssl.h', '/usr/include/openssl/ssl2.h', '/usr/include/openssl/ssl23.h', '/usr/include/openssl/tls1.h') +##### +# This reads the hex code for the ciphers that are used by firefox. +# sslProtoD is set to a map from macro name to macro value in sslproto.h; +# cipher_codes is set to an (unordered!) list of these hex values. sslProto = open('security/nss/lib/ssl/sslproto.h', 'r') sslProtoD = {} -# This reads the HEX code for the ciphers that are used -# by firefox. -for x in sslProto.readlines(): - line = x.strip() - if line.lower().startswith("#define"): - # If I ever see somebody putting mixed tab - # and spaces I will cut their fingers :) - line = line.replace('\t', ' ') - key = line.split(' ')[1] - value = line.split(' ')[-1] - key = key.strip() - value = value.strip() - print "%s %s\n\n" % (key, value) +for line in sslProto: + m = re.match('#define\s+(\S+)\s+(\S+)', line) + if m: + key, value = m.groups() sslProtoD[key] = value sslProto.close() @@ -84,23 +88,23 @@ cipher_codes = [] for x in used_ciphers: cipher_codes.append(sslProtoD[x].lower()) +#### +# Now read through all the openssl include files, and try to find the openssl +# macro names for those files. cipher_hex = {} for fl in oSSLinclude: fp = open(fl, 'r') - for x in fp.readlines(): - line = x.strip() - if line.lower().startswith("#define"): - line = line.replace('\t', ' ') - value = line.split(' ')[1] - key = line.split(' ')[-1] - key = key.strip() - value = value.strip() + for line in fp.readlines(): + m = re.match('#define\s+(\S+)\s+(\S+)', line) + if m: + value,key = m.groups() if key.startswith('0x'): key = key.replace('0x0300','0x').lower() #print "%s %s" % (key, value) cipher_hex[key] = value fp.close() +# Now generate the output. for x in cipher_codes: try: res = """#ifdef %s @@ -109,9 +113,6 @@ for x in cipher_codes: XCIPHER(%s, %s) #endif""" % (cipher_hex[x], x, cipher_hex[x], x, cipher_hex[x]) print res - except: + except KeyError: print "Not found %s" % x - -#print enabled_ciphers -#print ciphers