sshwot/src/process_known_hosts.py

77 lines
2.1 KiB
Python

import base64
import hashlib
import entry
class KnownHostsSyntaxError(Exception): pass
class HashedHostError(Exception): pass
def process_line(line):
"""process_line(str) → [Entry]
Given a string containing one line of .ssh/known_hosts file, create
a list of Entries based on it."""
assert type(line) == str
# Remove trailing newlines
if line[-1] == '\n': line = line[:-1]
# Just skip over empty lines
if line == '': return []
# Each line has host(s), algorithm, public key, and possibly one
# more optional field
fields = line.split(' ')
if len(fields) != 3 and len(fields) != 4:
raise KnownHostsSyntaxError('Weird number of fields on a line (%i)' % len(fields))
hosts, algorithm, public_key = fields[0:3]
# Generate public key fingerprint
# The key is stored base64 encoded, so decode it first
try:
public_key_binary = base64.b64decode(public_key, validate = True)
except (ValueError, base64.binascii.Error) as err:
raise KnownHostsSyntaxError('Malformed public key: %s' % public_key) from err
# Fingerprint is sha256 hash of the public key
m = hashlib.sha256()
m.update(public_key_binary)
fingerprint = m.digest()
# There can be several hosts separated with a comma
entries = []
for host in hosts.split(','):
# A host can't be empty
if len(host) == 0:
raise KnownHostsSyntaxError('An empty host')
# If the host begins with '|' it's hashed
# We cannot deal with those
if host[0] == '|':
raise HashedHostError('Cannot deal with hashed hosts')
# If the host behins with '[' it's a nonstandard port
# The format will be [domain]:port
# Extractt both
# Otherwise, default to port 22
if host[0] == '[':
host_and_port = host[1:].split(']:')
if len(host_and_port) != 2:
raise KnownHostsSyntaxError('Unrecognized host format: ' + host)
domain = host_and_port[0]
try:
port = int(host_and_port[1])
except ValueError:
raise KnownHostsSyntaxError('Malformed port: %i' % port)
else:
domain = host
port = 22
# Default to no comment
entries.append(entry.create_entry(domain, port, fingerprint, ''))
return entries