ref: da0a7ac387a0e99e46be7611fd8d7083c6ff85db
parent: 2b10f79119c2e6bead4b50a5173e531cb27dc36f
author: cinap_lenrek <[email protected]>
date: Sat Apr 22 22:54:41 EDT 2017
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.
--- 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,7 +77,7 @@
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;
@@ -83,6 +84,7 @@
Oneway recv, send;
void dispatch(void);
+int checkthumb(char*, uchar*);
void
shutdown(void)
@@ -577,14 +579,25 @@
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(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(debug)
- fprint(2, "host fingerprint: %s\n", thumb);
-
if((pub = ssh2rsapub(ks, nks)) == nil)
sysfatal("bad server public key");
if((S = ssh2rsasig(sig, nsig)) == nil)
@@ -1061,10 +1074,43 @@
}
}
+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 @@
case 'u':
user = EARGF(usage());
break;
+ case 't':
+ thumbfile = EARGF(usage());
+ break;
} ARGEND;
if(argc == 0)
@@ -1134,10 +1183,14 @@
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);