Update from Debian version 2.7-1.2.
[pound.git] / pound.c
1 /*
2  * Pound - the reverse-proxy load-balancer
3  * Copyright (C) 2002-2010 Apsis GmbH
4  *
5  * This file is part of Pound.
6  *
7  * Pound is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  * 
12  * Pound is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  * Contact information:
21  * Apsis GmbH
22  * P.O.Box
23  * 8707 Uetikon am See
24  * Switzerland
25  * EMail: roseg@apsis.ch
26  */
27
28 #include    "pound.h"
29
30 /* common variables */
31 char        *user,              /* user to run as */
32             *group,             /* group to run as */
33             *root_jail,         /* directory to chroot to */
34             *pid_name,          /* file to record pid in */
35             *ctrl_name;         /* control socket name */
36
37 int         alive_to,           /* check interval for resurrection */
38             anonymise,          /* anonymise client address */
39             daemonize,          /* run as daemon */
40             log_facility,       /* log facility to use */
41             print_log,          /* print log messages to stdout/stderr */
42             grace,              /* grace period before shutdown */
43             control_sock;       /* control socket */
44
45 SERVICE     *services;          /* global services (if any) */
46
47 LISTENER    *listeners;         /* all available listeners */
48
49 regex_t HEADER,             /* Allowed header */
50         CHUNK_HEAD,         /* chunk header line */
51         RESP_SKIP,          /* responses for which we skip response */
52         RESP_IGN,           /* responses for which we ignore content */
53         LOCATION,           /* the host we are redirected to */
54         AUTHORIZATION;      /* the Authorisation header */
55
56 static int  shut_down = 0;
57
58 #ifndef  SOL_TCP
59 /* for systems without the definition */
60 int     SOL_TCP;
61 #endif
62
63 /* worker pid */
64 static  pid_t               son = 0;
65
66 /*
67  * OpenSSL thread support stuff
68  */
69 static pthread_mutex_t  *l_array;
70
71 static void
72 l_init(void)
73 {
74     int i, n_locks;
75
76     n_locks = CRYPTO_num_locks();
77     if((l_array = (pthread_mutex_t *)calloc(n_locks, sizeof(pthread_mutex_t))) == NULL) {
78         logmsg(LOG_ERR, "lock init: out of memory - aborted...");
79         exit(1);
80     }
81     for(i = 0; i < n_locks; i++)
82         /* pthread_mutex_init() always returns 0 */
83         pthread_mutex_init(&l_array[i], NULL);
84     return;
85 }
86
87 static void
88 l_lock(const int mode, const int n, /* unused */ const char *file, /* unused */ int line)
89 {
90     int ret_val;
91
92     if(mode & CRYPTO_LOCK) {
93         if(ret_val = pthread_mutex_lock(&l_array[n]))
94             logmsg(LOG_ERR, "l_lock lock(): %s", strerror(ret_val));
95     } else {
96         if(ret_val = pthread_mutex_unlock(&l_array[n]))
97             logmsg(LOG_ERR, "l_lock unlock(): %s", strerror(ret_val));
98     }
99     return;
100 }
101
102 static unsigned long
103 l_id(void)
104 {
105     return (unsigned long)pthread_self();
106 }
107
108 /*
109  * work queue stuff
110  */
111 static thr_arg          *first = NULL, *last = NULL;
112 static pthread_cond_t   arg_cond;
113 static pthread_mutex_t  arg_mut;
114 int                     numthreads;
115
116 static void
117 init_thr_arg(void)
118 {
119     pthread_cond_init(&arg_cond, NULL);
120     pthread_mutex_init(&arg_mut, NULL);
121     return;
122 }
123
124 /*
125  * add a request to the queue
126  */
127 int
128 put_thr_arg(thr_arg *arg)
129 {
130     thr_arg *res;
131
132     if((res = malloc(sizeof(thr_arg))) == NULL) {
133         logmsg(LOG_WARNING, "thr_arg malloc");
134         return -1;
135     }
136     memcpy(res, arg, sizeof(thr_arg));
137     res->next = NULL;
138     (void)pthread_mutex_lock(&arg_mut);
139     if(last == NULL)
140         first = last = res;
141     else {
142         last->next = res;
143         last = last->next;
144     }
145     (void)pthread_mutex_unlock(&arg_mut);
146     pthread_cond_signal(&arg_cond);
147     return 0;
148 }
149
150 /*
151  * get a request from the queue
152  */
153 thr_arg *
154 get_thr_arg(void)
155 {
156     thr_arg *res;
157
158     (void)pthread_mutex_lock(&arg_mut);
159     if(first == NULL)
160         (void)pthread_cond_wait(&arg_cond, &arg_mut);
161     if((res = first) != NULL)
162         if((first = first->next) == NULL)
163             last = NULL;
164     (void)pthread_mutex_unlock(&arg_mut);
165     if(first != NULL)
166         pthread_cond_signal(&arg_cond);
167     return res;
168 }
169
170 /*
171  * get the current queue length
172  */
173 get_thr_qlen(void)
174 {
175     int     res;
176     thr_arg *tap;
177
178     (void)pthread_mutex_lock(&arg_mut);
179     for(res = 0, tap = first; tap != NULL; tap = tap->next, res++)
180         ;
181     (void)pthread_mutex_unlock(&arg_mut);
182     return res;
183 }
184
185 /*
186  * handle SIGTERM/SIGQUIT - exit
187  */
188 static RETSIGTYPE
189 h_term(const int sig)
190 {
191     logmsg(LOG_NOTICE, "received signal %d - exiting...", sig);
192     if(son > 0)
193         kill(son, sig);
194     if(ctrl_name != NULL)
195         (void)unlink(ctrl_name);
196     exit(0);
197 }
198
199 /*
200  * handle SIGHUP/SIGINT - exit after grace period
201  */
202 static RETSIGTYPE
203 h_shut(const int sig)
204 {
205     int         status;
206     LISTENER    *lstn;
207
208     logmsg(LOG_NOTICE, "received signal %d - shutting down...", sig);
209     if(son > 0) {
210         for(lstn = listeners; lstn; lstn = lstn->next)
211             close(lstn->sock);
212         kill(son, sig);
213         (void)wait(&status);
214         if(ctrl_name != NULL)
215             (void)unlink(ctrl_name);
216         exit(0);
217     } else
218         shut_down = 1;
219 }
220
221 /*
222  * Pound: the reverse-proxy/load-balancer
223  *
224  * Arguments:
225  *  -f config_file      configuration file - exclusive of other flags
226  */
227
228 int
229 main(const int argc, char **argv)
230 {
231     int                 n_listeners, i, clnt_length, clnt;
232     struct pollfd       *polls;
233     LISTENER            *lstn;
234     pthread_t           thr;
235     pthread_attr_t      attr;
236     struct sched_param  sp;
237     uid_t               user_id;
238     gid_t               group_id;
239     FILE                *fpid;
240     struct sockaddr_storage clnt_addr;
241     char                tmp[MAXBUF];
242 #ifndef SOL_TCP
243     struct protoent     *pe;
244 #endif
245
246     print_log = 0;
247     (void)umask(077);
248     control_sock = -1;
249     log_facility = -1;
250     logmsg(LOG_NOTICE, "starting...");
251
252     signal(SIGHUP, h_shut);
253     signal(SIGINT, h_shut);
254     signal(SIGTERM, h_term);
255     signal(SIGQUIT, h_term);
256     signal(SIGPIPE, SIG_IGN);
257
258     srandom(getpid());
259
260     /* SSL stuff */
261     SSL_load_error_strings();
262     SSL_library_init();
263     OpenSSL_add_all_algorithms();
264     l_init();
265     init_thr_arg();
266     CRYPTO_set_id_callback(l_id);
267     CRYPTO_set_locking_callback(l_lock);
268     init_timer();
269
270     /* Disable SSL Compression for OpenSSL pre-1.0.  1.0 is handled with an option in config.c */
271 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
272 #ifndef SSL_OP_NO_COMPRESSION
273     {
274       int i,n;
275       STACK_OF(SSL_COMP) *ssl_comp_methods;
276
277       ssl_comp_methods = SSL_COMP_get_compression_methods();
278       n = sk_SSL_COMP_num(ssl_comp_methods);
279
280       for(i=n-1; i>=0; i--) {
281         sk_SSL_COMP_delete(ssl_comp_methods, i);
282       }
283     }
284 #endif
285 #endif
286
287     /* prepare regular expressions */
288     if(regcomp(&HEADER, "^([a-z0-9!#$%&'*+.^_`|~-]+):[ \t]*(.*)[ \t]*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
289     || regcomp(&CHUNK_HEAD, "^([0-9a-f]+).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
290     || regcomp(&RESP_SKIP, "^HTTP/1.1 100.*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
291     || regcomp(&RESP_IGN, "^HTTP/1.[01] (10[1-9]|1[1-9][0-9]|204|30[456]).*$", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
292     || regcomp(&LOCATION, "(http|https)://([^/]+)(.*)", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
293     || regcomp(&AUTHORIZATION, "Authorization:[ \t]*Basic[ \t]*\"?([^ \t]*)\"?[ \t]*", REG_ICASE | REG_NEWLINE | REG_EXTENDED)
294     ) {
295         logmsg(LOG_ERR, "bad essential Regex - aborted");
296         exit(1);
297     }
298
299 #ifndef SOL_TCP
300     /* for systems without the definition */
301     if((pe = getprotobyname("tcp")) == NULL) {
302         logmsg(LOG_ERR, "missing TCP protocol");
303         exit(1);
304     }
305     SOL_TCP = pe->p_proto;
306 #endif
307
308     /* read config */
309     config_parse(argc, argv);
310
311     if(log_facility != -1)
312         openlog("pound", LOG_CONS | LOG_NDELAY, LOG_DAEMON);
313     if(ctrl_name != NULL) {
314         struct sockaddr_un  ctrl;
315
316         memset(&ctrl, 0, sizeof(ctrl));
317         ctrl.sun_family = AF_UNIX;
318         strncpy(ctrl.sun_path, ctrl_name, sizeof(ctrl.sun_path) - 1);
319         (void)unlink(ctrl.sun_path);
320         if((control_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
321             logmsg(LOG_ERR, "Control \"%s\" create: %s", ctrl.sun_path, strerror(errno));
322             exit(1);
323         }
324         if(bind(control_sock, (struct sockaddr *)&ctrl, (socklen_t)sizeof(ctrl)) < 0) {
325             logmsg(LOG_ERR, "Control \"%s\" bind: %s", ctrl.sun_path, strerror(errno));
326             exit(1);
327         }
328         listen(control_sock, 512);
329     }
330
331     /* open listeners */
332     for(lstn = listeners, n_listeners = 0; lstn; lstn = lstn->next, n_listeners++) {
333         int opt;
334
335         /* prepare the socket */
336         if((lstn->sock = socket(lstn->addr.ai_family == AF_INET? PF_INET: PF_INET6, SOCK_STREAM, 0)) < 0) {
337             addr2str(tmp, MAXBUF - 1, &lstn->addr, 0);
338             logmsg(LOG_ERR, "HTTP socket %s create: %s - aborted", tmp, strerror(errno));
339             exit(1);
340         }
341         opt = 1;
342         setsockopt(lstn->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));
343         if(bind(lstn->sock, lstn->addr.ai_addr, (socklen_t)lstn->addr.ai_addrlen) < 0) {
344             addr2str(tmp, MAXBUF - 1, &lstn->addr, 0);
345             logmsg(LOG_ERR, "HTTP socket bind %s: %s - aborted", tmp, strerror(errno));
346             exit(1);
347         }
348         listen(lstn->sock, 512);
349     }
350
351     /* alloc the poll structures */
352     if((polls = (struct pollfd *)calloc(n_listeners, sizeof(struct pollfd))) == NULL) {
353         logmsg(LOG_ERR, "Out of memory for poll - aborted");
354         exit(1);
355     }
356     for(lstn = listeners, i = 0; lstn; lstn = lstn->next, i++)
357         polls[i].fd = lstn->sock;
358
359     /* set uid if necessary */
360     if(user) {
361         struct passwd   *pw;
362
363         if((pw = getpwnam(user)) == NULL) {
364             logmsg(LOG_ERR, "no such user %s - aborted", user);
365             exit(1);
366         }
367         user_id = pw->pw_uid;
368     }
369
370     /* set gid if necessary */
371     if(group) {
372         struct group    *gr;
373
374         if((gr = getgrnam(group)) == NULL) {
375             logmsg(LOG_ERR, "no such group %s - aborted", group);
376             exit(1);
377         }
378         group_id = gr->gr_gid;
379     }
380
381     /* Turn off verbose messages (if necessary) */
382     print_log = 0;
383
384     if(daemonize) {
385         /* daemonize - make ourselves a subprocess. */
386         switch (fork()) {
387             case 0:
388                 if(log_facility != -1) {
389                     close(0);
390                     close(1);
391                     close(2);
392                 }
393                 break;
394             case -1:
395                 logmsg(LOG_ERR, "fork: %s - aborted", strerror(errno));
396                 exit(1);
397             default:
398                 exit(0);
399         }
400 #ifdef  HAVE_SETSID
401         (void) setsid();
402 #endif
403     }
404
405     /* record pid in file */
406     if((fpid = fopen(pid_name, "wt")) != NULL) {
407         fprintf(fpid, "%d\n", getpid());
408         fclose(fpid);
409     } else
410         logmsg(LOG_NOTICE, "Create \"%s\": %s", pid_name, strerror(errno));
411
412     /* chroot if necessary */
413     if(root_jail) {
414         if(chroot(root_jail)) {
415             logmsg(LOG_ERR, "chroot: %s - aborted", strerror(errno));
416             exit(1);
417         }
418         if(chdir("/")) {
419             logmsg(LOG_ERR, "chroot/chdir: %s - aborted", strerror(errno));
420             exit(1);
421         }
422     }
423
424     if(group)
425         if(setgid(group_id) || setegid(group_id)) {
426             logmsg(LOG_ERR, "setgid: %s - aborted", strerror(errno));
427             exit(1);
428         }
429     if(user)
430         if(setuid(user_id) || seteuid(user_id)) {
431             logmsg(LOG_ERR, "setuid: %s - aborted", strerror(errno));
432             exit(1);
433         }
434
435     /* split off into monitor and working process if necessary */
436     for(;;) {
437 #ifdef  UPER
438         if((son = fork()) > 0) {
439             int status;
440
441             (void)wait(&status);
442             if(WIFEXITED(status))
443                 logmsg(LOG_ERR, "MONITOR: worker exited normally %d, restarting...", WEXITSTATUS(status));
444             else if(WIFSIGNALED(status))
445                 logmsg(LOG_ERR, "MONITOR: worker exited on signal %d, restarting...", WTERMSIG(status));
446             else
447                 logmsg(LOG_ERR, "MONITOR: worker exited (stopped?) %d, restarting...", status);
448         } else if (son == 0) {
449 #endif
450
451             /* thread stuff */
452             pthread_attr_init(&attr);
453             pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
454
455 #ifdef  NEED_STACK
456             /* set new stack size - necessary for OpenBSD/FreeBSD and Linux NPTL */
457             if(pthread_attr_setstacksize(&attr, 1 << 18)) {
458                 logmsg(LOG_ERR, "can't set stack size - aborted");
459                 exit(1);
460             }
461 #endif
462             /* start timer */
463             if(pthread_create(&thr, &attr, thr_timer, NULL)) {
464                 logmsg(LOG_ERR, "create thr_resurect: %s - aborted", strerror(errno));
465                 exit(1);
466             }
467
468             /* start the controlling thread (if needed) */
469             if(control_sock >= 0 && pthread_create(&thr, &attr, thr_control, NULL)) {
470                 logmsg(LOG_ERR, "create thr_control: %s - aborted", strerror(errno));
471                 exit(1);
472             }
473
474             /* pause to make sure the service threads were started */
475             sleep(1);
476
477             /* create the worker threads */
478             for(i = 0; i < numthreads; i++)
479                 if(pthread_create(&thr, &attr, thr_http, NULL)) {
480                     logmsg(LOG_ERR, "create thr_http: %s - aborted", strerror(errno));
481                     exit(1);
482                 }
483
484             /* pause to make sure at least some of the worker threads were started */
485             sleep(1);
486
487             /* and start working */
488             for(;;) {
489                 if(shut_down) {
490                     logmsg(LOG_NOTICE, "shutting down...");
491                     for(lstn = listeners; lstn; lstn = lstn->next)
492                         close(lstn->sock);
493                     if(grace > 0) {
494                         sleep(grace);
495                         logmsg(LOG_NOTICE, "grace period expired - exiting...");
496                     }
497                     if(ctrl_name != NULL)
498                         (void)unlink(ctrl_name);
499                     exit(0);
500                 }
501                 for(lstn = listeners, i = 0; i < n_listeners; lstn = lstn->next, i++) {
502                     polls[i].events = POLLIN | POLLPRI;
503                     polls[i].revents = 0;
504                 }
505                 if(poll(polls, n_listeners, -1) < 0) {
506                     logmsg(LOG_WARNING, "poll: %s", strerror(errno));
507                 } else {
508                     for(lstn = listeners, i = 0; lstn; lstn = lstn->next, i++) {
509                         if(polls[i].revents & (POLLIN | POLLPRI)) {
510                             memset(&clnt_addr, 0, sizeof(clnt_addr));
511                             clnt_length = sizeof(clnt_addr);
512                             if((clnt = accept(lstn->sock, (struct sockaddr *)&clnt_addr,
513                                 (socklen_t *)&clnt_length)) < 0) {
514                                 logmsg(LOG_WARNING, "HTTP accept: %s", strerror(errno));
515                             } else if(((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET
516                                    || ((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET6) {
517                                 thr_arg arg;
518
519                                 if(lstn->disabled) {
520                                     /*
521                                     addr2str(tmp, MAXBUF - 1, &clnt_addr, 1);
522                                     logmsg(LOG_WARNING, "HTTP disabled listener from %s", tmp);
523                                     */
524                                     close(clnt);
525                                 }
526                                 arg.sock = clnt;
527                                 arg.lstn = lstn;
528                                 if((arg.from_host.ai_addr = (struct sockaddr *)malloc(clnt_length)) == NULL) {
529                                     logmsg(LOG_WARNING, "HTTP arg address: malloc");
530                                     close(clnt);
531                                     continue;
532                                 }
533                                 memcpy(arg.from_host.ai_addr, &clnt_addr, clnt_length);
534                                 arg.from_host.ai_addrlen = clnt_length;
535                                 if(((struct sockaddr_in *)&clnt_addr)->sin_family == AF_INET)
536                                     arg.from_host.ai_family = AF_INET;
537                                 else
538                                     arg.from_host.ai_family = AF_INET6;
539                                 if(put_thr_arg(&arg))
540                                     close(clnt);
541                             } else {
542                                 /* may happen on FreeBSD, I am told */
543                                 logmsg(LOG_WARNING, "HTTP connection prematurely closed by peer");
544                                 close(clnt);
545                             }
546                         }
547                     }
548                 }
549             }
550 #ifdef  UPER
551         } else {
552             /* failed to spawn son */
553             logmsg(LOG_ERR, "Can't fork worker (%s) - aborted", strerror(errno));
554             exit(1);
555         }
556 #endif
557     }
558 }