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