diff --git a/src/check_fingerprint.py b/src/check_fingerprint.py index 5d1d3a1..76b7fa1 100644 --- a/src/check_fingerprint.py +++ b/src/check_fingerprint.py @@ -3,6 +3,8 @@ import enum import entry import hashing +# TODO: Include a thing for checking what hosts match a given fingerprint + def check_fingerprint(entries, domain, port, fingerprint): """check_fingerprint([Entry], str, u16, bytes[32]) → ([str]: successes, [str]: fails) Checks if the given host is found with the given fingerprint. diff --git a/src/main-export-known-hosts.py b/src/main-export-known-hosts.py index 7253d73..d02948c 100644 --- a/src/main-export-known-hosts.py +++ b/src/main-export-known-hosts.py @@ -6,6 +6,7 @@ import write_file def main(): # TODO: Don't hardcode # TODO: Handle errors + # TODO: Add a switch for whether you want to include IPs with open(sys.argv[1], 'r') as f: try: entries = process_known_hosts.process_file(f) diff --git a/src/process_known_hosts.py b/src/process_known_hosts.py index e9c9687..0472900 100644 --- a/src/process_known_hosts.py +++ b/src/process_known_hosts.py @@ -25,11 +25,38 @@ class HashedHostError(Exception): else: return 'Line %i: %s' % (self.line, self.string) -def process_line(line): +def is_ip(domain): + """is_ip(str) → bool + Sees if a given domain would be a valid v4 or v6 IP""" + def is_ipv4(domain): + # IPv4 address has 4 fields separated by . + fields = domain.split('.') + if len(fields) != 4: return False + + # The fields are base-10 integers + fields_num = [] + for field in fields: + try: + fields_num.append(int(field, 10)) + except ValueError: + return False + + # The fields are in the range 0…255 + return all(0 <= field <= 266 for field in fields_num) + + def is_ipv6(domain): + # TODO: Implement this + return False # FIXME: This is wrong + + return is_ipv4(domain) or is_ipv6(domain) + +def process_line(line, ignore_ips): # TODO: Add a way to skip IPs - """process_line(str) → [Entry] + """process_line(str, bool) → [Entry] Given a string containing one line of .ssh/known_hosts file, create - a list of Entries based on it.""" + a list of Entries based on it. + + If ignore_ips is True, only create entries for domain names.""" assert type(line) == str # Remove trailing newlines @@ -89,21 +116,28 @@ def process_line(line): domain = host port = 22 + # As we have now extracted the domain, we can check if we + # need to throw it out + if ignore_ips and is_ip(domain): + continue + # Default to no comment entries.append(entry.create_entry(domain, port, fingerprint, '')) return entries -def process_file(f): - """process_file(file(r)) → [Entry] +def process_file(f, ignore_ips = True): + """process_file(file(r), bool) → [Entry] Given a file in the .ssh/known_hosts format, create a list of - entries""" + entries. + + If ignore_ips is True, only create entries for domain names.""" entries = [] # Line numbers are 1-indexed but enumerate 0-indexes for linenum_minus_one, line in enumerate(f): try: - entries.extend(process_line(line)) + entries.extend(process_line(line, ignore_ips)) except (KnownHostsSyntaxError, HashedHostError) as err: err.line = linenum_minus_one + 1 raise err