void doit() { char ch; int match = 1; long linenum = 0; stralloc fifoline = { 0 }; linenum = 0; /* try duming data in 23 seconds */ alarm(dumpfreq); buffer_putsflush(buffer_2, ARGV0 "entering main loop\n"); /* forever read from pipe line by line and handle it */ while(1) { while(match) { if(flagdumpasap == 1) dumpcheck(flagdumpasap, flagchanged, flagchildrunning, flagsighup); ++linenum; if(buffer_get(&wr, &ch, 1) == 1) { if(getln(&wr, &fifoline, &match, '\n') == -1) continue; buffer_put(buffer_2, &ch, 1); buffer_putflush(buffer_2, fifoline.s, fifoline.len); handle_line(&fifoline, ch); } } } }
int main (int argc, char const *const *argv) { s6_svstatus_t status ; char fmt[UINT_FMT] ; int isup, normallyup ; PROG = "s6-svstat" ; if (argc < 2) strerr_dieusage(100, USAGE) ; argv++ ; argc-- ; if (!s6_svstatus_read(*argv, &status)) strerr_diefu2sys(111, "read status for ", *argv) ; { struct stat st ; unsigned int dirlen = str_len(*argv) ; char fn[dirlen + 6] ; byte_copy(fn, dirlen, *argv) ; byte_copy(fn + dirlen, 6, "/down") ; if (stat(fn, &st) == -1) if (errno != ENOENT) strerr_diefu2sys(111, "stat ", fn) ; else normallyup = 1 ; else normallyup = 0 ; } taia_now_g() ; if (taia_future(&status.stamp)) taia_copynow(&status.stamp) ; taia_sub(&status.stamp, &STAMP, &status.stamp) ; isup = status.pid && !status.flagfinishing ; if (isup) { buffer_putnoflush(buffer_1small,"up (pid ", 8) ; buffer_putnoflush(buffer_1small, fmt, uint_fmt(fmt, status.pid)) ; buffer_putnoflush(buffer_1small, ") ", 2) ; } else buffer_putnoflush(buffer_1small, "down ", 5) ; buffer_putnoflush(buffer_1small, fmt, uint64_fmt(fmt, status.stamp.sec.x)) ; buffer_putnoflush(buffer_1small," seconds", 8) ; if (isup && !normallyup) buffer_putnoflush(buffer_1small, ", normally down", 15) ; if (!isup && normallyup) buffer_putnoflush(buffer_1small, ", normally up", 13) ; if (isup && status.flagpaused) buffer_putnoflush(buffer_1small, ", paused", 8) ; if (!isup && (status.flagwant == 'u')) buffer_putnoflush(buffer_1small, ", want up", 10) ; if (isup && (status.flagwant == 'd')) buffer_putnoflush(buffer_1small, ", want down", 12) ; if (buffer_putflush(buffer_1small, "\n", 1) == -1) strerr_diefu1sys(111, "write to stdout") ; return 0 ; }
int sgetopt_r (int argc, char const *const *argv, char const *opts, subgetopt_t *o) { int c = subgetopt_r(argc, argv, opts, o) ; if (o->err && ((c == '?') || (c == ':'))) { buffer_puts(buffer_2, o->prog ? o->prog : argv[0]) ; buffer_put(buffer_2, ": ", 2) ; buffer_puts(buffer_2, ((c == '?') && argv[o->ind] && (o->ind < argc)) ? "illegal option" : "option requires an argument") ; buffer_putflush(buffer_2, "\n", 1) ; } return c ; }
int main(int argc,const char *const *argv) { int opt; int fd; const char *dir; sig_ignore(sig_pipe); while ((opt = getopt(argc,argv,"?vudopchaitkx")) != opteof) if (opt == 'v'){ puts("version: 0.76d"); exit(0); } else if (opt == '?') strerr_die1x(100,"svc options: u up, d down, o once, x exit, p pause, c continue, h hup, a alarm, i interrupt, t term, k kill"); else if (datalen < sizeof data) if (byte_chr(data,datalen,opt) == datalen) data[datalen++] = opt; argv += optind; fdorigdir = open_read("."); if (fdorigdir == -1) strerr_die2sys(111,FATAL,"unable to open current directory: "); while (dir = *argv++) { if (chdir(dir) == -1) strerr_warn4(WARNING,"unable to chdir to ",dir,": ",&strerr_sys); else { fd = open_write("supervise/control"); if (fd == -1) if (errno == error_nodevice) strerr_warn4(WARNING,"unable to control ",dir,": supervise not running",0); else strerr_warn4(WARNING,"unable to control ",dir,": ",&strerr_sys); else { ndelay_off(fd); buffer_init(&b,buffer_unixwrite,fd,bspace,sizeof bspace); if (buffer_putflush(&b,data,datalen) == -1) strerr_warn4(WARNING,"error writing commands to ",dir,": ",&strerr_sys); close(fd); } } if (fchdir(fdorigdir) == -1) strerr_die2sys(111,FATAL,"unable to set directory: "); } _exit(0); }
void strerr_warn (char const *x1, char const *x2, char const *x3, char const *x4, char const *x5, char const *x6, char const *x7, char const *x8, char const *x9, char const *x10, char const *se) { int e = errno ; if (x1) buffer_putsalign(buffer_2, x1) ; if (x2) buffer_putsalign(buffer_2, x2) ; if (x3) buffer_putsalign(buffer_2, x3) ; if (x4) buffer_putsalign(buffer_2, x4) ; if (x5) buffer_putsalign(buffer_2, x5) ; if (x6) buffer_putsalign(buffer_2, x6) ; if (x7) buffer_putsalign(buffer_2, x7) ; if (x8) buffer_putsalign(buffer_2, x8) ; if (x9) buffer_putsalign(buffer_2, x9) ; if (x10) buffer_putsalign(buffer_2, x10) ; if (se) buffer_putsalign(buffer_2, se) ; buffer_putflush(buffer_2, "\n", 1) ; errno = e ; }
int main(int argc,char **argv) { uint16 u16; if (!*argv) usage(); if (!*++argv) usage(); if (!parsetype(*argv,type)) usage(); if (!*++argv) usage(); if (!dns_domain_fromdot(&q,*argv,str_len(*argv))) oops(); if (*++argv) { if (!ip4_scan(*argv,ip)) usage(); } if (!stralloc_copys(&out,"")) oops(); /* uint16_unpack_big(type,&u16); if (!stralloc_catulong0(&out,u16,0)) oops(); if (!stralloc_cats(&out," ")) oops(); if (!dns_domain_todot_cat(&out,q)) oops(); if (!stralloc_cats(&out,":\n")) oops(); */ if (!response_query(q,type,DNS_C_IN)) oops(); response[3] &= ~128; response[2] &= ~1; response[2] |= 4; case_lowerb(q,dns_domain_length(q)); if (byte_equal(type,2,DNS_T_AXFR)) { response[3] &= ~15; response[3] |= 4; } else if (!respond(q,type,ip)) goto DONE; if (!printpacket_cat(&out,response,response_len)) oops(); DONE: buffer_putflush(buffer_1,out.s,out.len); _exit(0); }
int main(int argc,char **argv) { a = init(argc - 1, ++argv); if (!mess822_begin(&h,a)) nomem(); for (;;) { if (getln(buffer_0,&line,&match,'\n') == -1) strerr_die2sys(111,FATAL,"unable to read input: "); if (!mess822_ok(&line)) break; if (!mess822_line(&h,&line)) nomem(); if (!match) break; } if (!mess822_end(&h)) nomem(); buffer_putflush(buffer_1,addr.s,addr.len); _exit(flag ? 0 : 100); }
int main (int argc, char const *const *argv) { unsigned int verbosity = 1 ; tain_t deadline ; PROG = "s6-rc-dryrun" ; { unsigned int t = 1000 ; subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "v:t:", &l) ; if (opt == -1) break ; switch (opt) { case 'v': if (!uint0_scan(l.arg, &verbosity)) dieusage() ; break ; case 't': if (!uint0_scan(l.arg, &t)) dieusage() ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; tain_from_millisecs(&deadline, t) ; } if (!argc) dieusage() ; if (verbosity) { buffer_puts(buffer_1, PROG) ; buffer_put(buffer_1, ":", 1) ; for (; *argv ; argv++) { buffer_put(buffer_1, " ", 1) ; buffer_puts(buffer_1, *argv) ; } buffer_putflush(buffer_1, "\n", 1) ; } tain_now_g() ; tain_add_g(&deadline, &deadline) ; deepsleepuntil_g(&deadline) ; return 0 ; }
int main(int argc,char **argv) { uint16 u16; dns_random_init(seed); if (!*argv) usage(); if (!*++argv) usage(); if (!parsetype(*argv,type)) usage(); if (!*++argv) usage(); if (!dns_domain_fromdot(&q,*argv,str_len(*argv))) oops(); if (!*++argv) usage(); if (!stralloc_copys(&out,*argv)) oops(); if (dns_ip6_qualify(&ip,&fqdn,&out) == -1) oops(); if (ip.len >= 256) ip.len = 256; byte_zero(servers,256); byte_copy(servers,ip.len,ip.s); if (!stralloc_copys(&out,"")) oops(); uint16_unpack_big(type,&u16); if (!stralloc_catulong0(&out,u16,0)) oops(); if (!stralloc_cats(&out," ")) oops(); if (!dns_domain_todot_cat(&out,q)) oops(); if (!stralloc_cats(&out,":\n")) oops(); if (resolve(q,type,servers) == -1) { if (!stralloc_cats(&out,error_str(errno))) oops(); if (!stralloc_cats(&out,"\n")) oops(); } else { if (!printpacket_cat(&out,tx.packet,tx.packetlen)) oops(); } buffer_putflush(buffer_1,out.s,out.len); _exit(0); }
int main (void) { char buf[TAIN_PACK] ; tain_t now, adj ; localtmn_t l ; char fmt[LOCALTMN_FMT] ; PROG = "s6-clockview" ; if (allread(0, buf, TAIN_PACK) < TAIN_PACK) strerr_diefu1sys(111, "read from stdin") ; tain_unpack(buf, &adj) ; if (!sysclock_get(&now)) strerr_diefu1sys(111, "sysclock_get") ; if (!localtmn_from_sysclock(&l, &now, 1)) strerr_diefu1sys(111, "localtmn_from_sysclock") ; if (buffer_puts(buffer_1, "before: ") < 0) goto fail ; if (buffer_put(buffer_1, fmt, localtmn_fmt(fmt, &l)) < 0) goto fail ; tain_add(&now, &now, &adj) ; if (!localtmn_from_sysclock(&l, &now, 1)) strerr_diefu1sys(111, "localtmn_from_sysclock") ; if (buffer_puts(buffer_1, "\nafter: ") < 0) goto fail ; if (buffer_put(buffer_1, fmt, localtmn_fmt(fmt, &l)) < 0) goto fail ; if (buffer_putflush(buffer_1, "\n", 1) < 0) goto fail ; return 0 ; fail: strerr_diefu1sys(111, "write to stdout") ; }
void doit(int t) { int fakev4=0; int j; SSL *ssl; int wstat; uint32 scope_id; int sslctl[2]; char *s; unsigned long tmp_long; char sslctl_cmd; stralloc ssl_env = { 0 }; buffer ssl_env_buf; if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: "); switch(fork()) { case -1: strerr_die2sys(111,DROP,"unable to fork: "); case 0: /* Child */ break; default: /* Parent */ close(pi[0]); close(po[1]); close(sslctl[1]); if ((s=env_get("SSL_CHROOT"))) if (chroot(s) == -1) strerr_die2x(111,DROPSSL,"unable to chroot"); if ((s=env_get("SSL_GID"))) { scan_ulong(s,&tmp_long); gid = tmp_long; } if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,DROPSSL,"unable to set gid: "); if ((s=env_get("SSL_UID"))) { scan_ulong(s,&tmp_long); uid = tmp_long; } if (uid) if (prot_uid(uid) == -1) strerr_die2sys(111,DROPSSL,"unable to set uid: "); /* This will exit on a fatal error or if the client quits * without activating SSL */ sslctl_cmd = ucspitls_master_wait_for_activation(sslctl[0]); /* If we got here, SSL must have been activated */ ssl = ssl_new(ctx,t); if (!ssl) strerr_die2x(111,DROP,"unable to create SSL instance"); if (ndelay_on(t) == -1) strerr_die2sys(111,DROP,"unable to set socket options: "); if (ssl_timeoutaccept(ssl,ssltimeout) == -1) strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno)); if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn3("sslserver: ssl ",strnum," accept ",0); } if (flagclientcert) { switch(ssl_verify(ssl,verifyhost)) { case -1: strerr_die2x(111,DROP,"unable to verify client certificate"); case -2: strerr_die2x(111,DROP,"no client certificate"); case -3: strerr_die2x(111,DROP,"client name does not match certificate"); default: break; } } if (sslctl_cmd == 'Y') { ssl_server_env(ssl, &ssl_env); stralloc_0(&ssl_env); /* Add another NUL */ buffer_init(&ssl_env_buf,buffer_unixwrite,sslctl[0],NULL,0); if (buffer_putflush(&ssl_env_buf, ssl_env.s, ssl_env.len) == -1) { strerr_die2sys(111, FATAL, "unable to write SSL environment: "); } } else if (sslctl_cmd != 'y') { strerr_die2x(111,DROP,"Protocol error on SSL control descriptor: invalid command character read"); } if (close(sslctl[0]) != 0) { strerr_die2sys(111, DROP, "Error closing SSL control socket: "); } if (ssl_io(ssl,pi[1],po[0],io_opt) != 0) strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno)); if (wait_nohang(&wstat) > 0) _exit(wait_exitcode(wstat)); ssl_close(ssl); _exit(0); } /* Child-only below this point */ if (close(sslctl[0]) != 0) { strerr_die2sys(111, DROP, "Error closing SSL control socket: "); } if (!forcev6 && ip6_isv4mapped(remoteip)) fakev4=1; if (fakev4) remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0; else remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn4("sslserver: pid ",strnum," from ",remoteipstr,0); } if (socket_local6(t,localip,&localport,&scope_id) == -1) strerr_die2sys(111,DROP,"unable to get local address: "); if (fakev4) localipstr[ip4_fmt(localipstr,localip+12)] = 0; else localipstr[ip6_fmt(localipstr,localip)] = 0; remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; if (!localhost) if (dns_name6(&localhostsa,localip) == 0) if (localhostsa.len) { if (!stralloc_0(&localhostsa)) drop_nomem(); localhost = localhostsa.s; } env("PROTO",fakev4?"SSL":"SSL6"); env("SSLLOCALIP",localipstr); env("SSL6LOCALIP",localipstr); env("SSLLOCALPORT",localportstr); env("SSL6LOCALPORT",localportstr); env("SSLLOCALHOST",localhost); env("SSL6LOCALHOST",localhost); if (!fakev4 && scope_id) env("SSL6INTERFACE",socket_getifname(scope_id)); if (flagtcpenv) { env("TCPLOCALIP",localipstr); env("TCP6LOCALIP",localipstr); env("TCPLOCALPORT",localportstr); env("TCP6LOCALPORT",localportstr); env("TCPLOCALHOST",localhost); env("TCP6LOCALHOST",localhost); if (!fakev4 && scope_id) env("TCP6INTERFACE",socket_getifname(scope_id)); } if (flagremotehost) if (dns_name6(&remotehostsa,remoteip) == 0) if (remotehostsa.len) { if (flagparanoid) { verifyhost = remoteipstr; if (dns_ip6(&tmp,&remotehostsa) == 0) for (j = 0;j + 16 <= tmp.len;j += 16) if (byte_equal(remoteip,16,tmp.s + j)) { flagparanoid = 0; break; } } if (!flagparanoid) { if (!stralloc_0(&remotehostsa)) drop_nomem(); remotehost = remotehostsa.s; verifyhost = remotehostsa.s; } } env("SSLREMOTEIP",remoteipstr); env("SSL6REMOTEIP",remoteipstr); remoteipstr[ip6_fmt(remoteipstr,remoteip)]=0; env("SSLREMOTEPORT",remoteportstr); env("SSL6REMOTEPORT",remoteportstr); env("SSLREMOTEHOST",remotehost); env("SSL6REMOTEHOST",remotehost); if (flagtcpenv) { env("TCPREMOTEIP",remoteipstr); env("TCP6REMOTEIP",remoteipstr); env("TCPREMOTEPORT",remoteportstr); env("TCP6REMOTEPORT",remoteportstr); env("TCPREMOTEHOST",remotehost); env("TCP6REMOTEHOST",remotehost); } if (flagremoteinfo) { if (remoteinfo6(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1) flagremoteinfo = 0; if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); } env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); env("SSL6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (flagtcpenv) { env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); env("TCP6REMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); } if (fnrules) { int fdrules; fdrules = open_read(fnrules); if (fdrules == -1) { if (errno != error_noent) drop_rules(); if (!flagallownorules) drop_rules(); } else { int fakev4=0; char* temp; if (!forcev6 && ip6_isv4mapped(remoteip)) fakev4=1; if (fakev4) temp=remoteipstr+7; else temp=remoteipstr; if (rules(found,fdrules,temp,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules(); close(fdrules); } } if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem(); safecats(flagdeny ? "deny" : "ok"); cats(" "); safecats(strnum); cats(" "); if (localhost) safecats(localhost); cats(":"); safecats(localipstr); cats(":"); safecats(localportstr); cats(" "); if (remotehost) safecats(remotehost); cats(":"); safecats(remoteipstr); cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); cats(":"); safecats(remoteportstr); cats("\n"); buffer_putflush(buffer_2,tmp.s,tmp.len); } if (flagdeny) _exit(100); if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,FATAL,"unable to set gid: "); if (uid) if (prot_uid(uid) == -1) strerr_die2sys(111,FATAL,"unable to set uid: "); close(pi[1]); close(po[0]); sig_uncatch(sig_child); sig_unblock(sig_child); sig_uncatch(sig_term); sig_uncatch(sig_pipe); if (fcntl(sslctl[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,sslctl[1])]=0; setenv("SSLCTLFD",strnum,1); if (fcntl(pi[0],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,pi[0])]=0; setenv("SSLREADFD",strnum,1); if (fcntl(po[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,po[1])]=0; setenv("SSLWRITEFD",strnum,1); if (flagsslwait) { if (fd_copy(0,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_copy(1,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } else { if (fd_move(0,pi[0]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_move(1,po[1]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } if (flagkillopts) socket_ipoptionskill(t); if (!flagdelay) socket_tcpnodelay(t); if (*banner) { buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace); if (buffer_putsflush(&b,banner) == -1) strerr_die2sys(111,DROP,"unable to print banner: "); } if (!flagsslwait) { strnum[fmt_ulong(strnum,flagsslenv)] = 0; strerr_warn2("flagsslenv: ", strnum, 0); ucspitls(flagsslenv,0,1); } pathexec(prog); strerr_die4sys(111,DROP,"unable to run ",*prog,": "); }
int buffer_putsflush(buffer *s,const char *buf) { return buffer_putflush(s,buf,str_len(buf)); }
void doit(int t) { int j; SSL *ssl; int wstat; int sslctl[2]; char *s; unsigned long tmp_long; char ssl_cmd; stralloc ssl_env = { 0 }; int bytesleft; char envbuf[8192]; int childpid; if (pipe(pi) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (pipe(po) == -1) strerr_die2sys(111,DROP,"unable to create pipe: "); if (socketpair(AF_UNIX, SOCK_STREAM, 0, sslctl) == -1) strerr_die2sys(111,DROP,"unable to create socketpair: "); if ((j = ip_fmt(&remoteipsa,&remoteaddr))) strerr_die3x(111,DROP,"unable to print remote ip",gai_strerror(j)); if (flagremotehost) { if (dns_name(&remotehostsa,&remoteaddr) == 0) if (remotehostsa.len) { if (flagparanoid) { struct addrinfo *reverse, hints = {0}; verifyhost = remoteipsa.s; hints.ai_family = remoteaddr.sa4.sin_family; if (remoteaddr.sa6.sin6_family == AF_INET6) { hints.ai_flags = AI_V4MAPPED | AI_ALL; } if (getaddrinfo(remotehostsa.s, NULL, &hints, &reverse) == 0) { hints.ai_next = reverse; while (hints.ai_next) { if (hints.ai_next->ai_family == AF_INET && remoteaddr.sa4.sin_family == AF_INET && byte_equal(&remoteaddr.sa4.sin_addr, 4, &((struct sockaddr_in*) hints.ai_next->ai_addr)->sin_addr) || hints.ai_next->ai_family == AF_INET6 && remoteaddr.sa6.sin6_family == AF_INET6 && byte_equal(remoteaddr.sa6.sin6_addr.s6_addr, 16, &((struct sockaddr_in6*) hints.ai_next->ai_addr)->sin6_addr.s6_addr)) { flagparanoid = 0; break; } hints.ai_next = hints.ai_next->ai_next; } freeaddrinfo(reverse); } } if (!flagparanoid) { remotehost = remotehostsa.s; verifyhost = remotehostsa.s; } } } switch(childpid=fork()) { case -1: strerr_die2sys(111,DROP,"unable to fork: "); case 0: /* Child */ close(sslctl[0]); break; default: /* Parent */ close(pi[0]); close(po[1]); close(sslctl[1]); if ((s=env_get("SSL_CHROOT"))) if (chroot(s) == -1) { kill(childpid, SIGTERM); strerr_die2x(111,DROP,"unable to chroot"); } if ((s=env_get("SSL_GID"))) { scan_ulong(s,&tmp_long); gid = tmp_long; } if (gid) if (prot_gid(gid) == -1) { kill(childpid, SIGTERM); strerr_die2sys(111,FATAL,"unable to set gid: "); } if ((s=env_get("SSL_UID"))) { scan_ulong(s,&tmp_long); uid = tmp_long; } if (uid) if (prot_uid(uid) == -1) { kill(childpid, SIGTERM); strerr_die2sys(111,FATAL,"unable to set uid: "); } /* Read the TLS command socket. This will block until/unless * TLS is requested. */ if (read(sslctl[0],&ssl_cmd,1) == 1) { ssl = ssl_new(ctx,t); if (!ssl) { kill(childpid, SIGTERM); strerr_die2x(111,DROP,"unable to create SSL instance"); } if (ndelay_on(t) == -1) { kill(childpid, SIGTERM); strerr_die2sys(111,DROP,"unable to set socket options: "); } if (ssl_timeoutaccept(ssl,ssltimeout) == -1) { kill(childpid, SIGTERM); strerr_die3x(111,DROP,"unable to accept SSL: ",ssl_error_str(ssl_errno)); } } if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn3("sslserver: ssl ",strnum," accept ",0); } if (flagclientcert) { switch(ssl_verify(ssl,verifyhost)) { case -1: kill(childpid, SIGTERM); strerr_die2x(111,DROP,"unable to verify client certificate"); case -2: kill(childpid, SIGTERM); strerr_die2x(111,DROP,"no client certificate"); case -3: kill(childpid, SIGTERM); strerr_die3x(111,DROP,"certificate name does not match client fqdn: ",verifyhost); default: break; } } if (ssl_cmd == 'Y') { ssl_server_env(ssl, &ssl_env); if(!stralloc_0(&ssl_env)) drop_nomem(); /* Add another NUL */ env("SSLCTL",ssl_env.s); for(bytesleft = ssl_env.len; bytesleft>0; bytesleft-=j) if ( (j=write(sslctl[0], ssl_env.s, bytesleft)) < 0) { kill(childpid, SIGTERM); strerr_die2sys(111, FATAL, "unable to write SSL environment: "); } } if (ssl_cmd == 'Y' || ssl_cmd == 'y') { if (ssl_io(ssl,pi[1],po[0],progtimeout) != 0) { kill(childpid, SIGTERM); strerr_die3x(111,DROP,"unable to speak SSL: ",ssl_error_str(ssl_errno)); } if (wait_nohang(&wstat) > 0) _exit(wait_exitcode(wstat)); ssl_close(ssl); } kill(childpid, SIGTERM); _exit(0); } /* Child-only below this point */ if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; strerr_warn4("sslserver: pid ",strnum," from ",remoteipsa.s,0); } if (socket_local(t,&localaddr,&localport) == -1) strerr_die2sys(111,DROP,"unable to get local address: "); if ((j = ip_fmt(&localipsa,&localaddr))) strerr_die3x(111,DROP,"unable to print local address: ",gai_strerror(j)); remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; if (!localhost) if (dns_name(&localhostsa,&localaddr) == 0) if (localhostsa.len) { if (!stralloc_0(&localhostsa)) drop_nomem(); localhost = localhostsa.s; } /* If remoteipsa.s contain ':' colon character will assume it is IPv6 */ if (byte_chr(remoteipsa.s, remoteipsa.len, ':') < remoteipsa.len) env("PROTO","SSL6"); else env("PROTO","SSL"); env("SSLLOCALIP",localipsa.s); env("SSLLOCALPORT",localportstr); env("SSLLOCALHOST",localhost); if (flagtcpenv) { env("TCPLOCALIP",localipsa.s); env("TCPLOCALPORT",localportstr); env("TCPLOCALHOST",localhost); } env("SSLREMOTEIP",remoteipsa.s); env("SSLREMOTEPORT",remoteportstr); env("SSLREMOTEHOST",remotehost); if (flagtcpenv) { env("TCPREMOTEIP",remoteipsa.s); env("TCPREMOTEPORT",remoteportstr); env("TCPREMOTEHOST",remotehost); } if (flagremoteinfo) { if (remoteinfo(&tcpremoteinfo,&remoteaddr,&localaddr,timeout) == -1) flagremoteinfo = 0; if (!stralloc_0(&tcpremoteinfo)) drop_nomem(); } env("SSLREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (flagtcpenv) env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (fnrules) { int fdrules; fdrules = open_read(fnrules); if (fdrules == -1) { if (errno != error_noent) drop_rules(); if (!flagallownorules) drop_rules(); } else { if (rules(found,fdrules,&remoteaddr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules(); close(fdrules); } } if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; if (!stralloc_copys(&tmp,"sslserver: ")) drop_nomem(); safecats(flagdeny ? "deny" : "ok"); cats(" "); safecats(strnum); cats(" "); if (localhost) safecats(localhost); cats(":"); safecats(localipsa.s); cats(":"); safecats(localportstr); cats(" "); if (remotehost) safecats(remotehost); cats(":"); safecats(remoteipsa.s); cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); cats(":"); safecats(remoteportstr); cats("\n"); buffer_putflush(buffer_2,tmp.s,tmp.len); } if (flagdeny) _exit(100); if (gid) if (prot_gid(gid) == -1) strerr_die2sys(111,FATAL,"unable to set gid: "); if (uid) if (prot_uid(uid) == -1) strerr_die2sys(111,FATAL,"unable to set uid: "); close(pi[1]); close(po[0]); close(sslctl[0]); sig_uncatch(sig_child); sig_unblock(sig_child); sig_uncatch(sig_term); sig_uncatch(sig_pipe); if (fcntl(sslctl[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,sslctl[1])]=0; env("SSLCTLFD",strnum); if (fcntl(pi[0],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,pi[0])]=0; env("SSLREADFD",strnum); if (fcntl(po[1],F_SETFD,0) == -1) strerr_die2sys(111,FATAL,"unable to clear close-on-exec flag"); strnum[fmt_ulong(strnum,po[1])]=0; env("SSLWRITEFD",strnum); if (flagsslwait) { if (fd_copy(0,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_copy(1,t) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } else { if (fd_move(0,pi[0]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 0: "); if (fd_move(1,po[1]) == -1) strerr_die2sys(111,DROP,"unable to set up descriptor 1: "); } if (flagkillopts) socket_ipoptionskill(t); if (!flagdelay) socket_tcpnodelay(t); if (*banner) { buffer_init(&b,buffer_unixwrite,1,bspace,sizeof bspace); if (buffer_putsflush(&b,banner) == -1) strerr_die2sys(111,DROP,"unable to print banner: "); } if (!flagsslwait) { ssl_cmd = flagsslenv ? 'Y' : 'y'; if (write(sslctl[1], &ssl_cmd, 1) < 1) strerr_die2sys(111,DROP,"unable to start SSL: "); if (flagsslenv) { while ((j=read(sslctl[1],envbuf,8192)) > 0) { stralloc_catb(&ssl_env,envbuf,j); if (ssl_env.len >= 2 && ssl_env.s[ssl_env.len-2]==0 && ssl_env.s[ssl_env.len-1]==0) break; } if (j < 0) strerr_die2sys(111,DROP,"unable to read SSL environment: "); pathexec_multienv(&ssl_env); } } pathexec(prog); strerr_die4sys(111,DROP,"unable to run ",*prog,": "); }
void doit(int t) { int j; uint32 scope_id; if (ip6_isv4mapped(remoteip)) remoteipstr[ip4_fmt(remoteipstr,remoteip+12)] = 0; else remoteipstr[ip6_fmt(remoteipstr,remoteip)] = 0; if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; log(B("pid ",strnum," from ",remoteipstr,0)); } if (flagkillopts) socket_ipoptionskill(t); if (!flagdelay) socket_tcpnodelay(t); if (*banner) { buffer_init(&b,write,t,bspace,sizeof bspace); if (buffer_putsflush(&b,banner) == -1) errint(EHARD,"unable to print banner: "); } if (socket_local(t,localip,&localport,&scope_id) == -1) errint(EHARD,"unable to get local address: "); if (ip6_isv4mapped(localip)) localipstr[ip4_fmt(localipstr,localip+12)] = 0; else localipstr[ip6_fmt(localipstr,localip)] = 0; remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0; if (!localhost) if (dns_name(&localhostsa,localip) == 0) if (localhostsa.len) { if (!stralloc_0(&localhostsa)) errmem; localhost = localhostsa.s; } env("PROTO","TCP"); env("TCPLOCALIP",localipstr); env("TCPLOCALPORT",localportstr); env("TCPLOCALHOST",localhost); if (flagremotehost) if (dns_name(&remotehostsa,remoteip) == 0) if (remotehostsa.len) { if (flagparanoid) if (dns_ip6(&tmp,&remotehostsa) == 0) for (j = 0;j + 16 <= tmp.len;j += 16) if (byte_equal(remoteip,16,tmp.s + j)) { flagparanoid = 0; break; } if (!flagparanoid) { if (!stralloc_0(&remotehostsa)) errmem; remotehost = remotehostsa.s; } } env("TCPREMOTEIP",remoteipstr); env("TCPREMOTEPORT",remoteportstr); env("TCPREMOTEHOST",remotehost); if (flagremoteinfo) { if (remoteinfo6(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout,netif) == -1) flagremoteinfo = 0; if (!stralloc_0(&tcpremoteinfo)) errmem; } env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0); if (fnrules) { int fdrules; fdrules = open_read(fnrules); if (fdrules == -1) { if (errno != error_noent) drop_rules(); if (!flagallownorules) drop_rules(); } else { char* temp; if (ip6_isv4mapped(remoteip)) temp=remoteipstr+7; else temp=remoteipstr; if (rules(found,fdrules,temp,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules(); close(fdrules); // log(B("checking tcp rules for ",remotehost,": pass")); } } if (verbosity >= 2) { strnum[fmt_ulong(strnum,getpid())] = 0; if (!stralloc_copys(&tmp,"qmail-tcpsrv: ")) errmem; safecats(flagdeny ? "deny" : "ok"); cats(" "); safecats(strnum); cats(" "); if (localhost) safecats(localhost); cats(":"); safecats(localipstr); cats(":"); safecats(localportstr); cats(" "); if (remotehost) safecats(remotehost); cats(":"); safecats(remoteipstr); // cats(":<remote info>"); if (flagremoteinfo) safecats(tcpremoteinfo.s); cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); cats(":"); safecats(remoteportstr); cats("\n"); buffer_putflush(buffer_2,tmp.s,tmp.len); } if (flagdeny) _exit(100); }