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

Generated by: LCOV version 1.13