52#define WHO "sslserver"
70static stralloc tcpremoteinfo;
73char iplocal[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
77static stralloc localhostsa;
84static stralloc remotehostsa;
94static char strnum[FMT_ULONG];
95static char strnum2[FMT_ULONG];
96static char strnum3[FMT_ULONG];
100static stralloc addresses;
112 logmsg(
WHO,111,FATAL,
"out of memory");
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)
126child_alloc children = {0};
130 struct child *ipchild = 0;
133 for (i = 0; i <= n; ++i) {
134 ipchild = &children.c[i];
135 if (byte_equal(ipchild->
ipaddr,16,ip)) {
139 byte_copy(ipchild->
ipaddr,16,ip);
148 struct child *ipchild = 0;
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;
164 for (i = 0; i <= n; ++i)
165 if (byte_equal(children.c[i].ipaddr,16,ip))
166 return children.c[i].
num;
219 for (i = 0;i < 100;++i) {
222 if (ch < 33) ch =
'?';
223 if (ch > 126) ch =
'?';
224 if (ch ==
'%') ch =
'?';
230void env(
const char *s,
const char *t)
237 logmsg(
WHO,110,FATAL,B(
"unable to read: ",fnbase));
240void found(
char *data,
unsigned int datalen)
247 while ((next0 = byte_chr(data,datalen,0)) < datalen) {
254 split = str_chr(data + 1,
'=');
255 if (data[1 + split] ==
'=') {
257 env(data + 1,data + 1 + split + 1);
259 if (!str_diff(data + 1,
"MAXCONIP")) {
260 scan_ulong(data + 1 + split + 1,&
maxconip);
269 data += next0; datalen -= next0;
280 unsigned long tmp_long;
282 stralloc ssl_env = {0};
287 stralloc tlsinfo = {0};
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");
325 if (dns_name(&remotehostsa,
remoteip) >= 0)
326 if (remotehostsa.len) {
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)) {
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)) {
352 if (!stralloc_0(&tcpremoteinfo))
drop_nomem();
372 switch (childpid = fork()) {
374 logmsg(
WHO,111,FATAL,
"unable to fork");
382 close(
pi[0]); close(
po[1]); close(sslctl[1]);
384 if ((s = env_get(
"SSL_CHROOT")))
385 if (chroot(s) == -1) {
386 kill(childpid,SIGTERM);
387 logmsg(
WHO,111,FATAL,
"unable to chroot");
390 if ((s = env_get(
"SSL_GID"))) {
391 scan_ulong(s,&tmp_long);
394 if (
gid)
if (prot_gid(
gid) == -1) {
395 kill(childpid,SIGTERM);
396 logmsg(
WHO,111,FATAL,
"unable to set gid");
399 if ((s = env_get(
"SSL_UID"))) {
400 scan_ulong(s,&tmp_long);
404 if (prot_uid(
uid) == -1) {
405 kill(childpid,SIGTERM);
406 logmsg(
WHO,111,FATAL,
"unable to set uid");
418 if (read(sslctl[0],&ssl_cmd,1) == 1) {
421 kill(childpid,SIGTERM);
422 logmsg(
WHO,111,FATAL,
"unable to create TLS instance");
424 if (ndelay_on(t) == -1) {
425 kill(childpid,SIGTERM);
426 logmsg(
WHO,111,FATAL,
"unable to set socket options");
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())));
433 }
else if (errno == EAGAIN) {
434 strnum[fmt_ulong(strnum,childpid)] = 0;
435 kill(childpid,SIGTERM);
442 strnum[fmt_ulong(strnum,childpid)] = 0;
446 kill(childpid,SIGTERM);
447 logmsg(
WHO,110,ERROR,B(
"no client certificate from: ",
remoteipstr,
" for pid: ",strnum));
449 kill(childpid,SIGTERM);
450 logmsg(
WHO,110,ERROR,B(
"missing credentials (CA) or unable to validate client certificate from: ",
remoteipstr,
" for pid: ",strnum));
452 kill(childpid,SIGTERM);
454 logmsg(
WHO,110,ERROR,B(
"client hostname does not match certificate for pid: ",strnum,
" ",
verifyhost,
" <=> ",
certfqdn.s));
457 strnum[fmt_ulong(strnum,childpid)] = 0;
458 logmsg(
WHO,0,INFO,B(
"valid client cert received from: ",
remoteipstr,
" for pid: ",strnum));
466 if (ssl_cmd ==
'Y') {
469 env(
"SSLCTL",ssl_env.s);
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");
479 strnum[fmt_ulong(strnum,childpid)] = 0;
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();
490 log_who(
WHO,B(
"tls ",strnum,
" accept ",tlsinfo.s));
492 log_who(
WHO,B(
"tls ",strnum,
" accept"));
495 if (ssl_cmd ==
'Y' || ssl_cmd ==
'y') {
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())));
501 if (wait_nohang(&wstat) > 0)
502 _exit(wait_exitcode(wstat));
505 kill(childpid,SIGTERM);
521 strnum[fmt_ulong(strnum,getpid())] = 0;
526 if (dns_name(&localhostsa,
localip) >= 0)
527 if (localhostsa.len) {
562 env(
"TCP6INTERFACE",socket_getifname(
netif));
570 strnum[fmt_ulong(strnum,getpid())] = 0;
571 strnum2[fmt_ulong(strnum2,
maxconip)] = 0;
572 if (!stralloc_copys(&tmp,
"sslserver: "))
drop_nomem();
584 buffer_putflush(buffer_2,tmp.s,tmp.len);
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");
594 close(
pi[1]); close(
po[0]); close(sslctl[0]);
596 sig_uncatch(sig_child);
597 sig_unblock(sig_child);
598 sig_uncatch(sig_term);
599 sig_uncatch(sig_pipe);
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);
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);
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);
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");
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");
629 socket_ipoptionskill(t);
632 socket_tcpnodelay(t);
636 if (buffer_putsflush(&
bo,
banner) == -1)
637 logmsg(
WHO,111,FATAL,
"unable to print banner");
642 if (write(sslctl[1],&ssl_cmd,1) < 1)
643 logmsg(
WHO,111,FATAL,
"unable to start TLS");
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)
651 logmsg(
WHO,111,FATAL,
"unable to read TLS environment");
652 pathexec_multienv(&ssl_env);
657 logmsg(
WHO,111,FATAL,B(
"unable to run: ",*
prog));
664 logmsg(
WHO,100,USAGE,
"sslserver \
665[ -1346UXpPhHrRoOdDqQvVIeEsSnNmzZ ] \
689 strnum2[fmt_ulong(strnum2,
limit)] = 0;
690 strnum3[fmt_ulong(strnum3,
maxconip)] = 0;
691 log_who(
WHO,B(
"status: ",strnum,
"/",strnum2,
"/",strnum3));
704 while ((pid = wait_nohang(&wstat)) > 0) {
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));
721 logmsg(
WHO,111,ERROR,
"unable to read password from FD3");
727int passwd_cb(
char *buff,
int size,
int rwflag,
void *userdata)
730 logmsg(
WHO,111,ERROR,
"password too long");
736int main(
int argc,
char *
const *argv)
747 while ((opt = getoptb(argc,argv,
"1346dDvVqQhHrRUXx:y:t:T:u:g:l:b:B:c:pPoOIEeSsw:nNzZm")) != opteof)
749 case 'b': scan_ulong(optarg,&
backlog);
break;
752 case 'x':
fnrules = optarg;
break;
754 case 'B':
banner = optarg;
break;
769 case 't': scan_ulong(optarg,&
timeout);
break;
770 case 'T': scan_ulong(optarg,&
ssltimeout);
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;
778 case '1':
flag1 = 1;
break;
779 case '3':
flag3 = 1;
break;
780 case '4': ipflag = 1;
break;
781 case '6': ipflag = 2;
break;
801 else if (str_equal((
char *)
hostname,
":0")) {
810 if (!x[scan_ulong(x,&u)])
813 se = getservbyname(x,
"tcp");
815 logmsg(
WHO,111,FATAL,B(
"unable to figure out port number for: ",x));
816 uint16_unpack_big((
char *)&se->s_port,&
localport);
819 if ((x = env_get(
"MAXCONIP"))) { scan_ulong(x,&u);
maxconip = u; }
822 if ((x = env_get(
"VERIFYDEPTH"))) { scan_ulong(x,&u);
verifydepth = u; }
824 if ((x = env_get(
"CAFILE")))
cafile = x;
827 if ((x = env_get(
"CCAFILE")))
ccafile = x;
832 if ((x = env_get(
"CADIR")))
cadir = x;
838 if ((x = env_get(
"CERTFILE")))
certfile = x;
841 if ((x = env_get(
"KEYFILE")))
keyfile = x;
844 if ((x = env_get(
"DHFILE")))
dhfile = x;
847 if ((x = env_get(
"CIPHERS")))
ciphers = x;
850 sig_block(sig_child);
853 sig_ignore(sig_pipe);
858 if (!stralloc_copyb(&addresses,(
char *)V4mappedprefix,12))
drop_nomem();
860 byte_copy(
localip,16,addresses.s);
863 byte_copy(
localip,16,addresses.s);
868 if (!addresses.len) {
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));
873 byte_copy(
localip,16,addresses.s);
875 for (j = 0; j < addresses.len; j += 16) {
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);
882 if (addresses.len < 16)
883 logmsg(
WHO,111,FATAL,B(
"no IP address for: ",(
char *)
hostname));
890 logmsg(
WHO,111,FATAL,
"unable to create socket");
904 if (socket_listen(s,
backlog) == -1)
905 logmsg(
WHO,111,FATAL,
"unable to listen");
911 buffer_puts(&
bo,
" : ");
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");
928 if (!
ctx) logmsg(
WHO,111,FATAL,
"unable to create TLS context");
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");
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");
948 logmsg(
WHO,111,ERROR,
"unable to load CA list");
950 logmsg(
WHO,111,ERROR,
"unable to load client CA list");
953 logmsg(
WHO,111,ERROR,
"unable to set RSA parameters");
955 logmsg(
WHO,111,ERROR,
"unable to set DH parameters");
957 logmsg(
WHO,111,ERROR,
"unable to set cipher list");
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));
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));
972 close(0); open_read(
"/dev/null");
973 close(1); open_append(
"/dev/null");
981 sig_unblock(sig_child);
983 sig_block(sig_child);
984 if (t == -1)
continue;
994 strnum[fmt_ulong(strnum,
maxconip)] = 0;
995 logmsg(
WHO,100,WARN,B(
"ip connection limit of ",strnum,
" exceeded for: ",
remoteipstr));
1008 logmsg(
WHO,111,FATAL,B(
"unable to run: ",*argv));
1011 logmsg(
WHO,111,FATAL,B(
"unable to fork: ",strnum));
char bspace[BUFFER_SMALL]
const char auto_ccafile[]
const char auto_certchainfile[]
const char auto_certfile[]
const char auto_ciphers[]
const char auto_keyfile[]
int remoteinfo(stralloc *out, char ipremote[16], uint16 portremote, char iplocal[16], uint16 portlocal, unsigned int timeout, uint32 netif)
int rules(void(*callback)(char *, unsigned int), int fd, char *ip, char *host, char *info)
int ssl_ca(SSL_CTX *ctx, const char *certfile, const char *certdir, int d)
int ssl_cca(SSL_CTX *ctx, const char *certfile)
int ssl_certkey(SSL_CTX *ctx, const char *certfile, const char *keyfile, pem_password_cb *passwd_cb)
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)
int ssl_server_env(SSL *ssl, stralloc *sa)
int ssl_io(SSL *ssl, int fdleft, int fdright, unsigned int timeout)
SSL * ssl_new(SSL_CTX *ctx, int s)
int ssl_params_dh(SSL_CTX *ctx, const char *dhfile)
int ssl_params_rsa(SSL_CTX *ctx, int len)
int ssl_timeoutaccept(SSL *ssl, unsigned int timeout)
int ssl_verify(SSL *ssl, const char *hostname, stralloc *dnsout)
int passwd_cb(char *buf, int size, int rwflag, void *userdata)
void found(char *data, unsigned int datalen)
char remoteportstr[FMT_ULONG]
char localportstr[FMT_ULONG]
char remoteipstr[IP6_FMT]
const char * certchainfile
unsigned long numchildren
void ipchild_append(char ip[16], unsigned long n)
void found(char *data, unsigned int datalen)
void env(const char *s, const char *t)
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)
void drop_rules(const char *fnbase)
void append(const char *ch)
void safecats(const char *s)
void ipchild_clear(char ip[16])
int passwd_cb(char *buff, int size, int rwflag, void *userdata)
int ipchild_limit(char ip[16], unsigned long n)
Header file to be used with sqmail; previously called ssl.h. (name clash)