From 2d51c14ff4bc8b00f53b29cd0b39197c2c676ec8 Mon Sep 17 00:00:00 2001 From: jacob Date: Sun, 10 Mar 2002 22:00:06 +0000 Subject: [PATCH] Slightly less grotty script to convert OpenSSH known_hosts and known_hosts2 host key files to .REG files for Windows. (renamed from 'hosts2reg' because of 8.3 considerations) git-svn-id: svn://svn.tartarus.org/sgt/putty@1586 cda61777-01e9-0310-a592-d414129be87e --- contrib/kh2reg.py | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100755 contrib/kh2reg.py diff --git a/contrib/kh2reg.py b/contrib/kh2reg.py new file mode 100755 index 00000000..ea6baac5 --- /dev/null +++ b/contrib/kh2reg.py @@ -0,0 +1,128 @@ +#! /usr/bin/env python + +# $Id: kh2reg.py,v 1.1 2002/03/10 22:00:06 jacob Exp $ +# Convert OpenSSH known_hosts and known_hosts2 files to "new format" PuTTY +# host keys in a Windows .REG file (double-click to install). +# usage: hosts2reg.py known_hosts1 2 3 4 ... > hosts.reg +# Line endings are someone else's problem as is traditional. +# Developed for Python 1.5.2. + +import fileinput +import base64 +import struct +import string +import re +import sys + +def mungestr(s): + "Duplicate of PuTTY's mungestr() in winstore.c:1.10 for Registry keys" + candot = 0 + r = "" + for c in s: + if c in ' \*?%~' or ord(c)%luB" % len(s), s) + return reduce ((lambda a, b: (long(a) << 8) + long(b)), bytes) + +def longtohex(n): + """Convert long int to lower-case hex. + + Ick, Python (at least in 1.5.2) doesn't appear to have a way to + turn a long int into an unadorned hex string -- % gets upset if the + number is too big, and raw hex() uses uppercase (sometimes), and + adds unwanted "0x...L" around it.""" + + plain=string.lower(re.match(r"0x([0-9A-Fa-f]*)l?$", hex(n), re.I).group(1)) + return "0x" + plain + +# Output REG file header. +sys.stdout.write("""REGEDIT4 + +[HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys] +""") + +# Now process all known_hosts input. +for line in fileinput.input(): + + try: + # Remove leading/trailing whitespace (should zap CR and LF) + line = string.strip (line) + + # Skip blanks and comments + if line == '' or line[0] == '#': + raise "Skipping input line" + + # Split line on spaces. + fields = string.split (line, ' ') + + # Common fields + hostpat = fields[0] + magicnumbers = [] # placeholder + keytype = "" # placeholder + + # Grotty heuristic to distinguish known_hosts from known_hosts2: + # is second field entirely decimal digits? + if re.match (r"\d*$", fields[1]): + + # Treat as SSH1-type host key. + # Format: hostpat bits10 exp10 mod10 comment... + # (PuTTY doesn't store the number of bits.) + magicnumbers = map (long, fields[2:4]) + keytype = "rsa" + + else: + + # Treat as SSH2-type host key. + # Format: hostpat keytype keyblob64 comment... + sshkeytype, blob = fields[1], base64.decodestring (fields[2]) + + # 'blob' consists of a number of + # uint32 N (big-endian) + # uint8[N] field_data + subfields = [] + while blob: + sizefmt = ">L" + (size,) = struct.unpack (sizefmt, blob[0:4]) + size = int(size) # req'd for slicage + (data,) = struct.unpack (">%lus" % size, blob[4:size+4]) + subfields.append(data) + blob = blob [struct.calcsize(sizefmt) + size : ] + + # The first field is keytype again, and the rest we can treat as + # an opaque list of bignums (same numbers and order as stored + # by PuTTY). (currently embedded keytype is ignored entirely) + magicnumbers = map (strtolong, subfields[1:]) + + # Translate key type into something PuTTY can use. + if sshkeytype == "ssh-rsa": keytype = "rsa2" + elif sshkeytype == "ssh-dss": keytype = "dss" + else: + raise "Unknown SSH key type", sshkeytype + + # Now print out one line per host pattern, discarding wildcards. + for host in string.split (hostpat, ','): + if re.search (r"[*?!]", host): + sys.stderr.write("Skipping wildcard host pattern '%s'\n" + % host) + continue + else: + # Slightly bizarre registry key format: 'type@port:hostname' + # As far as I know, the input never specifies a port. + port = 22 + # XXX: does PuTTY do anything useful with literal IP[v4]s? + key = keytype + ("@%d:%s" % (port, host)) + value = string.join (map (longtohex, magicnumbers), ',') + # XXX: worry about double quotes? + sys.stdout.write("\"%s\"=\"%s\"\n" % (mungestr(key), value)) + + except "Unknown SSH key type", k: + sys.stderr.write("Unknown SSH key type '%s', skipping\n" % k) + except "Skipping input line": + pass -- 2.11.0