1 /* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; version 2 of the License. For a copy,
4 * see http://www.gnu.org/licenses/gpl-2.0.html.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 */
11
12 #include "config.h"
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdbool.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <time.h>
21 #include <poll.h>
22 #include <fcntl.h>
23 #include <signal.h>
24 #include <errno.h>
25 #include <pthread.h>
26 #include <syslog.h>
27 #include <grp.h>
28 #ifdef HAVE_NETINET_IN_H
29 #include <netinet/in.h>
30 #endif
31 #ifdef HAVE_NETINET_TCP_H
32 #include <netinet/tcp.h>
33 #endif
34 #include <sys/socket.h>
35 #include <sys/resource.h>
36 #include "global.h"
37 #include "alternative.h"
38 #include "mimetype.h"
39 #include "serverconfig.h"
40 #include "cgi.h"
41 #include "session.h"
42 #include "workers.h"
43 #include "send.h"
44 #include "client.h"
45 #include "log.h"
46 #include "global.h"
47 #include "httpauth.h"
48 #include "tomahawk.h"
49 #include "tls.h"
50 #include "cache.h"
51 #include "xslt.h"
52 #include "monitor.h"
53 #include "memdbg.h"
54 #include "challenge.h"
55
56 #define rs_NONE 0
57 #define rs_QUIT_SERVER 1
58 #define rs_UNBAN_CLIENTS 2
59 #define rs_UNLOCK_LOGFILES 3
60 #define rs_CLEAR_CACHE 4
61
62 #define MAX_TOMAHAWK_CONNECTIONS 3
63
64 typedef struct {
65 char *config_dir;
66 bool daemon;
67 bool config_check;
68 } t_settings;
69
70 static volatile int received_signal = rs_NONE;
71 static bool must_quit = false;
72 #ifdef ENABLE_LOADCHECK
73 static double current_server_load = 0;
74 #endif
75
76 char *fb_symlink = "symlink not allowed";
77 char *version_string = "Hiawatha v"VERSION;
78 char *enabled_modules = ""
79 #ifdef ENABLE_CACHE
80 ", Cache"
81 #endif
82 #ifdef ENABLE_DEBUG
83 ", debug"
84 #endif
85 #ifdef ENABLE_HTTP2
86 ", HTTP/2"
87 #endif
88 #ifdef ENABLE_MONITOR
89 ", Monitor"
90 #endif
91 #ifdef ENABLE_RPROXY
92 ", ReverseProxy"
93 #endif
94 #ifdef ENABLE_TLS
95 ", TLS v"MBEDTLS_VERSION_STRING
96 #endif
97 #ifdef ENABLE_TOMAHAWK
98 ", Tomahawk"
99 #endif
100 #ifdef ENABLE_TOOLKIT
101 ", UrlToolkit"
102 #endif
103 #ifdef ENABLE_XSLT
104 ", XSLT"
105 #endif
106 ;
107
108 /* Create all logfiles with the right ownership and accessrights
109 */
create_logfile(char * logfile,mode_t mode,uid_t uid,gid_t gid)110 void create_logfile(char *logfile, mode_t mode, uid_t uid, gid_t gid) {
111 if (logfile != NULL) {
112 if (create_file(logfile, mode, uid, gid) != 0) {
113 fprintf(stderr, "Error creating logfile %s or changing its protection or ownership.\n", logfile);
114 }
115 }
116 }
117
create_logfiles(t_config * config)118 void create_logfiles(t_config *config) {
119 t_host *host;
120
121 create_logfile(config->system_logfile, LOG_PERM, config->server_uid, config->server_gid);
122 create_logfile(config->garbage_logfile, LOG_PERM, config->server_uid, config->server_gid);
123 create_logfile(config->exploit_logfile, LOG_PERM, config->server_uid, config->server_gid);
124 #ifdef ENABLE_DEBUG
125 create_logfile(TLS_ERROR_LOGFILE, LOG_PERM, config->server_uid, config->server_gid);
126 #endif
127
128 host = config->first_host;
129 while (host != NULL) {
130 if (host->access_fileptr != NULL) {
131 fflush(host->access_fileptr);
132 }
133
134 create_logfile(host->access_logfile, LOG_PERM, config->server_uid, config->server_gid);
135 create_logfile(host->error_logfile, LOG_PERM, config->server_uid, config->server_gid);
136 host = host->next;
137 }
138 }
139
140 /* Task-runner starts periodic tasks
141 */
task_runner(t_config * config)142 void task_runner(t_config *config) {
143 t_ip_addr ip_addr;
144 int delay = 0;
145 time_t now;
146 #ifdef ENABLE_LOADCHECK
147 #ifdef HAVE_GETLOADAVG
148 double loadavg[1];
149 #else
150 FILE *load_fp = NULL;
151 char load_str[50], *c;
152 #endif
153 #ifdef ENABLE_MONITOR
154 int load_monitor_timer = 0;
155 #endif
156 #endif
157
158 do {
159 sleep(1);
160
161 if (delay >= TASK_RUNNER_INTERVAL) {
162 now = time(NULL);
163
164 #ifdef ENABLE_MEMDBG
165 /* Print memory usage
166 */
167 memdbg_print_log(true);
168 #endif
169
170 #ifdef ENABLE_THREAD_POOL
171 /* Manage thread pool
172 */
173 manage_thread_pool(config->thread_pool_size, config->thread_kill_rate);
174 #endif
175
176 /* Client checks
177 */
178 check_ban_list(config, now);
179 check_remove_deadlines(config, now);
180 remove_wrong_password_list(config);
181
182 /* FastCGI check
183 */
184 manage_load_balancer(config, now);
185
186 /* Close idle logfile handles
187 */
188 close_logfiles(config->first_host, now);
189
190 #ifdef ENABLE_CACHE
191 /* Cache check
192 */
193 manage_cache(now);
194 #endif
195
196 #ifdef ENABLE_MONITOR
197 /* Monitor stats
198 */
199 if (config->monitor_enabled) {
200 monitor_stats_to_buffer(config, now);
201 }
202 #endif
203
204 /* Rotate access logfiles
205 */
206 if (config->rotate_access_logs) {
207 rotate_access_logfiles(config, now);
208 }
209
210 delay = 0;
211 } else {
212 delay++;
213 }
214
215 #ifdef ENABLE_TOMAHAWK
216 /* Tomahawk check
217 */
218 check_admin_list();
219 #endif
220
221 #ifdef ENABLE_LOADCHECK
222 if (config->max_server_load > 0) {
223 #ifdef HAVE_GETLOADAVG
224 if (getloadavg(loadavg, 1) >= 1) {
225 current_server_load = loadavg[0];
226 #ifdef ENABLE_MONITOR
227 if (config->monitor_enabled) {
228 if ((current_server_load > config->max_server_load) && (load_monitor_timer == 0)) {
229 monitor_event("High server load (%0.2f)", current_server_load);
230 load_monitor_timer = 60;
231 }
232 }
233 #endif
234 } else {
235 current_server_load = 0;
236 }
237 #else
238 if ((load_fp = fopen("/proc/loadavg", "r")) != NULL) {
239 if (fgets(load_str, 49, load_fp) != NULL) {
240 load_str[49] = '\0';
241 if ((c = strchr(load_str, ' ')) != NULL) {
242 *c = '\0';
243 current_server_load = atof(load_str);
244 #ifdef ENABLE_MONITOR
245 if (config->monitor_enabled) {
246 if ((current_server_load > config->max_server_load) && (load_monitor_timer == 0)) {
247 monitor_event("High server load (%0.2f)", current_server_load);
248 load_monitor_timer = 60;
249 }
250 }
251 #endif
252 } else {
253 current_server_load = 0;
254 }
255 } else {
256 current_server_load = 0;
257 }
258
259 fclose(load_fp);
260 } else {
261 current_server_load = 0;
262 }
263 #endif
264
265 #ifdef ENABLE_MONITOR
266 if (load_monitor_timer > 0) {
267 load_monitor_timer--;
268 }
269 #endif
270 }
271 #endif
272
273 switch (received_signal) {
274 case rs_NONE:
275 break;
276 case rs_QUIT_SERVER:
277 must_quit = true;
278 break;
279 case rs_UNBAN_CLIENTS:
280 default_ipv4(&ip_addr);
281 unban_ip(&ip_addr);
282 default_ipv6(&ip_addr);
283 unban_ip(&ip_addr);
284 received_signal = rs_NONE;
285 break;
286 case rs_UNLOCK_LOGFILES:
287 close_logfiles(config->first_host, 0);
288 received_signal = rs_NONE;
289 break;
290 #ifdef ENABLE_CACHE
291 case rs_CLEAR_CACHE:
292 clear_cache();
293 received_signal = rs_NONE;
294 break;
295 #endif
296 }
297 } while (must_quit == false);
298
299 pthread_exit(NULL);
300 }
301
302 /* Signal handlers
303 */
SEGV_handler()304 void SEGV_handler() {
305 syslog(LOG_DAEMON | LOG_ALERT, "segmentation fault!");
306 #ifdef ENABLE_MONITOR
307 monitor_event("Server crash!");
308 shutdown_monitor_module();
309 #endif
310 exit(EXIT_FAILURE);
311 }
312
TERM_handler()313 void TERM_handler() {
314 received_signal = rs_QUIT_SERVER;
315 }
316
HUP_handler()317 void HUP_handler() {
318 received_signal = rs_UNLOCK_LOGFILES;
319 }
320
USR1_handler()321 void USR1_handler() {
322 received_signal = rs_UNBAN_CLIENTS;
323 }
324
325 #ifdef ENABLE_CACHE
USR2_handler()326 void USR2_handler() {
327 received_signal = rs_CLEAR_CACHE;
328 }
329 #endif
330
331 /* Create a socketlist.
332 */
bind_sockets(t_binding * binding)333 int bind_sockets(t_binding *binding) {
334 char ip_address[MAX_IP_STR_LEN], separator;
335 struct sockaddr_in saddr4;
336 struct sockaddr_in6 saddr6;
337 int domain, optval, result;
338
339 while (binding != NULL) {
340 domain = (binding->interface.family == AF_INET ? PF_INET : PF_INET6);
341 if ((binding->socket = socket(domain, SOCK_STREAM, 0)) == -1) {
342 perror("socket()");
343 return -1;
344 }
345
346 optval = 1;
347 if (setsockopt(binding->socket, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) == -1) {
348 perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
349 }
350
351 optval = 1;
352 if (setsockopt(binding->socket, IPPROTO_TCP, TCP_NODELAY, (void*)&optval, sizeof(int)) == -1) {
353 perror("setsockopt(IPPROTO_TCP, TCP_NODELAY)");
354 }
355
356 if (binding->interface.family == AF_INET) {
357 /* IPv4
358 */
359 memset(&saddr4, 0, sizeof(struct sockaddr_in));
360 saddr4.sin_family = AF_INET;
361 memcpy(&(saddr4.sin_addr.s_addr), &(binding->interface.value), IPv4_LEN);
362 saddr4.sin_port = htons(binding->port);
363
364 result = bind(binding->socket, (struct sockaddr*)&saddr4, sizeof(struct sockaddr_in));
365
366 separator = ':';
367 } else if (binding->interface.family == AF_INET6) {
368 /* IPv6
369 */
370 optval = 1;
371 if (setsockopt(binding->socket, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(int)) < 0) {
372 perror("setsockopt(IPPROTO_IPV6, IPV6_V6ONLY)");
373 }
374
375 memset(&saddr6, 0, sizeof(struct sockaddr_in6));
376 saddr6.sin6_family = AF_INET6;
377 memcpy(&(saddr6.sin6_addr.s6_addr), &(binding->interface.value), IPv6_LEN);
378 saddr6.sin6_port = htons(binding->port);
379
380 result = bind(binding->socket, (struct sockaddr*)&saddr6, sizeof(struct sockaddr_in6));
381
382 separator = '.';
383 } else {
384 fprintf(stderr, "Unknown protocol (family %d).\n", binding->interface.family);
385 return -1;
386 }
387
388 if (result == -1) {
389 /* Handle error
390 */
391 if (inet_ntop(binding->interface.family, &(binding->interface.value), ip_address, MAX_IP_STR_LEN) == NULL) {
392 strcpy(ip_address, "?.?.?.?");
393 }
394 fprintf(stderr, "Error binding %s%c%d\n", ip_address, separator, binding->port);
395 return -1;
396 }
397
398 binding = binding->next;
399 }
400
401 return 0;
402 }
403
404 /* Accept or deny an incoming connection.
405 */
accept_connection(t_binding * binding,t_config * config)406 int accept_connection(t_binding *binding, t_config *config) {
407 socklen_t size;
408 bool kick_client;
409 t_session *session;
410 struct sockaddr_in caddr4;
411 struct sockaddr_in6 caddr6;
412 int optval, connections_per_ip, total_connections;
413 struct timeval timer;
414 #ifdef ENABLE_DEBUG
415 static int thread_id = 1;
416 #endif
417
418 if ((session = (t_session*)malloc(sizeof(t_session))) == NULL) {
419 return -1;
420 }
421 #ifdef ENABLE_DEBUG
422 session->thread_id = thread_id++;
423 session->current_task = "new";
424 #endif
425 session->config = config;
426 session->binding = binding;
427 init_session(session);
428
429 if (binding->interface.family == AF_INET) {
430 /* IPv4
431 */
432 size = sizeof(struct sockaddr_in);
433 memset((void*)&caddr4, 0, (size_t)size);
434 if ((session->client_socket = accept(binding->socket, (struct sockaddr*)&caddr4, &size)) == -1) {
435 free(session);
436 log_system(config, "Error accepting incoming IPv4 connection: %s", strerror(errno));
437 if (errno == EINTR) {
438 return 0;
439 }
440 return -1;
441 }
442
443 session->ip_address.family = AF_INET;
444 session->ip_address.size = IPv4_LEN;
445 memcpy(&(session->ip_address.value), (char*)&caddr4.sin_addr.s_addr, session->ip_address.size);
446 } else if (binding->interface.family == AF_INET6) {
447 /* IPv6
448 */
449 size = sizeof(struct sockaddr_in6);
450 memset((void*)&caddr6, 0, (size_t)size);
451 if ((session->client_socket = accept(binding->socket, (struct sockaddr*)&caddr6, &size)) == -1) {
452 free(session);
453 log_system(config, "Error accepting incoming IPv6 connection: %s", strerror(errno));
454 if (errno == EINTR) {
455 return 0;
456 }
457 return -1;
458 }
459
460 session->ip_address.family = AF_INET6;
461 session->ip_address.size = IPv6_LEN;
462 memcpy(&(session->ip_address.value), (char*)&caddr6.sin6_addr.s6_addr, session->ip_address.size);
463 } else {
464 log_system_session(session, "Incoming connection via unknown protocol");
465 free(session);
466 return -1;
467 }
468
469 session->request_limit = (ip_allowed(&(session->ip_address), session->config->request_limit_mask) != deny);
470
471 #ifdef ENABLE_LOADCHECK
472 if ((session->config->max_server_load > 0) && session->request_limit) {
473 if (current_server_load > session->config->max_server_load) {
474 close(session->client_socket);
475 free(session);
476 log_system(config, "Connection dropped due to high server load.");
477 return -1;
478 }
479 }
480 #endif
481
482 if (in_iplist(config->hide_proxy, &(session->ip_address))) {
483 session->via_trusted_proxy = true;
484 }
485
486 if (session->request_limit == false) {
487 connections_per_ip = config->total_connections;
488 } else {
489 connections_per_ip = config->connections_per_ip;
490 }
491
492 kick_client = true;
493
494 if ((total_connections = connection_allowed(&(session->ip_address), session->via_trusted_proxy, connections_per_ip, config->total_connections)) >= 0) {
495 if (total_connections < (config->total_connections >> 2)) {
496 optval = 1;
497 if (setsockopt(session->client_socket, IPPROTO_TCP, TCP_NODELAY, (void*)&optval, sizeof(int)) == -1) {
498 close(session->client_socket);
499 free(session);
500 log_system(config, "error setsockopt(TCP_NODELAY)");
501 return -1;
502 }
503 }
504
505 if (config->socket_send_timeout > 0) {
506 timer.tv_sec = config->socket_send_timeout;
507 timer.tv_usec = 0;
508 if (setsockopt(session->client_socket, SOL_SOCKET, SO_SNDTIMEO, &timer, sizeof(struct timeval)) == -1) {
509 close(session->client_socket);
510 free(session);
511 log_system(config, "error setsockopt(SO_SNDTIMEO)");
512 return -1;
513 }
514 }
515
516 /* Start worker
517 */
518 if (start_worker(session) == 0) {
519 kick_client = false;
520 }
521 } else {
522 handle_connection_not_allowed(session, total_connections);
523 }
524
525 if (kick_client) {
526 close(session->client_socket);
527 free(session);
528 }
529
530 return 0;
531 }
532
533 /* Change UID and GID
534 */
change_uid_gid(t_config * config)535 int change_uid_gid(t_config *config) {
536 if (setgroups(config->groups.number, config->groups.array) == -1) {
537 return -1;
538 }
539
540 if (setgid(config->server_gid) == -1) {
541 return -1;
542 }
543
544 if (setuid(config->server_uid) == -1) {
545 return -1;
546 }
547
548 return 0;
549 }
550
551 /* Run the Hiawatha webserver.
552 */
run_webserver(t_settings * settings)553 int run_webserver(t_settings *settings) {
554 int number_of_bindings = 0;
555 pthread_attr_t task_runner_attr;
556 pthread_t task_runner_thread;
557 struct pollfd *poll_data, *current_poll;
558 #ifdef ENABLE_TOMAHAWK
559 int number_of_admins;
560 struct sockaddr_in caddr;
561 socklen_t size;
562 int admin_socket;
563 FILE *admin_fp;
564 #endif
565 pid_t pid;
566 t_binding *binding;
567 t_config *config;
568 mode_t access_rights;
569 #ifndef CYGWIN
570 struct rlimit resource_limit;
571 #endif
572 #ifdef ENABLE_TLS
573 t_host *host;
574 t_tls_setup tls_setup;
575 #endif
576 #ifdef HAVE_ACCF
577 struct accept_filter_arg afa;
578 #endif
579
580 /* Read configuration
581 */
582 if (init_config_module(settings->config_dir) == -1) {
583 perror("init_config_module()");
584 return -1;
585 } else if ((config = default_config()) == NULL) {
586 perror("default_config()");
587 return -1;
588 } else if (chdir(settings->config_dir) == -1) {
589 perror(settings->config_dir);
590 return -1;
591 } else if (settings->config_check) {
592 printf("Using %s\n", settings->config_dir);
593 }
594
595 if (read_main_configfile("hiawatha.conf", config, settings->config_check) == -1) {
596 return -1;
597 } else if (check_configuration(config) == -1) {
598 return -1;
599 }
600
601 if (read_mimetypes(config->mimetype_config, &(config->mimetype), settings->config_check) == -1) {
602 fprintf(stderr, "Error while reading mimetype configuration.\n");
603 return -1;
604 }
605
606 if (settings->config_check) {
607 printf("Configuration OK.\n");
608 return 0;
609 }
610
611 /* Bind Serverports
612 */
613 if (bind_sockets(config->binding) == -1) {
614 return -1;
615 }
616
617 #ifdef ENABLE_TLS
618 if (init_tls_module(config->ca_certificates) == -1) {
619 return -1;
620 }
621
622 tls_setup.min_tls_version = config->min_tls_version;
623 tls_setup.dh_size = config->dh_size;
624 #endif
625
626 /* Load private keys and certificate for bindings
627 */
628 binding = config->binding;
629 while (binding != NULL) {
630 #ifdef ENABLE_TLS
631 if (binding->use_tls) {
632 if (tls_load_key_cert(binding->key_cert_file, &(binding->private_key), &(binding->certificate)) != 0) {
633 return -1;
634 }
635
636 if (binding->ca_cert_file != NULL) {
637 if (tls_load_ca_cert(binding->ca_cert_file, &(binding->ca_certificate)) != 0) {
638 return -1;
639 }
640 if (binding->ca_crl_file != NULL) {
641 if (tls_load_ca_crl(binding->ca_crl_file, &(binding->ca_crl)) != 0) {
642 return -1;
643 }
644 }
645 }
646
647 tls_setup.private_key = binding->private_key;
648 tls_setup.certificate = binding->certificate;
649 tls_setup.ca_certificate = binding->ca_certificate;
650 tls_setup.ca_crl = binding->ca_crl;
651
652 if (tls_set_config(&(binding->tls_config), &tls_setup) != 0) {
653 return -1;
654 }
655
656 #ifdef ENABLE_HTTP2
657 if (binding->use_tls && binding->accept_http2) {
658 tls_accept_http2(binding->tls_config);
659 }
660 #endif
661 }
662 #endif
663
664 number_of_bindings++;
665 binding = binding->next;
666 }
667
668 #ifdef ENABLE_TOMAHAWK
669 binding = config->tomahawk_port;
670 while (binding != NULL) {
671 number_of_bindings++;
672 binding = binding->next;
673 }
674 #endif
675
676 #ifdef ENABLE_TLS
677 host = config->first_host;
678 while (host != NULL) {
679 /* Load private key and certificates for virtual hosts
680 */
681 if (host->key_cert_file != NULL) {
682 if (tls_load_key_cert(host->key_cert_file, &(host->private_key), &(host->certificate)) != 0) {
683 return -1;
684 }
685 }
686
687 if (host->ca_cert_file != NULL) {
688 if (tls_load_ca_cert(host->ca_cert_file, &(host->ca_certificate)) != 0) {
689 return -1;
690 }
691 if (host->ca_crl_file != NULL) {
692 if (tls_load_ca_crl(host->ca_crl_file, &(host->ca_crl)) != 0) {
693 return -1;
694 }
695 }
696 }
697
698 if (host->hpkp_data != NULL) {
699 if (create_hpkp_header(host->hpkp_data) == -1) {
700 fprintf(stderr, "Error generating HPKP header for %s.\n", host->hostname.item[0]);
701 return -1;
702 }
703 host->hpkp_data->next = NULL;
704 }
705
706 /* Initialize Server Name Indication
707 */
708 if ((host->private_key != NULL) && (host->certificate != NULL)) {
709 tls_setup.private_key = host->private_key;
710 tls_setup.certificate = host->certificate;
711 tls_setup.ca_certificate = host->ca_certificate;
712 tls_setup.ca_crl = host->ca_crl;
713
714 if (tls_register_sni(&(host->hostname), &tls_setup) == -1) {
715 return -1;
716 }
717 }
718
719 host = host->next;
720 }
721 #endif
722
723 #ifdef ENABLE_TOMAHAWK
724 /* Bind Tomahawk
725 */
726 if (bind_sockets(config->tomahawk_port) == -1) {
727 return -1;
728 }
729 #endif
730
731 /* Misc settings
732 */
733 tzset();
734 clearenv();
735 umask(0117);
736
737 /* Become a daemon
738 */
739 if (settings->daemon) {
740 switch (pid = fork()) {
741 case -1:
742 perror("fork()");
743 return -1;
744 case 0:
745 if (setsid() == -1) {
746 perror("setsid()");
747 return -1;
748 }
749 break;
750 default:
751 log_pid(config, pid, config->server_uid);
752 return 0;
753 }
754 } else {
755 log_pid(config, getpid(), config->server_uid);
756 }
757
758 /* Create work directory
759 */
760 if (create_directory(config->work_directory, S_IRWXU, config->server_uid, config->server_gid) == -1) {
761 fprintf(stderr, "Error creating work directory '%s'\n", config->work_directory);
762 return -1;
763 }
764
765 /* Create gzipped work directory
766 */
767 if (create_directory(config->gzipped_directory, S_IRWXU, config->server_uid, config->server_gid) == -1) {
768 fprintf(stderr, "Error creating gzip work directory '%s'\n", config->gzipped_directory);
769 return -1;
770 }
771
772 wipe_directory(config->gzipped_directory, ".gz");
773
774 /* Create the upload directory for PUT requests
775 */
776 if ((getuid() == 0) || (geteuid() == 0)) {
777 access_rights = S_ISVTX | S_IRWXU | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH;
778 } else {
779 access_rights = S_ISVTX | S_IWUSR | S_IXUSR | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH;
780 }
781
782 if (create_directory(config->upload_directory, access_rights, 0, 0) != 0) {
783 fprintf(stderr, "Error creating upload directory '%s'\n", config->upload_directory);
784 return -1;
785 }
786
787 #ifdef ENABLE_MONITOR
788 /* Create monitor cache directory
789 */
790 if (config->monitor_enabled) {
791 if (create_directory(config->monitor_directory, S_IRWXU, config->server_uid, config->server_gid) != 0) {
792 fprintf(stderr, "Error creating monitor cache directory %s or changing its protection or ownership.\n", config->monitor_directory);
793 return -1;
794 }
795 }
796 #endif
797
798 /* Initialize random generator
799 */
800 srand((unsigned)time(NULL));
801
802 /* Create logfiles
803 */
804 create_logfiles(config);
805
806 #ifndef CYGWIN
807 /* Set resource limits
808 */
809 if (config->set_rlimits) {
810 resource_limit.rlim_max = resource_limit.rlim_cur = config->total_connections + 3;
811 if (setrlimit(RLIMIT_NPROC, &resource_limit) != 0) {
812 fprintf(stderr, "Error setting RLIMIT_NPROC.\n");
813 }
814
815 /* system: system.log, exploit.log, garbage.log, debug.log, all bindings, tomahawk connections
816 * per child: socket, access.log, error.log, 3 CGI pipes
817 */
818 resource_limit.rlim_max = resource_limit.rlim_cur = 4 + number_of_bindings + MAX_TOMAHAWK_CONNECTIONS +
819 6 * config->total_connections;
820 if (setrlimit(RLIMIT_NOFILE, &resource_limit) != 0) {
821 fprintf(stderr, "Error setting RLIMIT_NOFILE.\n");
822 }
823 }
824
825 /* Change user and group id
826 */
827 if ((getuid() == 0) || (geteuid() == 0)) {
828 if (change_uid_gid(config) == -1) {
829 fprintf(stderr, "\nError while changing uid/gid!\n");
830 return -1;
831 }
832 }
833 #endif
834
835 /* Set signal handlers
836 */
837 if (settings->daemon == false) {
838 printf("Press Ctrl-C to shutdown the Hiawatha webserver.\n");
839 signal(SIGINT, TERM_handler);
840 } else {
841 signal(SIGINT, SIG_IGN);
842 }
843 if (config->wait_for_cgi == false) {
844 signal(SIGCHLD, SIG_IGN);
845 }
846 signal(SIGPIPE, SIG_IGN);
847 signal(SIGTSTP, SIG_IGN);
848 signal(SIGABRT, SIG_IGN);
849 signal(SIGQUIT, SIG_IGN);
850 signal(SIGSEGV, SEGV_handler);
851 signal(SIGTERM, TERM_handler);
852 signal(SIGHUP, HUP_handler);
853 signal(SIGUSR1, USR1_handler);
854 #ifdef ENABLE_CACHE
855 signal(SIGUSR2, USR2_handler);
856 #endif
857
858 /* Start listening for incoming connections
859 */
860 binding = config->binding;
861 while (binding != NULL) {
862 if (listen(binding->socket, config->listen_backlog) == -1) {
863 perror("listen(http(s))");
864 return -1;
865 }
866 binding = binding->next;
867 }
868 #ifdef ENABLE_TOMAHAWK
869 binding = config->tomahawk_port;
870 while (binding != NULL) {
871 if (listen(binding->socket, 1) == -1) {
872 perror("listen(tomahawk)");
873 return -1;
874 }
875 binding = binding->next;
876 }
877 #endif
878
879 #ifdef ENABLE_THREAD_POOL
880 if (init_workers_module(config->thread_pool_size) == -1) {
881 fprintf(stderr, "Error initializing workers module.\n");
882 return -1;
883 }
884 #endif
885 if (init_httpauth_module() == -1) {
886 fprintf(stderr, "Error initializing HTTP authentication module.\n");
887 return -1;
888 }
889 init_send_module();
890 if (init_log_module(config) == -1) {
891 fprintf(stderr, "Error initializing log module.\n");
892 return -1;
893 }
894 if (init_client_module() == -1) {
895 fprintf(stderr, "Error initializing client module.\n");
896 return -1;
897 }
898 if (init_load_balancer(config->fcgi_server) == -1) {
899 fprintf(stderr, "Error initializing FastCGI load balancer.\n");
900 return -1;
901 }
902 #ifdef ENABLE_CACHE
903 if (init_cache_module() == -1) {
904 fprintf(stderr, "Error initializing cache module.\n");
905 return -1;
906 }
907 #endif
908 #ifdef ENABLE_TOMAHAWK
909 if (init_tomahawk_module() == -1) {
910 fprintf(stderr, "Error initializing Tomahawk module.\n");
911 return -1;
912 }
913 #endif
914 #ifdef ENABLE_XSLT
915 init_xslt_module();
916 #endif
917 #ifdef ENABLE_RPROXY
918 if (init_rproxy_module() == -1) {
919 fprintf(stderr, "Error initializing reverse proxy module.\n");
920 return -1;
921 }
922 #endif
923 if (init_sqli_detection() == -1) {
924 fprintf(stderr, "Error initializing SQL injection detection.\n");
925 return -1;
926 }
927 #ifdef ENABLE_MONITOR
928 if (config->monitor_enabled) {
929 if (init_monitor_module(config) == -1) {
930 fprintf(stderr, "Error initializing Monitor module.\n");
931 return -1;
932 }
933 monitor_event("Server start");
934 monitor_version(version_string, enabled_modules);
935 }
936 #endif
937 #ifdef ENABLE_MEMDBG
938 init_memdbg();
939 #endif
940 if (init_challenge_module(config->challenge_secret) == -1) {
941 fprintf(stderr, "Error initializing ChallengeClient module.\n");
942 return -1;
943 }
944
945 #ifdef HAVE_ACCF
946 binding = config->binding;
947 while (binding != NULL) {
948 if (binding->enable_accf
949 #ifdef ENABLE_TLS
950 && (binding->use_tls == false)
951 #endif
952 ) {
953 bzero(&afa, sizeof(afa));
954 strcpy(afa.af_name, "httpready");
955 if (setsockopt(binding->socket, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) == -1) {
956 fprintf(stderr, "Error while enabling HTTP accept filter. Kernel module 'accf_http' loaded?");
957 return -1;
958 }
959 }
960 binding = binding->next;
961 }
962 #endif
963
964 /* Redirecting I/O to /dev/null
965 */
966 if (settings->daemon) {
967 if (close(STDIN_FILENO) == -1) {
968 fprintf(stderr, "Warning: error closing STDIN\n");
969 } else if (open("/dev/null", O_RDONLY) == -1) {
970 fprintf(stderr, "Warning: error redirecting stdin\n");
971 }
972 if (close(STDOUT_FILENO) == -1) {
973 fprintf(stderr, "Warning: error closing STDOUT\n");
974 } else if (open("/dev/null", O_WRONLY) == -1) {
975 fprintf(stderr, "Warning: error redirecting stdout\n");
976 }
977 if (close(STDERR_FILENO) == -1) {
978 fprintf(stderr, "Warning: error closing STDERR\n");
979 } else if (open("/dev/null", O_WRONLY) == -1) {
980 log_system(config, "Warning: error redirecting stderr\n");
981 }
982 }
983
984 log_system(config, "Hiawatha v"VERSION" started.");
985
986 /* Start task_runner
987 */
988 if (pthread_attr_init(&task_runner_attr) != 0) {
989 log_system(config, "Task-runner pthread init error.");
990 return -1;
991 } else if (pthread_attr_setdetachstate(&task_runner_attr, PTHREAD_CREATE_DETACHED) != 0) {
992 log_system(config, "Task-runner pthread set detach state error.");
993 return -1;
994 } else if (pthread_attr_setstacksize(&task_runner_attr, PTHREAD_STACK_SIZE) != 0) {
995 log_system(config, "Task-runner pthread set stack size error.");
996 return -1;
997 } else if (pthread_create(&task_runner_thread, &task_runner_attr, (void*)task_runner, (void*)config) != 0) {
998 log_system(config, "Task-runner pthread create error.");
999 return -1;
1000 }
1001 pthread_attr_destroy(&task_runner_attr);
1002
1003 #ifdef ENABLE_MEMDBG
1004 /* Clear memory debugger log
1005 */
1006 memdbg_clear_log();
1007 #endif
1008
1009 /* Setup poll data
1010 */
1011 if ((poll_data = (struct pollfd*)malloc((number_of_bindings + MAX_TOMAHAWK_CONNECTIONS) * sizeof(struct pollfd))) == NULL) {
1012 return -1;
1013 }
1014
1015 current_poll = poll_data;
1016
1017 binding = config->binding;
1018 while (binding != NULL) {
1019 current_poll->fd = binding->socket;
1020 current_poll->events = POLL_EVENT_BITS;
1021 binding->poll_data = current_poll;
1022
1023 current_poll++;
1024 binding = binding->next;
1025 }
1026
1027 #ifdef ENABLE_TOMAHAWK
1028 binding = config->tomahawk_port;
1029 while (binding != NULL) {
1030 current_poll->fd = binding->socket;
1031 current_poll->events = POLL_EVENT_BITS;
1032 binding->poll_data = current_poll;
1033
1034 current_poll++;
1035 binding = binding->next;
1036 }
1037 #endif
1038
1039 /* Main loop
1040 */
1041 do {
1042 #ifdef ENABLE_TOMAHAWK
1043 current_poll = poll_data + number_of_bindings;
1044 number_of_admins = prepare_admins_for_poll(current_poll);
1045
1046 switch (poll(poll_data, number_of_bindings + number_of_admins, 1000)) {
1047 #else
1048 switch (poll(poll_data, number_of_bindings, 1000)) {
1049 #endif
1050 case -1:
1051 if (errno != EINTR) {
1052 log_system(config, "Fatal error selecting connection.");
1053 usleep(1000);
1054 }
1055 break;
1056 case 0:
1057 break;
1058 default:
1059 #ifdef ENABLE_TOMAHAWK
1060 /* Connected admins */
1061 handle_admins(config);
1062 #endif
1063
1064 /* HTTP(S) ports */
1065 binding = config->binding;
1066 while (binding != NULL) {
1067 if (binding->poll_data->revents != 0) {
1068 if (accept_connection(binding, config) != 0) {
1069 usleep(1000);
1070 break;
1071
1072 }
1073 }
1074 binding = binding->next;
1075 }
1076
1077 #ifdef ENABLE_TOMAHAWK
1078 /* Tomahawk ports */
1079 binding = config->tomahawk_port;
1080 while (binding != NULL) {
1081 if (binding->poll_data->revents != 0) {
1082 size = sizeof(struct sockaddr_in);
1083 memset((void*)&caddr, 0, (size_t)size);
1084 if ((admin_socket = accept(binding->socket, (struct sockaddr*)&caddr, &size)) == -1) {
1085 if (errno != EINTR) {
1086 log_system(config, "Fatal error accepting Tomahawk connection.");
1087 usleep(1000);
1088 break;
1089 }
1090 } else if (number_of_admins >= MAX_TOMAHAWK_CONNECTIONS) {
1091 if ((admin_fp = fdopen(admin_socket, "r+")) != NULL) {
1092 fprintf(admin_fp, "Maximum number of admin connections reached.\n\n");
1093 fclose(admin_fp);
1094 } else {
1095 close(admin_socket);
1096 }
1097 } else if (add_admin(admin_socket) == -1) {
1098 close(admin_socket);
1099 }
1100 }
1101 binding = binding->next;
1102 }
1103 #endif
1104 }
1105 } while (must_quit == false);
1106
1107 signal(SIGTERM, SIG_DFL);
1108
1109 close_bindings(config->binding);
1110
1111 disconnect_clients(config);
1112 #ifdef ENABLE_TOMAHAWK
1113 disconnect_admins();
1114 #endif
1115
1116 #ifdef ENABLE_TOMAHAWK
1117 binding = config->tomahawk_port;
1118 while (binding != NULL) {
1119 close(binding->socket);
1120 binding = binding->next;
1121 }
1122 #endif
1123
1124 #ifdef ENABLE_MONITOR
1125 if (config->monitor_enabled) {
1126 monitor_event("Server stop");
1127 shutdown_monitor_module();
1128 }
1129 #endif
1130
1131 log_system(config, "Hiawatha v"VERSION" stopped.");
1132 close_logfiles(config->first_host, 0);
1133
1134 free(poll_data);
1135
1136 return 0;
1137 }
1138
1139 void show_help(char *hiawatha) {
1140 printf("Usage: %s [options]\n", hiawatha);
1141 printf("Options: -c <path>: path to where the configrationfiles are located.\n");
1142 printf(" -d: don't fork to the background.\n");
1143 printf(" -h: show this information and exit.\n");
1144 printf(" -k: check configuration and exit.\n");
1145 printf(" -m: show enabled modules and exit.\n");
1146 printf(" -v: show version and copyright and exit.\n");
1147 }
1148
1149 /* Main and stuff...
1150 */
1151 int main(int argc, char *argv[]) {
1152 int i = 0;
1153 t_settings settings;
1154
1155 /* Default settings
1156 */
1157 settings.config_dir = CONFIG_DIR;
1158 settings.daemon = true;
1159 settings.config_check = false;
1160
1161 /* Read command line parameters
1162 */
1163 while (++i < argc) {
1164 if (strcmp(argv[i], "-c") == 0) {
1165 if (++i < argc) {
1166 settings.config_dir = argv[i];
1167 } else {
1168 fprintf(stderr, "Specify a directory.\n");
1169 return EXIT_FAILURE;
1170 }
1171 } else if (strcmp(argv[i], "-d") == 0) {
1172 settings.daemon = false;
1173 } else if (strcmp(argv[i], "-h") == 0) {
1174 show_help(argv[0]);
1175 return EXIT_SUCCESS;
1176 } else if (strcmp(argv[i], "-k") == 0) {
1177 settings.config_check = true;
1178 } else if (strcmp(argv[i], "-m") == 0) {
1179 if (strlen(enabled_modules) == 0) {
1180 enabled_modules = "none";
1181 } else {
1182 enabled_modules += 2;
1183 }
1184 printf("Enabled modules: %s\n", enabled_modules);
1185 return EXIT_SUCCESS;
1186 } else if (strcmp(argv[i], "-v") == 0) {
1187 printf("%s, copyright (c) by Hugo Leisink <hugo@leisink.net>\n", version_string);
1188 return EXIT_SUCCESS;
1189 } else {
1190 fprintf(stderr, "Unknown option. Use '-h' for help.\n");
1191 return EXIT_FAILURE;
1192 }
1193 }
1194
1195 /* Run Hiawatha
1196 */
1197 if (run_webserver(&settings) == -1) {
1198 return EXIT_FAILURE;
1199 }
1200
1201 return EXIT_SUCCESS;
1202 }
1203