diff options
-rw-r--r-- | epan/dissectors/packet-ssl-utils.c | 81 | ||||
-rwxr-xr-x | tools/make-tls-ct-logids.py | 92 |
2 files changed, 173 insertions, 0 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c index 4928130859..cf73c31a5a 100644 --- a/epan/dissectors/packet-ssl-utils.c +++ b/epan/dissectors/packet-ssl-utils.c @@ -1252,6 +1252,84 @@ const value_string tls_cert_status_type[] = { { 0, NULL } }; +/* Generated by tools/make-tls-ct-logids.py + * Last-Modified Mon, 06 Mar 2017 15:27:22 GMT, 24 entries. */ +static const bytes_string ct_logids[] = { + { "\xa4\xb9\x09\x90\xb4\x18\x58\x14\x87\xbb\x13\xa2\xcc\x67\x70\x0a" + "\x3c\x35\x98\x04\xf9\x1b\xdf\xb8\xe3\x77\xcd\x0e\xc8\x0d\xdc\x10", 32, + "Google 'Pilot' log" }, + { "\x68\xf6\x98\xf8\x1f\x64\x82\xbe\x3a\x8c\xee\xb9\x28\x1d\x4c\xfc" + "\x71\x51\x5d\x67\x93\xd4\x44\xd1\x0a\x67\xac\xbb\x4f\x4f\xfb\xc4", 32, + "Google 'Aviator' log" }, + { "\x56\x14\x06\x9a\x2f\xd7\xc2\xec\xd3\xf5\xe1\xbd\x44\xb2\x3e\xc7" + "\x46\x76\xb9\xbc\x99\x11\x5c\xc0\xef\x94\x98\x55\xd6\x89\xd0\xdd", 32, + "DigiCert Log Server" }, + { "\xee\x4b\xbd\xb7\x75\xce\x60\xba\xe1\x42\x69\x1f\xab\xe1\x9e\x66" + "\xa3\x0f\x7e\x5f\xb0\x72\xd8\x83\x00\xc4\x7b\x89\x7a\xa8\xfd\xcb", 32, + "Google 'Rocketeer' log" }, + { "\xcd\xb5\x17\x9b\x7f\xc1\xc0\x46\xfe\xea\x31\x13\x6a\x3f\x8f\x00" + "\x2e\x61\x82\xfa\xf8\x89\x6f\xec\xc8\xb2\xf5\xb5\xab\x60\x49\x00", 32, + "Certly.IO log" }, + { "\x74\x61\xb4\xa0\x9c\xfb\x3d\x41\xd7\x51\x59\x57\x5b\x2e\x76\x49" + "\xa4\x45\xa8\xd2\x77\x09\xb0\xcc\x56\x4a\x64\x82\xb7\xeb\x41\xa3", 32, + "Izenpe log" }, + { "\xdd\xeb\x1d\x2b\x7a\x0d\x4f\xa6\x20\x8b\x81\xad\x81\x68\x70\x7e" + "\x2e\x8e\x9d\x01\xd5\x5c\x88\x8d\x3d\x11\xc4\xcd\xb6\xec\xbe\xcc", 32, + "Symantec log" }, + { "\xac\x3b\x9a\xed\x7f\xa9\x67\x47\x57\x15\x9e\x6d\x7d\x57\x56\x72" + "\xf9\xd9\x81\x00\x94\x1e\x9b\xde\xff\xec\xa1\x31\x3b\x75\x78\x2d", 32, + "Venafi log" }, + { "\x9e\x4f\xf7\x3d\xc3\xce\x22\x0b\x69\x21\x7c\x89\x9e\x46\x80\x76" + "\xab\xf8\xd7\x86\x36\xd5\xcc\xfc\x85\xa3\x1a\x75\x62\x8b\xa8\x8b", 32, + "WoSign log" }, + { "\x41\xb2\xdc\x2e\x89\xe6\x3c\xe4\xaf\x1b\xa7\xbb\x29\xbf\x68\xc6" + "\xde\xe6\xf9\xf1\xcc\x04\x7e\x30\xdf\xfa\xe3\xb3\xba\x25\x92\x63", 32, + "WoSign ctlog" }, + { "\xbc\x78\xe1\xdf\xc5\xf6\x3c\x68\x46\x49\x33\x4d\xa1\x0f\xa1\x5f" + "\x09\x79\x69\x20\x09\xc0\x81\xb4\xf3\xf6\x91\x7f\x3e\xd9\xb8\xa5", 32, + "Symantec VEGA log" }, + { "\xa5\x77\xac\x9c\xed\x75\x48\xdd\x8f\x02\x5b\x67\xa2\x41\x08\x9d" + "\xf8\x6e\x0f\x47\x6e\xc2\x03\xc2\xec\xbe\xdb\x18\x5f\x28\x26\x38", 32, + "CNNIC CT log" }, + { "\xc9\xcf\x89\x0a\x21\x10\x9c\x66\x6c\xc1\x7a\x3e\xd0\x65\xc9\x30" + "\xd0\xe0\x13\x5a\x9f\xeb\xa8\x5a\xf1\x42\x10\xb8\x07\x24\x21\xaa", 32, + "Wang Shengnan GDCA log" }, + { "\xa8\x99\xd8\x78\x0c\x92\x90\xaa\xf4\x62\xf3\x18\x80\xcc\xfb\xd5" + "\x24\x51\xe9\x70\xd0\xfb\xf5\x91\xef\x75\xb0\xd9\x9b\x64\x56\x81", 32, + "Google 'Submariner' log" }, + { "\x89\x41\x44\x9c\x70\x74\x2e\x06\xb9\xfc\x9c\xe7\xb1\x16\xba\x00" + "\x24\xaa\x36\xd5\x9a\xf4\x4f\x02\x04\x40\x4f\x00\xf7\xea\x85\x66", 32, + "Izenpe 2nd log" }, + { "\x34\xbb\x6a\xd6\xc3\xdf\x9c\x03\xee\xa8\xa4\x99\xff\x78\x91\x48" + "\x6c\x9d\x5e\x5c\xac\x92\xd0\x1f\x7b\xfd\x1b\xce\x19\xdb\x48\xef", 32, + "StartCom CT log" }, + { "\xbb\xd9\xdf\xbc\x1f\x8a\x71\xb5\x93\x94\x23\x97\xaa\x92\x7b\x47" + "\x38\x57\x95\x0a\xab\x52\xe8\x1a\x90\x96\x64\x36\x8e\x1e\xd1\x85", 32, + "Google 'Skydiver' log" }, + { "\x29\x3c\x51\x96\x54\xc8\x39\x65\xba\xaa\x50\xfc\x58\x07\xd4\xb7" + "\x6f\xbf\x58\x7a\x29\x72\xdc\xa4\xc3\x0c\xf4\xe5\x45\x47\xf4\x78", 32, + "Google 'Icarus' log" }, + { "\x92\x4a\x30\xf9\x09\x33\x6f\xf4\x35\xd6\x99\x3a\x10\xac\x75\xa2" + "\xc6\x41\x72\x8e\x7f\xc2\xd6\x59\xae\x61\x88\xff\xad\x40\xce\x01", 32, + "GDCA log" }, + { "\x1d\x02\x4b\x8e\xb1\x49\x8b\x34\x4d\xfd\x87\xea\x3e\xfc\x09\x96" + "\xf7\x50\x6f\x23\x5d\x1d\x49\x70\x61\xa4\x77\x3c\x43\x9c\x25\xfb", 32, + "Google 'Daedalus' log" }, + { "\xe0\x12\x76\x29\xe9\x04\x96\x56\x4e\x3d\x01\x47\x98\x44\x98\xaa" + "\x48\xf8\xad\xb1\x66\x00\xeb\x79\x02\xa1\xef\x99\x09\x90\x62\x73", 32, + "PuChuangSiDa log" }, + { "\x03\x01\x9d\xf3\xfd\x85\xa6\x9a\x8e\xbd\x1f\xac\xc6\xda\x9b\xa7" + "\x3e\x46\x97\x74\xfe\x77\xf5\x79\xfc\x5a\x08\xb8\x32\x8c\x1d\x6b", 32, + "Venafi Gen2 CT log" }, + { "\x15\x97\x04\x88\xd7\xb9\x97\xa0\x5b\xeb\x52\x51\x2a\xde\xe8\xd2" + "\xe8\xb4\xa3\x16\x52\x64\x12\x1a\x9f\xab\xfb\xd5\xf8\x5a\xd9\x3f", 32, + "Symantec SIRIUS log" }, + { "\x87\x75\xbf\xe7\x59\x7c\xf8\x8c\x43\x99\x5f\xbd\xf3\x6e\xff\x56" + "\x8d\x47\x56\x36\xff\x4a\xb5\x60\xc1\xb4\xea\xff\x5e\xa0\x83\x0f", 32, + "DigiCert CT2 log" }, + { NULL, 0, NULL } +}; + /* string_string is inappropriate as it compares strings while * "byte strings MUST NOT be truncated" (RFC 7301) */ typedef struct ssl_alpn_protocol { @@ -6600,10 +6678,13 @@ tls_dissect_sct(ssl_common_dissect_t *hf, tvbuff_t *tvb, packet_info *pinfo, pro guint64 sct_timestamp_ms; nstime_t sct_timestamp; guint32 exts_len; + const gchar *log_name; proto_tree_add_item(tree, hf->hf.sct_sct_version, tvb, offset, 1, ENC_NA); offset++; proto_tree_add_item(tree, hf->hf.sct_sct_logid, tvb, offset, 32, ENC_BIG_ENDIAN); + log_name = bytesval_to_str(tvb_get_ptr(tvb, offset, 32), 32, ct_logids, "Unknown Log"); + proto_item_append_text(tree, " (%s)", log_name); offset += 32; sct_timestamp_ms = tvb_get_ntoh64(tvb, offset); sct_timestamp.secs = (time_t)(sct_timestamp_ms / 1000); diff --git a/tools/make-tls-ct-logids.py b/tools/make-tls-ct-logids.py new file mode 100755 index 0000000000..8f70c240a9 --- /dev/null +++ b/tools/make-tls-ct-logids.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# 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: +# +# python tools/make-tls-ct-logids.py --update +# + +import argparse +from base64 import b64decode, b64encode +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.certificate-transparency.org/known-logs/all_logs_list.json' +# File to be patched +SOURCE_FILE = "epan/dissectors/packet-ssl-utils.c" + +def escape_c(s): + return s.replace('\\', '\\\\').replace('"', '\\"') + +def byteshex(b): + return "".join("\\x%02x" % b for b in bytearray(b)) + +def process_json(obj, lastmod): + lines = HEADER + lines += " * Last-Modified %s, %s entries. */\n" % (lastmod, len(obj["logs"])) + lines += "static const bytes_string ct_logids[] = {\n" + for entry in obj["logs"]: + desc = entry["description"] + pubkey_der = b64decode(entry["key"]) + key_id = sha256(pubkey_der).digest() + lines += ' { ' + lines += '"%s"\n' % byteshex(key_id[:16]) + lines += ' "%s", %d,\n' % (byteshex(key_id[16:]), len(key_id)) + lines += ' "%s" },\n' % escape_c(desc) + lines += " { NULL, 0, NULL }\n" + lines += "};\n" + return lines + +def parse_source(): + """ + Reads the source file and tries to split it in the parts before, inside and + after the block. + """ + begin, block, end = '', '', '' + # Stages: 1 (before block), 2 (in block, skip), 3 (after block) + stage = 1 + with open(SOURCE_FILE) as f: + for line in f: + if line == HEADER: + stage = 2 # Begin of block + if stage == 1: + begin += line + elif stage == 2: + block += line + if line.startswith('}'): + stage = 3 # End of block reached + elif stage == 3: + end += line + if stage != 3: + raise RuntimeError("Could not parse file (in stage %d)" % stage) + return begin, 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() + r = requests.get(CT_JSON_URL) + code = process_json(r.json(), lastmod=r.headers['Last-Modified']) + + if args.update: + begin, block, end = parse_source() + if block == code: + print("File is up-to-date") + else: + with open(SOURCE_FILE, "w") as f: + f.write(begin) + f.write(code) + f.write(end) + print("Updated %s" % SOURCE_FILE) + else: + print(code) + +if __name__ == '__main__': + main() |