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 fprint(2, "\n"); 100 } 101 va_end(ap); 102 return 0; 103 } 104 105 void 106 usage(void) 107 { 108 fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n"); 109 fprint(2, " after auth/secretpem key.pem > /mnt/factotum/ctl\n"); 110 exits("usage"); 111 } 112 113 void 114 main(int argc, char *argv[]) 115 { 116 TLSconn *conn; 117 uchar buf[BufSize]; 118 char *cert; 119 int n, fd, clearfd; 120 121 debug = 0; 122 remotesys = nil; 123 cert = nil; 124 logfile = nil; 125 ARGBEGIN{ 126 case 'D': 127 debug++; 128 break; 129 case 'c': 130 cert = EARGF(usage()); 131 break; 132 case 'l': 133 logfile = EARGF(usage()); 134 break; 135 case 'r': 136 remotesys = EARGF(usage()); 137 break; 138 default: 139 usage(); 140 }ARGEND 141 142 if(cert == nil) 143 sysfatal("no certificate specified"); 144 if(remotesys == nil) 145 remotesys = ""; 146 conn = (TLSconn*)mallocz(sizeof *conn, 1); 147 if(conn == nil) 148 sysfatal("out of memory"); 149 conn->chain = readcertchain(cert); 150 if (conn->chain == nil) 151 sysfatal("can't read certificate"); 152 conn->cert = conn->chain->pem; 153 conn->certlen = conn->chain->pemlen; 154 conn->chain = conn->chain->next; 155 if(debug) 156 conn->trace = reporter; 157 158 clearfd = 0; 159 fd = 1; 160 if(debug > 1) 161 fd = dumper(fd); 162 fd = tlsServer(fd, conn); 163 if(fd < 0){ 164 reporter("failed: %r"); 165 exits(0); 166 } 167 reporter("open"); 168 169 if(argc > 0){ 170 if(pipe(p) < 0) 171 exits("pipe"); 172 switch(fork()){ 173 case 0: 174 close(fd); 175 dup(p[0], 0); 176 dup(p[0], 1); 177 close(p[1]); 178 close(p[0]); 179 exec(argv[0], argv); 180 reporter("can't exec %s: %r", argv[0]); 181 _exits("exec"); 182 case -1: 183 exits("fork"); 184 default: 185 close(p[0]); 186 clearfd = p[1]; 187 break; 188 } 189 } 190 191 rfork(RFNOTEG); 192 notify(death); 193 switch(rfork(RFPROC)){ 194 case -1: 195 sysfatal("can't fork"); 196 case 0: 197 for(;;){ 198 n = read(clearfd, buf, BufSize); 199 if(n <= 0) 200 break; 201 if(write(fd, buf, n) != n) 202 break; 203 } 204 break; 205 default: 206 for(;;){ 207 n = read(fd, buf, BufSize); 208 if(n <= 0) 209 break; 210 if(write(clearfd, buf, n) != n) 211 break; 212 } 213 break; 214 } 215 death(nil, nil); 216 } 217