1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mp.h> 5 #include <libsec.h> 6 7 enum{ BufSize = 8192 }; 8 9 char *remotesys, *logfile; 10 int debug, p[2]; 11 12 void 13 death(void *, char *) 14 { 15 int pid; 16 17 close(0); 18 close(1); 19 close(p[1]); 20 pid = getpid(); 21 postnote(PNGROUP, pid, "die"); 22 postnote(PNGROUP, pid, "die"); 23 postnote(PNGROUP, pid, "die"); 24 _exits(0); 25 } 26 27 static void 28 dump(int fd, uchar *buf, int n, char *label) 29 { 30 Biobuf bout; 31 int i; 32 33 Binit(&bout, fd, OWRITE); 34 Bprint(&bout, "%s<%d>: ", label, n); 35 if(n > 64) 36 n = 64; 37 for(i = 0; i < n; i++) 38 Bprint(&bout, "%2.2x ", buf[i]); 39 Bprint(&bout, "\n"); 40 Bterm(&bout); 41 } 42 43 static void 44 xfer(int from, int to, int cfd, char *label) 45 { 46 uchar buf[BufSize]; 47 int n; 48 49 if(fork() == 0) 50 return; 51 52 close(cfd); 53 for(;;){ 54 n = read(from, buf, sizeof(buf)); 55 if(n <= 0){ 56 fprint(2, "%s EOF\n", label); 57 close(to); 58 close(from); 59 death(nil, nil); 60 } 61 dump(2, buf, n, label); 62 n = write(to, buf, n); 63 if(n < 0){ 64 fprint(2, "%s write err\n", label); 65 close(to); 66 close(from); 67 death(nil, nil); 68 } 69 } 70 } 71 72 static int 73 dumper(int fd) 74 { 75 int p[2]; 76 77 if(pipe(p) < 0) 78 sysfatal("can't make pipe: %r"); 79 80 xfer(fd, p[0], p[1], "read"); 81 xfer(p[0], fd, p[1], "write"); 82 close(p[0]); 83 return p[1]; 84 } 85 86 static int 87 reporter(char *fmt, ...) 88 { 89 va_list ap; 90 char buf[2000]; 91 92 va_start(ap, fmt); 93 if(logfile){ 94 vsnprint(buf, sizeof buf, fmt, ap); 95 syslog(0, logfile, "%s tls reports %s", remotesys, buf); 96 }else{ 97 fprint(2, "%s: %s tls reports ", argv0, remotesys); 98 vfprint(2, fmt, ap); 99 } 100 va_end(ap); 101 return 0; 102 } 103 104 void 105 main(int argc, char *argv[]) 106 { 107 TLSconn *conn; 108 uchar buf[BufSize]; 109 char *cert; 110 int n, fd, clearfd; 111 112 debug = 0; 113 remotesys = nil; 114 cert = nil; 115 logfile = nil; 116 ARGBEGIN{ 117 case 'D': 118 debug++; 119 break; 120 case 'c': 121 cert = ARGF(); 122 break; 123 case 'l': 124 logfile = ARGF(); 125 break; 126 case 'r': 127 remotesys = ARGF(); 128 break; 129 default: 130 fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n"); 131 fprint(2, " after auth/secretpem key.pem > /mnt/factotum/ctl\n"); 132 exits("usage"); 133 }ARGEND 134 135 if(cert == nil) 136 sysfatal("no certificate specified"); 137 if(remotesys == nil) 138 remotesys = ""; 139 conn = (TLSconn*)mallocz(sizeof *conn, 1); 140 if(conn == nil) 141 sysfatal("out of memory"); 142 conn->cert = readcert(cert, &conn->certlen); 143 if(debug) 144 conn->trace = reporter; 145 146 clearfd = 0; 147 fd = 1; 148 if(debug > 1) 149 fd = dumper(fd); 150 fd = tlsServer(fd, conn); 151 if(fd < 0){ 152 reporter("failed: %r\n"); 153 exits(0); 154 } 155 reporter("open\n"); 156 157 if(argc > 0){ 158 if(pipe(p) < 0) 159 exits("pipe"); 160 switch(fork()){ 161 case 0: 162 close(fd); 163 dup(p[0], 0); 164 dup(p[0], 1); 165 close(p[1]); 166 close(p[0]); 167 exec(argv[0], argv); 168 reporter("can't exec %s: %r\n", argv[0]); 169 _exits("exec"); 170 case -1: 171 exits("fork"); 172 default: 173 close(p[0]); 174 clearfd = p[1]; 175 break; 176 } 177 } 178 179 rfork(RFNOTEG); 180 notify(death); 181 switch(rfork(RFPROC)){ 182 case -1: 183 sysfatal("can't fork"); 184 case 0: 185 for(;;){ 186 n = read(clearfd, buf, BufSize); 187 if(n <= 0) 188 break; 189 if(write(fd, buf, n) != n) 190 break; 191 } 192 break; 193 default: 194 for(;;){ 195 n = read(fd, buf, BufSize); 196 if(n <= 0) 197 break; 198 if(write(clearfd, buf, n) != n) 199 break; 200 } 201 break; 202 } 203 death(nil, nil); 204 } 205