summaryrefslogtreecommitdiff
path: root/sys/src/cmd/tlssrv.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/tlssrv.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/tlssrv.c')
-rwxr-xr-xsys/src/cmd/tlssrv.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/sys/src/cmd/tlssrv.c b/sys/src/cmd/tlssrv.c
new file mode 100755
index 000000000..ef27f26d9
--- /dev/null
+++ b/sys/src/cmd/tlssrv.c
@@ -0,0 +1,216 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <mp.h>
+#include <libsec.h>
+
+enum{ BufSize = 8192 };
+
+char *remotesys, *logfile;
+int debug, p[2];
+
+void
+death(void *, char *)
+{
+ int pid;
+
+ close(0);
+ close(1);
+ close(p[1]);
+ pid = getpid();
+ postnote(PNGROUP, pid, "die");
+ postnote(PNGROUP, pid, "die");
+ postnote(PNGROUP, pid, "die");
+ _exits(0);
+}
+
+static void
+dump(int fd, uchar *buf, int n, char *label)
+{
+ Biobuf bout;
+ int i;
+
+ Binit(&bout, fd, OWRITE);
+ Bprint(&bout, "%s<%d>: ", label, n);
+ if(n > 64)
+ n = 64;
+ for(i = 0; i < n; i++)
+ Bprint(&bout, "%2.2x ", buf[i]);
+ Bprint(&bout, "\n");
+ Bterm(&bout);
+}
+
+static void
+xfer(int from, int to, int cfd, char *label)
+{
+ uchar buf[BufSize];
+ int n;
+
+ if(fork() == 0)
+ return;
+
+ close(cfd);
+ for(;;){
+ n = read(from, buf, sizeof(buf));
+ if(n <= 0){
+ fprint(2, "%s EOF\n", label);
+ close(to);
+ close(from);
+ death(nil, nil);
+ }
+ dump(2, buf, n, label);
+ n = write(to, buf, n);
+ if(n < 0){
+ fprint(2, "%s write err\n", label);
+ close(to);
+ close(from);
+ death(nil, nil);
+ }
+ }
+}
+
+static int
+dumper(int fd)
+{
+ int p[2];
+
+ if(pipe(p) < 0)
+ sysfatal("can't make pipe: %r");
+
+ xfer(fd, p[0], p[1], "read");
+ xfer(p[0], fd, p[1], "write");
+ close(p[0]);
+ return p[1];
+}
+
+static int
+reporter(char *fmt, ...)
+{
+ va_list ap;
+ char buf[2000];
+
+ va_start(ap, fmt);
+ if(logfile){
+ vsnprint(buf, sizeof buf, fmt, ap);
+ syslog(0, logfile, "%s tls reports %s", remotesys, buf);
+ }else{
+ fprint(2, "%s: %s tls reports ", argv0, remotesys);
+ vfprint(2, fmt, ap);
+ fprint(2, "\n");
+ }
+ va_end(ap);
+ return 0;
+}
+
+void
+usage(void)
+{
+ fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n");
+ fprint(2, " after auth/secretpem key.pem > /mnt/factotum/ctl\n");
+ exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+ TLSconn *conn;
+ uchar buf[BufSize];
+ char *cert;
+ int n, fd, clearfd;
+
+ debug = 0;
+ remotesys = nil;
+ cert = nil;
+ logfile = nil;
+ ARGBEGIN{
+ case 'D':
+ debug++;
+ break;
+ case 'c':
+ cert = EARGF(usage());
+ break;
+ case 'l':
+ logfile = EARGF(usage());
+ break;
+ case 'r':
+ remotesys = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ if(cert == nil)
+ sysfatal("no certificate specified");
+ if(remotesys == nil)
+ remotesys = "";
+ conn = (TLSconn*)mallocz(sizeof *conn, 1);
+ if(conn == nil)
+ sysfatal("out of memory");
+ conn->chain = readcertchain(cert);
+ if (conn->chain == nil)
+ sysfatal("can't read certificate");
+ conn->cert = conn->chain->pem;
+ conn->certlen = conn->chain->pemlen;
+ conn->chain = conn->chain->next;
+ if(debug)
+ conn->trace = reporter;
+
+ clearfd = 0;
+ fd = 1;
+ if(debug > 1)
+ fd = dumper(fd);
+ fd = tlsServer(fd, conn);
+ if(fd < 0){
+ reporter("failed: %r");
+ exits(0);
+ }
+ reporter("open");
+
+ if(argc > 0){
+ if(pipe(p) < 0)
+ exits("pipe");
+ switch(fork()){
+ case 0:
+ close(fd);
+ dup(p[0], 0);
+ dup(p[0], 1);
+ close(p[1]);
+ close(p[0]);
+ exec(argv[0], argv);
+ reporter("can't exec %s: %r", argv[0]);
+ _exits("exec");
+ case -1:
+ exits("fork");
+ default:
+ close(p[0]);
+ clearfd = p[1];
+ break;
+ }
+ }
+
+ rfork(RFNOTEG);
+ notify(death);
+ switch(rfork(RFPROC)){
+ case -1:
+ sysfatal("can't fork");
+ case 0:
+ for(;;){
+ n = read(clearfd, buf, BufSize);
+ if(n <= 0)
+ break;
+ if(write(fd, buf, n) != n)
+ break;
+ }
+ break;
+ default:
+ for(;;){
+ n = read(fd, buf, BufSize);
+ if(n <= 0)
+ break;
+ if(write(clearfd, buf, n) != n)
+ break;
+ }
+ break;
+ }
+ death(nil, nil);
+}