static int run_child(int *cfd, SSL_CTX *ctx, struct sockaddr_storage *addr, int status_wfd, int status_rfd, const char *conffile, int forking) { int ret=-1; int ca_ret=0; SSL *ssl=NULL; BIO *sbio=NULL; struct conf **confs=NULL; struct conf **cconfs=NULL; struct cntr *cntr=NULL; struct async *as=NULL; const char *cname=NULL; struct asfd *asfd=NULL; int is_status_server=0; if(!(confs=confs_alloc()) || !(cconfs=confs_alloc())) goto end; set_peer_env_vars(addr); // Reload global config, in case things have changed. This means that // the server does not need to be restarted for most conf changes. confs_init(confs); confs_init(cconfs); if(conf_load_global_only(conffile, confs)) goto end; // Hack to keep forking turned off if it was specified as off on the // command line. if(!forking) set_int(confs[OPT_FORK], 0); if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE)) || !(ssl=SSL_new(ctx))) { logp("There was a problem joining ssl to the socket\n"); goto end; } SSL_set_bio(ssl, sbio, sbio); /* Do not try to check peer certificate straight away. Clients can send a certificate signing request when they have no certificate. */ SSL_set_verify(ssl, SSL_VERIFY_PEER /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, 0); if(ssl_do_accept(ssl)) goto end; if(!(as=async_alloc()) || as->init(as, 0) || !(asfd=setup_asfd_ssl(as, "main socket", cfd, ssl))) goto end; asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT])); asfd->ratelimit=get_float(confs[OPT_RATELIMIT]); if(authorise_server(as->asfd, confs, cconfs) || !(cname=get_string(cconfs[OPT_CNAME])) || !*cname) { // Add an annoying delay in case they are tempted to // try repeatedly. log_and_send(as->asfd, "unable to authorise on server"); sleep(1); goto end; } if(!get_int(cconfs[OPT_ENABLED])) { log_and_send(as->asfd, "client not enabled on server"); sleep(1); goto end; } // Set up counters. Have to wait until here to get cname. if(!(cntr=cntr_alloc()) || cntr_init(cntr, cname)) goto end; set_cntr(confs[OPT_CNTR], cntr); set_cntr(cconfs[OPT_CNTR], cntr); /* At this point, the client might want to get a new certificate signed. Clients on 1.3.2 or newer can do this. */ if((ca_ret=ca_server_maybe_sign_client_cert(as->asfd, confs, cconfs))<0) { logp("Error signing client certificate request for %s\n", cname); goto end; } else if(ca_ret>0) { // Certificate signed and sent back. // Everything is OK, but we will close this instance // so that the client can start again with a new // connection and its new certificates. logp("Signed and returned client certificate request for %s\n", cname); ret=0; goto end; } /* Now it is time to check the certificate. */ if(ssl_check_cert(ssl, confs, cconfs)) { log_and_send(as->asfd, "check cert failed on server"); goto end; } if(status_rfd>=0) { is_status_server=1; if(!setup_asfd(as, "status server parent socket", &status_rfd)) goto end; } ret=child(as, is_status_server, status_wfd, confs, cconfs); end: *cfd=-1; if(as && asfd_flush_asio(as->asfd)) ret=-1; async_asfd_free_all(&as); // This closes cfd for us. logp("exit child\n"); if(cntr) cntr_free(&cntr); if(confs) { set_cntr(confs[OPT_CNTR], NULL); confs_free(&confs); } if(cconfs) { set_cntr(cconfs[OPT_CNTR], NULL); confs_free(&cconfs); } return ret; }
static int run_child(int *rfd, int *cfd, SSL_CTX *ctx, const char *conffile, int forking) { int ret=-1; int ca_ret=0; SSL *ssl=NULL; BIO *sbio=NULL; struct conf *conf=NULL; struct conf *cconf=NULL; struct cntr *cntr=NULL; struct async *as=NULL; struct asfd *asfd=NULL; if(!(conf=conf_alloc()) || !(cconf=conf_alloc())) goto end; if(forking) close_fd(rfd); // Reload global config, in case things have changed. This means that // the server does not need to be restarted for most conf changes. conf_init(conf); conf_init(cconf); if(conf_load(conffile, conf, 1)) goto end; // Hack to keep forking turned off if it was specified as off on the // command line. if(!forking) conf->forking=0; if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE)) || !(ssl=SSL_new(ctx))) { logp("There was a problem joining ssl to the socket\n"); goto end; } SSL_set_bio(ssl, sbio, sbio); /* Do not try to check peer certificate straight away. Clients can send a certificate signing request when they have no certificate. */ SSL_set_verify(ssl, SSL_VERIFY_PEER /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, 0); if(SSL_accept(ssl)<=0) { char buf[256]=""; ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); logp("SSL_accept: %s\n", buf); goto end; } if(!(as=async_alloc()) || !(asfd=asfd_alloc()) || as->init(as, 0) || asfd->init(asfd, "main socket", as, *cfd, ssl, conf)) goto end; as->asfd_add(as, asfd); if(authorise_server(asfd, conf, cconf) || !cconf->cname || !*(cconf->cname)) { // Add an annoying delay in case they are tempted to // try repeatedly. log_and_send(asfd, "unable to authorise on server"); sleep(1); goto end; } // Set up counters. Have to wait until here to get cname. if(!(cntr=cntr_alloc()) || cntr_init(cntr, cconf->cname)) goto end; conf->cntr=cntr; cconf->cntr=cntr; /* At this point, the client might want to get a new certificate signed. Clients on 1.3.2 or newer can do this. */ if((ca_ret=ca_server_maybe_sign_client_cert(asfd, conf, cconf))<0) { logp("Error signing client certificate request for %s\n", cconf->cname); goto end; } else if(ca_ret>0) { // Certificate signed and sent back. // Everything is OK, but we will close this instance // so that the client can start again with a new // connection and its new certificates. logp("Signed and returned client certificate request for %s\n", cconf->cname); ret=0; goto end; } /* Now it is time to check the certificate. */ if(ssl_check_cert(ssl, cconf)) { log_and_send(asfd, "check cert failed on server"); goto end; } set_non_blocking(*cfd); ret=child(as, conf, cconf); end: *cfd=-1; async_free(&as); asfd_free(&asfd); // This closes cfd for us. logp("exit child\n"); if(cntr) cntr_free(&cntr); if(conf) conf_free(conf); if(cconf) conf_free(cconf); return ret; }