ucspi-ssl 0.13.03
ucspi-ssl
Loading...
Searching...
No Matches
sslhandle.c
Go to the documentation of this file.
1
6#include <unistd.h>
7#include <sys/types.h>
8#include <sys/socket.h>
9#include <sys/param.h>
10#include <netdb.h>
11#include <signal.h>
12#include <arpa/inet.h>
13#include "ucspissl.h"
14#include "uint_t.h"
15#include "str.h"
16#include "byte.h"
17#include "fmt.h"
18#include "scan.h"
19#include "ip.h"
20#include "fd.h"
21#include "exit.h"
22#include "env.h"
23#include "prot.h"
24#include "open.h"
25#include "wait.h"
26#include "stralloc.h"
27#include "alloc.h"
28#include "buffer.h"
29#include "getln.h"
30#include "logmsg.h"
31#include "getoptb.h"
32#include "socket_if.h"
33#include "ndelay.h"
34#include "remoteinfo.h"
35#include "rules.h"
36#include "sig.h"
37#include "iopause.h"
38#include "dnsresolv.h"
39#include "auto_cafile.h"
40#include "auto_cadir.h"
41#include "auto_ccafile.h"
42#include "auto_dhfile.h"
43#include "auto_certchainfile.h"
44#include "auto_certfile.h"
45#include "auto_keyfile.h"
46#include "auto_ciphers.h"
47#include "iopause.h"
48#include "coe.h"
49#include "lock.h"
50
51
52extern void server(int argcs,char * const *argvs);
53char *who;
54
55int verbosity = 1;
57int flagafter = 0;
58int flagdelay = 0;
59const char *banner = "";
64int flagsslenv = 0;
65int flagtcpenv = 0;
66unsigned long timeout = 26;
67unsigned long ssltimeout = 26;
68unsigned int progtimeout = 3600;
69uint32 netif = 0;
70int selfpipe[2];
71int flagexit = 0;
73
74static stralloc tcpremoteinfo = {0};
75
76uint16 localport;
77char localportstr[FMT_ULONG];
78char localip[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
79char localipstr[IP6_FMT];
80static stralloc localhostsa;
81const char *localhost = 0;
82const char *lockfile = 0;
84
86char remoteportstr[FMT_ULONG];
87char remoteip[16];
88char remoteipstr[IP6_FMT];
89static stralloc remotehostsa;
90char *remotehost = 0;
91
92const char *hostname;
93const char *loopback = "127.0.0.1";
94
95static char strnum[FMT_ULONG];
96static char strnum2[FMT_ULONG];
97
98static stralloc tmp;
99static stralloc fqdn;
100static stralloc addresses;
101static stralloc certname;
102stralloc envplus = {0};
103stralloc envtmp = {0};
104
105char bspace[16];
106buffer b;
107
108SSL_CTX *ctx;
111const char *keyfile = auto_keyfile;
112stralloc password = {0};
113int match = 0;
114const char *cafile = auto_cafile;
115const char *ccafile = auto_ccafile;
116const char *cadir = auto_cadir;
117const char *ciphers = auto_ciphers;
119const char *dhfile = auto_dhfile;
121char *keypass = 0;
122
123int pi[2];
124int po[2];
125
126X509 *cert;
128
129char **e;
130char **e1;
131
132/* ---------------------------- child */
133
134
135int flagdeny = 0;
136int flagallow = 0;
138const char *fnrules = 0;
139const char *fniprules = 0;
140
141void drop_nomem(void)
142{
143 logmsg(who,111,FATAL,"out of memory");
144}
145void drop_notemp(void)
146{
147 logmsg(who,111,FATAL,"out of timestamps");
148}
149void cats(const char *s)
150{
151 if (!stralloc_cats(&tmp,s)) drop_nomem();
152}
153void append(const char *ch)
154{
155 if (!stralloc_append(&tmp,ch)) drop_nomem();
156}
157void safecats(const char *s)
158{
159 char ch;
160 int i;
161
162 for (i = 0;i < 100;++i) {
163 ch = s[i];
164 if (!ch) return;
165 if (ch < 33) ch = '?';
166 if (ch > 126) ch = '?';
167 if (ch == '%') ch = '?'; /* logger stupidity */
168 append(&ch);
169 }
170 cats("...");
171}
172void env(const char *s,const char *t)
173{
174 if (!s) return;
175 if (!stralloc_copys(&envtmp,s)) drop_nomem();
176 if (t) {
177 if (!stralloc_cats(&envtmp,"=")) drop_nomem();
178 if (!stralloc_cats(&envtmp,t)) drop_nomem();
179 }
180 if (!stralloc_0(&envtmp)) drop_nomem();
181 if (!stralloc_cat(&envplus,&envtmp)) drop_nomem();
182}
183static void env_def() {
184 unsigned int elen;
185 unsigned int i;
186 unsigned int j;
187 unsigned int split;
188 unsigned int t;
189
190 if (!stralloc_cats(&envplus,"")) return;
191
192 elen = 0;
193 for (i = 0; environ[i]; ++i)
194 ++elen;
195 for (i = 0; i < envplus.len; ++i)
196 if (!envplus.s[i])
197 ++elen;
198
199 e = (char **) alloc((elen + 1) * sizeof(char *));
200 if (!e) return;
201
202 elen = 0;
203 for (i = 0; environ[i]; ++i)
204 e[elen++] = environ[i];
205
206 j = 0;
207 for (i = 0; i < envplus.len; ++i)
208 if (!envplus.s[i]) {
209 split = str_chr(envplus.s + j,'=');
210 for (t = 0;t < elen;++t)
211 if (byte_equal(envplus.s + j,split,e[t]))
212 if (e[t][split] == '=') {
213 --elen;
214 e[t] = e[elen];
215 break;
216 }
217 if (envplus.s[j + split])
218 e[elen++] = envplus.s + j;
219 j = i + 1;
220 }
221 e[elen] = 0;
222
223 e1 = environ;
224 environ = e;
225}
226void env_reset(void)
227{
228 if (e) {
229 if (e != environ) {
230 alloc_free((char *)e);
231 logmsg(who,111,FATAL,"environ changed");
232 }
233 }
234
235 environ = e1;
236 envplus.len = 0;
237}
238int error_warn(const char *x)
239{
240 if (!x) return 0;
241 log_who(who,"x");
242 return 0;
243}
244void drop_rules(const char *fnbase)
245{
246 logmsg(who,111,FATAL,B("unable to read: ",fnbase));
247}
248
249void found(char *data,unsigned int datalen)
250{
251 unsigned int next0;
252 unsigned int split;
253
254 flagallow = 1; // used for IP match only
255
256 while ((next0 = byte_chr(data,datalen,0)) < datalen) {
257 switch(data[0]) {
258 case 'D':
259 flagdeny = 1; flagallow = 0;
260 break;
261 case '+':
262 flagallow = 2; // qualified match
263 split = str_chr(data + 1,'=');
264 if (data[1 + split] == '=') {
265 data[1 + split] = 0;
266 env(data + 1,data + 1 + split + 1);
267 }
268 break;
269 }
270 ++next0;
271 data += next0; datalen -= next0;
272 }
273}
274
275int doit(int t)
276{
277 int j;
278 SSL *ssl;
279 uint32 netif;
280
281 if (ip6_isv4mapped(remoteip)) {
282 remoteipstr[ip4_fmt(remoteipstr,remoteip + 12)] = 0;
283 localipstr[ip4_fmt(localipstr,localip + 12)] = 0;
284 } else {
285 remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0;
286 localipstr[ip6_fmt(localipstr,localip)] = 0;
287 }
288
289 if (verbosity >= 2) {
290 strnum[fmt_ulong(strnum,getpid())] = 0;
291 log_who(who,B("pid ",strnum," from ",remoteipstr));
292 }
293
294 if (socket_local(t,localip,&localport,&netif) == -1)
295 logmsg(who,111,FATAL,"unable to get local address");
296
297 remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;
298
299 if (!localhost)
300 if (dns_name(&localhostsa,localip) >= 0)
301 if (localhostsa.len) {
302 if (!stralloc_0(&localhostsa)) drop_nomem();
303 localhost = localhostsa.s;
304 }
305
306/* Early evaluation of IP rules (only) */
307
308 if (fniprules) {
309 int fdrules;
310 fdrules = open_read(fniprules);
311 if (fdrules == -1) {
312 if (errno != ENOENT) drop_rules(fniprules);
314 } else {
315 if (rules(found,fdrules,remoteipstr,0,0) == -1)
317 close(fdrules);
318 }
319 }
320
321 if (flagdeny) goto FINISH;
322 if (flagallow) fnrules = 0;
323
324 if (flagremotehost)
325 if (dns_name(&remotehostsa,remoteip) >= 0)
326 if (remotehostsa.len) {
327 if (flagparanoid) {
328 if (dns_ip6(&tmp,&remotehostsa) >= 0)
329 for (j = 0; j + 16 <= tmp.len; j += 16)
330 if (byte_equal(remoteip,16,tmp.s + j)) {
331 flagparanoid = 0;
332 break;
333 }
334 if (dns_ip4(&tmp,&remotehostsa) >= 0)
335 for (j = 0; j + 4 <= tmp.len; j += 4)
336 if (byte_equal(remoteip,4,tmp.s + j)) {
337 flagparanoid = 0;
338 break;
339 }
340 }
341 if (!flagparanoid) {
342 if (!stralloc_0(&remotehostsa)) drop_nomem();
343 remotehost = remotehostsa.s;
344 }
345 }
346
347 if (flagremoteinfo) {
348 if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1)
349 flagremoteinfo = 0;
350 if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
351 }
352
353 if (fnrules) {
354 int fdrules;
355 flagdeny = 0;
356 fdrules = open_read(fnrules);
357 if (fdrules == -1) {
358 if (errno != ENOENT) drop_rules(fnrules);
360 } else {
361 if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1)
363 close(fdrules);
364 }
365 }
366
367 /* Set environment variables */
368
369 env("PROTO","TLS");
370 env("SSLLOCALIP",localipstr);
371 env("SSLLOCALPORT",localportstr);
372 env("SSLLOCALHOST",localhost);
373 env("SSLREMOTEIP",remoteipstr);
374 env("SSLREMOTEPORT",remoteportstr);
375 env("SSLREMOTEHOST",remotehost);
376 env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
377
378 if (flagtcpenv) {
379 env("TCPLOCALIP",localipstr);
380 env("TCPLOCALPORT",localportstr);
381 env("TCPLOCALHOST",localhost);
382 env("TCPREMOTEIP",remoteipstr);
383 env("TCPREMOTEPORT",remoteportstr);
384 env("TCPREMOTEHOST",remotehost);
385 env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
386 if (!ip6_isv4mapped(localip)) {
387 env("PROTO","TCP6");
388 env("TCP6LOCALIP",localipstr);
389 env("TCP6LOCALHOST",localhost);
390 env("TCP6LOCALPORT",localportstr);
391 env("TCP6REMOTEIP",remoteipstr);
392 env("TCP6REMOTEPORT",remoteportstr);
393 env("TCP6REMOTEHOST",remotehost);
394 if (netif)
395 env("TCP6INTERFACE",socket_getifname(netif));
396 } else
397 env("PROTO","TCP");
398 }
399
400 FINISH:
401
402 if (verbosity >= 2) {
403 strnum[fmt_ulong(strnum,getpid())] = 0;
404 if (!stralloc_copys(&tmp,who)) drop_nomem();
405 if (!stralloc_cats(&tmp,": ")) drop_nomem();
406 safecats(flagdeny ? "deny" : "ok");
407 cats(" "); safecats(strnum);
408 cats(" "); if (localhost) safecats(localhost);
409 cats(":"); safecats(localipstr);
413 cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
415 cats("\n");
416 buffer_putflush(buffer_2,tmp.s,tmp.len);
417 }
418
419 if (flagdeny) {
420 close(t);
421 return(0);
422 }
423
424 if (pipe(pi) == -1) logmsg(who,111,FATAL,"unable to create pipe");
425 if (pipe(po) == -1) logmsg(who,111,FATAL,"unable to create pipe");
426
427 ssl = ssl_new(ctx,t);
428 if (!ssl) logmsg(who,111,FATAL,"unable to create SSL instance");
429 if (ndelay_on(t) == -1)
430 logmsg(who,111,FATAL,"unable to set socket options");
431 if (ssl_timeoutaccept(ssl,ssltimeout) == -1) {
432 strnum[fmt_ulong(strnum,getpid())] = 0;
433 logmsg(who,110,DROP,B("unable to TLS accept for pid:",strnum));
435 }
436
437 if (verbosity >= 2) {
438 strnum[fmt_ulong(strnum,getpid())] = 0;
439 log_who(who,B("tls ",strnum," accept "));
440 }
441
442 if (flagclientcert) {
443 switch(ssl_verify(ssl,remotehost,&certname)) {
444 case -1:
445 logmsg(who,110,ERROR,"no client certificate");
446 case -2:
447 logmsg(who,110,ERROR,"missing credentials (CA) or unable to validate client certificate");
448 case -3:
449 if (!stralloc_0(&certname)) drop_nomem();
450 logmsg(who,110,ERROR,B("client hostname name does not match certificate: ",remotehost," <=> ",certname.s));
451 default:
452 break;
453 }
454 }
455
456 switch(fork()) {
457 case -1:
458 logmsg(who,111,FATAL,"unable to fork ");
459 case 0:
460 close(pi[0]); close(po[1]);
461 sig_uncatch(sig_child);
462 sig_unblock(sig_child);
463 if (ssl_io(ssl,pi[1],po[0],progtimeout) == -1) {
464 strnum[fmt_ulong(strnum,getpid())] = 0;
465 logmsg(who,-99,WARN,B("unable to speak TLS for pid: ",strnum));
467 _exit(111);
468 }
469 _exit(0);
470 }
471 close(pi[1]); close(po[0]);
472
474 env_def();
475
476 if (fd_move(0,pi[0]) == -1)
477 logmsg(who,111,FATAL,"unable to set up descriptor 0");
478 if (fd_move(1,po[1]) == -1)
479 logmsg(who,111,FATAL,"unable to set up descriptor 1");
480
481 if (flagkillopts) {
482 socket_ipoptionskill(t);
483 }
484 if (!flagdelay)
485 socket_tcpnodelay(t);
486
487 if (*banner) {
488 buffer_init(&b,buffer_unixwrite,1,bspace,sizeof(bspace));
489 if (buffer_putsflush(&b,banner) == -1)
490 logmsg(who,111,FATAL,"unable to print banner");
491 }
492
493 ssl_free(ssl);
494 return 1;
495}
496
497void done(void)
498{
499 if (verbosity >= 2) {
500 strnum[fmt_ulong(strnum,getpid())] = 0;
501 if (!stralloc_copys(&tmp,who)) drop_nomem();
502 if (!stralloc_cats(&tmp,": ")) drop_nomem();
503 cats("done "); safecats(strnum); cats("\n");
504 buffer_putflush(buffer_2,tmp.s,tmp.len);
505 }
506}
507
508
509/* ---------------------------- parent */
510
511void usage(void)
512{
513 logmsg(who,100,USAGE,B(who,"\
514[ -1346UXpPhHrRoOdDqQviIeEsS ] \
515[ -c limit ] \
516[ -x rules.cdb ] \
517[ -B banner ] \
518[ -g gid ] \
519[ -u uid ] \
520[ -b backlog ] \
521[ -l localname ] \
522[ -t timeout ] \
523[ -T ssltimeout ] \
524[ -w progtimeout ] \
525[ -f lockfile ] \
526[ -I interface ] \
527host port program"));
528}
529
530unsigned long limit = 40;
531unsigned long numchildren = 0;
532
533int flag1 = 0;
534int flag3 = 0;
535unsigned long backlog = 20;
536unsigned long uid = 0;
537unsigned long gid = 0;
538
539void printstatus(void)
540{
541 if (verbosity < 2) return;
542 strnum[fmt_ulong(strnum,numchildren)] = 0;
543 strnum2[fmt_ulong(strnum2,limit)] = 0;
544 log_who(who,B("status: ",strnum,"/",strnum2));
545}
546
547void trigger(void)
548{
549 buffer_unixwrite(selfpipe[1],"",1);
550}
551
552void sigterm(int dummy)
553{
554 int pid;
555
556 flagexit = 1;
557 pid = getpid();
558 if (pid < 0) logmsg(who,111,FATAL,"cannot get pid");
559 kill(-pid,SIGTERM);
560 trigger();
561}
562
563void sigchld(int dummy)
564{
565 int wstat;
566 int pid;
567
568 while ((pid = wait_nohang(&wstat)) > 0) {
569 if (verbosity >= 2) {
570 strnum[fmt_ulong(strnum,pid)] = 0;
571 strnum2[fmt_ulong(strnum2,wstat)] = 0;
572 log_who(who,B("end ",strnum," status ",strnum2));
573 }
575 if (flagexit && !numchildren) _exit(0);
576 }
577 trigger();
578}
579
580void read_passwd(void)
581{
582 if (!password.len) {
583 buffer_init(&b,buffer_unixread,3,bspace,sizeof(bspace));
584 if (getln(&b,&password,&match,'\0') == -1)
585 logmsg(who,111,ERROR,"unable to read password");
586 close(3);
587 if (match) --password.len;
588 }
589}
590
591int passwd_cb(char *buff,int size,int rwflag,void *userdata)
592{
593 if (size < password.len)
594 logmsg(who,111,ERROR,"password too long");
595
596 byte_copy(buff,password.len,password.s);
597 return password.len;
598}
599
600void spawn(int s,int argc,char * const *argv)
601{
602 int t;
603
604 while (numchildren >= limit) sig_pause();
605 while (numchildren < limit) {
607
608 switch(fork()) {
609 case 0:
610 sig_uncatch(sig_child);
611 sig_unblock(sig_child);
612 sig_uncatch(sig_term);
613 sig_uncatch(sig_pipe);
614 for (;;) {
615 if (lockfile) {
616 if (lock_ex(fdlock) == -1)
617 logmsg(who,111,FATAL,B("unable to lock: ",(char *)lockfile));
618 if (flagdualstack)
619 t = socket_accept6(s,remoteip,&remoteport,&netif);
620 else
621 t = socket_accept4(s,remoteip,&remoteport);
622 lock_un(fdlock);
623 } else {
624 if (flagdualstack)
625 t = socket_accept6(s,remoteip,&remoteport,&netif);
626 else
627 t = socket_accept4(s,remoteip,&remoteport);
628 }
629
630 if (t == -1) continue;
631 if (!doit(t)) continue;
632 server(argc,argv);
633 close(0); close(1);
634 env_reset();
635 done();
636 }
637 break;
638 case -1:
639 logmsg(who,111,FATAL,"unable to fork");
641 }
642 }
643}
644
645int main(int argc,char * const *argv)
646{
647 int opt;
648 struct servent *se;
649 char *x;
650 int j;
651 int s;
652 int ipflag = 0;
653 iopause_fd io[2];
654 char ch;
655 struct taia deadline;
656 struct taia stamp;
657 unsigned long u;
658
659 who = argv[0];
660 while ((opt = getoptb(argc,(char **)argv,"dDvqQhHrRUXx:y:t:T:u:g:l:b:B:c:pPoO1346I:EeSsaAf:w:K:zZ")) != opteof)
661 switch(opt) {
662 case 'b': scan_ulong(optarg,&backlog); break;
663 case 'c': scan_ulong(optarg,&limit); break;
664 case 'X': flagallownorules = 1; break;
665 case 'x': fnrules = optarg; break;
666 case 'y': fniprules = optarg; break;
667 case 'B': banner = optarg; break;
668 case 'd': flagdelay = 1; break;
669 case 'D': flagdelay = 0; break;
670 case 'v': verbosity = 2; break;
671 case 'q': verbosity = 0; break;
672 case 'Q': verbosity = 1; break;
673 case 'P': flagparanoid = 0; break;
674 case 'p': flagparanoid = 1; break;
675 case 'O': flagkillopts = 1; break;
676 case 'o': flagkillopts = 0; break;
677 case 'H': flagremotehost = 0; break;
678 case 'h': flagremotehost = 1; break;
679 case 'R': flagremoteinfo = 0; break;
680 case 'r': flagremoteinfo = 1; break;
681 case 't': scan_ulong(optarg,&timeout); break;
682 case 'T': scan_ulong(optarg,&ssltimeout); break;
683 case 'U': x = env_get("UID"); if (x) scan_ulong(x,&uid);
684 x = env_get("GID"); if (x) scan_ulong(x,&gid); break;
685 case 'u': scan_ulong(optarg,&uid); break;
686 case 'g': scan_ulong(optarg,&gid); break;
687 case 'l': localhost = optarg; break;
688 case 'I': netif = socket_getifidx(optarg); break;
689 case 'K': keypass = optarg; break;
690 case '1': flag1 = 1; break;
691 case '3': flag3 = 1; break;
692 case '4': ipflag = 1; break;
693 case '6': ipflag = 2; break;
694 case 'Z': flagclientcert = 0; break;
695 case 'z': flagclientcert = 1; break;
696 case 'S': flagsslenv = 0; break;
697 case 's': flagsslenv = 1; break;
698 case 'E': flagtcpenv = 0; break;
699 case 'e': flagtcpenv = 1; break;
700 case 'A': flagafter = 0; break;
701 case 'a': flagafter = 1; break;
702 case 'f': lockfile = optarg; break;
703 case 'w': scan_uint(optarg,&progtimeout); break;
704 default: usage();
705 }
706 argc -= optind;
707 argv += optind;
708
709 if (!verbosity) buffer_2->fd = -1;
710
711 hostname = *argv++;
712 if (!hostname || str_equal((char *)hostname,"")) usage();
713 if (str_equal((char *)hostname,"0")) hostname = loopback;
714 else if (str_equal((char *)hostname,":0")) {
715 flagdualstack = 1;
716 hostname = "::";
717 }
718
719 x = *argv++; --argc;
720 if (!x) usage();
721 if (!x[scan_ulong(x,&u)])
722 localport = u;
723 else {
724 se = getservbyname(x,"tcp");
725 if (!se)
726 logmsg(who,111,FATAL,B("unable to figure out port number for: ",x));
727 uint16_unpack_big((char*)&se->s_port,&localport);
728 }
729
730 if ((x = env_get("VERIFYDEPTH"))) {
731 scan_ulong(x,&u);
732 verifydepth = u;
733 }
734
735 if ((x = env_get("CAFILE"))) cafile = x;
736 if (cafile && str_equal((char *)cafile,"")) cafile = 0;
737
738 if ((x = env_get("CCAFILE"))) ccafile = x;
739 if (ccafile && str_equal((char *)ccafile,"")) ccafile = 0;
740 if (!flagclientcert) ccafile = 0;
741
742 if ((x = env_get("CADIR"))) cadir = x;
743 if (cadir && str_equal((char *)cadir,"")) cadir= 0;
744
745 if ((x = env_get("CERTCHAINFILE"))) certchainfile = x;
746 if (certchainfile && str_equal((char *)certchainfile,"")) certchainfile = 0;
747
748 if ((x = env_get("CERTFILE"))) certfile = x;
749 if (certfile && str_equal((char *)certfile,"")) certfile = 0;
750
751 if ((x = env_get("KEYFILE"))) keyfile = x;
752 if (keyfile && str_equal((char *)keyfile,"")) keyfile = 0;
753
754 if ((x = env_get("DHFILE"))) dhfile = x;
755 if (dhfile && str_equal((char *)dhfile,"")) dhfile = 0;
756
757 if ((x = env_get("CIPHERS"))) ciphers = x;
758 if (ciphers && str_equal((char *)ciphers,"")) ciphers = 0;
759
760 if (setsid() == -1)
761 if (getpgrp() != getpid())
762 logmsg(who,111,FATAL,"unable to create process group");
763
764 if (lockfile) {
765 fdlock = open_append(lockfile);
766 if (fdlock == -1)
767 logmsg(who,111,FATAL,B("unable to open: ",(char *)lockfile));
768 }
769
770 if (pipe(selfpipe) == -1)
771 logmsg(who,111,FATAL,"unable to create pipe");
772
773 coe(selfpipe[0]);
774 coe(selfpipe[1]);
775 ndelay_on(selfpipe[0]);
776 ndelay_on(selfpipe[1]);
777
778 sig_block(sig_child);
779 sig_catch(sig_child,sigchld);
780 sig_catch(sig_term,sigterm);
781 sig_ignore(sig_pipe);
782
783 /* IP address only */
784
785 if (ip4_scan(hostname,localip)) {
786 if (!stralloc_copyb(&addresses,(char *)V4mappedprefix,12)) drop_nomem();
787 if (!stralloc_catb(&addresses,localip,4)) drop_nomem();
788 byte_copy(localip,16,addresses.s);
789 } else if (ip6_scan(hostname,localip)) {
790 if (!stralloc_copyb(&addresses,localip,16)) drop_nomem();
791 byte_copy(localip,16,addresses.s);
792 }
793
794 /* Asynchronous DNS IPv4/IPv6 Name qualification */
795
796 if (!addresses.len) {
797 if (!stralloc_copys(&tmp,hostname)) drop_nomem();
798 if (dns_ip_qualify(&addresses,&fqdn,&tmp) < 0)
799 logmsg(who,111,FATAL,B("temporarily unable to figure out IP address for: ",(char *)hostname));
800
801 byte_copy(localip,16,addresses.s);
802
803 for (j = 0; j < addresses.len; j += 16) { // Select best matching IP address
804 if (ipflag == 1 && !ip6_isv4mapped(addresses.s + j)) continue;
805 if (ipflag == 2 && !ip6_isv4mapped(addresses.s + j)) continue;
806 byte_copy(localip,16,addresses.s + j);
807 }
808
809 }
810 if (addresses.len < 16)
811 logmsg(who,111,FATAL,B("no IP address for: ",(char *)hostname));
812
813 if (ip6_isv4mapped(localip))
814 s = socket_tcp4();
815 else
816 s = socket_tcp6();
817 if (s == -1)
818 logmsg(who,111,FATAL,"unable to create socket");
819
820 if (flagdualstack)
821 socket_dualstack(s);
822 if (socket_bind_reuse(s,localip,localport,netif) == -1)
823 logmsg(who,111,FATAL,"unable to bind");
824 if (socket_local(s,localip,&localport,&netif) == -1)
825 logmsg(who,111,FATAL,"unable to get local address");
826 if (socket_listen(s,backlog) == -1)
827 logmsg(who,111,FATAL,"unable to listen");
828 ndelay_off(s);
829
830 if (!flagafter) {
831 if (gid) if (prot_gid(gid) == -1)
832 logmsg(who,111,FATAL,"unable to set gid");
833 if (uid) if (prot_uid(uid) == -1)
834 logmsg(who,111,FATAL,"unable to set uid");
835 }
836
837 if (ip6_isv4mapped(localip))
838 localipstr[ip4_fmt(localipstr,localip + 12)] = 0;
839 else
840 localipstr[ip6_fmt(localipstr,localip)] = 0;
841
842 localportstr[fmt_ulong(localportstr,localport)] = 0;
843
844 if (flag1) {
845 buffer_init(&b,buffer_unixwrite,1,bspace,sizeof(bspace));
846 buffer_puts(&b,localipstr);
847 buffer_puts(&b," : ");
848 buffer_puts(&b,localportstr);
849 buffer_puts(&b,"\n");
850 buffer_flush(&b);
851 }
852
853 if (flag3) read_passwd();
854
855 ctx = ssl_server();
856 ssl_errstr();
857 if (!ctx) logmsg(who,111,FATAL,"unable to create TLS context");
858
859 if (certchainfile) {
861 case -1: logmsg(who,111,ERROR,"unable to load certificate chain file");
862 case -2: logmsg(who,111,ERROR,"unable to load key");
863 case -3: logmsg(who,111,ERROR,"key does not match certificate");
864 default: break;
865 }
866 } else {
868 case -1: logmsg(who,111,ERROR,"unable to load certificate");
869 case -2: logmsg(who,111,ERROR,"unable to load key");
870 case -3: logmsg(who,111,ERROR,"key does not match certificate");
871 default: break;
872 }
873 }
874
875 if (flagclientcert) {
877 logmsg(who,111,ERROR,"unable to load CA list");
878 if (!ssl_cca(ctx,ccafile))
879 logmsg(who,111,ERROR,"unable to load client CA list");
880 }
882 logmsg(who,111,ERROR,"unable to set RSA parameters");
884 logmsg(who,111,ERROR,"unable to set DH parameters");
885
886 if (flagafter) {
887 if (gid) if (prot_gid(gid) == -1)
888 logmsg(who,111,FATAL,"unable to set gid");
889 if (uid) if (prot_uid(uid) == -1)
890 logmsg(who,111,FATAL,"unable to set uid");
891 }
892
893 if (!ssl_ciphers(ctx,ciphers))
894 logmsg(who,111,ERROR,"unable to set cipher list");
895
896 if (verbosity >= 2) {
897 strnum[fmt_ulong(strnum,getpid())] = 0;
898 strnum2[fmt_ulong(strnum2,rsalen)] = 0;
899 log_who(who,B("ciphers ",strnum," ",(char *)ciphers));
900 log_who(who,B("cafile ",strnum," ",(char *)cafile));
901 log_who(who,B("ccafile ",strnum," ",(char *)ccafile));
902 log_who(who,B("cadir ",strnum," ",(char *)cadir));
903 log_who(who,B("certchainfile ",strnum," ",(char *)certchainfile));
904 log_who(who,B("cert ",strnum," ",(char *)certfile));
905 log_who(who,B("key ",strnum," ",(char *)keyfile));
906 /* XXX */
907 log_who(who,B("dhparam ",strnum," ",(char *)dhfile," ",strnum2));
908 }
909
910 close(0);
911 close(1);
912 printstatus();
913
914 for (;;) {
915 int pause_ret, read_ret;
916 if (!flagexit) spawn(s,argc,argv);
917
918 sig_unblock(sig_child);
919 io[0].fd = selfpipe[0];
920 io[0].events = IOPAUSE_READ;
921 taia_now(&stamp);
922 taia_uint(&deadline,3600);
923 taia_add(&deadline,&stamp,&deadline);
924 pause_ret = iopause(io,1,&deadline,&stamp);
925 sig_block(sig_child);
926
927 if (flagexit && !numchildren) _exit(0);
928 while ((read_ret = buffer_unixread(selfpipe[0],&ch,1)) == 1)
929 ;
930 if ((pause_ret > 0) && (read_ret == 0)) {
931 flagexit = 1;
932 --numchildren;
933 }
934 if (flagexit && !numchildren) _exit(0);
935 }
936}
const char auto_cadir[]
const char auto_cafile[]
const char auto_ccafile[]
const char auto_certchainfile[]
const char auto_certfile[]
const char auto_ciphers[]
const char auto_dhfile[]
const char auto_keyfile[]
int main()
Definition: chkshsgr.c:7
int coe(int fd)
Definition: coe.c:6
void _exit()
int remoteinfo(stralloc *out, char ipremote[16], uint16 portremote, char iplocal[16], uint16 portlocal, unsigned int timeout, uint32 netif)
Definition: remoteinfo.c:86
int rules(void(*callback)(char *, unsigned int), int fd, char *ip, char *host, char *info)
Definition: rules.c:135
int ssl_ca(SSL_CTX *ctx, const char *certfile, const char *certdir, int d)
Definition: ssl_ca.c:3
int ssl_cca(SSL_CTX *ctx, const char *certfile)
Definition: ssl_cca.c:3
int ssl_certkey(SSL_CTX *ctx, const char *certfile, const char *keyfile, pem_password_cb *passwd_cb)
Definition: ssl_certkey.c:3
int ssl_chainfile(SSL_CTX *ctx, const char *certchainfile, const char *keyfile, pem_password_cb *passwd_cb)
Definition: ssl_chainfile.c:8
int ssl_ciphers(SSL_CTX *ctx, const char *ciphers)
Definition: ssl_ciphers.c:3
int ssl_server_env(SSL *ssl, stralloc *sa)
Definition: ssl_env.c:456
int ssl_error(int(*op)(const char *))
Definition: ssl_error.c:3
int ssl_io(SSL *ssl, int fdleft, int fdright, unsigned int timeout)
Definition: ssl_io.c:20
SSL * ssl_new(SSL_CTX *ctx, int s)
Definition: ssl_new.c:4
int ssl_params_dh(SSL_CTX *ctx, const char *dhfile)
Definition: ssl_params.c:37
int ssl_params_rsa(SSL_CTX *ctx, int len)
Definition: ssl_params.c:8
int ssl_timeoutaccept(SSL *ssl, unsigned int timeout)
Definition: ssl_timeout.c:7
int ssl_verify(SSL *ssl, const char *hostname, stralloc *dnsout)
Definition: ssl_verify.c:10
void drop_nomem(void)
Definition: sslhandle.c:141
void sigchld(int dummy)
Definition: sslhandle.c:563
stralloc password
Definition: sslhandle.c:112
const char * certfile
Definition: sslhandle.c:110
int selfpipe[2]
Definition: sslhandle.c:70
int verbosity
Definition: sslhandle.c:55
const char * dhfile
Definition: sslhandle.c:119
unsigned long ssltimeout
Definition: sslhandle.c:67
const char * ciphers
Definition: sslhandle.c:117
void cats(const char *s)
Definition: sslhandle.c:149
void sigterm(int dummy)
Definition: sslhandle.c:552
int flagallownorules
Definition: sslhandle.c:137
int flagexit
Definition: sslhandle.c:71
X509 * cert
Definition: sslhandle.c:126
char ** e
Definition: sslhandle.c:129
char localipstr[IP6_FMT]
Definition: sslhandle.c:79
int flag3
Definition: sslhandle.c:534
void server(int argcs, char *const *argvs)
const char * fniprules
Definition: sslhandle.c:139
void found(char *data, unsigned int datalen)
Definition: sslhandle.c:249
uint16 localport
Definition: sslhandle.c:76
char remoteportstr[FMT_ULONG]
Definition: sslhandle.c:86
char localportstr[FMT_ULONG]
Definition: sslhandle.c:77
stralloc envplus
Definition: sslhandle.c:102
const char * fnrules
Definition: sslhandle.c:138
int flagclientcert
Definition: sslhandle.c:63
unsigned long uid
Definition: sslhandle.c:536
char localip[16]
Definition: sslhandle.c:78
unsigned long gid
Definition: sslhandle.c:537
const char * cadir
Definition: sslhandle.c:116
int flagremotehost
Definition: sslhandle.c:61
unsigned int progtimeout
Definition: sslhandle.c:68
int flagremoteinfo
Definition: sslhandle.c:60
int flagkillopts
Definition: sslhandle.c:56
unsigned long timeout
Definition: sslhandle.c:66
void printstatus(void)
Definition: sslhandle.c:539
buffer b
Definition: sslhandle.c:106
char remoteipstr[IP6_FMT]
Definition: sslhandle.c:88
const char * cafile
Definition: sslhandle.c:114
const char * banner
Definition: sslhandle.c:59
const char * certchainfile
Definition: sslhandle.c:109
int doit(int t)
Definition: sslhandle.c:275
int flagafter
Definition: sslhandle.c:57
void env_reset(void)
Definition: sslhandle.c:226
void env(const char *s, const char *t)
Definition: sslhandle.c:172
unsigned long numchildren
Definition: sslhandle.c:531
char buf[SSL_NAME_LEN]
Definition: sslhandle.c:127
const char * keyfile
Definition: sslhandle.c:111
unsigned long backlog
Definition: sslhandle.c:535
void drop_rules(const char *fnbase)
Definition: sslhandle.c:244
int rsalen
Definition: sslhandle.c:120
int flagdeny
Definition: sslhandle.c:135
uint16 remoteport
Definition: sslhandle.c:85
void done(void)
Definition: sslhandle.c:497
char * who
Definition: sslhandle.c:53
void read_passwd(void)
Definition: sslhandle.c:580
const char * hostname
Definition: sslhandle.c:92
const char * lockfile
Definition: sslhandle.c:82
const char * loopback
Definition: sslhandle.c:93
char remoteip[16]
Definition: sslhandle.c:87
void append(const char *ch)
Definition: sslhandle.c:153
int flagdelay
Definition: sslhandle.c:58
void safecats(const char *s)
Definition: sslhandle.c:157
unsigned long limit
Definition: sslhandle.c:530
uint32 netif
Definition: sslhandle.c:69
char * remotehost
Definition: sslhandle.c:90
int match
Definition: sslhandle.c:113
const char * localhost
Definition: sslhandle.c:81
stralloc envtmp
Definition: sslhandle.c:103
int pi[2]
Definition: sslhandle.c:123
SSL_CTX * ctx
Definition: sslhandle.c:108
int flagtcpenv
Definition: sslhandle.c:65
int passwd_cb(char *buff, int size, int rwflag, void *userdata)
Definition: sslhandle.c:591
void drop_notemp(void)
Definition: sslhandle.c:145
char bspace[16]
Definition: sslhandle.c:105
void spawn(int s, int argc, char *const *argv)
Definition: sslhandle.c:600
int flagallow
Definition: sslhandle.c:136
void usage(void)
Definition: sslhandle.c:511
const char * ccafile
Definition: sslhandle.c:115
int flagdualstack
Definition: sslhandle.c:72
int verifydepth
Definition: sslhandle.c:118
int flagparanoid
Definition: sslhandle.c:62
int fdlock
Definition: sslhandle.c:83
int flagsslenv
Definition: sslhandle.c:64
char * keypass
Definition: sslhandle.c:121
int error_warn(const char *x)
Definition: sslhandle.c:238
char ** e1
Definition: sslhandle.c:130
void trigger(void)
Definition: sslhandle.c:547
int po[2]
Definition: sslhandle.c:124
int flag1
Definition: sslhandle.c:533
Header file to be used with sqmail; previously called ssl.h. (name clash)
#define SSL_NAME_LEN
Definition: ucspissl.h:36
#define SSL_RSA_LEN
Definition: ucspissl.h:37
#define ssl_errstr()
Definition: ucspissl.h:61
#define ssl_free(ssl)
Definition: ucspissl.h:62
#define ssl_server()
Definition: ucspissl.h:40