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:
parent
2b10f79119
commit
da0a7ac387
1 changed files with 64 additions and 11 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue