1 #include <sys/types.h>
2 #include <unistd.h>
3 #include "matrixSsl.h"
4 #include "uidgid.h"
5 #include "prot.h"
6 #include "error.h"
7 #include "strerr.h"
8 #include "fd.h"
9 #include "pathexec.h"
10 #include "stralloc.h"
11 #include "byte.h"
12 #include "taia.h"
13 #include "iopause.h"
14 #include "ndelay.h"
15 #include "fmt.h"
16 #include "scan.h"
17 #include "sgetopt.h"
18 #include "env.h"
19 #include "sig.h"
20 #include "sslerror_str.h"
21
22 #define USAGEROOT " -u user [-U user] [-/ root] [-C cert] [-K key] [-A ca] [-vc] prog"
23 #define USAGE " [-C cert] [-K key] [-A ca] [-cv] prog"
24 #define VERSION "$Id: 5b49a0244b79fd00a69b028b11d60dde84c7a8a5 $"
25 #define NAME "sslio["
26 #define FATAL "]: fatal: "
27 #define WARNING "]: warning: "
28 #define INFO "]: info: "
29
30 const char *progname;
31 extern char id[FMT_ULONG];
32 extern char ul[FMT_ULONG];
33 extern int pid;
34
35 static void finish(void);
die_nomem()36 static void die_nomem() {
37 strerr_die4x(111, NAME, id, FATAL, "out of memory.");
38 }
fatalm(char * m0)39 static void fatalm(char *m0) { strerr_die5sys(111, NAME, id, FATAL, m0, ": "); }
fatalmx(char * m0)40 static void fatalmx(char *m0) { strerr_die4x(111, NAME, id, FATAL, m0); }
fatal(char * m0)41 static void fatal(char *m0) {
42 strerr_warn5(NAME, id, FATAL, m0, ": ", &strerr_sys); finish();
43 _exit(111);
44 }
fatalx(char * m0)45 static void fatalx(char *m0) {
46 strerr_warn4(NAME, id, FATAL, m0, 0); finish();
47 _exit(111);
48 }
fatals(char * m0,int e)49 static void fatals(char *m0, int e) {
50 strerr_warn6(NAME, id, FATAL, m0, ": ", sslerror_str(e), 0); finish();
51 _exit(111);
52 }
warn(char * m0)53 static void warn(char *m0) {
54 strerr_warn5(NAME, id, WARNING, m0, ": ", &strerr_sys);
55 }
warnx(char * m0)56 static void warnx(char *m0) { strerr_warn4(NAME, id, WARNING, m0, 0); }
info(char * m0)57 static void info(char *m0) { strerr_warn4(NAME, id, INFO, m0, 0); }
infou(char * m0,unsigned long u)58 static void infou(char *m0, unsigned long u) {
59 ul[fmt_ulong(ul, u)] =0;
60 strerr_warn5(NAME, id, INFO, m0, ul, 0);
61 }
62
63 extern char *cert;
64 extern char *key;
65 extern char *ssluser;
66 extern char *ca;
67 extern char *svuser;
68 extern char *root;
69 extern unsigned int client;
70 extern unsigned int verbose;
71 extern struct uidgid ugid, sslugid;
72 extern ssl_t *ssl;
73 extern sslKeys_t *keys;
74
75 static unsigned long bufsizein =8192;
76 static unsigned long bufsizeou =12288;
77
78 static int encpipe[2];
79 static int decpipe[2];
80 static int len;
81 static int rc;
82 static int handshake =1;
83 static int getdec =1;
84 static char *s;
85 static unsigned long handshake_timeout =300;
86
87 static sslBuf_t encin, encou;
88 static stralloc encinbuf ={0};
89 static stralloc encoubuf ={0};
90 static sslBuf_t decin, decou;
91 static stralloc decinbuf ={0};
92 static stralloc decoubuf ={0};
93
94 static int fdstdin =0;
95 static int fdstdou =1;
96 static unsigned long bytesin =0;
97 static unsigned long bytesou =0;
98
99 static unsigned char error, alvl, adesc;
100 static char *bad_certificate;
101
sig_term_handler(void)102 static void sig_term_handler(void) {
103 if (verbose) info("sigterm received, exit.");
104 finish();
105 _exit(0);
106 }
blowup(sslBuf_t * buf,stralloc * sa,unsigned int len)107 unsigned int blowup(sslBuf_t *buf, stralloc *sa, unsigned int len) {
108 sa->len =buf->end -buf->buf;
109 buf->size +=len;
110 if (! stralloc_ready(sa, buf->size)) return(0);
111 buf->end =sa->s +(buf->end -buf->buf);
112 buf->start =sa->s +(buf->start -buf->buf);
113 buf->buf =sa->s;
114 return(1);
115 }
finish(void)116 void finish(void) {
117 if (fdstdou != -1)
118 for (;;) {
119 decou.start =decou.end =decou.buf;
120 rc =matrixSslEncodeClosureAlert(ssl, &decou);
121 if (rc == SSL_FULL) {
122 if (! blowup(&decou, &decoubuf, bufsizeou)) die_nomem();
123 if (verbose > 1) infou("decode output buffer size: ", decou.size);
124 continue;
125 }
126 if (rc == SSL_ERROR)
127 if (verbose) warnx("unable to encode ssl close notify");
128 if (rc == 0) {
129 if (write(fdstdou, decou.start, decou.end -decou.start)
130 != (decou.end -decou.start)) {
131 if (verbose) warn("unable to send ssl close notify");
132 break;
133 }
134 if (verbose > 2) info("sending ssl close notify");
135 if (verbose > 2) infou("write bytes: ", decou.end -decou.start);
136 bytesou +=decou.end -decou.start;
137 }
138 break;
139 }
140 /* bummer */
141 matrixSslFreeKeys(keys);
142 matrixSslDeleteSession(ssl);
143 matrixSslClose();
144 if (fdstdou != -1) close(fdstdou);
145 if (encpipe[0] != -1) close(encpipe[0]);
146 if (fdstdin != -1) close(fdstdin);
147 if (decpipe[1] != -1) close(decpipe[1]);
148 if (verbose) { infou("bytes in: ", bytesin); infou("bytes ou: ", bytesou); }
149 }
validate(sslCertInfo_t * cert,void * arg)150 int validate(sslCertInfo_t *cert, void *arg) {
151 sslCertInfo_t *c =cert;
152
153 if (bad_certificate) return 1;
154 while (c->next) c =c->next;
155 return(c->verified);
156 }
157
encode(void)158 void encode(void) {
159 if ((len =read(encpipe[0], encinbuf.s, encin.size)) < 0)
160 fatal("unable to read from prog");
161 if (len == 0) {
162 if (verbose > 2) info("eof reading from proc");
163 finish();
164 _exit(0);
165 }
166 for (;;) {
167 rc =matrixSslEncode(ssl, encin.buf, len, &encou);
168 if (rc == SSL_ERROR) {
169 close(fdstdou); fdstdou =-1;
170 fatalx("unable to encode data");
171 }
172 if (rc == SSL_FULL) {
173 if (! blowup(&encou, &encoubuf, bufsizeou)) die_nomem();
174 if (verbose > 1) infou("encode output buffer size: ", encou.size);
175 continue;
176 }
177 if (write(fdstdou, encou.start, encou.end -encou.start)
178 != encou.end -encou.start) fatal("unable to write to network");
179 if (verbose > 2) infou("write bytes: ", encou.end -encou.start);
180 bytesou +=encou.end -encou.start;
181 encou.start =encou.end =encou.buf =encoubuf.s;
182 return;
183 }
184 }
decode(void)185 void decode(void) {
186 do {
187 if (getdec) {
188 len =decin.size -(decin.end -decin.buf);
189 if ((len =read(fdstdin, decin.end, len)) < 0)
190 fatal("unable to read from network");
191 if (len == 0) {
192 if (verbose > 2) info("eof reading from network");
193 close(fdstdin); close(decpipe[1]);
194 fdstdin =decpipe[1] =-1;
195 return;
196 }
197 if (verbose > 2) infou("read bytes: ", len);
198 bytesin +=len;
199 decin.end +=len;
200 getdec =0;
201 }
202 for (;;) {
203 rc =matrixSslDecode(ssl, &decin, &decou, &error, &alvl, &adesc);
204 if (rc == SSL_SUCCESS) break;
205 if (rc == SSL_ERROR) {
206 if (decou.end > decou.start)
207 if (write(fdstdou, decou.start, decou.end -decou.start)
208 != decou.end -decou.start) warn("unable to write to network");
209 close(fdstdou); fdstdou =-1;
210 fatals("ssl decode error", error);
211 }
212 if (rc == SSL_PROCESS_DATA) {
213 if (write(decpipe[1], decou.start, decou.end -decou.start)
214 != decou.end -decou.start) fatal("unable to write to prog");
215 decou.start =decou.end =decou.buf;
216 if (decin.start > decin.buf) { /* align */
217 byte_copy(decin.buf, decin.end -decin.start, decin.start);
218 decin.end -=decin.start -decin.buf;
219 decin.start =decin.buf;
220 }
221 break;
222 }
223 if (rc == SSL_SEND_RESPONSE) {
224 if (write(fdstdou, decou.start, decou.end -decou.start)
225 != (decou.end -decou.start))
226 fatal("unable to send ssl response");
227 bytesou +=decou.end -decou.start;
228 if (verbose > 2) info("sending ssl handshake response");
229 if (verbose > 2) infou("write bytes: ", decou.end -decou.start);
230 decou.start =decou.end =decou.buf;
231 break;
232 }
233 if (rc == SSL_ALERT) {
234 close(fdstdou); fdstdou =-1;
235 if (adesc != SSL_ALERT_CLOSE_NOTIFY)
236 fatals("ssl alert from peer", adesc);
237 if (verbose > 2) info("ssl close notify from peer");
238 finish();
239 _exit(0);
240 }
241 if (rc == SSL_PARTIAL) {
242 getdec =1;
243 if (decin.size -(decin.end -decin.buf) < bufsizein) {
244 if (! blowup(&decin, &decinbuf, bufsizein)) die_nomem();
245 if (verbose > 1) infou("decode input buffer size: ", decin.size);
246 }
247 break;
248 }
249 if (rc == SSL_FULL) {
250 if (! blowup(&decou, &decoubuf, bufsizeou)) die_nomem();
251 if (verbose > 1) infou("decode output buffer size: ", decou.size);
252 continue;
253 }
254 }
255 if (decin.start == decin.end) {
256 decin.start =decin.end =decin.buf;
257 getdec =1;
258 }
259 } while (getdec == 0);
260 if (handshake)
261 if (matrixSslHandshakeIsComplete(ssl)) {
262 handshake =0;
263 if (verbose > 2) info("ssl handshake complete");
264 }
265 }
266
doio(void)267 void doio(void) {
268 iopause_fd x[2];
269 struct taia deadline;
270 struct taia now;
271 struct taia timeout;
272
273 if (! stralloc_ready(&encinbuf, bufsizein)) die_nomem();
274 encin.buf =encin.start =encin.end =encinbuf.s; encin.size =bufsizein;
275 if (! stralloc_ready(&decinbuf, bufsizein)) die_nomem();
276 decin.buf =decin.start =decin.end =decinbuf.s; decin.size =bufsizein;
277 if (! stralloc_ready(&encoubuf, bufsizeou)) die_nomem();
278 encou.buf =encou.start =encou.end =encoubuf.s; encou.size =bufsizeou;
279 if (! stralloc_ready(&decoubuf, bufsizeou)) die_nomem();
280 decou.buf =decou.start =decou.end =decoubuf.s; decou.size =bufsizeou;
281
282 if (client) {
283 rc =matrixSslEncodeClientHello(ssl, &decou, 0);
284 if (rc != 0) fatalx("unable to encode client hello");
285 if (write(fdstdou, decou.start, decou.end -decou.start)
286 != (decou.end -decou.start))
287 fatal("unable to send client hello");
288 if (verbose > 2) info("sending client hello");
289 if (verbose > 2) infou("write bytes: ", decou.end -decou.start);
290 bytesou +=decou.end -decou.start;
291 decou.start =decou.end =decou.buf;
292 }
293
294 taia_now(&now);
295 taia_uint(&timeout, handshake_timeout);
296 taia_add(&timeout, &now, &timeout);
297
298 for (;;) {
299 iopause_fd *xx =x;
300 int l =2;
301
302 x[0].fd =encpipe[0];
303 x[0].events =IOPAUSE_READ;
304 x[0].revents =0;
305 x[1].fd =fdstdin;
306 x[1].events =IOPAUSE_READ;
307 x[1].revents =0;
308
309 if ((x[0].fd == -1) || handshake) { --l; ++xx; }
310 if (x[1].fd == -1) --l;
311 if (! l) return;
312
313 taia_now(&now);
314 if (handshake) {
315 if (taia_less(&timeout, &now)) {
316 if (verbose) info("ssl handshake timeout, exit.");
317 return;
318 }
319 deadline.sec =timeout.sec;
320 deadline.nano =timeout.nano;
321 deadline.atto =timeout.atto;
322 }
323 else {
324 taia_uint(&deadline, 30);
325 taia_add(&deadline, &now, &deadline);
326 }
327 iopause(xx, l, &deadline, &now);
328
329 if (x[0].revents) encode();
330 if (x[1].revents) decode();
331 }
332 }
333
ssl_io(unsigned int newsession,const char ** prog)334 int ssl_io(unsigned int newsession, const char **prog) {
335 if (client) { fdstdin =6; fdstdou =7; }
336 bad_certificate = env_get("SSLIO_BAD_CERTIFICATE");
337 if ((s =env_get("SSLIO_BUFIN"))) scan_ulong(s, &bufsizein);
338 if ((s =env_get("SSLIO_BUFOU"))) scan_ulong(s, &bufsizeou);
339 if (bufsizein < 64) bufsizein =64;
340 if (bufsizeou < 64) bufsizeou =64;
341 if ((s =env_get("SSLIO_HANDSHAKE_TIMEOUT")))
342 scan_ulong(s, &handshake_timeout);
343 if (handshake_timeout < 1) handshake_timeout =1;
344
345 if (pipe(encpipe) == -1) fatalm("unable to create pipe for encoding");
346 if (pipe(decpipe) == -1) fatalm("unable to create pipe for decoding");
347 if ((pid =fork()) == -1) fatalm("unable to fork");
348 if (pid == 0) {
349 if (close(encpipe[1]) == -1)
350 fatalm("unable to close encoding pipe output");
351 if (close(decpipe[0]) == -1)
352 fatalm("unable to close decoding pipe input");
353 if (newsession) if (matrixSslOpen() < 0) fatalm("unable to initialize ssl");
354 if (root) {
355 if (chdir(root) == -1) fatalm("unable to change to new root directory");
356 if (chroot(".") == -1) fatalm("unable to chroot");
357 }
358 if (ssluser) {
359 /* drop permissions */
360 if (setgroups(sslugid.gids, sslugid.gid) == -1)
361 fatal("unable to set groups");
362 if (setgid(*sslugid.gid) == -1) fatal("unable to set gid");
363 if (prot_uid(sslugid.uid) == -1) fatalm("unable to set uid");
364 }
365 if (newsession) {
366 if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) {
367 if (client) fatalm("unable to read cert, key, or ca file");
368 fatalm("unable to read cert or key file");
369 }
370 if (matrixSslNewSession(&ssl, keys, 0, client?0:SSL_FLAGS_SERVER) < 0)
371 fatalmx("unable to create ssl session");
372 }
373 if (client)
374 if (ca || bad_certificate) matrixSslSetCertValidator(ssl, &validate, 0);
375
376 sig_catch(sig_term, sig_term_handler);
377 sig_ignore(sig_pipe);
378 doio();
379 finish();
380 _exit(0);
381 }
382 if (close(encpipe[0]) == -1) fatalm("unable to close encoding pipe input");
383 if (close(decpipe[1]) == -1) fatalm("unable to close decoding pipe output");
384 if (fd_move(fdstdin, decpipe[0]) == -1)
385 fatalm("unable to setup filedescriptor for decoding");
386 if (fd_move(fdstdou, encpipe[1]) == -1)
387 fatalm("unable to setup filedescriptor for encoding");
388 sslCloseOsdep();
389 if (svuser) {
390 if (setgroups(ugid.gids, ugid.gid) == -1)
391 fatal("unable to set groups for prog");
392 if (setgid(*ugid.gid) == -1) fatal("unable to set gid for prog");
393 if (prot_uid(ugid.uid) == -1) fatalm("unable to set uid for prog");
394 }
395 pathexec(prog);
396 fatalm("unable to run prog");
397 return(111);
398 }
399