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.
This commit is contained in:
cinap_lenrek 2017-04-23 02:54:41 +02:00
parent 2b10f79119
commit da0a7ac387

View file

@ -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);