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 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 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 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 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 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); 99*f0ed0fb6SDavid 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 1069a747e4fSDavid du Colombier main(int argc, char *argv[]) 1079a747e4fSDavid du Colombier { 1089a747e4fSDavid du Colombier TLSconn *conn; 1099a747e4fSDavid du Colombier uchar buf[BufSize]; 1109a747e4fSDavid du Colombier char *cert; 1119a747e4fSDavid du Colombier int n, fd, clearfd; 1129a747e4fSDavid du Colombier 1139a747e4fSDavid du Colombier debug = 0; 1149a747e4fSDavid du Colombier remotesys = nil; 1159a747e4fSDavid du Colombier cert = nil; 1169a747e4fSDavid du Colombier logfile = nil; 1179a747e4fSDavid du Colombier ARGBEGIN{ 1189a747e4fSDavid du Colombier case 'D': 1199a747e4fSDavid du Colombier debug++; 1209a747e4fSDavid du Colombier break; 1219a747e4fSDavid du Colombier case 'c': 1229a747e4fSDavid du Colombier cert = ARGF(); 1239a747e4fSDavid du Colombier break; 1249a747e4fSDavid du Colombier case 'l': 1259a747e4fSDavid du Colombier logfile = ARGF(); 1269a747e4fSDavid du Colombier break; 1279a747e4fSDavid du Colombier case 'r': 1289a747e4fSDavid du Colombier remotesys = ARGF(); 1299a747e4fSDavid du Colombier break; 1309a747e4fSDavid du Colombier default: 1319a747e4fSDavid du Colombier fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n"); 1329a747e4fSDavid du Colombier fprint(2, " after auth/secretpem key.pem > /mnt/factotum/ctl\n"); 1339a747e4fSDavid du Colombier exits("usage"); 1349a747e4fSDavid du Colombier }ARGEND 1359a747e4fSDavid du Colombier 1369a747e4fSDavid du Colombier if(cert == nil) 1379a747e4fSDavid du Colombier sysfatal("no certificate specified"); 1389a747e4fSDavid du Colombier if(remotesys == nil) 1399a747e4fSDavid du Colombier remotesys = ""; 1409a747e4fSDavid du Colombier conn = (TLSconn*)mallocz(sizeof *conn, 1); 1419a747e4fSDavid du Colombier if(conn == nil) 1429a747e4fSDavid du Colombier sysfatal("out of memory"); 1435f6b17bbSDavid du Colombier conn->chain = readcertchain(cert); 1445f6b17bbSDavid du Colombier if (conn->chain == nil) 1455f6b17bbSDavid du Colombier sysfatal("can't read certificate"); 1465f6b17bbSDavid du Colombier conn->cert = conn->chain->pem; 1475f6b17bbSDavid du Colombier conn->certlen = conn->chain->pemlen; 1485f6b17bbSDavid du Colombier conn->chain = conn->chain->next; 1499a747e4fSDavid du Colombier if(debug) 1509a747e4fSDavid du Colombier conn->trace = reporter; 1519a747e4fSDavid du Colombier 1529a747e4fSDavid du Colombier clearfd = 0; 1539a747e4fSDavid du Colombier fd = 1; 1549a747e4fSDavid du Colombier if(debug > 1) 1559a747e4fSDavid du Colombier fd = dumper(fd); 1569a747e4fSDavid du Colombier fd = tlsServer(fd, conn); 1579a747e4fSDavid du Colombier if(fd < 0){ 158*f0ed0fb6SDavid du Colombier reporter("failed: %r"); 1599a747e4fSDavid du Colombier exits(0); 1609a747e4fSDavid du Colombier } 1619a747e4fSDavid du Colombier reporter("open\n"); 1629a747e4fSDavid du Colombier 1639a747e4fSDavid du Colombier if(argc > 0){ 1649a747e4fSDavid du Colombier if(pipe(p) < 0) 1659a747e4fSDavid du Colombier exits("pipe"); 1669a747e4fSDavid du Colombier switch(fork()){ 1679a747e4fSDavid du Colombier case 0: 1689a747e4fSDavid du Colombier close(fd); 1699a747e4fSDavid du Colombier dup(p[0], 0); 1709a747e4fSDavid du Colombier dup(p[0], 1); 1719a747e4fSDavid du Colombier close(p[1]); 1729a747e4fSDavid du Colombier close(p[0]); 1739a747e4fSDavid du Colombier exec(argv[0], argv); 174*f0ed0fb6SDavid du Colombier reporter("can't exec %s: %r", argv[0]); 1759a747e4fSDavid du Colombier _exits("exec"); 1769a747e4fSDavid du Colombier case -1: 1779a747e4fSDavid du Colombier exits("fork"); 1789a747e4fSDavid du Colombier default: 1799a747e4fSDavid du Colombier close(p[0]); 1809a747e4fSDavid du Colombier clearfd = p[1]; 1819a747e4fSDavid du Colombier break; 1829a747e4fSDavid du Colombier } 1839a747e4fSDavid du Colombier } 1849a747e4fSDavid du Colombier 1859a747e4fSDavid du Colombier rfork(RFNOTEG); 1869a747e4fSDavid du Colombier notify(death); 1879a747e4fSDavid du Colombier switch(rfork(RFPROC)){ 1889a747e4fSDavid du Colombier case -1: 1899a747e4fSDavid du Colombier sysfatal("can't fork"); 1909a747e4fSDavid du Colombier case 0: 1919a747e4fSDavid du Colombier for(;;){ 1929a747e4fSDavid du Colombier n = read(clearfd, buf, BufSize); 1939a747e4fSDavid du Colombier if(n <= 0) 1949a747e4fSDavid du Colombier break; 1959a747e4fSDavid du Colombier if(write(fd, buf, n) != n) 1969a747e4fSDavid du Colombier break; 1979a747e4fSDavid du Colombier } 1989a747e4fSDavid du Colombier break; 1999a747e4fSDavid du Colombier default: 2009a747e4fSDavid du Colombier for(;;){ 2019a747e4fSDavid du Colombier n = read(fd, buf, BufSize); 2029a747e4fSDavid du Colombier if(n <= 0) 2039a747e4fSDavid du Colombier break; 2049a747e4fSDavid du Colombier if(write(clearfd, buf, n) != n) 2059a747e4fSDavid du Colombier break; 2069a747e4fSDavid du Colombier } 2079a747e4fSDavid du Colombier break; 2089a747e4fSDavid du Colombier } 2099a747e4fSDavid du Colombier death(nil, nil); 2109a747e4fSDavid du Colombier } 211