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