xref: /plan9/sys/src/cmd/tlssrv.c (revision 3a32e1046e411eba43a878ebe72e5b0033495136)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <mp.h>
59a747e4fSDavid du Colombier #include <libsec.h>
69a747e4fSDavid du Colombier 
79a747e4fSDavid du Colombier enum{ BufSize = 8192 };
89a747e4fSDavid du Colombier 
99a747e4fSDavid du Colombier char *remotesys, *logfile;
109a747e4fSDavid du Colombier int debug, p[2];
119a747e4fSDavid du Colombier 
129a747e4fSDavid du Colombier void
death(void *,char *)139a747e4fSDavid du Colombier death(void *, char *)
149a747e4fSDavid du Colombier {
159a747e4fSDavid du Colombier 	int pid;
169a747e4fSDavid du Colombier 
179a747e4fSDavid du Colombier 	close(0);
189a747e4fSDavid du Colombier 	close(1);
199a747e4fSDavid du Colombier 	close(p[1]);
209a747e4fSDavid du Colombier 	pid = getpid();
219a747e4fSDavid du Colombier 	postnote(PNGROUP, pid, "die");
229a747e4fSDavid du Colombier 	postnote(PNGROUP, pid, "die");
239a747e4fSDavid du Colombier 	postnote(PNGROUP, pid, "die");
249a747e4fSDavid du Colombier 	_exits(0);
259a747e4fSDavid du Colombier }
269a747e4fSDavid du Colombier 
279a747e4fSDavid du Colombier static void
dump(int fd,uchar * buf,int n,char * label)289a747e4fSDavid du Colombier dump(int fd, uchar *buf, int n, char *label)
299a747e4fSDavid du Colombier {
309a747e4fSDavid du Colombier 	Biobuf bout;
319a747e4fSDavid du Colombier 	int i;
329a747e4fSDavid du Colombier 
339a747e4fSDavid du Colombier 	Binit(&bout, fd, OWRITE);
349a747e4fSDavid du Colombier 	Bprint(&bout, "%s<%d>: ", label, n);
359a747e4fSDavid du Colombier 	if(n > 64)
369a747e4fSDavid du Colombier 		n = 64;
379a747e4fSDavid du Colombier 	for(i = 0; i < n; i++)
389a747e4fSDavid du Colombier 		Bprint(&bout, "%2.2x ", buf[i]);
399a747e4fSDavid du Colombier 	Bprint(&bout, "\n");
409a747e4fSDavid du Colombier 	Bterm(&bout);
419a747e4fSDavid du Colombier }
429a747e4fSDavid du Colombier 
439a747e4fSDavid du Colombier static void
xfer(int from,int to,int cfd,char * label)449a747e4fSDavid du Colombier xfer(int from, int to, int cfd, char *label)
459a747e4fSDavid du Colombier {
469a747e4fSDavid du Colombier 	uchar buf[BufSize];
479a747e4fSDavid du Colombier 	int n;
489a747e4fSDavid du Colombier 
499a747e4fSDavid du Colombier 	if(fork() == 0)
509a747e4fSDavid du Colombier 		return;
519a747e4fSDavid du Colombier 
529a747e4fSDavid du Colombier 	close(cfd);
539a747e4fSDavid du Colombier 	for(;;){
549a747e4fSDavid du Colombier 		n = read(from, buf, sizeof(buf));
559a747e4fSDavid du Colombier 		if(n <= 0){
569a747e4fSDavid du Colombier 			fprint(2, "%s EOF\n", label);
579a747e4fSDavid du Colombier 			close(to);
589a747e4fSDavid du Colombier 			close(from);
599a747e4fSDavid du Colombier 			death(nil, nil);
609a747e4fSDavid du Colombier 		}
619a747e4fSDavid du Colombier 		dump(2, buf, n, label);
629a747e4fSDavid du Colombier 		n = write(to, buf, n);
639a747e4fSDavid du Colombier 		if(n < 0){
649a747e4fSDavid du Colombier 			fprint(2, "%s write err\n", label);
659a747e4fSDavid du Colombier 			close(to);
669a747e4fSDavid du Colombier 			close(from);
679a747e4fSDavid du Colombier 			death(nil, nil);
689a747e4fSDavid du Colombier 		}
699a747e4fSDavid du Colombier 	}
709a747e4fSDavid du Colombier }
719a747e4fSDavid du Colombier 
729a747e4fSDavid du Colombier static int
dumper(int fd)739a747e4fSDavid du Colombier dumper(int fd)
749a747e4fSDavid du Colombier {
759a747e4fSDavid du Colombier 	int p[2];
769a747e4fSDavid du Colombier 
779a747e4fSDavid du Colombier 	if(pipe(p) < 0)
789a747e4fSDavid du Colombier 		sysfatal("can't make pipe: %r");
799a747e4fSDavid du Colombier 
809a747e4fSDavid du Colombier 	xfer(fd, p[0], p[1], "read");
819a747e4fSDavid du Colombier 	xfer(p[0], fd, p[1], "write");
829a747e4fSDavid du Colombier 	close(p[0]);
839a747e4fSDavid du Colombier 	return p[1];
849a747e4fSDavid du Colombier }
859a747e4fSDavid du Colombier 
869a747e4fSDavid du Colombier static int
reporter(char * fmt,...)879a747e4fSDavid du Colombier reporter(char *fmt, ...)
889a747e4fSDavid du Colombier {
899a747e4fSDavid du Colombier 	va_list ap;
909a747e4fSDavid du Colombier 	char buf[2000];
919a747e4fSDavid du Colombier 
929a747e4fSDavid du Colombier 	va_start(ap, fmt);
939a747e4fSDavid du Colombier 	if(logfile){
949a747e4fSDavid du Colombier 		vsnprint(buf, sizeof buf, fmt, ap);
959a747e4fSDavid du Colombier 		syslog(0, logfile, "%s tls reports %s", remotesys, buf);
969a747e4fSDavid du Colombier 	}else{
979a747e4fSDavid du Colombier 		fprint(2, "%s: %s tls reports ", argv0, remotesys);
989a747e4fSDavid du Colombier 		vfprint(2, fmt, ap);
99f0ed0fb6SDavid du Colombier 		fprint(2, "\n");
1009a747e4fSDavid du Colombier 	}
1019a747e4fSDavid du Colombier 	va_end(ap);
1029a747e4fSDavid du Colombier 	return 0;
1039a747e4fSDavid du Colombier }
1049a747e4fSDavid du Colombier 
1059a747e4fSDavid du Colombier void
usage(void)106de8abbc9SDavid du Colombier usage(void)
107de8abbc9SDavid du Colombier {
108de8abbc9SDavid du Colombier 	fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n");
109de8abbc9SDavid du Colombier 	fprint(2, "  after  auth/secretpem key.pem > /mnt/factotum/ctl\n");
110de8abbc9SDavid du Colombier 	exits("usage");
111de8abbc9SDavid du Colombier }
112de8abbc9SDavid du Colombier 
113de8abbc9SDavid du Colombier void
main(int argc,char * argv[])1149a747e4fSDavid du Colombier main(int argc, char *argv[])
1159a747e4fSDavid du Colombier {
1169a747e4fSDavid du Colombier 	TLSconn *conn;
1179a747e4fSDavid du Colombier 	uchar buf[BufSize];
1189a747e4fSDavid du Colombier 	char *cert;
1199a747e4fSDavid du Colombier 	int n, fd, clearfd;
1209a747e4fSDavid du Colombier 
1219a747e4fSDavid du Colombier 	debug = 0;
1229a747e4fSDavid du Colombier 	remotesys = nil;
1239a747e4fSDavid du Colombier 	cert = nil;
1249a747e4fSDavid du Colombier 	logfile = nil;
1259a747e4fSDavid du Colombier 	ARGBEGIN{
1269a747e4fSDavid du Colombier 	case 'D':
1279a747e4fSDavid du Colombier 		debug++;
1289a747e4fSDavid du Colombier 		break;
1299a747e4fSDavid du Colombier 	case 'c':
130de8abbc9SDavid du Colombier 		cert = EARGF(usage());
1319a747e4fSDavid du Colombier 		break;
1329a747e4fSDavid du Colombier 	case 'l':
133de8abbc9SDavid du Colombier 		logfile = EARGF(usage());
1349a747e4fSDavid du Colombier 		break;
1359a747e4fSDavid du Colombier 	case 'r':
136de8abbc9SDavid du Colombier 		remotesys = EARGF(usage());
1379a747e4fSDavid du Colombier 		break;
1389a747e4fSDavid du Colombier 	default:
139de8abbc9SDavid du Colombier 		usage();
1409a747e4fSDavid du Colombier 	}ARGEND
1419a747e4fSDavid du Colombier 
1429a747e4fSDavid du Colombier 	if(cert == nil)
1439a747e4fSDavid du Colombier 		sysfatal("no certificate specified");
1449a747e4fSDavid du Colombier 	if(remotesys == nil)
1459a747e4fSDavid du Colombier 		remotesys = "";
1469a747e4fSDavid du Colombier 	conn = (TLSconn*)mallocz(sizeof *conn, 1);
1479a747e4fSDavid du Colombier 	if(conn == nil)
1489a747e4fSDavid du Colombier 		sysfatal("out of memory");
1495f6b17bbSDavid du Colombier 	conn->chain = readcertchain(cert);
1505f6b17bbSDavid du Colombier 	if (conn->chain == nil)
1515f6b17bbSDavid du Colombier 		sysfatal("can't read certificate");
1525f6b17bbSDavid du Colombier 	conn->cert = conn->chain->pem;
1535f6b17bbSDavid du Colombier 	conn->certlen = conn->chain->pemlen;
1545f6b17bbSDavid du Colombier 	conn->chain = conn->chain->next;
1559a747e4fSDavid du Colombier 	if(debug)
1569a747e4fSDavid du Colombier 		conn->trace = reporter;
1579a747e4fSDavid du Colombier 
1589a747e4fSDavid du Colombier 	clearfd = 0;
1599a747e4fSDavid du Colombier 	fd = 1;
1609a747e4fSDavid du Colombier 	if(debug > 1)
1619a747e4fSDavid du Colombier 		fd = dumper(fd);
1629a747e4fSDavid du Colombier 	fd = tlsServer(fd, conn);
1639a747e4fSDavid du Colombier 	if(fd < 0){
164f0ed0fb6SDavid du Colombier 		reporter("failed: %r");
1659a747e4fSDavid du Colombier 		exits(0);
1669a747e4fSDavid du Colombier 	}
167*3a32e104SDavid du Colombier 	reporter("open");
1689a747e4fSDavid du Colombier 
1699a747e4fSDavid du Colombier 	if(argc > 0){
1709a747e4fSDavid du Colombier 		if(pipe(p) < 0)
1719a747e4fSDavid du Colombier 			exits("pipe");
1729a747e4fSDavid du Colombier 		switch(fork()){
1739a747e4fSDavid du Colombier 		case 0:
1749a747e4fSDavid du Colombier 			close(fd);
1759a747e4fSDavid du Colombier 			dup(p[0], 0);
1769a747e4fSDavid du Colombier 			dup(p[0], 1);
1779a747e4fSDavid du Colombier 			close(p[1]);
1789a747e4fSDavid du Colombier 			close(p[0]);
1799a747e4fSDavid du Colombier 			exec(argv[0], argv);
180f0ed0fb6SDavid du Colombier 			reporter("can't exec %s: %r", argv[0]);
1819a747e4fSDavid du Colombier 			_exits("exec");
1829a747e4fSDavid du Colombier 		case -1:
1839a747e4fSDavid du Colombier 			exits("fork");
1849a747e4fSDavid du Colombier 		default:
1859a747e4fSDavid du Colombier 			close(p[0]);
1869a747e4fSDavid du Colombier 			clearfd = p[1];
1879a747e4fSDavid du Colombier 			break;
1889a747e4fSDavid du Colombier 		}
1899a747e4fSDavid du Colombier 	}
1909a747e4fSDavid du Colombier 
1919a747e4fSDavid du Colombier 	rfork(RFNOTEG);
1929a747e4fSDavid du Colombier 	notify(death);
1939a747e4fSDavid du Colombier 	switch(rfork(RFPROC)){
1949a747e4fSDavid du Colombier 	case -1:
1959a747e4fSDavid du Colombier 		sysfatal("can't fork");
1969a747e4fSDavid du Colombier 	case 0:
1979a747e4fSDavid du Colombier 		for(;;){
1989a747e4fSDavid du Colombier 			n = read(clearfd, buf, BufSize);
1999a747e4fSDavid du Colombier 			if(n <= 0)
2009a747e4fSDavid du Colombier 				break;
2019a747e4fSDavid du Colombier 			if(write(fd, buf, n) != n)
2029a747e4fSDavid du Colombier 				break;
2039a747e4fSDavid du Colombier 		}
2049a747e4fSDavid du Colombier 		break;
2059a747e4fSDavid du Colombier 	default:
2069a747e4fSDavid du Colombier 		for(;;){
2079a747e4fSDavid du Colombier 			n = read(fd, buf, BufSize);
2089a747e4fSDavid du Colombier 			if(n <= 0)
2099a747e4fSDavid du Colombier 				break;
2109a747e4fSDavid du Colombier 			if(write(clearfd, buf, n) != n)
2119a747e4fSDavid du Colombier 				break;
2129a747e4fSDavid du Colombier 		}
2139a747e4fSDavid du Colombier 		break;
2149a747e4fSDavid du Colombier 	}
2159a747e4fSDavid du Colombier 	death(nil, nil);
2169a747e4fSDavid du Colombier }
217