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