changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: tlssrv: p9any authentication support using TLS-PSK cipher suits

changeset 5070: 3f9227bd4f1d
parent 5069: 467142072a11
child 5071: cef65840a93a
author: cinap_lenrek@felloff.net
date: Mon, 01 Feb 2016 22:49:20 +0100
files: sys/man/8/tlssrv sys/src/cmd/tlsclient.c sys/src/cmd/tlssrv.c
description: tlssrv: p9any authentication support using TLS-PSK cipher suits
     1.1--- a/sys/man/8/tlssrv
     1.2+++ b/sys/man/8/tlssrv
     1.3@@ -5,6 +5,16 @@ tlssrv, tlsclient, tlssrvtunnel, tlsclie
     1.4 .PP
     1.5 .B tlssrv
     1.6 [
     1.7+.B -D
     1.8+]
     1.9+[
    1.10+.B -a
    1.11+[
    1.12+.B -k
    1.13+.I keyspec
    1.14+]
    1.15+]
    1.16+[
    1.17 .B -c
    1.18 .I cert.pem
    1.19 ]
    1.20@@ -27,6 +37,13 @@ logfile
    1.21 .B -D
    1.22 ]
    1.23 [
    1.24+.B -a
    1.25+[
    1.26+.B -k
    1.27+.I keyspec
    1.28+]
    1.29+]
    1.30+[
    1.31 .B -c
    1.32 .I cert.pem
    1.33 ]
    1.34@@ -38,6 +55,10 @@ logfile
    1.35 .B -x
    1.36 .I excludedkeys
    1.37 ]
    1.38+[
    1.39+.B -n
    1.40+.I servername
    1.41+]
    1.42 .I address
    1.43 .PP
    1.44 .B tlssrvtunnel
    1.45@@ -66,6 +87,14 @@ The specified
    1.46 is by convention the same as for the target server.
    1.47 .I Remotesys
    1.48 is mainly used for logging.
    1.49+If the
    1.50+.B -a
    1.51+flag is specified,
    1.52+.B p9any
    1.53+authentication is run before the TLS handshake and the resulting
    1.54+plan9 session secret is used as a pre-shared key for TLS encryption.
    1.55+This enables the use of TLS without certificates and also runs
    1.56+the server command as the authorized user.
    1.57 .PP
    1.58 .I Tlsclient
    1.59 is the reverse of
    1.60@@ -98,7 +127,12 @@ but not in the file
    1.61 .IR excludedkeys .
    1.62 See
    1.63 .IR thumbprint (6)
    1.64-for more information.
    1.65+for more information. The
    1.66+.B -n
    1.67+option passes the string
    1.68+.I servername
    1.69+in the TLS hello message (Server Name Idenfitication)
    1.70+which is usefull when talking to webservers.
    1.71 .PP
    1.72 .I Tlssrvtunnel
    1.73 and
     2.1--- a/sys/src/cmd/tlsclient.c
     2.2+++ b/sys/src/cmd/tlsclient.c
     2.3@@ -2,11 +2,16 @@
     2.4 #include <libc.h>
     2.5 #include <mp.h>
     2.6 #include <libsec.h>
     2.7+#include <auth.h>
     2.8+
     2.9+int debug, auth;
    2.10+char *keyspec = "";
    2.11+char *servername, *file, *filex, *ccert;
    2.12 
    2.13 void
    2.14 usage(void)
    2.15 {
    2.16-	fprint(2, "usage: tlsclient [-c lib/tls/clientcert] [-t /sys/lib/tls/xxx] [-x /sys/lib/tls/xxx.exclude] dialstring\n");
    2.17+	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");
    2.18 	exits("usage");
    2.19 }
    2.20 
    2.21@@ -38,72 +43,106 @@ reporter(char *fmt, ...)
    2.22 void
    2.23 main(int argc, char **argv)
    2.24 {
    2.25-	int fd, debug;
    2.26-	uchar digest[20];
    2.27+	int fd;
    2.28+	char *addr;
    2.29 	TLSconn *conn;
    2.30-	char *addr, *file, *filex, *ccert;
    2.31 	Thumbprint *thumb;
    2.32 
    2.33-	file = nil;
    2.34-	filex = nil;
    2.35-	thumb = nil;
    2.36-	ccert=nil;
    2.37-	debug=0;
    2.38+	fmtinstall('H', encodefmt);
    2.39+
    2.40 	ARGBEGIN{
    2.41+	case 'D':
    2.42+		debug++;
    2.43+		break;
    2.44+	case 'a':
    2.45+		auth++;
    2.46+		break;
    2.47+	case 'k':
    2.48+		keyspec = EARGF(usage());
    2.49+		break;
    2.50 	case 't':
    2.51 		file = EARGF(usage());
    2.52 		break;
    2.53 	case 'x':
    2.54 		filex = EARGF(usage());
    2.55 		break;
    2.56-	case 'D':
    2.57-		debug++;
    2.58-		break;
    2.59 	case 'c':
    2.60 		ccert = EARGF(usage());
    2.61 		break;
    2.62+	case 'n':
    2.63+		servername = EARGF(usage());
    2.64+		break;
    2.65 	default:
    2.66 		usage();
    2.67 	}ARGEND
    2.68 
    2.69-	if(argc != 1)
    2.70+	if(argc < 1)
    2.71 		usage();
    2.72 
    2.73 	if(filex && !file)	
    2.74 		sysfatal("specifying -x without -t is useless");
    2.75+
    2.76 	if(file){
    2.77 		thumb = initThumbprints(file, filex);
    2.78 		if(thumb == nil)
    2.79 			sysfatal("initThumbprints: %r");
    2.80-	}
    2.81+	} else
    2.82+		thumb = nil;
    2.83 
    2.84-	addr = argv[0];
    2.85+	addr = *argv++;
    2.86 	if((fd = dial(addr, 0, 0, 0)) < 0)
    2.87 		sysfatal("dial %s: %r", addr);
    2.88 
    2.89 	conn = (TLSconn*)mallocz(sizeof *conn, 1);
    2.90-	if(ccert)
    2.91+	conn->serverName = servername;
    2.92+	if(ccert){
    2.93 		conn->cert = readcert(ccert, &conn->certlen);
    2.94+		if(conn->cert == nil)
    2.95+			sysfatal("readcert: %r");
    2.96+	}
    2.97+
    2.98+	if(auth){
    2.99+		AuthInfo *ai;
   2.100+
   2.101+		ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
   2.102+		if(ai == nil)
   2.103+			sysfatal("auth_proxy: %r");
   2.104+
   2.105+		conn->pskID = "p9secret";
   2.106+		conn->psk = ai->secret;
   2.107+		conn->psklen = ai->nsecret;
   2.108+	}
   2.109+
   2.110 	if(debug)
   2.111 		conn->trace = reporter;
   2.112+
   2.113 	fd = tlsClient(fd, conn);
   2.114 	if(fd < 0)
   2.115 		sysfatal("tlsclient: %r");
   2.116+
   2.117 	if(thumb){
   2.118+		uchar digest[20];
   2.119+
   2.120 		if(conn->cert==nil || conn->certlen<=0)
   2.121 			sysfatal("server did not provide TLS certificate");
   2.122 		sha1(conn->cert, conn->certlen, digest, nil);
   2.123-		if(!okThumbprint(digest, thumb)){
   2.124-			fmtinstall('H', encodefmt);
   2.125+		if(!okThumbprint(digest, thumb))
   2.126 			sysfatal("server certificate %.*H not recognized", SHA1dlen, digest);
   2.127-		}
   2.128+	}
   2.129+
   2.130+	if(*argv){
   2.131+		dup(fd, 0);
   2.132+		dup(fd, 1);
   2.133+		if(fd > 1)
   2.134+			close(fd);
   2.135+		exec(*argv, argv);
   2.136+		sysfatal("exec: %r");
   2.137 	}
   2.138 
   2.139 	rfork(RFNOTEG);
   2.140 	switch(fork()){
   2.141 	case -1:
   2.142-		fprint(2, "%s: fork: %r\n", argv0);
   2.143-		exits("dial");
   2.144+		sysfatal("fork: %r");
   2.145 	case 0:
   2.146 		xfer(0, fd);
   2.147 		break;
     3.1--- a/sys/src/cmd/tlssrv.c
     3.2+++ b/sys/src/cmd/tlssrv.c
     3.3@@ -3,10 +3,12 @@
     3.4 #include <bio.h>
     3.5 #include <mp.h>
     3.6 #include <libsec.h>
     3.7+#include <auth.h>
     3.8 
     3.9+int debug, auth;
    3.10+char *keyspec = "";
    3.11 char *remotesys = "";
    3.12 char *logfile = nil;
    3.13-int debug = 0;
    3.14 
    3.15 static int
    3.16 reporter(char *fmt, ...)
    3.17@@ -30,7 +32,7 @@ reporter(char *fmt, ...)
    3.18 void
    3.19 usage(void)
    3.20 {
    3.21-	fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] cmd [args...]\n");
    3.22+	fprint(2, "usage: tlssrv [-a [-k keyspec]] [-c cert] [-D] [-l logfile] [-r remotesys] cmd [args...]\n");
    3.23 	fprint(2, "  after  auth/secretpem key.pem > /mnt/factotum/ctl\n");
    3.24 	exits("usage");
    3.25 }
    3.26@@ -47,6 +49,12 @@ main(int argc, char *argv[])
    3.27 	case 'D':
    3.28 		debug++;
    3.29 		break;
    3.30+	case 'a':
    3.31+		auth++;
    3.32+		break;
    3.33+	case 'k':
    3.34+		keyspec = EARGF(usage());
    3.35+		break;
    3.36 	case 'c':
    3.37 		cert = EARGF(usage());
    3.38 		break;
    3.39@@ -63,21 +71,41 @@ main(int argc, char *argv[])
    3.40 	if(*argv == nil)
    3.41 		usage();
    3.42 
    3.43-	if(cert == nil)
    3.44-		sysfatal("no certificate specified");
    3.45 	conn = (TLSconn*)mallocz(sizeof *conn, 1);
    3.46 	if(conn == nil)
    3.47 		sysfatal("out of memory");
    3.48-	conn->chain = readcertchain(cert);
    3.49-	if(conn->chain == nil)
    3.50-		sysfatal("%r");
    3.51-	conn->cert = conn->chain->pem;
    3.52-	conn->certlen = conn->chain->pemlen;
    3.53-	conn->chain = conn->chain->next;
    3.54+
    3.55+	if(auth){
    3.56+		AuthInfo *ai;
    3.57+
    3.58+		ai = auth_proxy(0, nil, "proto=p9any role=server %s", keyspec);
    3.59+		if(ai == nil)
    3.60+			sysfatal("auth_proxy: %r");
    3.61+
    3.62+		if(auth_chuid(ai, nil) < 0)
    3.63+			sysfatal("auth_chuid: %r");
    3.64+
    3.65+		conn->pskID = "p9secret";
    3.66+		conn->psk = ai->secret;
    3.67+		conn->psklen = ai->nsecret;
    3.68+	}
    3.69+
    3.70+	if(cert){
    3.71+		conn->chain = readcertchain(cert);
    3.72+		if(conn->chain == nil)
    3.73+			sysfatal("%r");
    3.74+		conn->cert = conn->chain->pem;
    3.75+		conn->certlen = conn->chain->pemlen;
    3.76+		conn->chain = conn->chain->next;
    3.77+	}
    3.78+
    3.79+	if(conn->cert == nil && conn->psklen == 0)
    3.80+		sysfatal("no certificate or shared secret");
    3.81+
    3.82 	if(debug)
    3.83 		conn->trace = reporter;
    3.84 
    3.85-	fd = tlsServer(1, conn);
    3.86+	fd = tlsServer(0, conn);
    3.87 	if(fd < 0){
    3.88 		reporter("failed: %r");
    3.89 		exits(0);
    3.90@@ -87,6 +115,8 @@ main(int argc, char *argv[])
    3.91 
    3.92 	dup(fd, 0);
    3.93 	dup(fd, 1);
    3.94+	if(fd > 1)
    3.95+		close(fd);
    3.96 
    3.97 	exec(*argv, argv);
    3.98 	reporter("can't exec %s: %r", *argv);