tlssrv.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <bio.h>
  12. #include <mp.h>
  13. #include <libsec.h>
  14. enum{ BufSize = 8192 };
  15. char *remotesys, *logfile;
  16. int debug, p[2];
  17. void
  18. death(void *v, char *c)
  19. {
  20. int pid;
  21. close(0);
  22. close(1);
  23. close(p[1]);
  24. pid = getpid();
  25. postnote(PNGROUP, pid, "die");
  26. postnote(PNGROUP, pid, "die");
  27. postnote(PNGROUP, pid, "die");
  28. _exits(0);
  29. }
  30. static void
  31. dump(int fd, uint8_t *buf, int n, char *label)
  32. {
  33. Biobuf bout;
  34. int i;
  35. Binit(&bout, fd, OWRITE);
  36. Bprint(&bout, "%s<%d>: ", label, n);
  37. if(n > 64)
  38. n = 64;
  39. for(i = 0; i < n; i++)
  40. Bprint(&bout, "%2.2x ", buf[i]);
  41. Bprint(&bout, "\n");
  42. Bterm(&bout);
  43. }
  44. static void
  45. xfer(int from, int to, int cfd, char *label)
  46. {
  47. uint8_t buf[BufSize];
  48. int n;
  49. if(fork() == 0)
  50. return;
  51. close(cfd);
  52. for(;;){
  53. n = read(from, buf, sizeof(buf));
  54. if(n <= 0){
  55. fprint(2, "%s EOF\n", label);
  56. close(to);
  57. close(from);
  58. death(nil, nil);
  59. }
  60. dump(2, buf, n, label);
  61. n = write(to, buf, n);
  62. if(n < 0){
  63. fprint(2, "%s write err\n", label);
  64. close(to);
  65. close(from);
  66. death(nil, nil);
  67. }
  68. }
  69. }
  70. static int
  71. dumper(int fd)
  72. {
  73. int p[2];
  74. if(pipe(p) < 0)
  75. sysfatal("can't make pipe: %r");
  76. xfer(fd, p[0], p[1], "read");
  77. xfer(p[0], fd, p[1], "write");
  78. close(p[0]);
  79. return p[1];
  80. }
  81. static int
  82. reporter(char *fmt, ...)
  83. {
  84. va_list ap;
  85. char buf[2000];
  86. va_start(ap, fmt);
  87. if(logfile){
  88. vsnprint(buf, sizeof buf, fmt, ap);
  89. syslog(0, logfile, "%s tls reports %s", remotesys, buf);
  90. }else{
  91. fprint(2, "%s: %s tls reports ", argv0, remotesys);
  92. vfprint(2, fmt, ap);
  93. fprint(2, "\n");
  94. }
  95. va_end(ap);
  96. return 0;
  97. }
  98. void
  99. usage(void)
  100. {
  101. fprint(2, "usage: tlssrv -c cert [-D] [-l logfile] [-r remotesys] [cmd args...]\n");
  102. fprint(2, " after auth/secretpem key.pem > /mnt/factotum/ctl\n");
  103. exits("usage");
  104. }
  105. void
  106. main(int argc, char *argv[])
  107. {
  108. TLSconn *conn;
  109. unsigned char buf[BufSize];
  110. char *cert;
  111. int n, fd, clearfd;
  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 = EARGF(usage());
  122. break;
  123. case 'l':
  124. logfile = EARGF(usage());
  125. break;
  126. case 'r':
  127. remotesys = EARGF(usage());
  128. break;
  129. default:
  130. usage();
  131. }ARGEND
  132. if(cert == nil)
  133. sysfatal("no certificate specified");
  134. if(remotesys == nil)
  135. remotesys = "";
  136. conn = (TLSconn*)mallocz(sizeof *conn, 1);
  137. if(conn == nil)
  138. sysfatal("out of memory");
  139. conn->chain = readcertchain(cert);
  140. if (conn->chain == nil)
  141. sysfatal("can't read certificate");
  142. conn->cert = conn->chain->pem;
  143. conn->certlen = conn->chain->pemlen;
  144. conn->chain = conn->chain->next;
  145. if(debug)
  146. conn->trace = reporter;
  147. clearfd = 0;
  148. fd = 1;
  149. if(debug > 1)
  150. fd = dumper(fd);
  151. fd = tlsServer(fd, conn);
  152. if(fd < 0){
  153. reporter("failed: %r");
  154. exits(0);
  155. }
  156. reporter("open");
  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", 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. rfork(RFNOTEG);
  179. notify(death);
  180. switch(rfork(RFPROC)){
  181. case -1:
  182. sysfatal("can't fork");
  183. case 0:
  184. for(;;){
  185. n = read(clearfd, buf, BufSize);
  186. if(n <= 0)
  187. break;
  188. if(write(fd, buf, n) != n)
  189. break;
  190. }
  191. break;
  192. default:
  193. for(;;){
  194. n = read(fd, buf, BufSize);
  195. if(n <= 0)
  196. break;
  197. if(write(clearfd, buf, n) != n)
  198. break;
  199. }
  200. break;
  201. }
  202. death(nil, nil);
  203. }