summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ssh.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2017-04-23 02:54:41 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2017-04-23 02:54:41 +0200
commitda0a7ac387a0e99e46be7611fd8d7083c6ff85db (patch)
treecff519bd3c5a66f238ea1be6fec64f4fd75d3f1a /sys/src/cmd/ssh.c
parent2b10f79119c2e6bead4b50a5173e531cb27dc36f (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.c75
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);