shithub: riscv

Download patch

ref: cc8e8c978cb48955417db592b799c4c65881c2b8
parent: a291bbdeddfd41a2f0907ecbd7b819f0eedffdaf
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Feb 1 17:49:20 EST 2016

tlssrv: p9any authentication support using TLS-PSK cipher suits

--- a/sys/man/8/tlssrv
+++ b/sys/man/8/tlssrv
@@ -5,6 +5,16 @@
 .PP
 .B tlssrv
 [
+.B -D
+]
+[
+.B -a
+[
+.B -k
+.I keyspec
+]
+]
+[
 .B -c
 .I cert.pem
 ]
@@ -27,6 +37,13 @@
 .B -D
 ]
 [
+.B -a
+[
+.B -k
+.I keyspec
+]
+]
+[
 .B -c
 .I cert.pem
 ]
@@ -38,6 +55,10 @@
 .B -x
 .I excludedkeys
 ]
+[
+.B -n
+.I servername
+]
 .I address
 .PP
 .B tlssrvtunnel
@@ -66,6 +87,14 @@
 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 @@
 .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
--- a/sys/src/cmd/tlsclient.c
+++ b/sys/src/cmd/tlsclient.c
@@ -2,11 +2,16 @@
 #include <libc.h>
 #include <mp.h>
 #include <libsec.h>
+#include <auth.h>
 
+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,18 +43,23 @@
 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;
@@ -56,54 +66,83 @@
 	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;
--- a/sys/src/cmd/tlssrv.c
+++ b/sys/src/cmd/tlssrv.c
@@ -3,10 +3,12 @@
 #include <bio.h>
 #include <mp.h>
 #include <libsec.h>
+#include <auth.h>
 
+int debug, auth;
+char *keyspec = "";
 char *remotesys = "";
 char *logfile = nil;
-int debug = 0;
 
 static int
 reporter(char *fmt, ...)
@@ -30,7 +32,7 @@
 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 @@
 	case 'D':
 		debug++;
 		break;
+	case 'a':
+		auth++;
+		break;
+	case 'k':
+		keyspec = EARGF(usage());
+		break;
 	case 'c':
 		cert = EARGF(usage());
 		break;
@@ -63,21 +71,41 @@
 	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 @@
 
 	dup(fd, 0);
 	dup(fd, 1);
+	if(fd > 1)
+		close(fd);
 
 	exec(*argv, argv);
 	reporter("can't exec %s: %r", *argv);