diff options
Diffstat (limited to 'ssh-update-host-keys')
-rwxr-xr-x | ssh-update-host-keys | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/ssh-update-host-keys b/ssh-update-host-keys new file mode 100755 index 0000000..896d983 --- /dev/null +++ b/ssh-update-host-keys | |||
@@ -0,0 +1,103 @@ | |||
1 | #!/bin/sh | ||
2 | public_suffix=cryptonomic.net | ||
3 | |||
4 | die() | ||
5 | { | ||
6 | printf "Error: %s\n" "$*" >&2 | ||
7 | exit 1 | ||
8 | } | ||
9 | |||
10 | b16_to_b32() | ||
11 | { | ||
12 | printf %s "$1" | basez -x -d | basez -j -l | tr -d = | ||
13 | } | ||
14 | |||
15 | openssh_knownhost_to_dnsname() | ||
16 | { | ||
17 | local hashtype=2 | ||
18 | local keystring keytype sshfp_b16 sshfp_b32 | ||
19 | [ -f "$1" ] || return | ||
20 | [ -s "$1" ] || return | ||
21 | sshfp_raw=$(ssh-keygen -r . -f "$1" | grep -E -e "^. IN SSHFP [0-9]+ $hashtype ") | ||
22 | case "$sshfp_raw" in | ||
23 | '. IN SSHFP 1 '*) keytype=1; keystring=rsa ;; | ||
24 | '. IN SSHFP 4 '*) keytype=4; keystring=ed25519 ;; | ||
25 | *) return 1 ;; | ||
26 | esac | ||
27 | sshfp_b16=$(printf '%s' "$sshfp_raw" | sed -ne "s/^. IN SSHFP $keytype $hashtype //p") && | ||
28 | [ "$sshfp_b16" ] || die "could not determine ssh client fingerprint" | ||
29 | sshfp_b32=$(b16_to_b32 "$sshfp_b16") | ||
30 | |||
31 | printf %s.%s.%s "$sshfp_b32" "$keystring" "$public_suffix" | tail -c64 | ||
32 | } | ||
33 | |||
34 | dnsname_to_openssh_knownhost() | ||
35 | { | ||
36 | local host="$1" t r | ||
37 | t=$(mktemp) | ||
38 | case "$host" in | ||
39 | *.ed25519."$public_suffix" ) ;; | ||
40 | * ) return 1 ;; | ||
41 | esac | ||
42 | ssh-keyscan -t ed25519 "$host" 2>/dev/null | ( | ||
43 | while read h keytype keydata comment | ||
44 | do | ||
45 | [ "$h $keytype" = "$host ssh-ed25519" ] || continue | ||
46 | echo "$keytype $keydata" > "$t" | ||
47 | validated=$(openssh_knownhost_to_dnsname "$t") || continue | ||
48 | case "$host" in | ||
49 | "$validated" | *."$validated" ) | ||
50 | read line < "$t" | ||
51 | echo "$host $line" | ||
52 | rm -f "$t" | ||
53 | exit 0 | ||
54 | ;; | ||
55 | esac | ||
56 | done | ||
57 | rm -f "$t" | ||
58 | exit 1 | ||
59 | ) | ||
60 | } | ||
61 | |||
62 | set -e | ||
63 | |||
64 | [ $# = 1 ] || die 'usage' | ||
65 | host=$1 | ||
66 | shift | ||
67 | |||
68 | _TEMP_DIR_=$(mktemp -d) | ||
69 | cd "$_TEMP_DIR_" | ||
70 | trap 'rm -rf "$_TEMP_DIR_"' EXIT | ||
71 | |||
72 | if ssh-keygen -F "${host#*@}" | grep -v '^#' > ssh_known_hosts 2>/dev/null | ||
73 | then | ||
74 | cp ssh_known_hosts ssh_known_hosts~ | ||
75 | else | ||
76 | touch ssh_known_hosts~ | ||
77 | dnsname_to_openssh_knownhost "${host##*@}" >> ssh_known_hosts || die "could not validate hostname cryptographically" | ||
78 | fi | ||
79 | |||
80 | modify_known_hosts=y | ||
81 | |||
82 | set -- ssh | ||
83 | if [ ! "$modify_known_hosts" ] | ||
84 | then | ||
85 | set -- "$@" -F /dev/null | ||
86 | set -- "$@" -o GlobalKnownHostsFile=$PWD/ssh_known_hosts | ||
87 | set -- "$@" -o UserKnownHostsFile=$PWD/ssh_known_hosts | ||
88 | fi | ||
89 | set -- "$@" -o UpdateHostKeys=yes | ||
90 | set -- "$@" -o PasswordAuthentication=no | ||
91 | set -- "$@" -o StrictHostKeyChecking=yes | ||
92 | set -- "$@" -n -T | ||
93 | set -- "$@" "$host" | ||
94 | |||
95 | "$@" || true | ||
96 | |||
97 | if test -t 1 | ||
98 | then | ||
99 | diff -u ssh_known_hosts~ ssh_known_hosts || true | ||
100 | else | ||
101 | cat ssh_known_hosts | ||
102 | fi | ||
103 | |||