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