Line data Source code
1 : /*
2 : * lwan - web server
3 : * Copyright (c) 2012, 2013 L. A. F. Pereira <l@tia.mat.br>
4 : *
5 : * This program is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU General Public License
7 : * as published by the Free Software Foundation; either version 2
8 : * of the License, or any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : * GNU General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License
16 : * along with this program; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 : * USA.
19 : */
20 :
21 : #define _GNU_SOURCE
22 : #include <assert.h>
23 : #include <ctype.h>
24 : #include <dlfcn.h>
25 : #include <errno.h>
26 : #include <fcntl.h>
27 : #include <libproc.h>
28 : #include <limits.h>
29 : #include <signal.h>
30 : #include <stdlib.h>
31 : #include <string.h>
32 : #include <sys/resource.h>
33 : #include <sys/socket.h>
34 : #include <sys/types.h>
35 : #include <unistd.h>
36 :
37 : #include "lwan-private.h"
38 :
39 : #include "lwan-config.h"
40 : #include "lwan-http-authorize.h"
41 :
42 : #if defined(LWAN_HAVE_LUA)
43 : #include "lwan-lua.h"
44 : #endif
45 :
46 : /* Ideally, this would check if all items in enum lwan_request_flags,
47 : * when bitwise-or'd together, would not have have any bit set that
48 : * is also set in REQUEST_METHOD_MASK. */
49 : static_assert(REQUEST_ACCEPT_DEFLATE > REQUEST_METHOD_MASK,
50 : "enough bits to store request methods");
51 :
52 : /* See detect_fastest_monotonic_clock() */
53 : clockid_t monotonic_clock_id = CLOCK_MONOTONIC;
54 :
55 : static const struct lwan_config default_config = {
56 : .listener = "localhost:8080",
57 : .keep_alive_timeout = 15,
58 : .quiet = false,
59 : .proxy_protocol = false,
60 : .allow_cors = false,
61 : .expires = 1 * ONE_WEEK,
62 : .n_threads = 0,
63 : .max_post_data_size = 10 * DEFAULT_BUFFER_SIZE,
64 : .allow_post_temp_file = false,
65 : .max_put_data_size = 10 * DEFAULT_BUFFER_SIZE,
66 : .allow_put_temp_file = false,
67 : };
68 :
69 0 : LWAN_HANDLER_ROUTE(brew_coffee, NULL /* do not autodetect this route */)
70 : {
71 : /* Placeholder handler so that __start_lwan_handler and __stop_lwan_handler
72 : * symbols will get defined.
73 : */
74 0 : return HTTP_I_AM_A_TEAPOT;
75 : }
76 :
77 : __attribute__((no_sanitize_address))
78 1084 : static void *find_handler(const char *name)
79 : {
80 : const struct lwan_handler_info *handler;
81 :
82 5820 : LWAN_SECTION_FOREACH(lwan_handler, handler) {
83 5820 : if (streq(handler->name, name))
84 1084 : return handler->handler;
85 : }
86 :
87 0 : return NULL;
88 : }
89 :
90 : __attribute__((no_sanitize_address))
91 875 : static const struct lwan_module *find_module(const char *name)
92 : {
93 : const struct lwan_module_info *module;
94 :
95 3075 : LWAN_SECTION_FOREACH(lwan_module, module) {
96 3075 : if (streq(module->name, name))
97 875 : return module->module;
98 : }
99 :
100 0 : return NULL;
101 : }
102 :
103 0 : static void destroy_urlmap(void *data)
104 : {
105 0 : struct lwan_url_map *url_map = data;
106 :
107 0 : if (url_map->module) {
108 0 : const struct lwan_module *module = url_map->module;
109 :
110 0 : if (module->destroy)
111 0 : module->destroy(url_map->data);
112 0 : } else if (url_map->data && url_map->flags & HANDLER_DATA_IS_HASH_TABLE) {
113 0 : hash_free(url_map->data);
114 : }
115 :
116 0 : free(url_map->authorization.realm);
117 0 : free(url_map->authorization.password_file);
118 0 : free((char *)url_map->prefix);
119 0 : free(url_map);
120 0 : }
121 :
122 1959 : static struct lwan_url_map *add_url_map(struct lwan_trie *t, const char *prefix,
123 : const struct lwan_url_map *map)
124 : {
125 1959 : struct lwan_url_map *copy = malloc(sizeof(*copy));
126 :
127 1959 : if (!copy)
128 0 : lwan_status_critical_perror("Could not copy URL map");
129 :
130 1959 : memcpy(copy, map, sizeof(*copy));
131 :
132 1959 : copy->prefix = strdup(prefix ? prefix : copy->prefix);
133 1959 : if (!copy->prefix)
134 0 : lwan_status_critical_perror("Could not copy URL prefix");
135 :
136 1959 : copy->prefix_len = strlen(copy->prefix);
137 1959 : lwan_trie_add(t, copy->prefix, copy);
138 :
139 1959 : return copy;
140 : }
141 :
142 174 : static bool can_override_header(const char *name)
143 : {
144 : /* NOTE: Update lwan_prepare_response_header_full() in lwan-response.c
145 : * if new headers are added here. */
146 :
147 174 : if (strcaseequal_neutral(name, "Date"))
148 0 : return false;
149 174 : if (strcaseequal_neutral(name, "Expires"))
150 0 : return false;
151 174 : if (strcaseequal_neutral(name, "WWW-Authenticate"))
152 0 : return false;
153 174 : if (strcaseequal_neutral(name, "Connection"))
154 0 : return false;
155 174 : if (strcaseequal_neutral(name, "Content-Type"))
156 0 : return false;
157 174 : if (strcaseequal_neutral(name, "Transfer-Encoding"))
158 0 : return false;
159 174 : if (!strncasecmp(name, "Access-Control-Allow-",
160 : sizeof("Access-Control-Allow-") - 1))
161 0 : return false;
162 :
163 174 : return true;
164 : }
165 :
166 92 : static void build_response_headers(struct lwan *l,
167 : const struct lwan_key_value *kv)
168 : {
169 : struct lwan_strbuf strbuf;
170 92 : bool set_server = false;
171 :
172 92 : assert(l);
173 :
174 92 : lwan_strbuf_init(&strbuf);
175 :
176 266 : for (; kv && kv->key; kv++) {
177 174 : if (!can_override_header(kv->key)) {
178 0 : lwan_status_warning("Cannot override header '%s'", kv->key);
179 : } else {
180 174 : if (strcaseequal_neutral(kv->key, "Server"))
181 87 : set_server = true;
182 :
183 174 : lwan_strbuf_append_printf(&strbuf, "\r\n%s: %s", kv->key,
184 174 : kv->value);
185 : }
186 : }
187 :
188 92 : if (!set_server)
189 5 : lwan_strbuf_append_strz(&strbuf, "\r\nServer: lwan");
190 :
191 92 : lwan_strbuf_append_strz(&strbuf, "\r\n\r\n");
192 :
193 92 : l->headers = (struct lwan_value){.value = lwan_strbuf_get_buffer(&strbuf),
194 92 : .len = lwan_strbuf_get_length(&strbuf)};
195 92 : }
196 :
197 87 : static void parse_global_headers(struct config *c,
198 : struct lwan *lwan)
199 : {
200 : struct lwan_key_value_array hdrs;
201 : const struct config_line *l;
202 : struct lwan_key_value *kv;
203 :
204 87 : lwan_key_value_array_init(&hdrs);
205 :
206 348 : while ((l = config_read_line(c))) {
207 261 : switch (l->type) {
208 0 : case CONFIG_LINE_TYPE_SECTION:
209 0 : config_error(
210 : c, "No sections are supported under the 'headers' section");
211 0 : goto cleanup;
212 :
213 174 : case CONFIG_LINE_TYPE_LINE:
214 174 : kv = lwan_key_value_array_append(&hdrs);
215 174 : if (!kv) {
216 0 : lwan_status_critical_perror(
217 : "Could not allocate memory for custom response header");
218 : }
219 :
220 174 : kv->key = strdup(l->key);
221 174 : if (!kv->key) {
222 0 : lwan_status_critical_perror(
223 : "Could not allocate memory for custom response header");
224 : }
225 :
226 174 : kv->value = strdup(l->value);
227 174 : if (!kv->value) {
228 0 : lwan_status_critical_perror(
229 : "Could not allocate memory for custom response header");
230 : }
231 174 : break;
232 :
233 87 : case CONFIG_LINE_TYPE_SECTION_END:
234 87 : kv = lwan_key_value_array_append(&hdrs);
235 87 : if (!kv) {
236 0 : lwan_status_critical_perror(
237 : "Could not allocate memory for custom response header");
238 : }
239 :
240 87 : kv->key = NULL;
241 87 : kv->value = NULL;
242 :
243 87 : build_response_headers(lwan, lwan_key_value_array_get_array(&hdrs));
244 87 : goto cleanup;
245 : }
246 : }
247 :
248 0 : config_error(c, "EOF while looking for end of 'headers' section");
249 :
250 87 : cleanup:
251 348 : LWAN_ARRAY_FOREACH (&hdrs, kv) {
252 261 : free(kv->key);
253 261 : free(kv->value);
254 : }
255 87 : lwan_key_value_array_reset(&hdrs);
256 87 : }
257 :
258 87 : static void parse_listener_prefix_authorization(struct config *c,
259 : const struct config_line *l,
260 : struct lwan_url_map *url_map)
261 : {
262 87 : if (!streq(l->value, "basic")) {
263 0 : config_error(c, "Only basic authorization supported");
264 0 : return;
265 : }
266 :
267 87 : memset(&url_map->authorization, 0, sizeof(url_map->authorization));
268 :
269 348 : while ((l = config_read_line(c))) {
270 261 : switch (l->type) {
271 174 : case CONFIG_LINE_TYPE_LINE:
272 174 : if (streq(l->key, "realm")) {
273 87 : free(url_map->authorization.realm);
274 87 : url_map->authorization.realm = strdup(l->value);
275 87 : } else if (streq(l->key, "password_file")) {
276 87 : free(url_map->authorization.password_file);
277 87 : url_map->authorization.password_file = realpath(l->value, NULL);
278 87 : if (!url_map->authorization.password_file)
279 0 : config_error(c, "Could not determine full path for password file: %s", l->value);
280 : }
281 174 : break;
282 :
283 0 : case CONFIG_LINE_TYPE_SECTION:
284 0 : config_error(c, "Unexpected section: %s", l->key);
285 0 : goto error;
286 :
287 87 : case CONFIG_LINE_TYPE_SECTION_END:
288 87 : if (!url_map->authorization.realm)
289 0 : url_map->authorization.realm = strdup("Lwan");
290 87 : if (!url_map->authorization.password_file)
291 0 : url_map->authorization.password_file = strdup("htpasswd");
292 :
293 87 : url_map->flags |= HANDLER_MUST_AUTHORIZE;
294 87 : return;
295 : }
296 : }
297 :
298 0 : config_error(c, "Could not find end of authorization section");
299 :
300 0 : error:
301 0 : free(url_map->authorization.realm);
302 0 : free(url_map->authorization.password_file);
303 : }
304 :
305 : __attribute__((no_sanitize_address))
306 875 : static const char *get_module_name(const struct lwan_module *module)
307 : {
308 : const struct lwan_module_info *iter;
309 :
310 3075 : LWAN_SECTION_FOREACH(lwan_module, iter) {
311 3075 : if (iter->module == module)
312 875 : return iter->name;
313 : }
314 :
315 0 : return "<unknown>";
316 : }
317 :
318 1959 : static void parse_listener_prefix(struct config *c,
319 : const struct config_line *l,
320 : struct lwan *lwan,
321 : const struct lwan_module *module,
322 : void *handler)
323 : {
324 1959 : struct lwan_url_map url_map = {};
325 1959 : struct hash *hash = hash_str_new(free, free);
326 1959 : char *prefix = strdupa(l->value);
327 : struct config *isolated;
328 :
329 1959 : if (!hash)
330 0 : lwan_status_critical("Could not allocate hash table");
331 :
332 1959 : isolated = config_isolate_section(c, l);
333 1959 : if (!isolated) {
334 0 : config_error(c, "Could not isolate configuration file");
335 0 : goto out;
336 : }
337 :
338 6021 : while ((l = config_read_line(c))) {
339 4062 : switch (l->type) {
340 1233 : case CONFIG_LINE_TYPE_LINE: {
341 1233 : char *key_copy = strdup(l->key);
342 1233 : char *value_copy = strdup(l->value);
343 :
344 1233 : if (!key_copy)
345 0 : lwan_status_critical("Could not copy key from config file");
346 1233 : if (!value_copy)
347 0 : lwan_status_critical("Could not copy value from config file");
348 :
349 1233 : hash_add(hash, key_copy, value_copy);
350 1233 : break;
351 : }
352 :
353 870 : case CONFIG_LINE_TYPE_SECTION:
354 870 : if (streq(l->key, "authorization")) {
355 87 : parse_listener_prefix_authorization(c, l, &url_map);
356 783 : } else if (!config_skip_section(c, l)) {
357 0 : config_error(c, "Could not skip section");
358 0 : goto out;
359 : }
360 870 : break;
361 :
362 1959 : case CONFIG_LINE_TYPE_SECTION_END:
363 1959 : goto add_map;
364 : }
365 : }
366 :
367 0 : config_error(c, "Expecting section end while parsing prefix");
368 0 : goto out;
369 :
370 1959 : add_map:
371 1959 : assert((handler && !module) || (!handler && module));
372 :
373 1959 : if (handler) {
374 1084 : url_map.handler = handler;
375 1084 : url_map.flags |= HANDLER_PARSE_MASK | HANDLER_DATA_IS_HASH_TABLE;
376 1084 : url_map.data = hash;
377 1084 : url_map.module = NULL;
378 :
379 1084 : hash = NULL;
380 875 : } else if (module->create_from_hash && module->handle_request) {
381 875 : lwan_status_debug("Initializing module %s from config",
382 : get_module_name(module));
383 :
384 875 : url_map.data = module->create_from_hash(prefix, hash);
385 875 : if (!url_map.data) {
386 0 : config_error(c, "Could not create module instance");
387 0 : goto out;
388 : }
389 :
390 875 : if (module->parse_conf && !module->parse_conf(url_map.data, isolated)) {
391 0 : const char *msg = config_last_error(isolated);
392 :
393 0 : config_error(c, "Error from module: %s", msg ? msg : "Unknown");
394 0 : goto out;
395 : }
396 :
397 875 : url_map.handler = module->handle_request;
398 875 : url_map.flags |= module->flags;
399 875 : url_map.module = module;
400 0 : } else if (UNLIKELY(!module->create_from_hash)) {
401 0 : config_error(c, "Module isn't prepared to load settings from a file; "
402 : "create_from_hash() method isn't present");
403 0 : goto out;
404 0 : } else if (UNLIKELY(!module->handle_request)) {
405 0 : config_error(c, "Module does not have handle_request() method");
406 0 : goto out;
407 : }
408 :
409 1959 : add_url_map(&lwan->url_map_trie, prefix, &url_map);
410 :
411 1959 : out:
412 1959 : hash_free(hash);
413 1959 : config_close(isolated);
414 1959 : }
415 :
416 0 : static void register_url_map(struct lwan *l, const struct lwan_url_map *map)
417 : {
418 0 : struct lwan_url_map *copy = add_url_map(&l->url_map_trie, NULL, map);
419 :
420 0 : if (copy->module && copy->module->create) {
421 0 : lwan_status_debug("Initializing module %s from struct",
422 : get_module_name(copy->module));
423 :
424 0 : copy->data = copy->module->create(map->prefix, copy->args);
425 0 : if (!copy->data) {
426 0 : lwan_status_critical("Could not initialize module %s",
427 : get_module_name(copy->module));
428 : }
429 :
430 0 : copy->flags = copy->module->flags;
431 0 : copy->handler = copy->module->handle_request;
432 : } else {
433 0 : copy->flags = HANDLER_PARSE_MASK;
434 : }
435 0 : }
436 :
437 0 : void lwan_set_url_map(struct lwan *l, const struct lwan_url_map *map)
438 : {
439 0 : lwan_trie_destroy(&l->url_map_trie);
440 0 : if (UNLIKELY(!lwan_trie_init(&l->url_map_trie, destroy_urlmap)))
441 0 : lwan_status_critical_perror("Could not initialize trie");
442 :
443 0 : for (; map->prefix; map++)
444 0 : register_url_map(l, map);
445 0 : }
446 :
447 : __attribute__((no_sanitize_address))
448 0 : void lwan_detect_url_map(struct lwan *l)
449 : {
450 : const struct lwan_handler_info *iter;
451 :
452 0 : lwan_trie_destroy(&l->url_map_trie);
453 0 : if (UNLIKELY(!lwan_trie_init(&l->url_map_trie, destroy_urlmap)))
454 0 : lwan_status_critical_perror("Could not initialize trie");
455 :
456 0 : LWAN_SECTION_FOREACH(lwan_handler, iter) {
457 0 : if (!iter->route)
458 0 : continue;
459 :
460 0 : const struct lwan_url_map map = {.prefix = iter->route,
461 0 : .handler = iter->handler};
462 0 : register_url_map(l, &map);
463 : }
464 0 : }
465 :
466 92 : const char *lwan_get_config_path(char *path_buf, size_t path_buf_len)
467 : {
468 : char buffer[PATH_MAX];
469 :
470 92 : if (proc_pidpath(getpid(), buffer, sizeof(buffer)) < 0)
471 0 : goto out;
472 :
473 92 : char *path = strrchr(buffer, '/');
474 92 : if (!path)
475 0 : goto out;
476 92 : int ret = snprintf(path_buf, path_buf_len, "%s.conf", path + 1);
477 92 : if (ret < 0 || ret >= (int)path_buf_len)
478 0 : goto out;
479 :
480 92 : return path_buf;
481 :
482 0 : out:
483 0 : return "lwan.conf";
484 : }
485 :
486 0 : static void parse_tls_listener(struct config *conf, const struct config_line *line, struct lwan *lwan)
487 : {
488 : #if !defined(LWAN_HAVE_MBEDTLS)
489 : config_error(conf, "Lwan has been built without mbedTLS support");
490 : return;
491 : #endif
492 :
493 0 : lwan->config.tls_listener = strdup(line->value);
494 0 : if (!lwan->config.tls_listener) {
495 0 : config_error(conf, "Could not allocate memory for tls_listener");
496 0 : return;
497 : }
498 :
499 0 : lwan->config.ssl.cert = NULL;
500 0 : lwan->config.ssl.key = NULL;
501 :
502 0 : while ((line = config_read_line(conf))) {
503 0 : switch (line->type) {
504 0 : case CONFIG_LINE_TYPE_SECTION_END:
505 0 : if (!lwan->config.ssl.cert)
506 0 : config_error(conf, "Missing path to certificate");
507 0 : if (!lwan->config.ssl.key)
508 0 : config_error(conf, "Missing path to private key");
509 0 : return;
510 0 : case CONFIG_LINE_TYPE_SECTION:
511 0 : config_error(conf, "Unexpected section: %s", line->key);
512 0 : return;
513 0 : case CONFIG_LINE_TYPE_LINE:
514 0 : if (streq(line->key, "cert")) {
515 0 : free(lwan->config.ssl.cert);
516 0 : lwan->config.ssl.cert = strdup(line->value);
517 0 : if (!lwan->config.ssl.cert)
518 0 : return lwan_status_critical("Could not copy string");
519 0 : } else if (streq(line->key, "key")) {
520 0 : free(lwan->config.ssl.key);
521 0 : lwan->config.ssl.key = strdup(line->value);
522 0 : if (!lwan->config.ssl.key)
523 0 : return lwan_status_critical("Could not copy string");
524 0 : } else if (streq(line->key, "hsts")) {
525 0 : lwan->config.ssl.send_hsts_header = parse_bool(line->value, false);
526 : } else {
527 0 : config_error(conf, "Unexpected key: %s", line->key);
528 : }
529 : }
530 : }
531 :
532 0 : config_error(conf, "Expecting section end while parsing SSL configuration");
533 : }
534 :
535 : static void
536 92 : parse_listener(struct config *c, const struct config_line *l, struct lwan *lwan)
537 : {
538 92 : lwan->config.listener = strdup(l->value);
539 92 : if (!lwan->config.listener)
540 0 : config_error(c, "Could not allocate memory for listener");
541 :
542 92 : while ((l = config_read_line(c))) {
543 92 : switch (l->type) {
544 0 : case CONFIG_LINE_TYPE_LINE:
545 0 : config_error(c, "Unexpected key %s", l->key);
546 0 : return;
547 0 : case CONFIG_LINE_TYPE_SECTION:
548 0 : config_error(c, "Unexpected section %s", l->key);
549 0 : return;
550 92 : case CONFIG_LINE_TYPE_SECTION_END:
551 92 : return;
552 : }
553 : }
554 :
555 0 : config_error(c, "Unexpected EOF while parsing listener");
556 : }
557 :
558 : static void
559 92 : parse_site(struct config *c, const struct config_line *l, struct lwan *lwan)
560 : {
561 2143 : while ((l = config_read_line(c))) {
562 2051 : switch (l->type) {
563 0 : case CONFIG_LINE_TYPE_LINE:
564 0 : config_error(c, "Expecting prefix section");
565 0 : return;
566 1959 : case CONFIG_LINE_TYPE_SECTION:
567 : /* FIXME: per-site authorization? */
568 :
569 1959 : if (l->key[0] == '&') {
570 1084 : void *handler = find_handler(l->key + 1);
571 1084 : if (handler) {
572 1084 : parse_listener_prefix(c, l, lwan, NULL, handler);
573 1084 : continue;
574 : }
575 :
576 0 : config_error(c, "Could not find handler name: %s", l->key + 1);
577 0 : return;
578 : }
579 :
580 875 : const struct lwan_module *module = find_module(l->key);
581 875 : if (module) {
582 875 : parse_listener_prefix(c, l, lwan, module, NULL);
583 875 : continue;
584 : }
585 :
586 0 : config_error(c, "Invalid section or module not found: %s", l->key);
587 0 : return;
588 92 : case CONFIG_LINE_TYPE_SECTION_END:
589 92 : return;
590 : }
591 : }
592 :
593 0 : config_error(c, "Expecting section end while parsing listener");
594 : }
595 :
596 92 : static bool setup_from_config(struct lwan *lwan, const char *path)
597 : {
598 : const struct config_line *line;
599 : struct config *conf;
600 92 : bool has_site = false;
601 92 : bool has_listener = false;
602 92 : bool has_tls_listener = false;
603 : char path_buf[PATH_MAX];
604 :
605 92 : if (!path)
606 92 : path = lwan_get_config_path(path_buf, sizeof(path_buf));
607 92 : lwan_status_info("Loading configuration file: %s", path);
608 :
609 92 : conf = config_open(path);
610 92 : if (!conf)
611 0 : return false;
612 :
613 92 : if (!lwan_trie_init(&lwan->url_map_trie, destroy_urlmap))
614 0 : return false;
615 :
616 1064 : while ((line = config_read_line(conf))) {
617 880 : switch (line->type) {
618 522 : case CONFIG_LINE_TYPE_LINE:
619 522 : if (streq(line->key, "keep_alive_timeout")) {
620 87 : lwan->config.keep_alive_timeout = (unsigned int)parse_long(
621 87 : line->value, default_config.keep_alive_timeout);
622 435 : } else if (streq(line->key, "quiet")) {
623 87 : lwan->config.quiet =
624 87 : parse_bool(line->value, default_config.quiet);
625 348 : } else if (streq(line->key, "proxy_protocol")) {
626 87 : lwan->config.proxy_protocol =
627 87 : parse_bool(line->value, default_config.proxy_protocol);
628 261 : } else if (streq(line->key, "allow_cors")) {
629 0 : lwan->config.allow_cors =
630 0 : parse_bool(line->value, default_config.allow_cors);
631 261 : } else if (streq(line->key, "expires")) {
632 87 : lwan->config.expires =
633 87 : parse_time_period(line->value, default_config.expires);
634 174 : } else if (streq(line->key, "error_template")) {
635 0 : free(lwan->config.error_template);
636 0 : lwan->config.error_template = strdup(line->value);
637 174 : } else if (streq(line->key, "threads")) {
638 : long n_threads =
639 87 : parse_long(line->value, default_config.n_threads);
640 87 : if (n_threads < 0)
641 0 : config_error(conf, "Invalid number of threads: %ld",
642 : n_threads);
643 87 : lwan->config.n_threads = (unsigned int)n_threads;
644 87 : } else if (streq(line->key, "max_post_data_size")) {
645 87 : long max_post_data_size = parse_long(
646 87 : line->value, (long)default_config.max_post_data_size);
647 87 : if (max_post_data_size < 0)
648 0 : config_error(conf, "Negative maximum post data size");
649 87 : else if (max_post_data_size > 128 * (1 << 20))
650 0 : config_error(conf,
651 : "Maximum post data can't be over 128MiB");
652 87 : lwan->config.max_post_data_size = (size_t)max_post_data_size;
653 0 : } else if (streq(line->key, "max_put_data_size")) {
654 0 : long max_put_data_size = parse_long(
655 0 : line->value, (long)default_config.max_put_data_size);
656 0 : if (max_put_data_size < 0)
657 0 : config_error(conf, "Negative maximum put data size");
658 0 : else if (max_put_data_size > 128 * (1 << 20))
659 0 : config_error(conf,
660 : "Maximum put data can't be over 128MiB");
661 0 : lwan->config.max_put_data_size = (size_t)max_put_data_size;
662 0 : } else if (streq(line->key, "allow_temp_files")) {
663 : bool has_post, has_put;
664 :
665 0 : if (strstr(line->value, "all")) {
666 0 : has_post = has_put = true;
667 : } else {
668 0 : has_post = !!strstr(line->value, "post");
669 0 : has_put = !!strstr(line->value, "put");
670 : }
671 :
672 0 : lwan->config.allow_post_temp_file = has_post;
673 0 : lwan->config.allow_put_temp_file = has_put;
674 : } else {
675 0 : config_error(conf, "Unknown config key: %s", line->key);
676 : }
677 522 : break;
678 358 : case CONFIG_LINE_TYPE_SECTION:
679 358 : if (streq(line->key, "site")) {
680 92 : if (!has_site) {
681 92 : parse_site(conf, line, lwan);
682 92 : has_site = true;
683 : } else {
684 0 : config_error(conf, "Only one site may be configured");
685 : }
686 266 : } else if (streq(line->key, "straitjacket")) {
687 87 : lwan_straitjacket_enforce_from_config(conf);
688 179 : } else if (streq(line->key, "headers")) {
689 87 : parse_global_headers(conf, lwan);
690 92 : } else if (streq(line->key, "listener")) {
691 92 : if (has_listener) {
692 0 : config_error(conf, "Listener already set up");
693 : } else {
694 92 : parse_listener(conf, line, lwan);
695 92 : has_listener = true;
696 : }
697 0 : } else if (streq(line->key, "tls_listener")) {
698 0 : if (has_tls_listener) {
699 0 : config_error(conf, "TLS Listener already set up");
700 : } else {
701 0 : parse_tls_listener(conf, line, lwan);
702 0 : has_tls_listener = true;
703 : }
704 : } else {
705 0 : config_error(conf, "Unknown section type: %s", line->key);
706 : }
707 358 : break;
708 0 : case CONFIG_LINE_TYPE_SECTION_END:
709 0 : config_error(conf, "Unexpected section end");
710 : }
711 : }
712 :
713 92 : if (config_last_error(conf)) {
714 0 : lwan_status_critical("Error on config file \"%s\", line %d: %s", path,
715 : config_cur_line(conf), config_last_error(conf));
716 : lwan_trie_destroy(&lwan->url_map_trie);
717 : }
718 :
719 92 : config_close(conf);
720 :
721 92 : return true;
722 : }
723 :
724 92 : static void try_setup_from_config(struct lwan *l,
725 : const struct lwan_config *config)
726 : {
727 92 : if (!setup_from_config(l, config->config_file_path)) {
728 0 : if (config->config_file_path) {
729 0 : lwan_status_critical("Could not read config file: %s",
730 : config->config_file_path);
731 : }
732 : }
733 :
734 92 : lwan_status_init(l); /* `quiet` key might have changed value. */
735 :
736 92 : l->config.request_flags =
737 92 : (l->config.proxy_protocol ? REQUEST_ALLOW_PROXY_REQS : 0) |
738 92 : (l->config.allow_cors ? REQUEST_ALLOW_CORS : 0) |
739 92 : (l->config.ssl.send_hsts_header ? REQUEST_WANTS_HSTS_HEADER : 0);
740 92 : }
741 :
742 92 : static rlim_t setup_open_file_count_limits(void)
743 : {
744 : struct rlimit r;
745 :
746 92 : if (getrlimit(RLIMIT_NOFILE, &r) < 0) {
747 0 : lwan_status_perror("Could not obtain maximum number of file "
748 : "descriptors. Assuming %d",
749 : OPEN_MAX);
750 0 : return OPEN_MAX;
751 : }
752 :
753 92 : if (r.rlim_max != r.rlim_cur) {
754 92 : const rlim_t current = r.rlim_cur;
755 :
756 92 : if (r.rlim_max == RLIM_INFINITY && r.rlim_cur < OPEN_MAX) {
757 0 : r.rlim_cur = OPEN_MAX;
758 92 : } else if (r.rlim_cur < r.rlim_max) {
759 92 : r.rlim_cur = r.rlim_max;
760 : } else {
761 : /* Shouldn't happen, so just return the current value. */
762 0 : goto out;
763 : }
764 :
765 92 : if (setrlimit(RLIMIT_NOFILE, &r) < 0) {
766 0 : lwan_status_perror("Could not raise maximum number of file "
767 : "descriptors to %" PRIu64 ". Leaving at "
768 : "%" PRIu64, r.rlim_max, current);
769 0 : r.rlim_cur = current;
770 : }
771 : }
772 :
773 92 : out:
774 92 : return r.rlim_cur;
775 : }
776 :
777 92 : static void allocate_connections(struct lwan *l, size_t max_open_files)
778 : {
779 92 : const size_t sz = max_open_files * sizeof(struct lwan_connection);
780 :
781 92 : l->conns = lwan_aligned_alloc(sz, 64);
782 92 : if (UNLIKELY(!l->conns))
783 0 : lwan_status_critical_perror("lwan_alloc_aligned");
784 :
785 92 : memset(l->conns, 0, sz);
786 92 : }
787 :
788 92 : static void get_number_of_cpus(struct lwan *l)
789 : {
790 92 : long n_online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
791 92 : long n_available_cpus = sysconf(_SC_NPROCESSORS_CONF);
792 :
793 92 : if (n_online_cpus < 0) {
794 0 : lwan_status_warning(
795 : "Could not get number of online CPUs, assuming 1 CPU");
796 0 : n_online_cpus = 1;
797 : }
798 :
799 92 : if (n_available_cpus < 0) {
800 0 : lwan_status_warning(
801 : "Could not get number of available CPUs, assuming %ld CPUs",
802 : n_online_cpus);
803 0 : n_available_cpus = n_online_cpus;
804 : }
805 :
806 92 : l->online_cpus = (unsigned int)n_online_cpus;
807 92 : l->available_cpus = (unsigned int)n_available_cpus;
808 92 : }
809 :
810 92 : void lwan_init(struct lwan *l) { lwan_init_with_config(l, &default_config); }
811 :
812 0 : const struct lwan_config *lwan_get_default_config(void)
813 : {
814 0 : return &default_config;
815 : }
816 :
817 368 : static char *dup_or_null(const char *s)
818 : {
819 368 : return s ? strdup(s) : NULL;
820 : }
821 :
822 92 : void lwan_init_with_config(struct lwan *l, const struct lwan_config *config)
823 : {
824 : /* Load defaults */
825 92 : memset(l, 0, sizeof(*l));
826 92 : memcpy(&l->config, config, sizeof(*config));
827 92 : l->config.listener = dup_or_null(l->config.listener);
828 92 : l->config.config_file_path = dup_or_null(l->config.config_file_path);
829 92 : l->config.ssl.key = dup_or_null(l->config.ssl.key);
830 92 : l->config.ssl.cert = dup_or_null(l->config.ssl.cert);
831 :
832 : /* Initialize status first, as it is used by other things during
833 : * their initialization. */
834 92 : lwan_status_init(l);
835 :
836 : /* These will only print debugging messages. Debug messages are always
837 : * printed if we're on a debug build, so the quiet setting will be
838 : * respected. */
839 92 : lwan_job_thread_init();
840 92 : lwan_tables_init();
841 :
842 : /* Get the number of CPUs here because straightjacket might be active
843 : * and this will block access to /proc and /sys, which will cause
844 : * get_number_of_cpus() to get incorrect fallback values. */
845 92 : get_number_of_cpus(l);
846 :
847 92 : try_setup_from_config(l, config);
848 :
849 92 : if (!l->headers.len)
850 5 : build_response_headers(l, config->global_headers);
851 :
852 92 : lwan_response_init(l);
853 :
854 : /* Continue initialization as normal. */
855 92 : lwan_status_debug("Initializing lwan web server");
856 :
857 92 : if (!l->config.n_threads) {
858 92 : l->thread.count = l->online_cpus;
859 92 : if (l->thread.count == 1)
860 92 : l->thread.count = 2;
861 0 : } else if (l->config.n_threads > 3 * l->online_cpus) {
862 0 : l->thread.count = l->online_cpus * 3;
863 :
864 0 : lwan_status_warning("%d threads requested, but only %d online CPUs "
865 : "(out of %d configured CPUs); capping to %d threads",
866 : l->config.n_threads, l->online_cpus, l->available_cpus,
867 : 3 * l->online_cpus);
868 0 : } else if (l->config.n_threads > 255) {
869 0 : l->thread.count = 256;
870 :
871 0 : lwan_status_warning("%d threads requested, but max 256 supported",
872 : l->config.n_threads);
873 : } else {
874 0 : l->thread.count = l->config.n_threads;
875 : }
876 :
877 92 : rlim_t max_open_files = setup_open_file_count_limits();
878 92 : allocate_connections(l, (size_t)max_open_files);
879 :
880 92 : l->thread.max_fd = (unsigned)max_open_files / (unsigned)l->thread.count;
881 92 : lwan_status_info("Using %d threads, maximum %d sockets per thread",
882 : l->thread.count, l->thread.max_fd);
883 :
884 92 : signal(SIGPIPE, SIG_IGN);
885 :
886 92 : lwan_readahead_init();
887 92 : lwan_thread_init(l);
888 92 : lwan_http_authorize_init();
889 92 : }
890 :
891 0 : void lwan_shutdown(struct lwan *l)
892 : {
893 0 : lwan_status_info("Shutting down");
894 :
895 0 : free(l->config.listener);
896 0 : free(l->config.error_template);
897 0 : free(l->config.config_file_path);
898 :
899 0 : lwan_always_bzero(l->config.ssl.cert, strlen(l->config.ssl.cert));
900 0 : free(l->config.ssl.cert);
901 0 : lwan_always_bzero(l->config.ssl.key, strlen(l->config.ssl.key));
902 0 : free(l->config.ssl.key);
903 :
904 0 : lwan_job_thread_shutdown();
905 0 : lwan_thread_shutdown(l);
906 :
907 0 : lwan_status_debug("Shutting down URL handlers");
908 0 : lwan_trie_destroy(&l->url_map_trie);
909 :
910 0 : free(l->headers.value);
911 0 : free(l->conns);
912 :
913 0 : lwan_response_shutdown(l);
914 0 : lwan_tables_shutdown();
915 0 : lwan_status_shutdown(l);
916 0 : lwan_http_authorize_shutdown();
917 0 : lwan_readahead_shutdown();
918 0 : }
919 :
920 92 : void lwan_main_loop(struct lwan *l)
921 : {
922 92 : lwan_status_info("Ready to serve");
923 :
924 92 : lwan_job_thread_main_loop();
925 0 : }
926 :
927 : #ifdef CLOCK_MONOTONIC_COARSE
928 92 : __attribute__((constructor)) static void detect_fastest_monotonic_clock(void)
929 : {
930 : struct timespec ts;
931 :
932 92 : if (!clock_gettime(CLOCK_MONOTONIC_COARSE, &ts))
933 92 : monotonic_clock_id = CLOCK_MONOTONIC_COARSE;
934 92 : }
935 : #endif
936 :
937 368 : void lwan_set_thread_name(const char *name)
938 : {
939 : char thread_name[16];
940 : char process_name[PATH_MAX];
941 : char *tmp;
942 : int ret;
943 :
944 368 : if (proc_pidpath(getpid(), process_name, sizeof(process_name)) < 0)
945 0 : return;
946 :
947 368 : tmp = strrchr(process_name, '/');
948 368 : if (!tmp)
949 0 : return;
950 :
951 368 : ret = snprintf(thread_name, sizeof(thread_name), "%s %s", tmp + 1, name);
952 368 : if (ret < 0)
953 0 : return;
954 :
955 368 : pthread_set_name_np(pthread_self(), thread_name);
956 : }
|