From cc8e8c978cb48955417db592b799c4c65881c2b8 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 1 Feb 2016 22:49:20 +0100 Subject: [PATCH] tlssrv: p9any authentication support using TLS-PSK cipher suits --- sys/man/8/tlssrv | 36 +++++++++++++++++- sys/src/cmd/tlsclient.c | 81 ++++++++++++++++++++++++++++++----------- sys/src/cmd/tlssrv.c | 52 ++++++++++++++++++++------ 3 files changed, 136 insertions(+), 33 deletions(-) diff --git a/sys/man/8/tlssrv b/sys/man/8/tlssrv index 1adf30d43..35285e045 100644 --- a/sys/man/8/tlssrv +++ b/sys/man/8/tlssrv @@ -5,6 +5,16 @@ tlssrv, tlsclient, tlssrvtunnel, tlsclienttunnel \- TLS server and client .PP .B tlssrv [ +.B -D +] +[ +.B -a +[ +.B -k +.I keyspec +] +] +[ .B -c .I cert.pem ] @@ -27,6 +37,13 @@ logfile .B -D ] [ +.B -a +[ +.B -k +.I keyspec +] +] +[ .B -c .I cert.pem ] @@ -38,6 +55,10 @@ logfile .B -x .I excludedkeys ] +[ +.B -n +.I servername +] .I address .PP .B tlssrvtunnel @@ -66,6 +87,14 @@ The specified is by convention the same as for the target server. .I Remotesys is mainly used for logging. +If the +.B -a +flag is specified, +.B p9any +authentication is run before the TLS handshake and the resulting +plan9 session secret is used as a pre-shared key for TLS encryption. +This enables the use of TLS without certificates and also runs +the server command as the authorized user. .PP .I Tlsclient is the reverse of @@ -98,7 +127,12 @@ but not in the file .IR excludedkeys . See .IR thumbprint (6) -for more information. +for more information. The +.B -n +option passes the string +.I servername +in the TLS hello message (Server Name Idenfitication) +which is usefull when talking to webservers. .PP .I Tlssrvtunnel and diff --git a/sys/src/cmd/tlsclient.c b/sys/src/cmd/tlsclient.c index d96e733b4..bc4b6d678 100644 --- a/sys/src/cmd/tlsclient.c +++ b/sys/src/cmd/tlsclient.c @@ -2,11 +2,16 @@ #include #include #include +#include + +int debug, auth; +char *keyspec = ""; +char *servername, *file, *filex, *ccert; void usage(void) { - fprint(2, "usage: tlsclient [-c lib/tls/clientcert] [-t /sys/lib/tls/xxx] [-x /sys/lib/tls/xxx.exclude] dialstring\n"); + fprint(2, "usage: tlsclient [-D] [-a [-k keyspec] ] [-c lib/tls/clientcert] [-t /sys/lib/tls/xxx] [-x /sys/lib/tls/xxx.exclude] [-n servername] dialstring [cmd [args...]]\n"); exits("usage"); } @@ -38,72 +43,106 @@ reporter(char *fmt, ...) void main(int argc, char **argv) { - int fd, debug; - uchar digest[20]; + int fd; + char *addr; TLSconn *conn; - char *addr, *file, *filex, *ccert; Thumbprint *thumb; - file = nil; - filex = nil; - thumb = nil; - ccert=nil; - debug=0; + fmtinstall('H', encodefmt); + ARGBEGIN{ + case 'D': + debug++; + break; + case 'a': + auth++; + break; + case 'k': + keyspec = EARGF(usage()); + break; case 't': file = EARGF(usage()); break; case 'x': filex = EARGF(usage()); break; - case 'D': - debug++; - break; case 'c': ccert = EARGF(usage()); break; + case 'n': + servername = EARGF(usage()); + break; default: usage(); }ARGEND - if(argc != 1) + if(argc < 1) usage(); if(filex && !file) sysfatal("specifying -x without -t is useless"); + if(file){ thumb = initThumbprints(file, filex); if(thumb == nil) sysfatal("initThumbprints: %r"); - } + } else + thumb = nil; - addr = argv[0]; + addr = *argv++; if((fd = dial(addr, 0, 0, 0)) < 0) sysfatal("dial %s: %r", addr); conn = (TLSconn*)mallocz(sizeof *conn, 1); - if(ccert) + conn->serverName = servername; + if(ccert){ conn->cert = readcert(ccert, &conn->certlen); + if(conn->cert == nil) + sysfatal("readcert: %r"); + } + + if(auth){ + AuthInfo *ai; + + ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); + if(ai == nil) + sysfatal("auth_proxy: %r"); + + conn->pskID = "p9secret"; + conn->psk = ai->secret; + conn->psklen = ai->nsecret; + } + if(debug) conn->trace = reporter; + fd = tlsClient(fd, conn); if(fd < 0) sysfatal("tlsclient: %r"); + if(thumb){ + uchar digest[20]; + if(conn->cert==nil || conn->certlen<=0) sysfatal("server did not provide TLS certificate"); sha1(conn->cert, conn->certlen, digest, nil); - if(!okThumbprint(digest, thumb)){ - fmtinstall('H', encodefmt); + if(!okThumbprint(digest, thumb)) sysfatal("server certificate %.*H not recognized", SHA1dlen, digest); - } + } + + if(*argv){ + dup(fd, 0); + dup(fd, 1); + if(fd > 1) + close(fd); + exec(*argv, argv); + sysfatal("exec: %r"); } rfork(RFNOTEG); switch(fork()){ case -1: - fprint(2, "%s: fork: %r\n", argv0); - exits("dial"); + sysfatal("fork: %r"); case 0: xfer(0, fd); break; diff --git a/sys/src/cmd/tlssrv.c b/sys/src/cmd/tlssrv.c index d9d24489c..853e208d6 100644 --- a/sys/src/cmd/tlssrv.c +++ b/sys/src/cmd/tlssrv.c @@ -3,10 +3,12 @@ #include #include #include +#include +int debug, auth; +char *keyspec = ""; char *remotesys = ""; char *logfile = nil; -int debug = 0; static int reporter(char *fmt, ...) @@ -30,7 +32,7 @@ reporter(char *fmt, ...) void usage(void) { - fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] cmd [args...]\n"); + fprint(2, "usage: tlssrv [-a [-k keyspec]] [-c cert] [-D] [-l logfile] [-r remotesys] cmd [args...]\n"); fprint(2, " after auth/secretpem key.pem > /mnt/factotum/ctl\n"); exits("usage"); } @@ -47,6 +49,12 @@ main(int argc, char *argv[]) case 'D': debug++; break; + case 'a': + auth++; + break; + case 'k': + keyspec = EARGF(usage()); + break; case 'c': cert = EARGF(usage()); break; @@ -63,21 +71,41 @@ main(int argc, char *argv[]) if(*argv == nil) usage(); - if(cert == nil) - sysfatal("no certificate specified"); conn = (TLSconn*)mallocz(sizeof *conn, 1); if(conn == nil) sysfatal("out of memory"); - conn->chain = readcertchain(cert); - if(conn->chain == nil) - sysfatal("%r"); - conn->cert = conn->chain->pem; - conn->certlen = conn->chain->pemlen; - conn->chain = conn->chain->next; + + if(auth){ + AuthInfo *ai; + + ai = auth_proxy(0, nil, "proto=p9any role=server %s", keyspec); + if(ai == nil) + sysfatal("auth_proxy: %r"); + + if(auth_chuid(ai, nil) < 0) + sysfatal("auth_chuid: %r"); + + conn->pskID = "p9secret"; + conn->psk = ai->secret; + conn->psklen = ai->nsecret; + } + + if(cert){ + conn->chain = readcertchain(cert); + if(conn->chain == nil) + sysfatal("%r"); + conn->cert = conn->chain->pem; + conn->certlen = conn->chain->pemlen; + conn->chain = conn->chain->next; + } + + if(conn->cert == nil && conn->psklen == 0) + sysfatal("no certificate or shared secret"); + if(debug) conn->trace = reporter; - fd = tlsServer(1, conn); + fd = tlsServer(0, conn); if(fd < 0){ reporter("failed: %r"); exits(0); @@ -87,6 +115,8 @@ main(int argc, char *argv[]) dup(fd, 0); dup(fd, 1); + if(fd > 1) + close(fd); exec(*argv, argv); reporter("can't exec %s: %r", *argv); -- 2.44.0