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 "config.h" 29 #include <stdio.h> 30 #include <math.h> 31 32 #if HAVE_STDLIB_H 33 #include <stdlib.h> 34 #else 35 #error "Pound needs stdlib.h" 36 #endif 37 38 #if HAVE_UNISTD_H 39 #include <unistd.h> 40 #else 41 #error "Pound needs unistd.h" 42 #endif 43 44 #if HAVE_GETOPT_H 45 #include <getopt.h> 46 #endif 47 48 #if HAVE_PTHREAD_H 49 #include <pthread.h> 50 #else 51 #error "Pound needs pthread.h" 52 #endif 53 54 #if HAVE_STRING_H 55 #include <string.h> 56 #else 57 #error "Pound needs string.h" 58 #endif 59 60 #if TIME_WITH_SYS_TIME 61 #if HAVE_SYS_TIME_H 62 #include <sys/time.h> 63 #else 64 #error "Pound needs sys/time.h" 65 #endif 66 #if HAVE_TIME_H 67 #include <time.h> 68 #else 69 #error "Pound needs time.h" 70 #endif 71 #else /* may not mix sys/time.h and time.h */ 72 #if HAVE_SYS_TIME_H 73 #include <sys/time.h> 74 #elif HAVE_TIME_H 75 #include <time.h> 76 #else 77 #error "Pound needs time.h" 78 #endif 79 #endif /* mix */ 80 81 #if HAVE_SYS_TYPES_H 82 #include <sys/types.h> 83 #else 84 #error "Pound needs sys/types.h" 85 #endif 86 87 #if HAVE_SYS_SOCKET_H 88 #include <sys/socket.h> 89 #else 90 #error "Pound needs sys/socket.h" 91 #endif 92 93 #if HAVE_SYS_UN_H 94 #include <sys/un.h> 95 #else 96 #error "Pound needs sys/un.h" 97 #endif 98 99 #ifndef UNIX_PATH_MAX 100 /* on Linux this is defined in linux/un.h rather than sys/un.h - go figure */ 101 #define UNIX_PATH_MAX 108 102 #endif 103 104 #if HAVE_NETINET_IN_H 105 #include <netinet/in.h> 106 #else 107 #error "Pound needs netinet/in.h" 108 #endif 109 110 #if HAVE_NETINET_TCP_H 111 #include <netinet/tcp.h> 112 #else 113 #error "Pound needs netinet/tcp.h" 114 #endif 115 116 #if HAVE_ARPA_INET_H 117 #include <arpa/inet.h> 118 #else 119 #error "Pound needs arpa/inet.h" 120 #endif 121 122 #if HAVE_NETDB_H 123 #include <netdb.h> 124 #else 125 #error "Pound needs netdb.h" 126 #endif 127 128 #if HAVE_SYS_POLL_H 129 #include <sys/poll.h> 130 #else 131 #error "Pound needs sys/poll.h" 132 #endif 133 134 #if HAVE_OPENSSL_SSL_H 135 #define OPENSSL_THREAD_DEFINES 136 #include <openssl/ssl.h> 137 #include <openssl/lhash.h> 138 #include <openssl/err.h> 139 #if OPENSSL_VERSION_NUMBER >= 0x00907000L 140 #ifndef OPENSSL_THREADS 141 #error "Pound requires OpenSSL with thread support" 142 #endif 143 #else 144 #ifndef THREADS 145 #error "Pound requires OpenSSL with thread support" 146 #endif 147 #endif 148 #else 149 #error "Pound needs openssl/ssl.h" 150 #endif 151 152 #if HAVE_OPENSSL_ENGINE_H 153 #include <openssl/engine.h> 154 #endif 155 156 #if HAVE_PWD_H 157 #include <pwd.h> 158 #else 159 #error "Pound needs pwd.h" 160 #endif 161 162 #if HAVE_GRP_H 163 #include <grp.h> 164 #else 165 #error "Pound needs grp.h" 166 #endif 167 168 #if HAVE_SYSLOG_H 169 #include <syslog.h> 170 #endif 171 172 #if HAVE_SYS_SYSLOG_H 173 #include <sys/syslog.h> 174 #endif 175 176 #if HAVE_SIGNAL_H 177 #include <signal.h> 178 #else 179 #error "Pound needs signal.h" 180 #endif 181 182 #if HAVE_LIBPCREPOSIX 183 #if HAVE_PCREPOSIX_H 184 #include <pcreposix.h> 185 #elif HAVE_PCRE_PCREPOSIX_H 186 #include <pcre/pcreposix.h> 187 #else 188 #error "You have libpcreposix, but the header files are missing. Use --disable-pcreposix" 189 #endif 190 #elif HAVE_REGEX_H 191 #include <regex.h> 192 #else 193 #error "Pound needs regex.h" 194 #endif 195 196 #if HAVE_CTYPE_H 197 #include <ctype.h> 198 #else 199 #error "Pound needs ctype.h" 200 #endif 201 202 #if HAVE_ERRNO_H 203 #include <errno.h> 204 #else 205 #error "Pound needs errno.h" 206 #endif 207 208 #if HAVE_WAIT_H 209 #include <wait.h> 210 #elif HAVE_SYS_WAIT_H 211 #include <sys/wait.h> 212 #else 213 #error "Pound needs sys/wait.h" 214 #endif 215 216 #if HAVE_SYS_STAT_H 217 #include <sys/stat.h> 218 #else 219 #error "Pound needs sys/stat.h" 220 #endif 221 222 #if HAVE_FCNTL_H 223 #include <fcntl.h> 224 #else 225 #error "Pound needs fcntl.h" 226 #endif 227 228 #if HAVE_STDARG_H 229 #include <stdarg.h> 230 #else 231 #include <varargs.h> 232 #endif 233 234 #if HAVE_FNMATCH_H 235 #include <fnmatch.h> 236 #else 237 #error "Pound needs fnmatch.h" 238 #endif 239 240 #ifndef __STDC__ 241 #define const 242 #endif 243 244 #ifdef HAVE_LONG_LONG_INT 245 #define LONG long long 246 #define L0 0LL 247 #define L_1 -1LL 248 #define STRTOL strtoll 249 #define ATOL atoll 250 #else 251 #define LONG long 252 #define L0 0L 253 #define L_1 -1L 254 #define STRTOL strtol 255 #define ATOL atol 256 #endif 257 258 #ifndef NO_EXTERNALS 259 /* 260 * Global variables needed by everybody 261 */ 262 263 extern char *user, /* user to run as */ 264 *group, /* group to run as */ 265 *root_jail, /* directory to chroot to */ 266 *pid_name, /* file to record pid in */ 267 *ctrl_name; /* control socket name */ 268 269 extern int numthreads, /* number of worker threads */ 270 anonymise, /* anonymise client address */ 271 alive_to, /* check interval for resurrection */ 272 daemonize, /* run as daemon */ 273 log_facility, /* log facility to use */ 274 print_log, /* print log messages to stdout/stderr */ 275 grace, /* grace period before shutdown */ 276 control_sock; /* control socket */ 277 278 extern regex_t HEADER, /* Allowed header */ 279 CONN_UPGRD, /* upgrade in connection header */ 280 CHUNK_HEAD, /* chunk header line */ 281 RESP_SKIP, /* responses for which we skip response */ 282 RESP_IGN, /* responses for which we ignore content */ 283 LOCATION, /* the host we are redirected to */ 284 AUTHORIZATION; /* the Authorisation header */ 285 286 #ifndef SOL_TCP 287 /* for systems without the definition */ 288 extern int SOL_TCP; 289 #endif 290 291 #endif /* NO_EXTERNALS */ 292 293 #ifndef MAXBUF 294 #define MAXBUF 4096 295 #endif 296 297 #define MAXHEADERS 128 298 299 #ifndef F_CONF 300 #define F_CONF "/usr/local/etc/pound.cfg" 301 #endif 302 303 #ifndef F_PID 304 #define F_PID "/var/run/pound.pid" 305 #endif 306 307 /* matcher chain */ 308 typedef struct _matcher { 309 regex_t pat; /* pattern to match the request/header against */ 310 struct _matcher *next; 311 } MATCHER; 312 313 /* back-end types */ 314 typedef enum { SESS_NONE, SESS_IP, SESS_COOKIE, SESS_URL, SESS_PARM, SESS_HEADER, SESS_BASIC } SESS_TYPE; 315 316 /* back-end definition */ 317 typedef struct _backend { 318 int be_type; /* 0 if real back-end, otherwise code (301, 302/default, 307) */ 319 struct addrinfo addr; /* IPv4/6 address */ 320 int priority; /* priority */ 321 int to; /* read/write time-out */ 322 int conn_to; /* connection time-out */ 323 int ws_to; /* websocket time-out */ 324 struct addrinfo ha_addr; /* HA address/port */ 325 char *url; /* for redirectors */ 326 int redir_req; /* the redirect should include the request path */ 327 SSL_CTX *ctx; /* CTX for SSL connections */ 328 pthread_mutex_t mut; /* mutex for this back-end */ 329 int n_requests; /* number of requests seen */ 330 double t_requests; /* time to answer these requests */ 331 double t_average; /* average time to answer requests */ 332 int alive; /* false if the back-end is dead */ 333 int resurrect; /* this back-end is to be resurrected */ 334 int disabled; /* true if the back-end is disabled */ 335 struct _backend *next; 336 } BACKEND; 337 338 typedef struct _tn { 339 char *key; 340 void *content; 341 time_t last_acc; 342 } TABNODE; 343 344 #define n_children(N) ((N)? (N)->children: 0) 345 346 /* maximal session key size */ 347 #define KEY_SIZE 127 348 349 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) 350 DEFINE_LHASH_OF(TABNODE); 351 #elif OPENSSL_VERSION_NUMBER >= 0x10000000L 352 DECLARE_LHASH_OF(TABNODE); 353 #endif 354 355 /* service definition */ 356 typedef struct _service { 357 char name[KEY_SIZE + 1]; /* symbolic name */ 358 MATCHER *url, /* request matcher */ 359 *req_head, /* required headers */ 360 *deny_head; /* forbidden headers */ 361 BACKEND *backends; 362 BACKEND *emergency; 363 int abs_pri; /* abs total priority for all back-ends */ 364 int tot_pri; /* total priority for current back-ends */ 365 pthread_mutex_t mut; /* mutex for this service */ 366 SESS_TYPE sess_type; 367 int sess_ttl; /* session time-to-live */ 368 regex_t sess_start; /* pattern to identify the session data */ 369 regex_t sess_pat; /* pattern to match the session data */ 370 #if OPENSSL_VERSION_NUMBER >= 0x10000000L 371 LHASH_OF(TABNODE) *sessions; /* currently active sessions */ 372 #else 373 LHASH *sessions; /* currently active sessions */ 374 #endif 375 int disabled; /* true if the service is disabled */ 376 struct _service *next; 377 } SERVICE; 378 379 #ifndef NO_EXTERNALS 380 extern SERVICE *services; /* global services (if any) */ 381 #endif /* NO_EXTERNALS */ 382 383 typedef struct _pound_ctx { 384 SSL_CTX *ctx; 385 char *server_name; 386 unsigned char **subjectAltNames; 387 unsigned int subjectAltNameCount; 388 struct _pound_ctx *next; 389 } POUND_CTX; 390 391 /* Listener definition */ 392 typedef struct _listener { 393 struct addrinfo addr; /* IPv4/6 address */ 394 int sock; /* listening socket */ 395 POUND_CTX *ctx; /* CTX for SSL connections */ 396 int clnt_check; /* client verification mode */ 397 int noHTTPS11; /* HTTP 1.1 mode for SSL */ 398 char *add_head; /* extra SSL header */ 399 regex_t verb; /* pattern to match the request verb against */ 400 int to; /* client time-out */ 401 int has_pat; /* was a URL pattern defined? */ 402 regex_t url_pat; /* pattern to match the request URL against */ 403 char *err414, /* error messages */ 404 *err500, 405 *err501, 406 *err503; 407 LONG max_req; /* max. request size */ 408 MATCHER *head_off; /* headers to remove */ 409 int rewr_loc; /* rewrite location response */ 410 int rewr_dest; /* rewrite destination header */ 411 int disabled; /* true if the listener is disabled */ 412 int log_level; /* log level for this listener */ 413 int allow_client_reneg; /* Allow Client SSL Renegotiation */ 414 int disable_ssl_v2; /* Disable SSL version 2 */ 415 SERVICE *services; 416 struct _listener *next; 417 } LISTENER; 418 419 #ifndef NO_EXTERNALS 420 extern LISTENER *listeners; /* all available listeners */ 421 #endif /* NO_EXTERNALS */ 422 423 typedef struct _thr_arg { 424 int sock; 425 LISTENER *lstn; 426 struct addrinfo from_host; 427 struct _thr_arg *next; 428 } thr_arg; /* argument to processing threads: socket, origin */ 429 430 /* Track SSL handshare/renegotiation so we can reject client-renegotiations. */ 431 typedef enum { RENEG_INIT=0, RENEG_REJECT, RENEG_ALLOW, RENEG_ABORT } RENEG_STATE; 432 433 /* Header types */ 434 #define HEADER_ILLEGAL -1 435 #define HEADER_OTHER 0 436 #define HEADER_TRANSFER_ENCODING 1 437 #define HEADER_CONTENT_LENGTH 2 438 #define HEADER_CONNECTION 3 439 #define HEADER_LOCATION 4 440 #define HEADER_CONTLOCATION 5 441 #define HEADER_HOST 6 442 #define HEADER_REFERER 7 443 #define HEADER_USER_AGENT 8 444 #define HEADER_URI 9 445 #define HEADER_DESTINATION 10 446 #define HEADER_EXPECT 11 447 #define HEADER_UPGRADE 13 448 449 /* control request stuff */ 450 typedef enum { 451 CTRL_LST, 452 CTRL_EN_LSTN, CTRL_DE_LSTN, 453 CTRL_EN_SVC, CTRL_DE_SVC, 454 CTRL_EN_BE, CTRL_DE_BE, 455 CTRL_ADD_SESS, CTRL_DEL_SESS 456 } CTRL_CODE; 457 458 typedef struct { 459 CTRL_CODE cmd; 460 int listener; 461 int service; 462 int backend; 463 char key[KEY_SIZE + 1]; 464 } CTRL_CMD; 465 466 #ifdef NEED_INADDRT 467 /* for oldish Unices - normally this is in /usr/include/netinet/in.h */ 468 typedef u_int32_t in_addr_t; 469 #endif 470 471 #ifdef NEED_INPORTT 472 /* for oldish Unices - normally this is in /usr/include/netinet/in.h */ 473 typedef u_int16_t in_port_t; 474 #endif 475 476 #ifdef NEED_TIMET 477 /* for oldish Unices - normally this is in /usr/include/time.h */ 478 typedef u_int32_t time_t; 479 #endif 480 481 /* 482 * add a request to the queue 483 */ 484 extern int put_thr_arg(thr_arg *); 485 486 /* 487 * get a request from the queue 488 */ 489 extern thr_arg *get_thr_arg(void); 490 491 /* 492 * get the current queue length 493 */ 494 extern int get_thr_qlen(void); 495 496 /* 497 * handle an HTTP request 498 */ 499 extern void *thr_http(void *); 500 501 /* 502 * Log an error to the syslog or to stderr 503 */ 504 extern void logmsg(const int, const char *, ...); 505 506 /* 507 * Parse a URL, possibly decoding hexadecimal-encoded characters 508 */ 509 extern int cpURL(char *, char *, int); 510 511 /* 512 * Translate inet/inet6 address into a string 513 */ 514 extern void addr2str(char *, const int, const struct addrinfo *, const int); 515 516 /* 517 * Return a string representation for a back-end address 518 */ 519 #define str_be(BUF, LEN, BE) addr2str((BUF), (LEN), &(BE)->addr, 0) 520 521 /* 522 * Find the right service for a request 523 */ 524 extern SERVICE *get_service(const LISTENER *, const char *, char **const); 525 526 /* 527 * Find the right back-end for a request 528 */ 529 extern BACKEND *get_backend(SERVICE *const, const struct addrinfo *, const char *, char **const); 530 531 /* 532 * Search for a host name, return the addrinfo for it 533 */ 534 extern int get_host(char *const, struct addrinfo *, int); 535 536 /* 537 * Find if a redirect needs rewriting 538 * In general we have two possibilities that require it: 539 * (1) if the redirect was done to the correct location with the wrong protocol 540 * (2) if the redirect was done to the back-end rather than the listener 541 */ 542 extern int need_rewrite(const int, char *const, char *const, const char *, const LISTENER *, const BACKEND *); 543 /* 544 * (for cookies only) possibly create session based on response headers 545 */ 546 extern void upd_session(SERVICE *const, char **const, BACKEND *const); 547 548 /* 549 * Parse a header 550 */ 551 extern int check_header(const char *, char *); 552 553 #define BE_DISABLE -1 554 #define BE_KILL 1 555 #define BE_ENABLE 0 556 /* 557 * mark a backend host as dead; 558 * do nothing if no resurection code is active 559 */ 560 extern void kill_be(SERVICE *const, const BACKEND *, const int); 561 562 /* 563 * Update the number of requests and time to answer for a given back-end 564 */ 565 extern void upd_be(SERVICE *const svc, BACKEND *const be, const double); 566 567 /* 568 * Non-blocking version of connect(2). Does the same as connect(2) but 569 * ensures it will time-out after a much shorter time period CONN_TO. 570 */ 571 extern int connect_nb(const int, const struct addrinfo *, const int); 572 573 /* 574 * Parse arguments/config file 575 */ 576 extern void config_parse(const int, char **const); 577 578 /* 579 * RSA ephemeral keys: how many and how often 580 */ 581 #define N_RSA_KEYS 11 582 #ifndef T_RSA_KEYS 583 #define T_RSA_KEYS 7200 584 #endif 585 586 /* 587 * return a pre-generated RSA key 588 */ 589 extern RSA *RSA_tmp_callback(SSL *, int, int); 590 591 /* 592 * return a pre-generated RSA key 593 */ 594 extern DH *DH_tmp_callback(SSL *, int, int); 595 596 /* 597 * Renegotiation callback 598 */ 599 extern void SSLINFO_callback(const SSL *s, int where, int rc); 600 601 /* 602 * expiration stuff 603 */ 604 #ifndef EXPIRE_TO 605 #define EXPIRE_TO 60 606 #endif 607 608 #ifndef HOST_TO 609 #define HOST_TO 300 610 #endif 611 612 /* 613 * initialise the timer functions: 614 * - host_mut 615 * - RSA_mut and keys 616 */ 617 extern void init_timer(void); 618 619 /* 620 * run timed functions: 621 * - RSAgen every T_RSA_KEYS seconds 622 * - resurrect every alive_to seconds 623 * - expire every EXPIRE_TO seconds 624 */ 625 extern void *thr_timer(void *); 626 627 /* 628 * The controlling thread 629 * listens to client requests and calls the appropriate functions 630 */ 631 extern void *thr_control(void *); 632