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