diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /tools/make-tls-ct-logids.py | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tools/make-tls-ct-logids.py')
-rwxr-xr-x | tools/make-tls-ct-logids.py | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/tools/make-tls-ct-logids.py b/tools/make-tls-ct-logids.py new file mode 100755 index 00000000..0b74c513 --- /dev/null +++ b/tools/make-tls-ct-logids.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# Generate the array of Certificate Transparency Log ID to description mappings +# for the TLS dissector. +# +# To update the TLS dissector source file, run this from the source directory: +# +# python3 tools/make-tls-ct-logids.py --update +# + +import argparse +from base64 import b64decode, b64encode +from enum import Enum +import itertools +import os +import requests +from hashlib import sha256 + + +# Begin of comment, followed by the actual array definition +HEADER = "/* Generated by tools/make-tls-ct-logids.py\n" +# See also https://www.certificate-transparency.org/known-logs +CT_JSON_URL = 'https://www.gstatic.com/ct/log_list/v3/all_logs_list.json' +# File to be patched +SOURCE_FILE = os.path.join('epan', 'dissectors', 'packet-tls-utils.c') + +# Maximum elements per line in the value array. 11 is chosen because it results +# in output consistent with clang-format. +BYTES_PER_LINE = 11 + +class SourceStage(Enum): + BEGIN = 1 + IN_METAINFO = 2 + IN_BLOCK = 3 + END = 4 + + +def escape_c(s): + return s.replace('\\', '\\\\').replace('"', '\\"') + + +def byteshex(b): + return " ".join("0x%02x," % b for b in bytearray(b)) + + +def process_json(obj, lastmod): + logs = list(itertools.chain(*[op['logs'] for op in obj['operators']])) + metainfo, block = HEADER, '' + metainfo += " * Last-Modified %s, %s entries. */\n" % (lastmod, len(logs)) + block += "static const bytes_string ct_logids[] = {\n" + for entry in logs: + desc = entry["description"] + pubkey_der = b64decode(entry["key"]) + key_id = sha256(pubkey_der).digest() + block += ' { (const uint8_t[]){\n' + for offset in range(0, len(key_id), BYTES_PER_LINE): + block += ' %s\n' % \ + byteshex(key_id[offset:offset+BYTES_PER_LINE]) + block += ' },\n' + block += ' %d, "%s" },\n' % (len(key_id), escape_c(desc)) + block += " { NULL, 0, NULL }\n" + block += "};\n" + return metainfo, block + + +def parse_source(source_path): + """ + Reads the source file and tries to split it in the parts before, inside and + after the block. + """ + begin, metainfo, block, end = '', '', '', '' + # Stages: BEGIN (before block), IN_METAINFO, IN_BLOCK (skip), END + stage = SourceStage.BEGIN + with open(source_path) as f: + for line in f: + if line.startswith('/* Generated by '): + stage = SourceStage.IN_METAINFO + + + if stage == SourceStage.BEGIN: + begin += line + elif stage == SourceStage.IN_METAINFO: + metainfo += line + elif stage == SourceStage.IN_BLOCK: + block += line + if line.startswith('}'): + stage = SourceStage.END + elif stage == SourceStage.END: + end += line + + if line.startswith(' * Last-Modified '): + stage = SourceStage.IN_BLOCK + + if stage != SourceStage.END: + raise RuntimeError("Could not parse file (in stage %s)" % stage.name) + return begin, metainfo, block, end + + +parser = argparse.ArgumentParser() +parser.add_argument("--update", action="store_true", + help="Update %s as needed instead of writing to stdout" % SOURCE_FILE) + + +def main(): + args = parser.parse_args() + this_dir = os.path.dirname(__file__) + r = requests.get(CT_JSON_URL) + j_metainfo, j_block = process_json(r.json(), lastmod=r.headers['Last-Modified']) + source_path = os.path.join(this_dir, '..', SOURCE_FILE) + + if args.update: + s_begin, _, s_block, s_end = parse_source(source_path) + if s_block == j_block: + print("File is up-to-date") + else: + with open(source_path, "w") as f: + f.write(s_begin) + f.write(j_metainfo) + f.write(j_block) + f.write(s_end) + print("Updated %s" % source_path) + else: + print(j_metainfo, j_block) + + +if __name__ == '__main__': + main() |