ucspi-ssl 0.13.03
ucspi-ssl
Loading...
Searching...
No Matches
sslserver.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 <signal.h>
11#include <netdb.h>
12#include <fcntl.h>
13#include <arpa/inet.h>
14#include "ucspissl.h"
15#include "uint_t.h"
16#include "str.h"
17#include "byte.h"
18#include "fmt.h"
19#include "scan.h"
20#include "ip.h"
21#include "fd.h"
22#include "exit.h"
23#include "env.h"
24#include "prot.h"
25#include "open.h"
26#include "wait.h"
27#include "stralloc.h"
28#include "genalloc.h"
29#include "alloc.h"
30#include "buffer.h"
31#include "getln.h"
32#include "error.h"
33#include "logmsg.h"
34#include "getoptb.h"
35#include "pathexec.h"
36#include "socket_if.h"
37#include "ndelay.h"
38#include "remoteinfo.h"
39#include "rules.h"
40#include "sig.h"
41#include "iopause.h"
42#include "dnsresolv.h"
43#include "auto_cafile.h"
44#include "auto_cadir.h"
45#include "auto_ccafile.h"
46#include "auto_dhfile.h"
47#include "auto_certfile.h"
48#include "auto_certchainfile.h"
49#include "auto_keyfile.h"
50#include "auto_ciphers.h"
51
52#define WHO "sslserver"
53
54int verbosity = 1;
56int flagdelay = 0;
57const char *banner = "";
62int flagsslenv = 0;
63int flagtcpenv = 1;
65unsigned long timeout = 26;
66unsigned long ssltimeout = 26;
67unsigned int progtimeout = 3600;
68uint32 netif = 0;
69
70static stralloc tcpremoteinfo;
71
72uint16 localport;
73char iplocal[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
74char localportstr[FMT_ULONG];
75char localip[16];
76char localipstr[IP6_FMT];
77static stralloc localhostsa;
78const char *localhost = 0;
79
81char remoteportstr[FMT_ULONG];
82char remoteip[16];
83char remoteipstr[IP6_FMT];
84static stralloc remotehostsa;
85char *remotehost = 0;
86char *verifyhost = 0;
87
88const char *hostname;
89const char *thishost = "0.0.0.0";
90
91unsigned long uid = 0;
92unsigned long gid = 0;
93
94static char strnum[FMT_ULONG];
95static char strnum2[FMT_ULONG];
96static char strnum3[FMT_ULONG];
97
98static stralloc tmp;
99static stralloc fqdn;
100static stralloc addresses;
101
102unsigned long limit = 40;
103unsigned long numchildren = 0;
104unsigned long ipchildren = 0;
105unsigned long maxconip = 0;
106
107char bspace[16];
108buffer bo;
109
110void drop_nomem(void)
111{
112 logmsg(WHO,111,FATAL,"out of memory");
113}
114
115/* ---------------------------- per ip limit */
116
117struct child {
118 char ipaddr[16];
119 uint32 num;
120};
121
122GEN_ALLOC_typedef(child_alloc,struct child,c,len,a)
123GEN_ALLOC_readyplus(child_alloc,struct child,c,len,a,i,n,x,24,child_readyplus)
124GEN_ALLOC_append(child_alloc,struct child,c,len,a,i,n,x,24,child_readyplus,child_append)
125
126child_alloc children = {0};
127
128void ipchild_append(char ip[16],unsigned long n)
129{
130 struct child *ipchild = 0;
131 int i;
132
133 for (i = 0; i <= n; ++i) {
134 ipchild = &children.c[i];
135 if (byte_equal(ipchild->ipaddr,16,ip)) {
136 ++ipchild->num;
137 break;
138 } else {
139 byte_copy(ipchild->ipaddr,16,ip);
140 ++ipchild->num;
141 break;
142 }
143 }
144}
145
146void ipchild_clear(char ip[16])
147{
148 struct child *ipchild = 0;
149 int i;
150
151 for (i = 0; i <= children.len; ++i) {
152 ipchild = &children.c[i];
153 if (byte_equal(ipchild->ipaddr,16,ip)) {
154 if (ipchild->num) --ipchild->num;
155 break;
156 }
157 }
158}
159
160int ipchild_limit(char ip[16],unsigned long n)
161{
162 int i;
163
164 for (i = 0; i <= n; ++i)
165 if (byte_equal(children.c[i].ipaddr,16,ip))
166 return children.c[i].num;
167
168 return 0;
169}
170
171SSL_CTX *ctx;
174const char *keyfile = auto_keyfile;
175stralloc password = {0};
176stralloc certfqdn = {0};
177int match = 0;
178const char *cafile = auto_cafile;
179const char *ccafile = auto_ccafile;
180const char *cadir = auto_cadir;
181const char *ciphers = auto_ciphers;
183const char *dhfile = auto_dhfile;
185char *keypass = 0;
186
187char * const *prog;
188
189int pi[2];
190int po[2];
191int pt[2];
192
193stralloc envsa = {0};
194
195X509 *cert;
197
198/* ---------------------------- child */
199
201int flagdeny = 0;
202int flagallow = 0;
204const char *fnrules = 0;
205const char *fniprules = 0;
206
207void cats(const char *s)
208{
209 if (!stralloc_cats(&tmp,s)) drop_nomem();
210}
211void append(const char *ch)
212{
213 if (!stralloc_append(&tmp,ch)) drop_nomem();
214}
215void safecats(const char *s)
216{
217 char ch;
218 int i;
219
220 for (i = 0;i < 100;++i) {
221 ch = s[i];
222 if (!ch) return;
223 if (ch < 33) ch = '?';
224 if (ch > 126) ch = '?';
225 if (ch == '%') ch = '?'; /* logger stupidity */
226 append(&ch);
227 }
228 cats("...");
229}
230
231void env(const char *s,const char *t)
232{
233 if (!pathexec_env(s,t)) drop_nomem();
234}
235
236void drop_rules(const char *fnbase)
237{
238 logmsg(WHO,110,FATAL,B("unable to read: ",fnbase));
239}
240
241void found(char *data,unsigned int datalen)
242{
243 unsigned int next0;
244 unsigned int split;
245
246 flagallow = 1; // used for IP match only
247
248 while ((next0 = byte_chr(data,datalen,0)) < datalen) {
249 switch (data[0]) {
250 case 'D':
251 flagdeny = 1; flagallow = 0;
252 break;
253 case '+':
254 flagallow = 2; // qualified match
255 split = str_chr(data + 1,'=');
256 if (data[1 + split] == '=') {
257 data[1 + split] = 0;
258 env(data + 1,data + 1 + split + 1);
259 if (!str_diff(data + 1,"MAXCONIP")) {
260 scan_ulong(data + 1 + split + 1,&maxconip);
261 if (limit && maxconip > limit) maxconip = limit;
262 if (ipchildren >= maxconip) flagdeny = 2;
263 }
264 }
265 break;
266 }
267 ++next0;
268 data += next0; datalen -= next0;
269 }
270}
271
272void doit(int t)
273{
274 int j;
275 SSL *ssl = 0;
276 int wstat;
277 int sslctl[2];
278 char *s;
279 unsigned long tmp_long;
280 char ssl_cmd;
281 stralloc ssl_env = {0};
282 int bytesleft;
283 char envbuf[8192];
284 int childpid;
285 uint32 netif = 0;
286 stralloc tlsinfo = {0};
287
288 if (pipe(pi) == -1) logmsg(WHO,111,FATAL,"unable to create pipe");
289 if (pipe(po) == -1) logmsg(WHO,111,FATAL,"unable to create pipe");
290 if (socketpair(AF_UNIX,SOCK_STREAM,0,sslctl) == -1)
291 logmsg(WHO,111,FATAL,"unable to create socketpair");
292
293/* Get remote IP and FQDN to validate X.509 cert */
294
295 if (ip6_isv4mapped(remoteip)) {
296 localipstr[ip4_fmt(localipstr,localip + 12)] = 0;
297 remoteipstr[ip4_fmt(remoteipstr,remoteip + 12)] = 0;
298 } else {
299 remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0;
300 localipstr[ip6_fmt(localipstr,localip)] = 0;
301 }
302
303/* Early evaluation of IP rules (only) */
304
305 if (fniprules) {
306 int fdrules;
307 fdrules = open_read(fniprules);
308 if (fdrules == -1) {
309 if (errno != ENOENT) drop_rules(fniprules);
311 } else {
312 if (rules(found,fdrules,remoteipstr,0,0) == -1)
314 close(fdrules);
315 }
316 }
317
318 if (flagdeny) goto FINISH;
319 if (flagallow) fnrules = 0;
320
321/* Early lookup of remote information (before child invoked) */
322
323 if (flagremotehost)
324 if (dns_name(&remotehostsa,remoteip) >= 0)
325 if (remotehostsa.len) {
326 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 + 12,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 verifyhost = remotehostsa.s;
345 }
346 }
347
348 if (flagremoteinfo) {
349 if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1)
350 flagremoteinfo = 0;
351 if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
352 }
353
354 if (fnrules) {
355 int fdrules;
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 if (flagdeny) goto FINISH;
368
369/* Prepare the child process */
370
371 switch (childpid = fork()) {
372 case -1:
373 logmsg(WHO,111,FATAL,"unable to fork");
374 case 0:
375 /* Child */
376 close(sslctl[0]);
377 break;
378 default:
379 /* Parent */
380
381 close(pi[0]); close(po[1]); close(sslctl[1]);
382
383 if ((s = env_get("SSL_CHROOT")))
384 if (chroot(s) == -1) {
385 kill(childpid,SIGTERM);
386 logmsg(WHO,111,FATAL,"unable to chroot");
387 }
388
389 if ((s = env_get("SSL_GID"))) {
390 scan_ulong(s,&tmp_long);
391 gid = tmp_long;
392 }
393 if (gid) if (prot_gid(gid) == -1) {
394 kill(childpid,SIGTERM);
395 logmsg(WHO,111,FATAL,"unable to set gid");
396 }
397
398 if ((s = env_get("SSL_UID"))) {
399 scan_ulong(s,&tmp_long);
400 uid = tmp_long;
401 }
402 if (uid)
403 if (prot_uid(uid) == -1) {
404 kill(childpid,SIGTERM);
405 logmsg(WHO,111,FATAL,"unable to set uid");
406 }
407
408/* Get remote IP info to report in logmsg */
409
410 if (ip6_isv4mapped(remoteip))
411 remoteipstr[ip4_fmt(remoteipstr,remoteip + 12)] = 0;
412 else
413 remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0;
414
415/* Read the TLS command socket. This will block until/unless TLS is requested. */
416
417 if (read(sslctl[0],&ssl_cmd,1) == 1) {
418 ssl = ssl_new(ctx,t);
419 if (!ssl) {
420 kill(childpid,SIGTERM);
421 logmsg(WHO,111,FATAL,"unable to create TLS instance");
422 }
423 if (ndelay_on(t) == -1) {
424 kill(childpid,SIGTERM);
425 logmsg(WHO,111,FATAL,"unable to set socket options");
426 }
427 if (ssl_timeoutaccept(ssl,ssltimeout) == -1) {
428 strnum[fmt_ulong(strnum,childpid)] = 0;
429 kill(childpid,SIGTERM);
430 logmsg(WHO,111,FATAL,B("unable to accept TLS from: ",remoteipstr," for pid: ",strnum," ",ERR_reason_error_string(ERR_peek_last_error())));
431 }
432 } else if (errno == EAGAIN) {
433 strnum[fmt_ulong(strnum,childpid)] = 0;
434 kill(childpid,SIGTERM);
435 _exit(100);
436 }
437
438/* Check the remote client cert during TLS handshake; if requested */
439
440 if (flagclientcert) {
441 strnum[fmt_ulong(strnum,childpid)] = 0;
442 if (flagclientcert == 2) verifyhost = 0;
443 switch (ssl_verify(ssl,verifyhost,&certfqdn)) {
444 case -1:
445 kill(childpid,SIGTERM);
446 logmsg(WHO,110,ERROR,B("no client certificate from: ",remoteipstr," for pid: ",strnum));
447 case -2:
448 kill(childpid,SIGTERM);
449 logmsg(WHO,110,ERROR,B("missing credentials (CA) or unable to validate client certificate from: ",remoteipstr," for pid: ",strnum));
450 case -3:
451 kill(childpid,SIGTERM);
452 if (!stralloc_0(&certfqdn)) drop_nomem();
453 logmsg(WHO,110,ERROR,B("client hostname does not match certificate for pid: ",strnum," ",verifyhost," <=> ",certfqdn.s));
454 default:
455 if (verbosity >= 2) {
456 strnum[fmt_ulong(strnum,childpid)] = 0;
457 logmsg(WHO,0,INFO,B("valid client cert received from: ",remoteipstr," for pid: ",strnum));
458 }
459 break;
460 }
461 }
462
463/* Request TLS communication pipe from/to the child process (the application called) */
464
465 if (ssl_cmd == 'Y') {
466 ssl_server_env(ssl,&ssl_env);
467 if (!stralloc_0(&ssl_env)) drop_nomem(); /* Add another NUL */
468 env("SSLCTL",ssl_env.s);
469
470 for (bytesleft = ssl_env.len; bytesleft > 0; bytesleft -= j)
471 if ((j = write(sslctl[0],ssl_env.s,bytesleft)) < 0) {
472 kill(childpid,SIGTERM);
473 logmsg(WHO,111,FATAL,"unable to write TLS environment");
474 }
475 }
476
477 if (verbosity >= 2) {
478 strnum[fmt_ulong(strnum,childpid)] = 0;
479 if (verbosity >= 3 && ssl_env.len > 1) {
480 s = ssl_env.s;
481 if ((j = str_chr(s,'=')))
482 if (!stralloc_copys(&tlsinfo,s + j + 1)) drop_nomem();
483 if (!stralloc_cats(&tlsinfo,":")) drop_nomem();
484 s = s + str_len(s) + 1;
485 s = s + str_len(s) + 1;
486 if ((j = str_chr(s,'=')))
487 if (!stralloc_cats(&tlsinfo,s + j + 1)) drop_nomem();
488 if (!stralloc_0(&tlsinfo)) drop_nomem();
489 log_who(WHO,B("tls ",strnum," accept ",tlsinfo.s));
490 } else
491 log_who(WHO,B("tls ",strnum," accept"));
492 }
493
494 if (ssl_cmd == 'Y' || ssl_cmd == 'y') {
495 if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) {
496 strnum[fmt_ulong(strnum,childpid)] = 0;
497 kill(childpid,SIGTERM);
498 logmsg(WHO,111,ERROR,B("unable to speak TLS with: ",remoteipstr," for pid: ",strnum," ",ERR_reason_error_string(ERR_peek_last_error())));
499 }
500 if (wait_nohang(&wstat) > 0)
501 _exit(wait_exitcode(wstat));
502 ssl_close(ssl);
503 }
504 kill(childpid,SIGTERM);
505 _exit(0);
506 }
507
508/* Child-only below this point */
509
510 if (ip6_isv4mapped(remoteip))
511 localipstr[ip4_fmt(localipstr,localip + 12)] = 0;
512 else
513 localipstr[ip6_fmt(localipstr,localip)] = 0;
514 localportstr[fmt_ulong(localportstr,localport)] = 0;
515
516 if (socket_local(t,localip,&localport,&netif) == -1)
517 logmsg(WHO,111,FATAL,B("unable to set local address/port: ",localipstr,"/",localportstr));
518
519 if (verbosity >= 2) {
520 strnum[fmt_ulong(strnum,getpid())] = 0;
521 log_who(WHO,B("pid ",strnum," from ",remoteipstr));
522 }
523
524 if (!localhost)
525 if (dns_name(&localhostsa,localip) >= 0)
526 if (localhostsa.len) {
527 if (!stralloc_0(&localhostsa)) drop_nomem();
528 localhost = localhostsa.s;
529 }
530
531 remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;
532
533/* Setup environment variables */
534
535 env("PROTO","TLS");
536 env("SSLLOCALIP",localipstr);
537 env("SSLLOCALPORT",localportstr);
538 env("SSLLOCALHOST",localhost);
539 env("SSLREMOTEIP",remoteipstr);
540 env("SSLREMOTEPORT",remoteportstr);
541 env("SSLREMOTEHOST",remotehost);
542 env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
543
544 if (flagtcpenv) {
545 env("TCPLOCALIP",localipstr);
546 env("TCPLOCALPORT",localportstr);
547 env("TCPLOCALHOST",localhost);
548 env("TCPREMOTEIP",remoteipstr);
549 env("TCPREMOTEPORT",remoteportstr);
550 env("TCPREMOTEHOST",remotehost);
551 env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
552 if (!ip6_isv4mapped(remoteip)) {
553 env("PROTO","TCP6");
554 env("TCP6LOCALIP",localipstr);
555 env("TCP6LOCALHOST",localhost);
556 env("TCP6LOCALPORT",localportstr);
557 env("TCP6REMOTEIP",remoteipstr);
558 env("TCP6REMOTEPORT",remoteportstr);
559 env("TCP6REMOTEHOST",remotehost);
560 if (netif)
561 env("TCP6INTERFACE",socket_getifname(netif));
562 } else
563 env("PROTO","TCP");
564 }
565
566 FINISH:
567
568 if (verbosity >= 2) {
569 strnum[fmt_ulong(strnum,getpid())] = 0;
570 strnum2[fmt_ulong(strnum2,maxconip)] = 0;
571 if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem();
572 safecats(flagdeny ? "deny" : "ok");
573 cats(" "); safecats(strnum);
574 cats(" "); if (localhost) safecats(localhost);
575 cats(":"); safecats(localipstr);
579 cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
581 if (flagdeny == 2) { cats(" ip connection limit:"); cats(strnum2); cats(" exceeded"); }
582 cats("\n");
583 buffer_putflush(buffer_2,tmp.s,tmp.len);
584 }
585
586 if (flagdeny) _exit(100);
587
588 if (gid) if (prot_gid(gid) == -1)
589 logmsg(WHO,111,FATAL,"unable to set gid");
590 if (uid) if (prot_uid(uid) == -1)
591 logmsg(WHO,111,FATAL,"unable to set uid");
592
593 close(pi[1]); close(po[0]); close(sslctl[0]);
594
595 sig_uncatch(sig_child);
596 sig_unblock(sig_child);
597 sig_uncatch(sig_term);
598 sig_uncatch(sig_pipe);
599
600 if (fcntl(sslctl[1],F_SETFD,0) == -1)
601 logmsg(WHO,111,FATAL,"unable to clear close-on-exec flag");
602 strnum[fmt_ulong(strnum,sslctl[1])] = 0;
603 env("SSLCTLFD",strnum);
604
605 if (fcntl(pi[0],F_SETFD,0) == -1)
606 logmsg(WHO,111,FATAL,"unable to clear close-on-exec flag");
607 strnum[fmt_ulong(strnum,pi[0])] = 0;
608 env("SSLREADFD",strnum);
609
610 if (fcntl(po[1],F_SETFD,0) == -1)
611 logmsg(WHO,111,FATAL,"unable to clear close-on-exec flag");
612 strnum[fmt_ulong(strnum,po[1])] = 0;
613 env("SSLWRITEFD",strnum);
614
615 if (flagsslwait) {
616 if (fd_copy(0,t) == -1)
617 logmsg(WHO,111,FATAL,"unable to set up descriptor 0");
618 if (fd_copy(1,t) == -1)
619 logmsg(WHO,111,FATAL,"unable to set up descriptor 1");
620 } else {
621 if (fd_move(0,pi[0]) == -1)
622 logmsg(WHO,111,FATAL,"unable to set up descriptor 0");
623 if (fd_move(1,po[1]) == -1)
624 logmsg(WHO,111,FATAL,"unable to set up descriptor 1");
625 }
626
627 if (flagkillopts)
628 socket_ipoptionskill(t);
629
630 if (!flagdelay)
631 socket_tcpnodelay(t);
632
633 if (*banner) {
634 buffer_init(&bo,buffer_unixwrite,1,bspace,sizeof(bspace));
635 if (buffer_putsflush(&bo,banner) == -1)
636 logmsg(WHO,111,FATAL,"unable to print banner");
637 }
638
639 if (!flagsslwait) {
640 ssl_cmd = flagsslenv ? 'Y' : 'y';
641 if (write(sslctl[1],&ssl_cmd,1) < 1)
642 logmsg(WHO,111,FATAL,"unable to start TLS");
643 if (flagsslenv) {
644 while ((j = read(sslctl[1],envbuf,8192)) > 0) {
645 stralloc_catb(&ssl_env,envbuf,j);
646 if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len - 2] == 0 && ssl_env.s[ssl_env.len - 1] == 0)
647 break;
648 }
649 if (j < 0)
650 logmsg(WHO,111,FATAL,"unable to read TLS environment");
651 pathexec_multienv(&ssl_env);
652 }
653 }
654
655 pathexec(prog);
656 logmsg(WHO,111,FATAL,B("unable to run: ",*prog));
657}
658
659/* ---------------------------- parent */
660
661void usage(void)
662{
663 logmsg(WHO,100,USAGE,"sslserver \
664[ -1346UXpPhHrRoOdDqQvVIeEsSnNmzZ ] \
665[ -c limit ] \
666[ -y iprules.cdb ] \
667[ -x rules.cdb ] \
668[ -B banner ] \
669[ -g gid ] \
670[ -u uid ] \
671[ -b backlog ] \
672[ -l localname ] \
673[ -t timeout ] \
674[ -I interface ] \
675[ -T ssltimeout ] \
676[ -w progtimeout ] \
677host port program");
678}
679
680int flag1 = 0;
681int flag3 = 0;
682unsigned long backlog = 20;
683
684void printstatus(void)
685{
686 if (verbosity < 2) return;
687 strnum[fmt_ulong(strnum,numchildren)] = 0;
688 strnum2[fmt_ulong(strnum2,limit)] = 0;
689 strnum3[fmt_ulong(strnum3,maxconip)] = 0;
690 log_who(WHO,B("status: ",strnum,"/",strnum2,"/",strnum3));
691}
692
693static void sigterm(int dummy)
694{
695 _exit(0);
696}
697
698static void sigchld(int dummy)
699{
700 int wstat;
701 int pid;
702
703 while ((pid = wait_nohang(&wstat)) > 0) {
704 if (verbosity >= 2) {
705 strnum[fmt_ulong(strnum,pid + 1)] = 0;
706 strnum2[fmt_ulong(strnum2,wstat)] = 0;
707 log_who(WHO,B("ended by ",strnum," status ",strnum2));
708 }
711 printstatus();
712 }
713}
714
715void read_passwd(void)
716{
717 if (!password.len) {
718 buffer_init(&bo,buffer_unixread,3,bspace,sizeof(bspace));
719 if (getln(&bo,&password,&match,'\0') == -1)
720 logmsg(WHO,111,ERROR,"unable to read password from FD3");
721 close(3);
722 if (match) --password.len;
723 }
724}
725
726int passwd_cb(char *buff,int size,int rwflag,void *userdata)
727{
728 if (size < password.len)
729 logmsg(WHO,111,ERROR,"password too long");
730
731 byte_copy(buff,password.len,password.s);
732 return password.len;
733}
734
735int main(int argc,char * const *argv)
736{
737 int opt;
738 struct servent *se;
739 char *x;
740 unsigned long u = 0;
741 int j;
742 int s;
743 int t;
744 int ipflag = 0;
745
746 while ((opt = getoptb(argc,(char **)argv,"1346dDvVqQhHrRUXx:y:t:T:u:g:l:b:B:c:K:pPoOIEeSsw:nNzZm")) != opteof)
747 switch (opt) {
748 case 'b': scan_ulong(optarg,&backlog); break;
749 case 'c': scan_ulong(optarg,&limit); break;
750 case 'X': flagallownorules = 1; break;
751 case 'x': fnrules = optarg; break;
752 case 'y': fniprules = optarg; break;
753 case 'B': banner = optarg; break;
754 case 'd': flagdelay = 1; break;
755 case 'D': flagdelay = 0; break;
756 case 'v': verbosity = 2; break;
757 case 'V': verbosity = 3; break;
758 case 'q': verbosity = 0; break;
759 case 'Q': verbosity = 1; break;
760 case 'P': flagparanoid = 0; break;
761 case 'p': flagparanoid = 1; break;
762 case 'O': flagkillopts = 1; break;
763 case 'o': flagkillopts = 0; break;
764 case 'H': flagremotehost = 0; break;
765 case 'h': flagremotehost = 1; break;
766 case 'R': flagremoteinfo = 0; break;
767 case 'r': flagremoteinfo = 1; break;
768 case 't': scan_ulong(optarg,&timeout); break;
769 case 'T': scan_ulong(optarg,&ssltimeout); break;
770 case 'w': scan_uint(optarg,&progtimeout); break;
771 case 'U': x = env_get("UID"); if (x) scan_ulong(x,&uid);
772 x = env_get("GID"); if (x) scan_ulong(x,&gid); break;
773 case 'u': scan_ulong(optarg,&uid); break;
774 case 'g': scan_ulong(optarg,&gid); break;
775 case 'I': netif = socket_getifidx(optarg); break;
776 case 'l': localhost = optarg; break;
777 case 'K': keypass = optarg; break;
778 case '1': flag1 = 1; break;
779 case '3': flag3 = 1; break;
780 case '4': ipflag = 1; break;
781 case '6': ipflag = 2; break;
782 case 'Z': flagclientcert = 0; break;
783 case 'z': flagclientcert = 1; break;
784 case 'm': flagclientcert = 2; break;
785 case 'S': flagsslenv = 0; break;
786 case 's': flagsslenv = 1; break;
787 case 'E': flagtcpenv = 0; break;
788 case 'e': flagtcpenv = 1; break;
789 case 'n': flagsslwait = 1; break;
790 case 'N': flagsslwait = 0; break;
791 default: usage();
792 }
793 argc -= optind;
794 argv += optind;
795
796 if (!verbosity) buffer_2->fd = -1;
797
798 hostname = *argv++;
799 if (!hostname || (str_equal((char *)hostname,""))) usage();
800 if (str_equal((char *)hostname,"0")) hostname = thishost;
801 else if (str_equal((char *)hostname,":0")) {
802 flagdualstack = 1;
803 hostname = "::";
804 }
805
806 x = *argv++;
807 if (!x) usage();
808 prog = argv;
809 if (!*argv) usage();
810 if (!x[scan_ulong(x,&u)])
811 localport = u;
812 else {
813 se = getservbyname(x,"tcp");
814 if (!se)
815 logmsg(WHO,111,FATAL,B("unable to figure out port number for: ",x));
816 uint16_unpack_big((char *)&se->s_port,&localport);
817 }
818
819 if ((x = env_get("MAXCONIP"))) { scan_ulong(x,&u); maxconip = u; }
820 if (limit && maxconip > limit) maxconip = limit;
821 if (!child_readyplus(&children,limit)) drop_nomem();
822
823 if ((x = env_get("VERIFYDEPTH"))) { scan_ulong(x,&u); verifydepth = u; }
824
825 if ((x = env_get("CAFILE"))) cafile = x;
826 if (cafile && str_equal((char *)cafile,"")) cafile = 0;
827
828 if ((x = env_get("CCAFILE"))) ccafile = x;
829 if (ccafile && str_equal((char *)ccafile,"")) ccafile = 0;
830 if (ccafile && str_equal((char*)ccafile,"-")) flagclientcert = 0;
831 if (!flagclientcert) ccafile = 0;
832
833 if ((x = env_get("CADIR"))) cadir = x;
834 if (cadir && str_equal((char *)cadir,"")) cadir= 0;
835
836 if ((x = env_get("CERTCHAINFILE"))) certchainfile = x;
837 if (certchainfile && str_equal((char *)certchainfile,"")) certchainfile = 0;
838
839 if ((x = env_get("CERTFILE"))) certfile = x;
840 if (certfile && str_equal((char *)certfile,"")) certfile = 0;
841
842 if ((x = env_get("KEYFILE"))) keyfile = x;
843 if (keyfile && str_equal((char *)keyfile,"")) keyfile = 0;
844
845 if ((x = env_get("DHFILE"))) dhfile = x;
846 if (dhfile && str_equal((char *)dhfile,"")) dhfile = 0;
847
848 if ((x = env_get("CIPHERS"))) ciphers = x;
849 if (ciphers && str_equal((char *)ciphers,"")) ciphers = 0;
850
851 sig_block(sig_child);
852 sig_catch(sig_child,sigchld);
853 sig_catch(sig_term,sigterm);
854 sig_ignore(sig_pipe);
855
856 /* IP address only */
857
858 if (ip4_scan(hostname,localip)) {
859 if (!stralloc_copyb(&addresses,(char *)V4mappedprefix,12)) drop_nomem();
860 if (!stralloc_catb(&addresses,localip,4)) drop_nomem();
861 byte_copy(localip,16,addresses.s);
862 } else if (ip6_scan(hostname,localip)) {
863 if (!stralloc_copyb(&addresses,localip,16)) drop_nomem();
864 byte_copy(localip,16,addresses.s);
865 }
866
867 /* Asynchronous DNS IPv4/IPv6 Name qualification */
868
869 if (!addresses.len) {
870 if (!stralloc_copys(&tmp,hostname)) drop_nomem();
871 if (dns_ip_qualify(&addresses,&fqdn,&tmp) < 0)
872 logmsg(WHO,111,FATAL,B("temporarily unable to figure out IP address for: ",(char *)hostname));
873
874 byte_copy(localip,16,addresses.s);
875
876 for (j = 0; j < addresses.len; j += 16) { // Select best matching IP address
877 if (ipflag == 1 && !ip6_isv4mapped(addresses.s + j)) continue;
878 if (ipflag == 2 && !ip6_isv4mapped(addresses.s + j)) continue;
879 byte_copy(localip,16,addresses.s + j);
880 }
881
882 }
883 if (addresses.len < 16)
884 logmsg(WHO,111,FATAL,B("no IP address for: ",(char *)hostname));
885
886 if (ip6_isv4mapped(localip))
887 s = socket_tcp4();
888 else
889 s = socket_tcp6();
890 if (s == -1)
891 logmsg(WHO,111,FATAL,"unable to create socket");
892
893 if (ip6_isv4mapped(localip))
894 localipstr[ip4_fmt(localipstr,localip + 12)] = 0;
895 else
896 localipstr[ip6_fmt(localipstr,localip)] = 0;
897 localportstr[fmt_ulong(localportstr,localport)] = 0;
898
899 if (flagdualstack)
900 socket_dualstack(s);
901 if (socket_bind_reuse(s,localip,localport,netif) == -1)
902 logmsg(WHO,111,FATAL,B("unable to bind to: ",localipstr," port: ",localportstr));
903 if (socket_local(s,localip,&localport,&netif) == -1)
904 logmsg(WHO,111,FATAL,B("unable to set local address/port: ",localipstr,"/",localportstr));
905 if (socket_listen(s,backlog) == -1)
906 logmsg(WHO,111,FATAL,"unable to listen");
907 ndelay_off(s);
908
909 if (flag1) {
910 buffer_init(&bo,write,1,bspace,sizeof(bspace));
911 buffer_puts(&bo,localipstr);
912 buffer_puts(&bo," : ");
913 buffer_puts(&bo,localportstr);
914 buffer_puts(&bo,"\n");
915 buffer_flush(&bo);
916 }
917
918 if (flag3 == 1) read_passwd();
919
920 ctx = ssl_server();
921 ssl_errstr();
922 if (!ctx) logmsg(WHO,111,FATAL,"unable to create TLS context");
923
924 if (certchainfile) {
926 case -1: logmsg(WHO,111,ERROR,B("unable to load certificate chain file: ",certchainfile));
927 case -2: logmsg(WHO,111,ERROR,B("unable to load key: ",keyfile));
928 case -3: logmsg(WHO,111,ERROR,"key does not match certificate");
929 default: break;
930 }
931 } else {
933 case -1: logmsg(WHO,111,ERROR,B("unable to load certificate: ",certfile));
934 case -2: logmsg(WHO,111,ERROR,B("unable to load key: ",keyfile));
935 case -3: logmsg(WHO,111,ERROR,"key does not match certificate");
936 default: break;
937 }
938 }
939
940 if (flagclientcert) {
942 logmsg(WHO,111,ERROR,"unable to load CA list");
943 if (!ssl_cca(ctx,ccafile))
944 logmsg(WHO,111,ERROR,"unable to load client CA list");
945 }
947 logmsg(WHO,111,ERROR,"unable to set RSA parameters");
949 logmsg(WHO,111,ERROR,"unable to set DH parameters");
950 if (!ssl_ciphers(ctx,ciphers))
951 logmsg(WHO,111,ERROR,"unable to set cipher list");
952
953 if (verbosity >= 2) {
954 strnum[fmt_ulong(strnum,getpid())] = 0;
955 strnum2[fmt_ulong(strnum2,rsalen)] = 0;
956 log_who(WHO,B("ciphers ",strnum," ",(char *)ciphers));
957 log_who(WHO,B("cafile ",strnum," ",(char *)cafile));
958 log_who(WHO,B("ccafile ",strnum," ",(char *)ccafile));
959 log_who(WHO,B("cadir ",strnum," ",(char *)cadir));
960 log_who(WHO,B("certchainfile ",strnum," ",(char *)certchainfile));
961 log_who(WHO,B("cert ",strnum," ",(char *)certfile));
962 log_who(WHO,B("key ",strnum," ",(char *)keyfile));
963 log_who(WHO,B("dhparam ",strnum," ",(char *)dhfile," ",strnum2));
964 }
965
966 close(0); open_read("/dev/null");
967 close(1); open_append("/dev/null");
968
969 printstatus();
970
971 for (;;) {
972 while (numchildren >= limit) sig_pause();
973 strnum[fmt_ulong(x,numchildren)] = 0;
974
975 sig_unblock(sig_child);
976 t = socket_accept(s,remoteip,&remoteport,&netif);
977 sig_block(sig_child);
978 if (t == -1) continue;
979
980 if (maxconip) {
982 if (ipchildren >= maxconip) {
983 if (ip6_isv4mapped(remoteip))
984 remoteipstr[ip4_fmt(remoteipstr,remoteip + 12)] = 0;
985 else
986 remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0;
987
988 strnum[fmt_ulong(strnum,maxconip)] = 0;
989 logmsg(WHO,100,WARN,B("ip connection limit of ",strnum," exceeded for: ",remoteipstr));
990 close(t);
991 continue;
992 }
993 ipchild_append(remoteip,numchildren); // needs to happen in parent
994 }
995 ++numchildren;
996 printstatus();
997
998 switch (fork()) {
999 case 0:
1000 close(s);
1001 doit(t);
1002 logmsg(WHO,111,FATAL,B("unable to run: ",*argv));
1003 case -1:
1005 logmsg(WHO,111,FATAL,B("unable to fork: ",strnum));
1006 }
1007 close(t);
1008 }
1009}
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
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_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 sigchld(int dummy)
Definition: sslhandle.c:563
void sigterm(int dummy)
Definition: sslhandle.c:552
void drop_nomem(void)
Definition: sslserver.c:110
unsigned long ipchildren
Definition: sslserver.c:104
void ipchild_append(char ip[16], unsigned long n)
Definition: sslserver.c:128
unsigned long maxconip
Definition: sslserver.c:105
stralloc password
Definition: sslserver.c:175
const char * certfile
Definition: sslserver.c:173
int verbosity
Definition: sslserver.c:54
const char * dhfile
Definition: sslserver.c:183
unsigned long ssltimeout
Definition: sslserver.c:66
const char * ciphers
Definition: sslserver.c:181
void cats(const char *s)
Definition: sslserver.c:207
int flagallownorules
Definition: sslserver.c:203
X509 * cert
Definition: sslserver.c:195
char localipstr[IP6_FMT]
Definition: sslserver.c:76
char * verifyhost
Definition: sslserver.c:86
int flag3
Definition: sslserver.c:681
stralloc envsa
Definition: sslserver.c:193
const char * fniprules
Definition: sslserver.c:205
stralloc certfqdn
Definition: sslserver.c:176
void found(char *data, unsigned int datalen)
Definition: sslserver.c:241
char iplocal[16]
Definition: sslserver.c:73
uint16 localport
Definition: sslserver.c:72
char remoteportstr[FMT_ULONG]
Definition: sslserver.c:81
char localportstr[FMT_ULONG]
Definition: sslserver.c:74
int pt[2]
Definition: sslserver.c:191
const char * fnrules
Definition: sslserver.c:204
int flagclientcert
Definition: sslserver.c:61
unsigned long uid
Definition: sslserver.c:91
char localip[16]
Definition: sslserver.c:75
unsigned long gid
Definition: sslserver.c:92
const char * cadir
Definition: sslserver.c:180
int flagremotehost
Definition: sslserver.c:59
unsigned int progtimeout
Definition: sslserver.c:67
int flagremoteinfo
Definition: sslserver.c:58
int flagkillopts
Definition: sslserver.c:55
unsigned long timeout
Definition: sslserver.c:65
void printstatus(void)
Definition: sslserver.c:684
char remoteipstr[IP6_FMT]
Definition: sslserver.c:83
const char * cafile
Definition: sslserver.c:178
const char * banner
Definition: sslserver.c:57
const char * certchainfile
Definition: sslserver.c:172
void env(const char *s, const char *t)
Definition: sslserver.c:231
unsigned long numchildren
Definition: sslserver.c:103
GEN_ALLOC_typedef(GEN_ALLOC_readyplus(child_alloc, GEN_ALLOC_readyplus(struct child, GEN_ALLOC_readyplus(c, GEN_ALLOC_readyplus(len, GEN_ALLOC_readyplus(a)
Definition: sslserver.c:122
char buf[SSL_NAME_LEN]
Definition: sslserver.c:196
const char * keyfile
Definition: sslserver.c:174
unsigned long backlog
Definition: sslserver.c:682
void drop_rules(const char *fnbase)
Definition: sslserver.c:236
int rsalen
Definition: sslserver.c:184
int flagdeny
Definition: sslserver.c:201
const char * thishost
Definition: sslserver.c:89
uint16 remoteport
Definition: sslserver.c:80
void doit(int t)
Definition: sslserver.c:272
void read_passwd(void)
Definition: sslserver.c:715
const char * hostname
Definition: sslserver.c:88
char remoteip[16]
Definition: sslserver.c:82
void append(const char *ch)
Definition: sslserver.c:211
int flagdelay
Definition: sslserver.c:56
int flagsslwait
Definition: sslserver.c:64
void safecats(const char *s)
Definition: sslserver.c:215
unsigned long limit
Definition: sslserver.c:102
uint32 netif
Definition: sslserver.c:68
void ipchild_clear(char ip[16])
Definition: sslserver.c:146
char * remotehost
Definition: sslserver.c:85
int match
Definition: sslserver.c:177
const char * localhost
Definition: sslserver.c:78
int pi[2]
Definition: sslserver.c:189
char *const * prog
Definition: sslserver.c:187
buffer bo
Definition: sslserver.c:108
SSL_CTX * ctx
Definition: sslserver.c:171
int flagtcpenv
Definition: sslserver.c:63
int passwd_cb(char *buff, int size, int rwflag, void *userdata)
Definition: sslserver.c:726
#define WHO
Definition: sslserver.c:52
int ipchild_limit(char ip[16], unsigned long n)
Definition: sslserver.c:160
char bspace[16]
Definition: sslserver.c:107
int flagallow
Definition: sslserver.c:202
void usage(void)
Definition: sslserver.c:661
const char * ccafile
Definition: sslserver.c:179
int flagdualstack
Definition: sslserver.c:200
int verifydepth
Definition: sslserver.c:182
int flagparanoid
Definition: sslserver.c:60
int flagsslenv
Definition: sslserver.c:62
char * keypass
Definition: sslserver.c:185
int po[2]
Definition: sslserver.c:190
int flag1
Definition: sslserver.c:680
char ipaddr[16]
Definition: sslserver.c:118
uint32 num
Definition: sslserver.c:119
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_close(ssl)
Definition: ucspissl.h:63
#define ssl_server()
Definition: ucspissl.h:40