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
death(void *,char *)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
dump(int fd,uchar * buf,int n,char * label)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
xfer(int from,int to,int cfd,char * label)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
dumper(int fd)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
reporter(char * fmt,...)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
usage(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
main(int argc,char * argv[])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