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