diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-04-23 02:54:41 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-04-23 02:54:41 +0200 |
commit | da0a7ac387a0e99e46be7611fd8d7083c6ff85db (patch) | |
tree | cff519bd3c5a66f238ea1be6fec64f4fd75d3f1a /sys/src/cmd/ssh.c | |
parent | 2b10f79119c2e6bead4b50a5173e531cb27dc36f (diff) |
ssh: implement primitive hostkey verification
this checks $home/lib/sshthumbs for the sha256 hash
of the hosts rsa public key. if its not there, it
prints the rc command to add it and exits.
Diffstat (limited to 'sys/src/cmd/ssh.c')
-rw-r--r-- | sys/src/cmd/ssh.c | 75 |
1 files changed, 64 insertions, 11 deletions
diff --git a/sys/src/cmd/ssh.c b/sys/src/cmd/ssh.c index 904ce85a9..a635dd546 100644 --- a/sys/src/cmd/ssh.c +++ b/sys/src/cmd/ssh.c @@ -4,6 +4,7 @@ #include <libsec.h> #include <auth.h> #include <authsrv.h> +#include <bio.h> enum { MSG_DISCONNECT = 1, @@ -76,13 +77,14 @@ typedef struct int nsid; uchar sid[256]; -char thumb[2*SHA2_256dlen+1]; +char thumb[2*SHA2_256dlen+1], *thumbfile; int fd, intr, raw, debug; char *user, *service, *status, *host, *cmd; Oneway recv, send; void dispatch(void); +int checkthumb(char*, uchar*); void shutdown(void) @@ -577,13 +579,24 @@ Next1: switch(recvpkt()){ ds = hashstr(yc, 32, ds); ds = hashstr(ys, 32, ds); - sha2_256(ks, nks, h, nil); - i = snprint(thumb, sizeof(thumb), "%.*[", sizeof(h), h); - while(i > 0 && thumb[i-1] == '=') - thumb[--i] = '\0'; - -if(debug) - fprint(2, "host fingerprint: %s\n", thumb); + if(thumb[0] == 0){ + sha2_256(ks, nks, h, nil); + i = snprint(thumb, sizeof(thumb), "%.*[", sizeof(h), h); + while(i > 0 && thumb[i-1] == '=') + thumb[--i] = '\0'; + if(debug) + fprint(2, "host fingerprint: %s\n", thumb); + switch(checkthumb(thumbfile, h)){ + case 0: + werrstr("host unknown"); + default: + fprint(2, "%s: %r, to add after verification:\n", argv0); + fprint(2, "\techo 'ssh sha256=%s # %s' >> %q\n", thumb, host, thumbfile); + sysfatal("checking hostkey failed: %r"); + case 1: + break; + } + } if((pub = ssh2rsapub(ks, nks)) == nil) sysfatal("bad server public key"); @@ -1061,10 +1074,43 @@ rawon(void) } } +int +checkthumb(char *file, uchar hash[SHA2_256dlen]) +{ + uchar sum[SHA2_256dlen]; + char *line, *field[50]; + Biobuf *bin; + + if((bin = Bopen(file, OREAD)) == nil) + return -1; + for(; (line = Brdstr(bin, '\n', 1)) != nil; free(line)){ + if(tokenize(line, field, nelem(field)) < 2) + continue; + if(strcmp(field[0], "ssh") != 0 || strncmp(field[1], "sha256=", 7) != 0) + continue; + field[1] += 7; + if(dec64(sum, SHA2_256dlen, field[1], strlen(field[1])) != SHA2_256dlen){ + werrstr("malformed ssh entry in %s: %s", file, field[1]); + goto err; + } + if(memcmp(sum, hash, SHA2_256dlen) == 0){ + free(line); + Bterm(bin); + return 1; + } + } + Bterm(bin); + return 0; +err: + free(line); + Bterm(bin); + return -1; +} + void usage(void) { - fprint(2, "usage: %s [-dR] [-u user] [user@]host [cmd]\n", argv0); + fprint(2, "usage: %s [-dR] [-t thumbfile] [-u user] [user@]host [cmd]\n", argv0); exits("usage"); } @@ -1094,6 +1140,9 @@ main(int argc, char *argv[]) case 'u': user = EARGF(usage()); break; + case 't': + thumbfile = EARGF(usage()); + break; } ARGEND; if(argc == 0) @@ -1134,10 +1183,14 @@ main(int argc, char *argv[]) send.l = recv.l = &sl; - kex(0); - if(user == nil) user = getuser(); + if(thumbfile == nil) + thumbfile = smprint("%s/lib/sshthumbs", getenv("home")); + + kex(0); + + service = "ssh-connection"; sendpkt("bs", MSG_SERVICE_REQUEST, "ssh-userauth", 12); |