123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #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 *v, char *c)
- {
- 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, uint8_t *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)
- {
- uint8_t 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;
- unsigned char 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);
- }
|