LCOV - code coverage report
Current view: top level - src/server - main.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 0 383 0.0 %
Date: 2017-10-31 Functions: 0 19 0.0 %

          Line data    Source code
       1             : #include "../burp.h"
       2             : #include "../asfd.h"
       3             : #include "../async.h"
       4             : #include "../cntr.h"
       5             : #include "../conf.h"
       6             : #include "../conffile.h"
       7             : #include "../cstat.h"
       8             : #include "../fsops.h"
       9             : #include "../handy.h"
      10             : #include "../iobuf.h"
      11             : #include "../lock.h"
      12             : #include "../log.h"
      13             : #include "auth.h"
      14             : #include "ca.h"
      15             : #include "child.h"
      16             : #include "main.h"
      17             : #include "monitor/status_server.h"
      18             : 
      19             : // FIX THIS: Should be able to configure multiple addresses and ports.
      20             : #define LISTEN_SOCKETS  32
      21             : 
      22             : static int hupreload=0;
      23             : static int hupreload_logged=0;
      24             : static int gentleshutdown=0;
      25             : static int gentleshutdown_logged=0;
      26             : 
      27             : // These will also be used as the exit codes of the program and are therefore
      28             : // unsigned integers.
      29             : // Remember to update the man page if you update these.
      30             : enum serret
      31             : {
      32             :         SERVER_OK=0,
      33             :         SERVER_ERROR=1
      34             : };
      35             : 
      36           0 : static void huphandler(__attribute__ ((unused)) int sig)
      37             : {
      38           0 :         hupreload=1;
      39             :         // Be careful about not logging inside a signal handler.
      40           0 :         hupreload_logged=0;
      41           0 : }
      42             : 
      43           0 : static void usr2handler(__attribute__ ((unused)) int sig)
      44             : {
      45           0 :         gentleshutdown=1;
      46             :         // Be careful about not logging inside a signal handler.
      47           0 :         gentleshutdown_logged=0;
      48           0 : }
      49             : 
      50             : // Remove any exiting child pids from our list.
      51           0 : static void chld_check_for_exiting(struct async *mainas)
      52             : {
      53             :         pid_t p;
      54             :         int status;
      55             :         struct asfd *asfd;
      56             : 
      57           0 :         while((p=waitpid(-1, &status, WNOHANG))>0)
      58             :         {
      59             :                 // Logging a message here appeared to occasionally lock burp up
      60             :                 // on a Ubuntu server that I used to use.
      61           0 :                 for(asfd=mainas->asfd; asfd; asfd=asfd->next)
      62             :                 {
      63           0 :                         if(p!=asfd->pid) continue;
      64           0 :                         mainas->asfd_remove(mainas, asfd);
      65           0 :                         asfd_free(&asfd);
      66           0 :                         break;
      67             :                 }
      68             :         }
      69           0 : }
      70             : 
      71             : static void *get_in_addr(struct sockaddr *sa)
      72             : {
      73             : #ifdef HAVE_IPV6
      74           0 :         if(sa->sa_family==AF_INET6)
      75           0 :                 return &(((struct sockaddr_in6*)sa)->sin6_addr);
      76             : #endif
      77           0 :         return &(((struct sockaddr_in*)sa)->sin_addr);
      78             : }
      79             : 
      80           0 : static void log_listen_socket(const char *desc,
      81             :         struct addrinfo *rp, struct strlist *port)
      82             : {
      83             : #ifdef HAVE_IPV6
      84           0 :         char addr[INET6_ADDRSTRLEN]="";
      85             : #else
      86             :         char addr[INET_ADDRSTRLEN]="";
      87             : #endif
      88           0 :         inet_ntop(rp->ai_family, get_in_addr((struct sockaddr *)rp->ai_addr),
      89             :                 addr, sizeof(addr));
      90           0 :         logp("%s %s:%s (max %d)\n",
      91           0 :                 desc, addr, port->path, (int)port->flag);
      92           0 : }
      93             : 
      94           0 : static int init_listen_socket(const char *address, struct strlist *port,
      95             :         struct async *mainas, enum asfd_fdtype fdtype, const char *desc)
      96             : {
      97             :         int i;
      98           0 :         int fd=-1;
      99             :         int gai_ret;
     100             :         struct addrinfo hints;
     101           0 :         struct addrinfo *rp=NULL;
     102           0 :         struct addrinfo *info=NULL;
     103             : 
     104             :         memset(&hints, 0, sizeof(struct addrinfo));
     105             :         hints.ai_family=AF_UNSPEC;
     106           0 :         hints.ai_socktype=SOCK_STREAM;
     107           0 :         hints.ai_protocol=IPPROTO_TCP;
     108           0 :         hints.ai_flags=AI_NUMERICHOST;
     109           0 :         hints.ai_flags|=AI_PASSIVE;
     110             : 
     111           0 :         if((gai_ret=getaddrinfo(address, port->path, &hints, &info)))
     112             :         {
     113           0 :                 logp("unable to getaddrinfo on port %s: %s\n",
     114             :                         port->path, gai_strerror(gai_ret));
     115           0 :                 return -1;
     116             :         }
     117             : 
     118           0 :         i=0;
     119           0 :         for(rp=info; rp && i<LISTEN_SOCKETS; rp=rp->ai_next)
     120             :         {
     121             :                 struct asfd *newfd;
     122             : 
     123           0 :                 close_fd(&fd);
     124             : 
     125           0 :                 fd=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
     126           0 :                 if(fd<0)
     127             :                 {
     128           0 :                         logp("unable to create socket on port %s: %s\n",
     129           0 :                                 port->path, strerror(errno));
     130           0 :                         continue;
     131             :                 }
     132           0 :                 set_keepalive(fd, 1);
     133             : #ifdef HAVE_IPV6
     134           0 :                 if(rp->ai_family==AF_INET6)
     135             :                 {
     136             :                         // Attempt to say that it should not listen on IPv6
     137             :                         // only.
     138           0 :                         int optval=0;
     139           0 :                         setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY,
     140             :                                 &optval, sizeof(optval));
     141             :                 }
     142             : #endif
     143           0 :                 reuseaddr(fd);
     144           0 :                 if(bind(fd, rp->ai_addr, rp->ai_addrlen))
     145             :                 {
     146           0 :                         logp("unable to bind socket on port %s: %s\n",
     147           0 :                                 port->path, strerror(errno));
     148           0 :                         continue;
     149             :                 }
     150             : 
     151             :                 // Say that we are happy to accept connections.
     152           0 :                 if(listen(fd, 5)<0)
     153             :                 {
     154           0 :                         logp("could not listen on %s: %s\n",
     155           0 :                                 port->path, strerror(errno));
     156           0 :                         continue;
     157             :                 }
     158           0 :                 log_listen_socket(desc, rp, port);
     159           0 :                 if(!(newfd=setup_asfd(mainas, desc, &fd, atoi(port->path))))
     160           0 :                         continue;
     161           0 :                 newfd->fdtype=fdtype;
     162             : 
     163           0 :                 fd=-1;
     164           0 :                 i++;
     165             :         }
     166             : 
     167           0 :         freeaddrinfo(info);
     168             : 
     169           0 :         if(!i)
     170             :         {
     171           0 :                 logp("could not listen on address: %s\n", address);
     172             : #ifdef HAVE_IPV6
     173           0 :                 if(strchr(address, ':'))
     174           0 :                         logp("maybe check whether your OS has IPv6 enabled.\n");
     175             : #endif
     176             :                 return -1;
     177             :         }
     178             : 
     179             :         return 0;
     180             : }
     181             : 
     182           0 : static int init_listen_sockets(const char *address, struct strlist *ports,
     183             :         struct async *mainas, enum asfd_fdtype fdtype, const char *desc)
     184             : {
     185             :         struct strlist *p;
     186           0 :         if(!strcmp(address, "localhost")) {
     187             :                 // If we only support "localhost" here, we can skip
     188             :                 // gethostbyname call due to RFC 6761.
     189             : #ifdef HAVE_IPV6
     190             :                 address="::1";
     191           0 :                 for(p=ports; p; p=p->next)
     192             :                         // Ignore errors for IPv6 attempt.
     193           0 :                         init_listen_socket(address, p, mainas, fdtype, desc);
     194             : #endif
     195             :                 address="127.0.0.1";
     196             :         }
     197           0 :         for(p=ports; p; p=p->next)
     198             :         {
     199           0 :                 if(init_listen_socket(address, p, mainas, fdtype, desc))
     200             :                         return -1;
     201             :         }
     202             :         return 0;
     203             : }
     204             : 
     205           0 : void setup_signals(void)
     206             : {
     207             :         // Ignore SIGPIPE - we are careful with read and write return values.
     208           0 :         signal(SIGPIPE, SIG_IGN);
     209             : 
     210           0 :         setup_signal(SIGHUP, huphandler);
     211           0 :         setup_signal(SIGUSR2, usr2handler);
     212           0 : }
     213             : 
     214           0 : static int run_child(int *cfd, SSL_CTX *ctx, struct sockaddr_storage *addr,
     215             :         int status_wfd, int status_rfd, const char *conffile, int forking)
     216             : {
     217           0 :         int ret=-1;
     218           0 :         int ca_ret=0;
     219           0 :         SSL *ssl=NULL;
     220           0 :         BIO *sbio=NULL;
     221           0 :         struct conf **confs=NULL;
     222           0 :         struct conf **cconfs=NULL;
     223           0 :         struct cntr *cntr=NULL;
     224           0 :         struct async *as=NULL;
     225           0 :         const char *cname=NULL;
     226           0 :         struct asfd *asfd=NULL;
     227           0 :         int is_status_server=0;
     228             : 
     229           0 :         if(!(confs=confs_alloc())
     230           0 :           || !(cconfs=confs_alloc()))
     231             :                 goto end;
     232             : 
     233           0 :         set_peer_env_vars(addr);
     234             : 
     235             :         // Reload global config, in case things have changed. This means that
     236             :         // the server does not need to be restarted for most conf changes.
     237           0 :         confs_init(confs);
     238           0 :         confs_init(cconfs);
     239           0 :         if(conf_load_global_only(conffile, confs)) goto end;
     240             : 
     241             :         // Hack to keep forking turned off if it was specified as off on the
     242             :         // command line.
     243           0 :         if(!forking) set_int(confs[OPT_FORK], 0);
     244             : 
     245           0 :         if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE))
     246           0 :           || !(ssl=SSL_new(ctx)))
     247             :         {
     248           0 :                 logp("There was a problem joining ssl to the socket\n");
     249           0 :                 goto end;
     250             :         }
     251           0 :         SSL_set_bio(ssl, sbio, sbio);
     252             : 
     253             :         /* Do not try to check peer certificate straight away.
     254             :            Clients can send a certificate signing request when they have
     255             :            no certificate. */
     256           0 :         SSL_set_verify(ssl, SSL_VERIFY_PEER
     257             :                 /* | SSL_VERIFY_FAIL_IF_NO_PEER_CERT */, 0);
     258             : 
     259           0 :         if(ssl_do_accept(ssl))
     260             :                 goto end;
     261           0 :         if(!(as=async_alloc())
     262           0 :           || as->init(as, 0)
     263           0 :           || !(asfd=setup_asfd_ssl(as, "main socket", cfd, ssl)))
     264             :                 goto end;
     265           0 :         asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT]));
     266           0 :         asfd->ratelimit=get_float(confs[OPT_RATELIMIT]);
     267             : 
     268           0 :         if(authorise_server(as->asfd, confs, cconfs)
     269           0 :           || !(cname=get_string(cconfs[OPT_CNAME])) || !*cname)
     270             :         {
     271             :                 // Add an annoying delay in case they are tempted to
     272             :                 // try repeatedly.
     273           0 :                 log_and_send(as->asfd, "unable to authorise on server");
     274           0 :                 sleep(1);
     275           0 :                 goto end;
     276             :         }
     277             : 
     278           0 :         if(!get_int(cconfs[OPT_ENABLED]))
     279             :         {
     280           0 :                 log_and_send(as->asfd, "client not enabled on server");
     281           0 :                 sleep(1);
     282           0 :                 goto end;
     283             :         }
     284             : 
     285             :         // Set up counters. Have to wait until here to get cname.
     286           0 :         if(!(cntr=cntr_alloc())
     287           0 :           || cntr_init(cntr, cname, getpid()))
     288             :                 goto end;
     289           0 :         set_cntr(confs[OPT_CNTR], cntr);
     290           0 :         set_cntr(cconfs[OPT_CNTR], cntr);
     291             : 
     292             :         /* At this point, the client might want to get a new certificate
     293             :            signed. Clients on 1.3.2 or newer can do this. */
     294           0 :         if((ca_ret=ca_server_maybe_sign_client_cert(as->asfd, confs, cconfs))<0)
     295             :         {
     296           0 :                 logp("Error signing client certificate request for %s\n",
     297             :                         cname);
     298           0 :                 goto end;
     299             :         }
     300           0 :         else if(ca_ret>0)
     301             :         {
     302             :                 // Certificate signed and sent back.
     303             :                 // Everything is OK, but we will close this instance
     304             :                 // so that the client can start again with a new
     305             :                 // connection and its new certificates.
     306           0 :                 logp("Signed and returned client certificate request for %s\n",
     307             :                         cname);
     308           0 :                 ret=0;
     309           0 :                 goto end;
     310             :         }
     311             : 
     312             :         /* Now it is time to check the certificate. */
     313           0 :         if(ssl_check_cert(ssl, confs, cconfs))
     314             :         {
     315           0 :                 log_and_send(as->asfd, "check cert failed on server");
     316           0 :                 goto end;
     317             :         }
     318           0 :         if(status_rfd>=0)
     319             :         {
     320           0 :                 is_status_server=1;
     321           0 :                 if(!setup_asfd(as, "status server parent socket", &status_rfd,
     322             :                         /*port*/-1))
     323             :                                 goto end;
     324             :         }
     325             : 
     326           0 :         ret=child(as, is_status_server, status_wfd, confs, cconfs);
     327             : end:
     328           0 :         *cfd=-1;
     329           0 :         if(as && asfd_flush_asio(as->asfd))
     330           0 :                 ret=-1;
     331           0 :         async_asfd_free_all(&as); // This closes cfd for us.
     332           0 :         logp("exit child\n");
     333           0 :         if(cntr) cntr_free(&cntr);
     334           0 :         if(confs)
     335             :         {
     336           0 :                 set_cntr(confs[OPT_CNTR], NULL);
     337           0 :                 confs_free(&confs);
     338             :         }
     339           0 :         if(cconfs)
     340             :         {
     341           0 :                 set_cntr(cconfs[OPT_CNTR], NULL);
     342           0 :                 confs_free(&cconfs);
     343             :         }
     344           0 :         return ret;
     345             : }
     346             : 
     347           0 : static struct strlist *find_port_in_conf(struct conf **confs,
     348             :         enum conf_opt port_opt, int port)
     349             : {
     350             :         struct strlist *p;
     351           0 :         for(p=get_strlist(confs[port_opt]); p; p=p->next)
     352           0 :                 if(port==atoi(p->path))
     353             :                         return p;
     354           0 :         logp("Could not find port %d in %s confs\n",
     355           0 :                 port, confs[port_opt]->field);
     356           0 :         return NULL;
     357             : }
     358             : 
     359           0 : static int chld_check_counts(struct conf **confs, struct asfd *asfd)
     360             : {
     361           0 :         long count=0;
     362             :         struct asfd *a;
     363             :         struct strlist *port;
     364             :         enum conf_opt port_opt;
     365             : 
     366           0 :         switch(asfd->fdtype)
     367             :         {
     368             :                 case ASFD_FD_SERVER_LISTEN_MAIN:
     369           0 :                         port_opt=OPT_PORT;
     370           0 :                         if(!(port=find_port_in_conf(confs,
     371             :                                 port_opt, asfd->port)))
     372             :                                         return -1;
     373             :                         break;
     374             :                 case ASFD_FD_SERVER_LISTEN_STATUS:
     375           0 :                         port_opt=OPT_STATUS_PORT;
     376           0 :                         if(!(port=find_port_in_conf(confs,
     377             :                                 port_opt, asfd->port)))
     378             :                                         return -1;
     379             :                         break;
     380             :                 default:
     381           0 :                         logp("Unexpected fdtype in %s: %d.\n",
     382             :                                 __func__, asfd->fdtype);
     383           0 :                         return -1;
     384             :         }
     385             : 
     386           0 :         for(a=asfd->as->asfd; a; a=a->next)
     387           0 :                 if(a!=asfd
     388           0 :                   && asfd->port==a->port)
     389           0 :                         count++;
     390             : 
     391           0 :         logp("%d/%d child processes running on %s %d\n",
     392           0 :                 (int)count, (int)port->flag,
     393           0 :                 confs[port_opt]->field, asfd->port);
     394           0 :         if(count<port->flag)
     395           0 :                 logp("Child %d available\n", (int)count+1);
     396             :         else
     397             :         {
     398           0 :                 logp("No spare children available.\n");
     399           0 :                 return -1;
     400             :         }
     401             : 
     402           0 :         return 0;
     403             : }
     404             : 
     405             : static struct asfd *setup_parent_child_pipe(struct async *as,
     406             :         const char *desc,
     407             :         int *fd_to_use, int *fd_to_close, pid_t childpid, int port,
     408             :         enum asfd_fdtype fdtype)
     409             : {
     410             :         struct asfd *newfd;
     411           0 :         close_fd(fd_to_close);
     412           0 :         if(!(newfd=setup_asfd(as, desc, fd_to_use, port)))
     413             :                 return NULL;
     414           0 :         newfd->pid=childpid;
     415           0 :         newfd->fdtype=fdtype;
     416             :         return newfd;
     417             : }
     418             : 
     419           0 : static int setup_parent_child_pipes(struct asfd *asfd,
     420             :         pid_t childpid, int *rfd, int *wfd)
     421             : {
     422             :         struct asfd *newfd;
     423           0 :         struct async *as=asfd->as;
     424           0 :         switch(asfd->fdtype)
     425             :         {
     426             :                 case ASFD_FD_SERVER_LISTEN_MAIN:
     427           0 :                         logp("forked child on port %d: %d\n",
     428             :                                 asfd->port, childpid);
     429           0 :                         if(!(newfd=setup_parent_child_pipe(as,
     430             :                                 "pipe from child",
     431             :                                 rfd, wfd, childpid, asfd->port,
     432             :                                 ASFD_FD_SERVER_PIPE_READ)))
     433             :                                         return -1;
     434           0 :                         return 0;
     435             :                 case ASFD_FD_SERVER_LISTEN_STATUS:
     436           0 :                         logp("forked status child on port %d: %d\n",
     437             :                                 asfd->port, childpid);
     438           0 :                         if(!(newfd=setup_parent_child_pipe(as,
     439             :                                 "pipe to status child",
     440             :                                 wfd, rfd, childpid, asfd->port,
     441             :                                 ASFD_FD_SERVER_PIPE_WRITE)))
     442             :                                         return -1;
     443           0 :                         newfd->attempt_reads=0;
     444           0 :                         return 0;
     445             :                 default:
     446           0 :                         logp("Strange fdtype after fork: %d\n",
     447             :                                 asfd->fdtype);
     448           0 :                         return -1;
     449             :         }
     450             : 
     451             :         return 0;
     452             : }
     453             : 
     454           0 : static int process_incoming_client(struct asfd *asfd, SSL_CTX *ctx,
     455             :         const char *conffile, struct conf **confs)
     456             : {
     457           0 :         int cfd=-1;
     458             :         pid_t childpid;
     459             :         int pipe_rfd[2];
     460             :         int pipe_wfd[2];
     461           0 :         socklen_t client_length=0;
     462             :         struct sockaddr_storage client_name;
     463           0 :         enum asfd_fdtype fdtype=asfd->fdtype;
     464           0 :         int forking=get_int(confs[OPT_FORK]);
     465             : 
     466           0 :         client_length=sizeof(client_name);
     467           0 :         if((cfd=accept(asfd->fd,
     468             :                 (struct sockaddr *)&client_name, &client_length))==-1)
     469             :         {
     470             :                 // Look out, accept will get interrupted by SIGCHLDs.
     471           0 :                 if(errno==EINTR) return 0;
     472           0 :                 logp("accept failed on %s (%d) in %s: %s\n", asfd->desc,
     473             :                         asfd->fd, __func__, strerror(errno));
     474           0 :                 return -1;
     475             :         }
     476           0 :         reuseaddr(cfd);
     477           0 :         if(log_peer_address(&client_name))
     478             :                 return -1;
     479             : 
     480           0 :         if(!forking)
     481           0 :                 return run_child(&cfd, ctx,
     482             :                         &client_name, -1, -1, conffile, forking);
     483             : 
     484           0 :         if(chld_check_counts(confs, asfd))
     485             :         {
     486           0 :                 logp("Closing new connection.\n");
     487           0 :                 close_fd(&cfd);
     488           0 :                 return 0;
     489             :         }
     490             : 
     491           0 :         if(pipe(pipe_rfd)<0 || pipe(pipe_wfd)<0)
     492             :         {
     493           0 :                 logp("pipe failed: %s", strerror(errno));
     494           0 :                 close_fd(&cfd);
     495           0 :                 return -1;
     496             :         }
     497             : 
     498           0 :         switch((childpid=fork()))
     499             :         {
     500             :                 case -1:
     501           0 :                         logp("fork failed: %s\n", strerror(errno));
     502           0 :                         return -1;
     503             :                 case 0:
     504             :                 {
     505             :                         // Child.
     506             :                         int p;
     507             :                         int ret;
     508             :                         struct sigaction sa;
     509           0 :                         struct async *as=asfd->as;
     510           0 :                         async_asfd_free_all(&as);
     511             : 
     512             :                         // Close unnecessary file descriptors.
     513             :                         // Go up to FD_SETSIZE and hope for the best.
     514             :                         // FIX THIS: Now that async_asfd_free_all() is doing
     515             :                         // everything, double check whether this is needed.
     516           0 :                         for(p=3; p<(int)FD_SETSIZE; p++)
     517             :                         {
     518           0 :                                 if(p!=pipe_rfd[1]
     519           0 :                                   && p!=pipe_wfd[0]
     520           0 :                                   && p!=cfd)
     521           0 :                                         close(p);
     522             :                         }
     523             : 
     524             :                         // Set SIGCHLD back to default, so that I
     525             :                         // can get sensible returns from waitpid.
     526             :                         memset(&sa, 0, sizeof(sa));
     527             :                         sa.sa_handler=SIG_DFL;
     528           0 :                         sigaction(SIGCHLD, &sa, NULL);
     529             : 
     530           0 :                         close(pipe_rfd[0]); // close read end
     531           0 :                         close(pipe_wfd[1]); // close write end
     532             : 
     533           0 :                         confs_free_content(confs);
     534           0 :                         confs_init(confs);
     535             : 
     536           0 :                         ret=run_child(&cfd, ctx, &client_name, pipe_rfd[1],
     537             :                           fdtype==ASFD_FD_SERVER_LISTEN_STATUS?pipe_wfd[0]:-1,
     538             :                           conffile, forking);
     539             : 
     540           0 :                         close(pipe_rfd[1]);
     541           0 :                         close(pipe_wfd[0]);
     542           0 :                         close_fd(&cfd);
     543           0 :                         exit(ret);
     544             :                 }
     545             :                 default:
     546             :                         // Parent.
     547           0 :                         close(pipe_rfd[1]); // close write end
     548           0 :                         close(pipe_wfd[0]); // close read end
     549           0 :                         close_fd(&cfd);
     550             : 
     551           0 :                         return setup_parent_child_pipes(asfd, childpid,
     552             :                                 &pipe_rfd[0], &pipe_wfd[1]);
     553             :         }
     554             : }
     555             : 
     556           0 : static int daemonise(void)
     557             : {
     558             :         /* process ID */
     559             :         pid_t pid;
     560             : 
     561             :         /* session ID */
     562             :         pid_t sid;
     563             : 
     564             :         /* fork new child and end parent */
     565           0 :         pid=fork();
     566             : 
     567             :         /* did we fork? */
     568           0 :         if(pid<0)
     569             :         {
     570           0 :                 logp("error forking\n");
     571           0 :                 return -1;
     572             :         }
     573             : 
     574             :         /* parent? */
     575           0 :         if(pid>0)
     576           0 :                 exit(EXIT_SUCCESS);
     577             : 
     578             :         /* now we are in the child process */
     579             : 
     580             :         /* create a session and set the process group ID */
     581           0 :         sid=setsid();
     582           0 :         if(sid<0)
     583             :         {
     584           0 :                 logp("error setting sid\n");
     585           0 :                 return -1;
     586             :         }
     587             : 
     588             :         /* leave and unblock current working dir */
     589           0 :         if(chdir("/")<0)
     590             :         {
     591           0 :                 logp("error changing working dir\n");
     592           0 :                 return -1;
     593             :         }
     594             : 
     595             :         /* close std* */
     596           0 :         close(STDIN_FILENO);
     597           0 :         close(STDOUT_FILENO);
     598           0 :         close(STDERR_FILENO);
     599             : 
     600           0 :         return 0;
     601             : }
     602             : 
     603           0 : static int extract_client_name(struct asfd *asfd)
     604             : {
     605             :         size_t l;
     606           0 :         const char *cp=NULL;
     607           0 :         const char *dp=NULL;
     608             : 
     609           0 :         if(asfd->client)
     610             :                 return 0;
     611           0 :         if(!(dp=strchr(asfd->rbuf->buf, '\t')))
     612             :                 return 0;
     613           0 :         dp++;
     614           0 :         if(!(cp=strchr(dp, '\t')))
     615             :                 return 0;
     616           0 :         cp++;
     617           0 :         l=cp-dp;
     618           0 :         if(!(asfd->client=malloc_w(l+1, __func__)))
     619             :                 return -1;
     620           0 :         snprintf(asfd->client, l, "%s", dp);
     621             :         return 0;
     622             : }
     623             : 
     624           0 : static int write_to_status_children(struct async *mainas, struct iobuf *iobuf)
     625             : {
     626             :         size_t wlen;
     627           0 :         struct asfd *scfd=NULL;
     628             : 
     629             :         // One of the child processes is giving us information.
     630             :         // Try to append it to any of the status child pipes.
     631           0 :         for(scfd=mainas->asfd; scfd; scfd=scfd->next)
     632             :         {
     633           0 :                 if(scfd->fdtype!=ASFD_FD_SERVER_PIPE_WRITE)
     634           0 :                         continue;
     635           0 :                 wlen=iobuf->len;
     636           0 :                 switch(scfd->append_all_to_write_buffer(scfd, iobuf))
     637             :                 {
     638             :                         case APPEND_OK:
     639             :                                 // Hack - the append function
     640             :                                 // will set the length to zero
     641             :                                 // on success. Set it back for
     642             :                                 // the next status child pipe.
     643           0 :                                 iobuf->len=wlen;
     644             :                                 break;
     645             :                         case APPEND_BLOCKED:
     646             :                                 break;
     647             :                         default:
     648             :                                 return -1;
     649             :                 }
     650             :         }
     651             :         // Free the information, even if we did not manage to append it. That
     652             :         // should be OK, more will be along soon.
     653           0 :         iobuf_free_content(iobuf);
     654             :         return 0;
     655             : }
     656             : 
     657           0 : static int update_status_child_client_lists(struct async *mainas)
     658             : {
     659           0 :         int ret=-1;
     660           0 :         char *buf=NULL;
     661           0 :         struct asfd *a=NULL;
     662             :         struct iobuf wbuf;
     663             : 
     664           0 :         if(!(buf=strdup_w("clients", __func__)))
     665             :                 goto end;
     666           0 :         for(a=mainas->asfd; a; a=a->next)
     667             :         {
     668           0 :                 if(a->fdtype!=ASFD_FD_SERVER_PIPE_READ
     669           0 :                   || !a->client)
     670           0 :                         continue;
     671           0 :                 if(astrcat(&buf, "\t", __func__))
     672             :                         goto end;
     673           0 :                 if(astrcat(&buf, a->client, __func__))
     674             :                         goto end;
     675             :         }
     676             : 
     677           0 :         iobuf_set(&wbuf, CMD_GEN, buf, strlen(buf));
     678             : 
     679           0 :         ret=write_to_status_children(mainas, &wbuf);
     680             : end:
     681           0 :         return ret;
     682             : }
     683             : 
     684           0 : static int maybe_update_status_child_client_lists(struct async *mainas)
     685             : {
     686           0 :         time_t now=0;
     687           0 :         time_t diff=0;
     688             :         static time_t lasttime=0;
     689           0 :         struct asfd *asfd=NULL;
     690             : 
     691             :         // If we have no status server child processes, do not bother.
     692           0 :         for(asfd=mainas->asfd; asfd; asfd=asfd->next)
     693           0 :                 if(asfd->fdtype==ASFD_FD_SERVER_PIPE_WRITE)
     694             :                         break;
     695           0 :         if(!asfd)
     696             :                 return 0;
     697             : 
     698             :         // Only update every 5 seconds.
     699           0 :         now=time(NULL);
     700           0 :         diff=now-lasttime;
     701           0 :         if(diff<5)
     702             :         {
     703             :                 // Might as well do this in case they fiddled their
     704             :                 // clock back in time.
     705           0 :                 if(diff<0) lasttime=now;
     706             :                 return 0;
     707             :         }
     708           0 :         lasttime=now;
     709             : 
     710           0 :         return update_status_child_client_lists(mainas);
     711             : }
     712             : 
     713           0 : static int run_server(struct conf **confs, const char *conffile)
     714             : {
     715           0 :         int ret=-1;
     716           0 :         SSL_CTX *ctx=NULL;
     717           0 :         int found_normal_child=0;
     718           0 :         struct asfd *asfd=NULL;
     719           0 :         struct async *mainas=NULL;
     720           0 :         struct strlist *ports=get_strlist(confs[OPT_PORT]);
     721           0 :         const char *address=get_string(confs[OPT_ADDRESS]);
     722           0 :         struct strlist *status_ports=get_strlist(confs[OPT_STATUS_PORT]);
     723           0 :         const char *status_address=get_string(confs[OPT_STATUS_ADDRESS]);
     724             : 
     725           0 :         if(!(ctx=ssl_initialise_ctx(confs)))
     726             :         {
     727           0 :                 logp("error initialising ssl ctx\n");
     728           0 :                 goto end;
     729             :         }
     730           0 :         if((ssl_load_dh_params(ctx, confs)))
     731             :         {
     732           0 :                 logp("error loading dh params\n");
     733           0 :                 goto end;
     734             :         }
     735             : 
     736           0 :         if(!(mainas=async_alloc())
     737           0 :           || mainas->init(mainas, 0))
     738             :                 goto end;
     739             : 
     740           0 :         if(init_listen_sockets(address, ports, mainas,
     741             :                 ASFD_FD_SERVER_LISTEN_MAIN, "server")
     742           0 :           || init_listen_sockets(status_address, status_ports, mainas,
     743             :                 ASFD_FD_SERVER_LISTEN_STATUS, "server status"))
     744             :                         goto end;
     745             : 
     746           0 :         while(!hupreload)
     747             :         {
     748             :                 int removed;
     749           0 :                 switch(mainas->read_write(mainas))
     750             :                 {
     751             :                         case 0:
     752           0 :                                 for(asfd=mainas->asfd; asfd; asfd=asfd->next)
     753             :                                 {
     754           0 :                                         if(asfd->new_client)
     755             :                                         {
     756             :                                                 // Incoming client.
     757           0 :                                                 asfd->new_client=0;
     758           0 :                                                 if(process_incoming_client(asfd,
     759             :                                                         ctx, conffile, confs))
     760             :                                                                 goto end;
     761           0 :                                                 if(!get_int(confs[OPT_FORK]))
     762             :                                                 {
     763           0 :                                                         gentleshutdown++;
     764           0 :                                                         ret=1;
     765           0 :                                                         goto end;
     766             :                                                 }
     767           0 :                                                 continue;
     768             :                                         }
     769             :                                 }
     770             :                                 break;
     771             :                         default:
     772           0 :                                 removed=0;
     773             :                                 // Maybe one of the fds had a problem.
     774             :                                 // Find and remove it and carry on if possible.
     775           0 :                                 for(asfd=mainas->asfd; asfd; )
     776             :                                 {
     777             :                                         struct asfd *a;
     778           0 :                                         if(!asfd->want_to_remove)
     779             :                                         {
     780           0 :                                                 asfd=asfd->next;
     781           0 :                                                 continue;
     782             :                                         }
     783           0 :                                         mainas->asfd_remove(mainas, asfd);
     784           0 :                                         logp("%s: disconnected fd %d\n",
     785           0 :                                                 asfd->desc, asfd->fd);
     786           0 :                                         a=asfd->next;
     787           0 :                                         asfd_free(&asfd);
     788           0 :                                         asfd=a;
     789           0 :                                         removed++;
     790             :                                 }
     791           0 :                                 if(removed) break;
     792             :                                 // If we got here, there was no fd to remove.
     793             :                                 // It is a fatal error.
     794             :                                 goto end;
     795             :                 }
     796             : 
     797           0 :                 for(asfd=mainas->asfd; asfd; asfd=asfd->next)
     798             :                 {
     799           0 :                         if(asfd->fdtype!=ASFD_FD_SERVER_PIPE_READ
     800           0 :                           || !asfd->rbuf->buf)
     801           0 :                                 continue;
     802             : 
     803             : //printf("got info from child: %s\n", asfd->rbuf->buf);
     804           0 :                         if(extract_client_name(asfd))
     805             :                                 goto end;
     806             : 
     807           0 :                         if(write_to_status_children(mainas, asfd->rbuf))
     808             :                                 goto end;
     809             :                 }
     810             : 
     811           0 :                 if(maybe_update_status_child_client_lists(mainas))
     812             :                         goto end;
     813             : 
     814           0 :                 chld_check_for_exiting(mainas);
     815             : 
     816             :                 // Leave if we had a SIGUSR1 and there are no children running.
     817           0 :                 if(gentleshutdown)
     818             :                 {
     819           0 :                         if(!gentleshutdown_logged)
     820             :                         {
     821           0 :                                 logp("got SIGUSR2 gentle reload signal\n");
     822           0 :                                 logp("will shut down once children have exited\n");
     823           0 :                                 gentleshutdown_logged++;
     824             :                         }
     825             : // FIX THIS:
     826             : // found_normal_child=chld_add_fd_to_normal_sets(confs, &fsr, &fse, &mfd);
     827             :                         else if(!found_normal_child)
     828             :                         {
     829           0 :                                 logp("all children have exited - shutting down\n");
     830           0 :                                 break;
     831             :                         }
     832             :                 }
     833             :         }
     834             : 
     835           0 :         if(hupreload) logp("got SIGHUP reload signal\n");
     836             : 
     837             :         ret=0;
     838             : end:
     839           0 :         async_asfd_free_all(&mainas);
     840           0 :         if(ctx) ssl_destroy_ctx(ctx);
     841           0 :         return ret;
     842             : }
     843             : 
     844           0 : int server(struct conf **confs, const char *conffile,
     845             :         struct lock *lock, int generate_ca_only)
     846             : {
     847           0 :         enum serret ret=SERVER_ERROR;
     848             : 
     849             :         //return champ_test(confs);
     850             : 
     851           0 :         if(ca_server_setup(confs)) goto error;
     852           0 :         if(generate_ca_only)
     853             :         {
     854           0 :                 logp("The '-g' command line option was given. Exiting now.\n");
     855           0 :                 goto end;
     856             :         }
     857             : 
     858           0 :         if(get_int(confs[OPT_FORK]) && get_int(confs[OPT_DAEMON]))
     859             :         {
     860           0 :                 if(daemonise()
     861             :                 // Need to write the new pid to the already open lock fd.
     862           0 :                   || lock_write_pid_and_prog(lock))
     863             :                         goto error;
     864             :         }
     865             : 
     866           0 :         ssl_load_globals();
     867             : 
     868           0 :         while(!gentleshutdown)
     869             :         {
     870           0 :                 if(run_server(confs, conffile))
     871             :                         goto error;
     872             : 
     873           0 :                 if(hupreload && !gentleshutdown)
     874             :                 {
     875           0 :                         if(reload(confs, conffile,
     876             :                                 0 // Not first time.
     877             :                                 ))
     878             :                                         goto error;
     879             :                 }
     880           0 :                 hupreload=0;
     881             :         }
     882             : 
     883             : end:
     884             :         ret=SERVER_OK;
     885             : error:
     886             : 
     887             : // FIX THIS: Have an enum for a return value, so that it is more obvious what
     888             : // is happening, like client.c does.
     889           0 :         return ret;
     890             : }

Generated by: LCOV version 1.10