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

Generated by: LCOV version 1.10