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 : const char *peer_addr)
203 : {
204 0 : int ret=-1;
205 0 : int ca_ret=0;
206 0 : SSL *ssl=NULL;
207 0 : BIO *sbio=NULL;
208 0 : struct conf **confs=NULL;
209 0 : struct conf **cconfs=NULL;
210 0 : struct cntr *cntr=NULL;
211 0 : struct async *as=NULL;
212 0 : const char *cname=NULL;
213 0 : struct asfd *asfd=NULL;
214 0 : int is_status_server=0;
215 :
216 0 : if(!(confs=confs_alloc())
217 0 : || !(cconfs=confs_alloc()))
218 : goto end;
219 :
220 0 : set_peer_env_vars(addr);
221 :
222 : // Reload global config, in case things have changed. This means that
223 : // the server does not need to be restarted for most conf changes.
224 0 : confs_init(confs);
225 0 : confs_init(cconfs);
226 0 : if(conf_load_global_only(conffile, confs)) goto end;
227 :
228 : // Hack to keep forking turned off if it was specified as off on the
229 : // command line.
230 0 : if(!forking) set_int(confs[OPT_FORK], 0);
231 :
232 0 : if(!(sbio=BIO_new_socket(*cfd, BIO_NOCLOSE))
233 0 : || !(ssl=SSL_new(ctx)))
234 : {
235 0 : logp("There was a problem joining ssl to the socket\n");
236 0 : goto end;
237 : }
238 0 : SSL_set_bio(ssl, sbio, sbio);
239 :
240 : /* Check peer certificate straight away if the "verify_peer_early"
241 : option is enabled. Otherwise clients may send a certificate signing
242 : request when they have no certificate. */
243 0 : SSL_set_verify(ssl, SSL_VERIFY_PEER |
244 0 : (get_int(confs[OPT_SSL_VERIFY_PEER_EARLY])?SSL_VERIFY_FAIL_IF_NO_PEER_CERT:0),
245 : 0);
246 :
247 0 : if(ssl_do_accept(ssl))
248 : goto end;
249 0 : if(!(as=async_alloc())
250 0 : || as->init(as, 0)
251 0 : || !(asfd=setup_asfd_ssl(as, "main socket", cfd, ssl)))
252 : goto end;
253 0 : asfd->set_timeout(asfd, get_int(confs[OPT_NETWORK_TIMEOUT]));
254 0 : asfd->ratelimit=get_float(confs[OPT_RATELIMIT]);
255 0 : asfd->peer_addr=peer_addr;
256 :
257 0 : if(authorise_server(as->asfd, confs, cconfs)
258 0 : || !(cname=get_string(cconfs[OPT_CNAME])) || !*cname)
259 : {
260 : // Add an annoying delay in case they are tempted to
261 : // try repeatedly.
262 0 : sleep(1);
263 0 : log_and_send(as->asfd, "unable to authorise on server");
264 0 : goto end;
265 : }
266 :
267 0 : if(!get_int(cconfs[OPT_ENABLED]))
268 : {
269 0 : sleep(1);
270 0 : log_and_send(as->asfd, "client not enabled on server");
271 0 : goto end;
272 : }
273 :
274 : // Set up counters. Have to wait until here to get cname.
275 0 : if(!(cntr=cntr_alloc())
276 0 : || cntr_init(cntr, cname, getpid()))
277 : goto end;
278 0 : set_cntr(confs[OPT_CNTR], cntr);
279 0 : set_cntr(cconfs[OPT_CNTR], cntr);
280 :
281 : /* At this point, the client might want to get a new certificate
282 : signed. Clients on 1.3.2 or newer can do this. */
283 0 : if((ca_ret=ca_server_maybe_sign_client_cert(as->asfd, confs, cconfs))<0)
284 : {
285 0 : logp("Error signing client certificate request for %s\n",
286 : cname);
287 0 : goto end;
288 : }
289 0 : else if(ca_ret>0)
290 : {
291 : // Certificate signed and sent back.
292 : // Everything is OK, but we will close this instance
293 : // so that the client can start again with a new
294 : // connection and its new certificates.
295 0 : logp("Signed and returned client certificate request for %s\n",
296 : cname);
297 0 : ret=0;
298 0 : goto end;
299 : }
300 :
301 : /* Now it is time to check the certificate. */
302 0 : if(ssl_check_cert(ssl, confs, cconfs))
303 : {
304 0 : log_and_send(as->asfd, "check cert failed on server");
305 0 : goto end;
306 : }
307 0 : if(status_rfd>=0)
308 : {
309 0 : is_status_server=1;
310 0 : if(!setup_asfd(as, "status server parent socket", &status_rfd,
311 : /*listen*/""))
312 : goto end;
313 0 : if(!client_can_monitor(cconfs))
314 : {
315 0 : logp("Not allowing monitor request from %s\n", cname);
316 0 : if(as->asfd->write_str(asfd, CMD_GEN,
317 : "Monitor is not allowed"))
318 : ret=-1;
319 : goto end;
320 : }
321 : }
322 :
323 0 : ret=child(as, is_status_server, status_wfd, confs, cconfs);
324 : end:
325 0 : *cfd=-1;
326 0 : if(as && asfd_flush_asio(as->asfd))
327 0 : ret=-1;
328 0 : async_asfd_free_all(&as); // This closes cfd for us.
329 0 : logp("exit child\n");
330 0 : if(cntr) cntr_free(&cntr);
331 0 : if(confs)
332 : {
333 0 : set_cntr(confs[OPT_CNTR], NULL);
334 0 : confs_free(&confs);
335 : }
336 0 : if(cconfs)
337 : {
338 0 : set_cntr(cconfs[OPT_CNTR], NULL);
339 0 : confs_free(&cconfs);
340 : }
341 0 : return ret;
342 : }
343 :
344 0 : static struct strlist *find_listen_in_conf(struct conf **confs,
345 : enum conf_opt listen_opt, const char *listen)
346 : {
347 : struct strlist *l;
348 0 : for(l=get_strlist(confs[listen_opt]); l; l=l->next)
349 0 : if(!strcmp(listen, l->path))
350 : return l;
351 0 : logp("Could not find %s in %s confs\n",
352 0 : listen, confs[listen_opt]->field);
353 0 : return NULL;
354 : }
355 :
356 0 : static int chld_check_counts(struct conf **confs, struct asfd *asfd)
357 : {
358 0 : long count=0;
359 : struct asfd *a;
360 : struct strlist *listen;
361 : enum conf_opt listen_opt;
362 :
363 0 : switch(asfd->fdtype)
364 : {
365 : case ASFD_FD_SERVER_LISTEN_MAIN:
366 0 : listen_opt=OPT_LISTEN;
367 0 : if(!(listen=find_listen_in_conf(confs,
368 0 : listen_opt, asfd->listen)))
369 : return -1;
370 : break;
371 : case ASFD_FD_SERVER_LISTEN_STATUS:
372 0 : listen_opt=OPT_LISTEN_STATUS;
373 0 : if(!(listen=find_listen_in_conf(confs,
374 0 : listen_opt, asfd->listen)))
375 : return -1;
376 : break;
377 : default:
378 0 : logp("Unexpected fdtype in %s: %d.\n",
379 : __func__, asfd->fdtype);
380 0 : return -1;
381 : }
382 :
383 0 : for(a=asfd->as->asfd; a; a=a->next)
384 0 : if(a!=asfd
385 0 : && !strcmp(asfd->listen, a->listen))
386 0 : count++;
387 :
388 0 : logp("%d/%d child processes running on %s %s\n",
389 0 : (int)count, (int)listen->flag,
390 0 : confs[listen_opt]->field, asfd->listen);
391 0 : if(count<listen->flag)
392 0 : logp("Child %d available\n", (int)count+1);
393 : else
394 : {
395 0 : logp("No spare children available.\n");
396 0 : return -1;
397 : }
398 :
399 0 : return 0;
400 : }
401 :
402 : static struct asfd *setup_parent_child_pipe(struct async *as,
403 : const char *desc,
404 : int *fd_to_use, int *fd_to_close, pid_t childpid, const char *listen,
405 : enum asfd_fdtype fdtype)
406 : {
407 : struct asfd *newfd;
408 0 : close_fd(fd_to_close);
409 0 : if(!(newfd=setup_asfd(as, desc, fd_to_use, listen)))
410 : return NULL;
411 0 : newfd->pid=childpid;
412 0 : newfd->fdtype=fdtype;
413 : return newfd;
414 : }
415 :
416 0 : static int setup_parent_child_pipes(struct asfd *asfd,
417 : pid_t childpid, int *rfd, int *wfd)
418 : {
419 : struct asfd *newfd;
420 0 : struct async *as=asfd->as;
421 0 : switch(asfd->fdtype)
422 : {
423 : case ASFD_FD_SERVER_LISTEN_MAIN:
424 0 : logp("forked child on %s: %d\n",
425 : asfd->listen, childpid);
426 0 : if(!(newfd=setup_parent_child_pipe(as,
427 : "pipe from child",
428 0 : rfd, wfd, childpid, asfd->listen,
429 : ASFD_FD_SERVER_PIPE_READ)))
430 : return -1;
431 0 : return 0;
432 : case ASFD_FD_SERVER_LISTEN_STATUS:
433 0 : logp("forked status child on %s: %d\n",
434 : asfd->listen, childpid);
435 0 : if(!(newfd=setup_parent_child_pipe(as,
436 : "pipe to status child",
437 0 : wfd, rfd, childpid, asfd->listen,
438 : ASFD_FD_SERVER_PIPE_WRITE)))
439 : return -1;
440 0 : newfd->attempt_reads=0;
441 0 : return 0;
442 : default:
443 0 : logp("Strange fdtype after fork: %d\n",
444 : asfd->fdtype);
445 0 : return -1;
446 : }
447 :
448 : return 0;
449 : }
450 :
451 0 : static int process_incoming_client(struct asfd *asfd, SSL_CTX *ctx,
452 : const char *conffile, struct conf **confs)
453 : {
454 0 : int cfd=-1;
455 : pid_t childpid;
456 : int pipe_rfd[2];
457 : int pipe_wfd[2];
458 0 : uint16_t peer_port=0;
459 0 : char peer_addr[INET6_ADDRSTRLEN]="";
460 0 : socklen_t client_length=0;
461 : struct sockaddr_storage client_name;
462 0 : enum asfd_fdtype fdtype=asfd->fdtype;
463 0 : int forking=get_int(confs[OPT_FORK]);
464 :
465 0 : client_length=sizeof(client_name);
466 0 : if((cfd=accept(asfd->fd,
467 : (struct sockaddr *)&client_name, &client_length))==-1)
468 : {
469 : // Look out, accept will get interrupted by SIGCHLDs.
470 0 : if(errno==EINTR) return 0;
471 0 : logp("accept failed on %s (%d) in %s: %s\n", asfd->desc,
472 : asfd->fd, __func__, strerror(errno));
473 0 : return -1;
474 : }
475 0 : reuseaddr(cfd);
476 :
477 0 : if(get_address_and_port(&client_name,
478 : peer_addr, INET6_ADDRSTRLEN, &peer_port))
479 : return -1;
480 0 : logp("Connect from peer: %s:%d\n", peer_addr, peer_port);
481 :
482 0 : if(!forking)
483 0 : return run_child(&cfd, ctx,
484 : &client_name, -1, -1, conffile, forking, peer_addr);
485 :
486 0 : if(chld_check_counts(confs, asfd))
487 : {
488 0 : logp("Closing new connection.\n");
489 0 : close_fd(&cfd);
490 0 : return 0;
491 : }
492 :
493 0 : if(pipe(pipe_rfd)<0 || pipe(pipe_wfd)<0)
494 : {
495 0 : logp("pipe failed: %s", strerror(errno));
496 0 : close_fd(&cfd);
497 0 : return -1;
498 : }
499 :
500 0 : switch((childpid=fork()))
501 : {
502 : case -1:
503 0 : logp("fork failed: %s\n", strerror(errno));
504 0 : return -1;
505 : case 0:
506 : {
507 : // Child.
508 : int p;
509 : int ret;
510 : struct sigaction sa;
511 0 : struct async *as=asfd->as;
512 0 : async_asfd_free_all(&as);
513 :
514 : // Close unnecessary file descriptors.
515 : // Go up to FD_SETSIZE and hope for the best.
516 : // FIX THIS: Now that async_asfd_free_all() is doing
517 : // everything, double check whether this is needed.
518 0 : for(p=3; p<(int)FD_SETSIZE; p++)
519 : {
520 0 : if(p!=pipe_rfd[1]
521 0 : && p!=pipe_wfd[0]
522 0 : && p!=cfd)
523 0 : close(p);
524 : }
525 :
526 : // Set SIGCHLD back to default, so that I
527 : // can get sensible returns from waitpid.
528 0 : memset(&sa, 0, sizeof(sa));
529 : sa.sa_handler=SIG_DFL;
530 0 : sigaction(SIGCHLD, &sa, NULL);
531 :
532 0 : close(pipe_rfd[0]); // close read end
533 0 : close(pipe_wfd[1]); // close write end
534 :
535 0 : confs_free_content(confs);
536 0 : confs_init(confs);
537 :
538 0 : ret=run_child(&cfd, ctx, &client_name, pipe_rfd[1],
539 : fdtype==ASFD_FD_SERVER_LISTEN_STATUS?pipe_wfd[0]:-1,
540 : conffile, forking, peer_addr);
541 :
542 0 : close(pipe_rfd[1]);
543 0 : close(pipe_wfd[0]);
544 0 : close_fd(&cfd);
545 0 : exit(ret);
546 : }
547 : default:
548 : // Parent.
549 0 : close(pipe_rfd[1]); // close write end
550 0 : close(pipe_wfd[0]); // close read end
551 0 : close_fd(&cfd);
552 :
553 0 : return setup_parent_child_pipes(asfd, childpid,
554 : &pipe_rfd[0], &pipe_wfd[1]);
555 : }
556 : }
557 :
558 0 : static int daemonise(void)
559 : {
560 : /* process ID */
561 : pid_t pid;
562 :
563 : /* session ID */
564 : pid_t sid;
565 :
566 : /* fork new child and end parent */
567 0 : pid=fork();
568 :
569 : /* did we fork? */
570 0 : if(pid<0)
571 : {
572 0 : logp("error forking\n");
573 0 : return -1;
574 : }
575 :
576 : /* parent? */
577 0 : if(pid>0)
578 0 : exit(EXIT_SUCCESS);
579 :
580 : /* now we are in the child process */
581 :
582 : /* create a session and set the process group ID */
583 0 : sid=setsid();
584 0 : if(sid<0)
585 : {
586 0 : logp("error setting sid\n");
587 0 : return -1;
588 : }
589 :
590 : /* leave and unblock current working dir */
591 0 : if(chdir("/")<0)
592 : {
593 0 : logp("error changing working dir\n");
594 0 : return -1;
595 : }
596 :
597 0 : close(STDOUT_FILENO);
598 0 : close(STDERR_FILENO);
599 : // It turns out that if I close stdin (fd=0), and have exactly one
600 : // listen address configured (listen=0.0.0.0:4971), with no
601 : // listen_status configured, then the socket file descriptor will be 0.
602 : // In this case, select() in async.c will raise an exception on fd=0.
603 : // It does not raise an exception if you have a socket fd 0 and 1
604 : // (ie, two listen addresses).
605 : // Seems like a linux bug to me. Anyway, hack around it by immediately
606 : // opening /dev/null, so that the sockets can never get fd=0.
607 0 : close(STDIN_FILENO);
608 0 : devnull=fzp_open("/dev/null", "w");
609 :
610 0 : return 0;
611 : }
612 :
613 0 : static int extract_client_name(struct asfd *asfd)
614 : {
615 : size_t l;
616 0 : const char *cp=NULL;
617 0 : const char *dp=NULL;
618 :
619 0 : if(asfd->client)
620 : return 0;
621 0 : if(!(dp=strchr(asfd->rbuf->buf, '\t')))
622 : return 0;
623 0 : dp++;
624 0 : if(!(cp=strchr(dp, '\t')))
625 : return 0;
626 0 : cp++;
627 0 : l=cp-dp;
628 0 : if(!(asfd->client=malloc_w(l+1, __func__)))
629 : return -1;
630 0 : snprintf(asfd->client, l, "%s", dp);
631 : return 0;
632 : }
633 :
634 0 : static int write_to_status_children(struct async *mainas, struct iobuf *iobuf)
635 : {
636 : size_t wlen;
637 0 : struct asfd *scfd=NULL;
638 :
639 : // One of the child processes is giving us information.
640 : // Try to append it to any of the status child pipes.
641 0 : for(scfd=mainas->asfd; scfd; scfd=scfd->next)
642 : {
643 0 : if(scfd->fdtype!=ASFD_FD_SERVER_PIPE_WRITE)
644 0 : continue;
645 0 : wlen=iobuf->len;
646 0 : switch(scfd->append_all_to_write_buffer(scfd, iobuf))
647 : {
648 : case APPEND_OK:
649 : // Hack - the append function
650 : // will set the length to zero
651 : // on success. Set it back for
652 : // the next status child pipe.
653 0 : iobuf->len=wlen;
654 : break;
655 : case APPEND_BLOCKED:
656 : break;
657 : default:
658 : return -1;
659 : }
660 : }
661 : // Free the information, even if we did not manage to append it. That
662 : // should be OK, more will be along soon.
663 0 : iobuf_free_content(iobuf);
664 : return 0;
665 : }
666 :
667 0 : static int update_status_child_client_lists(struct async *mainas)
668 : {
669 0 : int ret=-1;
670 0 : char *buf=NULL;
671 0 : struct asfd *a=NULL;
672 : struct iobuf wbuf;
673 :
674 0 : if(!(buf=strdup_w("clients", __func__)))
675 : goto end;
676 0 : for(a=mainas->asfd; a; a=a->next)
677 : {
678 0 : if(a->fdtype!=ASFD_FD_SERVER_PIPE_READ
679 0 : || !a->client)
680 0 : continue;
681 0 : if(astrcat(&buf, "\t", __func__))
682 : goto end;
683 0 : if(astrcat(&buf, a->client, __func__))
684 : goto end;
685 : }
686 :
687 0 : iobuf_set(&wbuf, CMD_GEN, buf, strlen(buf));
688 :
689 0 : ret=write_to_status_children(mainas, &wbuf);
690 : end:
691 0 : return ret;
692 : }
693 :
694 0 : static int maybe_update_status_child_client_lists(struct async *mainas)
695 : {
696 0 : time_t now=0;
697 0 : time_t diff=0;
698 : static time_t lasttime=0;
699 0 : struct asfd *asfd=NULL;
700 :
701 : // If we have no status server child processes, do not bother.
702 0 : for(asfd=mainas->asfd; asfd; asfd=asfd->next)
703 0 : if(asfd->fdtype==ASFD_FD_SERVER_PIPE_WRITE)
704 : break;
705 0 : if(!asfd)
706 : return 0;
707 :
708 : // Only update every 5 seconds.
709 0 : now=time(NULL);
710 0 : diff=now-lasttime;
711 0 : if(diff<5)
712 : {
713 : // Might as well do this in case they fiddled their
714 : // clock back in time.
715 0 : if(diff<0) lasttime=now;
716 : return 0;
717 : }
718 0 : lasttime=now;
719 :
720 0 : return update_status_child_client_lists(mainas);
721 : }
722 :
723 0 : static int run_server(struct conf **confs, const char *conffile)
724 : {
725 0 : int ret=-1;
726 0 : SSL_CTX *ctx=NULL;
727 0 : int found_normal_child=0;
728 0 : struct asfd *asfd=NULL;
729 0 : struct async *mainas=NULL;
730 0 : struct strlist *addresses=get_strlist(confs[OPT_LISTEN]);
731 0 : struct strlist *addresses_status=get_strlist(confs[OPT_LISTEN_STATUS]);
732 :
733 0 : if(!(ctx=ssl_initialise_ctx(confs)))
734 : {
735 0 : logp("error initialising ssl ctx\n");
736 0 : goto end;
737 : }
738 0 : if((ssl_load_dh_params(ctx, confs)))
739 : {
740 0 : logp("error loading dh params\n");
741 0 : goto end;
742 : }
743 :
744 0 : if(!(mainas=async_alloc())
745 0 : || mainas->init(mainas, 0))
746 : goto end;
747 :
748 0 : if(init_listen_sockets(addresses, mainas,
749 : ASFD_FD_SERVER_LISTEN_MAIN, "server")
750 0 : || init_listen_sockets(addresses_status, mainas,
751 : ASFD_FD_SERVER_LISTEN_STATUS, "server status"))
752 : goto end;
753 :
754 0 : while(!hupreload)
755 : {
756 : int removed;
757 0 : switch(mainas->read_write(mainas))
758 : {
759 : case 0:
760 0 : for(asfd=mainas->asfd; asfd; asfd=asfd->next)
761 : {
762 0 : if(asfd->new_client)
763 : {
764 : // Incoming client.
765 0 : asfd->new_client=0;
766 0 : if(process_incoming_client(asfd,
767 : ctx, conffile, confs))
768 : goto end;
769 0 : if(!get_int(confs[OPT_FORK]))
770 : {
771 0 : gentleshutdown++;
772 0 : ret=1;
773 0 : goto end;
774 : }
775 0 : continue;
776 : }
777 : }
778 : break;
779 : default:
780 0 : removed=0;
781 : // Maybe one of the fds had a problem.
782 : // Find and remove it and carry on if possible.
783 0 : for(asfd=mainas->asfd; asfd; )
784 : {
785 : struct asfd *a;
786 0 : if(!asfd->want_to_remove)
787 : {
788 0 : asfd=asfd->next;
789 0 : continue;
790 : }
791 0 : mainas->asfd_remove(mainas, asfd);
792 0 : logp("%s: disconnected fd %d\n",
793 0 : asfd->desc, asfd->fd);
794 0 : a=asfd->next;
795 0 : asfd_free(&asfd);
796 0 : asfd=a;
797 0 : removed++;
798 : }
799 0 : if(removed) break;
800 : // If we got here, there was no fd to remove.
801 : // It is a fatal error.
802 : goto end;
803 : }
804 :
805 0 : for(asfd=mainas->asfd; asfd; asfd=asfd->next)
806 : {
807 0 : if(asfd->fdtype!=ASFD_FD_SERVER_PIPE_READ
808 0 : || !asfd->rbuf->buf)
809 0 : continue;
810 :
811 : //printf("got info from child: %s\n", asfd->rbuf->buf);
812 0 : if(extract_client_name(asfd))
813 : goto end;
814 :
815 0 : if(write_to_status_children(mainas, asfd->rbuf))
816 : goto end;
817 : }
818 :
819 0 : if(maybe_update_status_child_client_lists(mainas))
820 : goto end;
821 :
822 0 : chld_check_for_exiting(mainas);
823 :
824 : // Leave if we had a SIGUSR1 and there are no children running.
825 0 : if(gentleshutdown)
826 : {
827 0 : if(!gentleshutdown_logged)
828 : {
829 0 : logp("got SIGUSR2 gentle reload signal\n");
830 0 : logp("will shut down once children have exited\n");
831 0 : gentleshutdown_logged++;
832 : }
833 : // FIX THIS:
834 : // found_normal_child=chld_add_fd_to_normal_sets(confs, &fsr, &fse, &mfd);
835 : else if(!found_normal_child)
836 : {
837 0 : logp("all children have exited - shutting down\n");
838 0 : break;
839 : }
840 : }
841 : }
842 :
843 0 : if(hupreload) logp("got SIGHUP reload signal\n");
844 :
845 : ret=0;
846 : end:
847 0 : async_asfd_free_all(&mainas);
848 0 : if(ctx) ssl_destroy_ctx(ctx);
849 0 : return ret;
850 : }
851 :
852 0 : int server(struct conf **confs, const char *conffile,
853 : struct lock *lock, int generate_ca_only)
854 : {
855 0 : enum serret ret=SERVER_ERROR;
856 :
857 : //return champ_test(confs);
858 :
859 0 : if(ca_server_setup(confs)) goto error;
860 0 : if(generate_ca_only)
861 : {
862 0 : logp("The '-g' command line option was given. Exiting now.\n");
863 0 : goto end;
864 : }
865 :
866 0 : if(get_int(confs[OPT_FORK]) && get_int(confs[OPT_DAEMON]))
867 : {
868 0 : if(daemonise()
869 : // Need to write the new pid to the already open lock fd.
870 0 : || lock_write_pid(lock))
871 : goto error;
872 : }
873 :
874 0 : ssl_load_globals();
875 :
876 0 : while(!gentleshutdown)
877 : {
878 0 : if(run_server(confs, conffile))
879 : goto error;
880 :
881 0 : if(hupreload && !gentleshutdown)
882 : {
883 0 : if(reload(confs, conffile,
884 : 0 // Not first time.
885 : ))
886 : goto error;
887 : }
888 0 : hupreload=0;
889 : }
890 :
891 : end:
892 : ret=SERVER_OK;
893 : error:
894 0 : fzp_close(&devnull);
895 :
896 : // FIX THIS: Have an enum for a return value, so that it is more obvious what
897 : // is happening, like client.c does.
898 0 : return ret;
899 : }
|