1 /* $OpenBSD: httpd.c,v 1.74 2024/04/08 12:45:18 tobhe Exp $ */
2
3 /*
4 * Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <sys/resource.h>
24
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31 #include <string.h>
32 #include <signal.h>
33 #include <getopt.h>
34 #include <netdb.h>
35 #include <fnmatch.h>
36 #include <err.h>
37 #include <errno.h>
38 #include <event.h>
39 #include <syslog.h>
40 #include <unistd.h>
41 #include <ctype.h>
42 #include <pwd.h>
43
44 #include "httpd.h"
45
46 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
47
48 __dead void usage(void);
49
50 int parent_configure(struct httpd *);
51 void parent_configure_done(struct httpd *);
52 void parent_reload(struct httpd *, unsigned int, const char *);
53 void parent_reopen(struct httpd *);
54 void parent_sig_handler(int, short, void *);
55 void parent_shutdown(struct httpd *);
56 int parent_dispatch_server(int, struct privsep_proc *,
57 struct imsg *);
58 int parent_dispatch_logger(int, struct privsep_proc *,
59 struct imsg *);
60 void parent_tls_ticket_rekey_start(struct server *);
61 void parent_tls_ticket_rekey(int, short, void *);
62
63 struct httpd *httpd_env;
64
65 static struct privsep_proc procs[] = {
66 { "server", PROC_SERVER, parent_dispatch_server, server },
67 { "logger", PROC_LOGGER, parent_dispatch_logger, logger }
68 };
69
70 enum privsep_procid privsep_process;
71
72 void
parent_sig_handler(int sig,short event,void * arg)73 parent_sig_handler(int sig, short event, void *arg)
74 {
75 struct privsep *ps = arg;
76
77 switch (sig) {
78 case SIGTERM:
79 case SIGINT:
80 parent_shutdown(ps->ps_env);
81 break;
82 case SIGHUP:
83 log_info("%s: reload requested with SIGHUP", __func__);
84
85 /*
86 * This is safe because libevent uses async signal handlers
87 * that run in the event loop and not in signal context.
88 */
89 parent_reload(ps->ps_env, CONFIG_RELOAD, NULL);
90 break;
91 case SIGPIPE:
92 /* ignore */
93 break;
94 case SIGUSR1:
95 log_info("%s: reopen requested with SIGUSR1", __func__);
96
97 parent_reopen(ps->ps_env);
98 break;
99 default:
100 fatalx("unexpected signal");
101 }
102 }
103
104 __dead void
usage(void)105 usage(void)
106 {
107 extern char *__progname;
108
109 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
110 __progname);
111 exit(1);
112 }
113
114 int
main(int argc,char * argv[])115 main(int argc, char *argv[])
116 {
117 int c;
118 unsigned int proc;
119 int debug = 0, verbose = 0;
120 uint32_t opts = 0;
121 struct httpd *env;
122 struct privsep *ps;
123 const char *conffile = CONF_FILE;
124 enum privsep_procid proc_id = PROC_PARENT;
125 int proc_instance = 0;
126 const char *errp, *title = NULL;
127 int argc0 = argc;
128
129 while ((c = getopt(argc, argv, "dD:nf:I:P:v")) != -1) {
130 switch (c) {
131 case 'd':
132 debug = 2;
133 break;
134 case 'D':
135 if (cmdline_symset(optarg) < 0)
136 log_warnx("could not parse macro definition %s",
137 optarg);
138 break;
139 case 'n':
140 debug = 2;
141 opts |= HTTPD_OPT_NOACTION;
142 break;
143 case 'f':
144 conffile = optarg;
145 break;
146 case 'v':
147 verbose++;
148 opts |= HTTPD_OPT_VERBOSE;
149 break;
150 case 'P':
151 title = optarg;
152 proc_id = proc_getid(procs, nitems(procs), title);
153 if (proc_id == PROC_MAX)
154 fatalx("invalid process name");
155 break;
156 case 'I':
157 proc_instance = strtonum(optarg, 0,
158 PROC_MAX_INSTANCES, &errp);
159 if (errp)
160 fatalx("invalid process instance");
161 break;
162 default:
163 usage();
164 }
165 }
166
167 /* log to stderr until daemonized */
168 log_init(debug ? debug : 1, LOG_DAEMON);
169
170 argc -= optind;
171 if (argc > 0)
172 usage();
173
174 if ((env = calloc(1, sizeof(*env))) == NULL ||
175 (ps = calloc(1, sizeof(*ps))) == NULL)
176 exit(1);
177
178 httpd_env = env;
179 env->sc_ps = ps;
180 ps->ps_env = env;
181 TAILQ_INIT(&ps->ps_rcsocks);
182 env->sc_conffile = conffile;
183 env->sc_opts = opts;
184
185 if (parse_config(env->sc_conffile, env) == -1)
186 exit(1);
187
188 if (geteuid())
189 errx(1, "need root privileges");
190
191 if ((ps->ps_pw = getpwnam(HTTPD_USER)) == NULL)
192 errx(1, "unknown user %s", HTTPD_USER);
193
194 /* Configure the control socket */
195 ps->ps_csock.cs_name = NULL;
196
197 log_init(debug, LOG_DAEMON);
198 log_setverbose(verbose);
199
200 if (env->sc_opts & HTTPD_OPT_NOACTION)
201 ps->ps_noaction = 1;
202
203 ps->ps_instances[PROC_SERVER] = env->sc_prefork_server;
204 ps->ps_instance = proc_instance;
205 if (title != NULL)
206 ps->ps_title[proc_id] = title;
207
208 if (env->sc_chroot == NULL)
209 env->sc_chroot = ps->ps_pw->pw_dir;
210 for (proc = 0; proc < nitems(procs); proc++)
211 procs[proc].p_chroot = env->sc_chroot;
212
213 if (env->sc_logdir == NULL) {
214 if (asprintf(&env->sc_logdir, "%s%s", env->sc_chroot,
215 HTTPD_LOGROOT) == -1)
216 errx(1, "malloc failed");
217 }
218
219 /* only the parent returns */
220 proc_init(ps, procs, nitems(procs), debug, argc0, argv, proc_id);
221
222 log_procinit("parent");
223
224 if (ps->ps_noaction == 0)
225 log_info("startup");
226
227 if (pledge("stdio rpath wpath cpath inet dns sendfd", NULL) == -1)
228 fatal("pledge");
229
230 event_init();
231
232 signal_set(&ps->ps_evsigint, SIGINT, parent_sig_handler, ps);
233 signal_set(&ps->ps_evsigterm, SIGTERM, parent_sig_handler, ps);
234 signal_set(&ps->ps_evsighup, SIGHUP, parent_sig_handler, ps);
235 signal_set(&ps->ps_evsigpipe, SIGPIPE, parent_sig_handler, ps);
236 signal_set(&ps->ps_evsigusr1, SIGUSR1, parent_sig_handler, ps);
237
238 signal_add(&ps->ps_evsigint, NULL);
239 signal_add(&ps->ps_evsigterm, NULL);
240 signal_add(&ps->ps_evsighup, NULL);
241 signal_add(&ps->ps_evsigpipe, NULL);
242 signal_add(&ps->ps_evsigusr1, NULL);
243
244 proc_connect(ps);
245
246 if (load_config(env->sc_conffile, env) == -1) {
247 proc_kill(env->sc_ps);
248 exit(1);
249 }
250
251 if (env->sc_opts & HTTPD_OPT_NOACTION) {
252 fprintf(stderr, "configuration OK\n");
253 proc_kill(env->sc_ps);
254 exit(0);
255 }
256
257 /* initialize the TLS session id to a random key for all procs */
258 arc4random_buf(env->sc_tls_sid, sizeof(env->sc_tls_sid));
259
260 if (parent_configure(env) == -1)
261 fatalx("configuration failed");
262
263 event_dispatch();
264
265 parent_shutdown(env);
266 /* NOTREACHED */
267
268 return (0);
269 }
270
271 int
parent_configure(struct httpd * env)272 parent_configure(struct httpd *env)
273 {
274 int id;
275 struct ctl_flags cf;
276 int ret = -1;
277 struct server *srv;
278 struct media_type *media;
279 struct auth *auth;
280
281 RB_FOREACH(media, mediatypes, env->sc_mediatypes) {
282 if (config_setmedia(env, media) == -1)
283 fatal("send media");
284 }
285
286 TAILQ_FOREACH(auth, env->sc_auth, auth_entry) {
287 if (config_setauth(env, auth) == -1)
288 fatal("send auth");
289 }
290
291 /* First send the servers... */
292 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
293 if (srv->srv_conf.flags & SRVFLAG_LOCATION)
294 continue;
295 /* start the rekey of the tls ticket keys */
296 if (srv->srv_conf.flags & SRVFLAG_TLS &&
297 srv->srv_conf.tls_ticket_lifetime)
298 parent_tls_ticket_rekey_start(srv);
299 if (config_setserver(env, srv) == -1)
300 fatal("send server");
301 }
302 /* ...and now send the locations */
303 TAILQ_FOREACH(srv, env->sc_servers, srv_entry) {
304 if ((srv->srv_conf.flags & SRVFLAG_LOCATION) == 0)
305 continue;
306 if (config_setserver(env, srv) == -1)
307 fatal("send location");
308 }
309
310 /* The servers need to reload their config. */
311 env->sc_reload = env->sc_prefork_server + 1;
312
313 for (id = 0; id < PROC_MAX; id++) {
314 if (id == privsep_process)
315 continue;
316 cf.cf_opts = env->sc_opts;
317 cf.cf_flags = env->sc_flags;
318 memcpy(cf.cf_tls_sid, env->sc_tls_sid, sizeof(cf.cf_tls_sid));
319
320 proc_compose(env->sc_ps, id, IMSG_CFG_DONE, &cf, sizeof(cf));
321 }
322
323 ret = 0;
324
325 config_purge(env, CONFIG_ALL & ~CONFIG_SERVERS);
326 return (ret);
327 }
328
329 void
parent_reload(struct httpd * env,unsigned int reset,const char * filename)330 parent_reload(struct httpd *env, unsigned int reset, const char *filename)
331 {
332 if (env->sc_reload) {
333 log_debug("%s: already in progress: %d pending",
334 __func__, env->sc_reload);
335 return;
336 }
337
338 /* Switch back to the default config file */
339 if (filename == NULL || *filename == '\0')
340 filename = env->sc_conffile;
341
342 log_debug("%s: level %d config file %s", __func__, reset, filename);
343
344 config_purge(env, CONFIG_ALL);
345
346 if (reset == CONFIG_RELOAD) {
347 if (load_config(filename, env) == -1) {
348 log_debug("%s: failed to load config file %s",
349 __func__, filename);
350 }
351
352 config_setreset(env, CONFIG_ALL);
353
354 if (parent_configure(env) == -1) {
355 log_debug("%s: failed to commit config from %s",
356 __func__, filename);
357 }
358 } else
359 config_setreset(env, reset);
360 }
361
362 void
parent_reopen(struct httpd * env)363 parent_reopen(struct httpd *env)
364 {
365 proc_compose(env->sc_ps, PROC_LOGGER, IMSG_CTL_REOPEN, NULL, 0);
366 }
367
368 void
parent_configure_done(struct httpd * env)369 parent_configure_done(struct httpd *env)
370 {
371 int id;
372
373 if (env->sc_reload == 0) {
374 log_warnx("%s: configuration already finished", __func__);
375 return;
376 }
377
378 env->sc_reload--;
379 if (env->sc_reload == 0) {
380 for (id = 0; id < PROC_MAX; id++) {
381 if (id == privsep_process)
382 continue;
383
384 proc_compose(env->sc_ps, id, IMSG_CTL_START, NULL, 0);
385 }
386 }
387 }
388
389 void
parent_shutdown(struct httpd * env)390 parent_shutdown(struct httpd *env)
391 {
392 config_purge(env, CONFIG_ALL);
393
394 proc_kill(env->sc_ps);
395 control_cleanup(&env->sc_ps->ps_csock);
396 if (env->sc_ps->ps_csock.cs_name != NULL)
397 (void)unlink(env->sc_ps->ps_csock.cs_name);
398
399 free(env->sc_ps);
400 free(env);
401
402 log_info("parent terminating, pid %d", getpid());
403
404 exit(0);
405 }
406
407 int
parent_dispatch_server(int fd,struct privsep_proc * p,struct imsg * imsg)408 parent_dispatch_server(int fd, struct privsep_proc *p, struct imsg *imsg)
409 {
410 struct privsep *ps = p->p_ps;
411 struct httpd *env = ps->ps_env;
412
413 switch (imsg->hdr.type) {
414 case IMSG_CFG_DONE:
415 parent_configure_done(env);
416 break;
417 default:
418 return (-1);
419 }
420
421 return (0);
422 }
423
424 int
parent_dispatch_logger(int fd,struct privsep_proc * p,struct imsg * imsg)425 parent_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg)
426 {
427 struct privsep *ps = p->p_ps;
428 struct httpd *env = ps->ps_env;
429 unsigned int v;
430 char *str = NULL;
431
432 switch (imsg->hdr.type) {
433 case IMSG_CTL_RESET:
434 IMSG_SIZE_CHECK(imsg, &v);
435 memcpy(&v, imsg->data, sizeof(v));
436 parent_reload(env, v, NULL);
437 break;
438 case IMSG_CTL_RELOAD:
439 if (IMSG_DATA_SIZE(imsg) > 0)
440 str = get_string(imsg->data, IMSG_DATA_SIZE(imsg));
441 parent_reload(env, CONFIG_RELOAD, str);
442 free(str);
443 break;
444 case IMSG_CTL_SHUTDOWN:
445 parent_shutdown(env);
446 break;
447 case IMSG_CTL_REOPEN:
448 parent_reopen(env);
449 break;
450 case IMSG_CFG_DONE:
451 parent_configure_done(env);
452 break;
453 case IMSG_LOG_OPEN:
454 if (logger_open_priv(imsg) == -1)
455 fatalx("failed to open log file");
456 break;
457 default:
458 return (-1);
459 }
460
461 return (0);
462 }
463
464 void
parent_tls_ticket_rekey_start(struct server * srv)465 parent_tls_ticket_rekey_start(struct server *srv)
466 {
467 struct timeval tv;
468
469 server_generate_ticket_key(&srv->srv_conf);
470
471 evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv);
472 timerclear(&tv);
473 tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4;
474 evtimer_add(&srv->srv_evt, &tv);
475 }
476
477 void
parent_tls_ticket_rekey(int fd,short events,void * arg)478 parent_tls_ticket_rekey(int fd, short events, void *arg)
479 {
480 struct server *srv = arg;
481 struct timeval tv;
482
483 server_generate_ticket_key(&srv->srv_conf);
484 proc_compose_imsg(httpd_env->sc_ps, PROC_SERVER, -1,
485 IMSG_TLSTICKET_REKEY, -1, -1, &srv->srv_conf.tls_ticket_key,
486 sizeof(srv->srv_conf.tls_ticket_key));
487 explicit_bzero(&srv->srv_conf.tls_ticket_key,
488 sizeof(srv->srv_conf.tls_ticket_key));
489
490 evtimer_set(&srv->srv_evt, parent_tls_ticket_rekey, srv);
491 timerclear(&tv);
492 tv.tv_sec = srv->srv_conf.tls_ticket_lifetime / 4;
493 evtimer_add(&srv->srv_evt, &tv);
494 }
495
496 /*
497 * Utility functions
498 */
499
500 void
event_again(struct event * ev,int fd,short event,void (* fn)(int,short,void *),struct timeval * start,struct timeval * end,void * arg)501 event_again(struct event *ev, int fd, short event,
502 void (*fn)(int, short, void *),
503 struct timeval *start, struct timeval *end, void *arg)
504 {
505 struct timeval tv_next, tv_now, tv;
506
507 getmonotime(&tv_now);
508 memcpy(&tv_next, end, sizeof(tv_next));
509 timersub(&tv_now, start, &tv_now);
510 timersub(&tv_next, &tv_now, &tv_next);
511
512 memset(&tv, 0, sizeof(tv));
513 if (timercmp(&tv_next, &tv, >))
514 memcpy(&tv, &tv_next, sizeof(tv));
515
516 event_del(ev);
517 event_set(ev, fd, event, fn, arg);
518 event_add(ev, &tv);
519 }
520
521 int
expand_string(char * label,size_t len,const char * srch,const char * repl)522 expand_string(char *label, size_t len, const char *srch, const char *repl)
523 {
524 char *tmp;
525 char *p, *q;
526
527 if ((tmp = calloc(1, len)) == NULL) {
528 log_debug("%s: calloc", __func__);
529 return (-1);
530 }
531 p = q = label;
532 while ((q = strstr(p, srch)) != NULL) {
533 *q = '\0';
534 if ((strlcat(tmp, p, len) >= len) ||
535 (strlcat(tmp, repl, len) >= len)) {
536 log_debug("%s: string too long", __func__);
537 free(tmp);
538 return (-1);
539 }
540 q += strlen(srch);
541 p = q;
542 }
543 if (strlcat(tmp, p, len) >= len) {
544 log_debug("%s: string too long", __func__);
545 free(tmp);
546 return (-1);
547 }
548 (void)strlcpy(label, tmp, len); /* always fits */
549 free(tmp);
550
551 return (0);
552 }
553
554 const char *
url_decode(char * url)555 url_decode(char *url)
556 {
557 char *p, *q;
558 char hex[3];
559 unsigned long x;
560
561 hex[2] = '\0';
562 p = q = url;
563
564 while (*p != '\0') {
565 switch (*p) {
566 case '%':
567 /* Encoding character is followed by two hex chars */
568 if (!(isxdigit((unsigned char)p[1]) &&
569 isxdigit((unsigned char)p[2])))
570 return (NULL);
571
572 hex[0] = p[1];
573 hex[1] = p[2];
574
575 /*
576 * We don't have to validate "hex" because it is
577 * guaranteed to include two hex chars followed by nul.
578 */
579 x = strtoul(hex, NULL, 16);
580 *q = (char)x;
581 p += 2;
582 break;
583 default:
584 *q = *p;
585 break;
586 }
587 p++;
588 q++;
589 }
590 *q = '\0';
591
592 return (url);
593 }
594
595 const char *
canonicalize_path(const char * input,char * path,size_t len)596 canonicalize_path(const char *input, char *path, size_t len)
597 {
598 const char *i;
599 char *p, *start, *end;
600
601 /* assuming input starts with '/' and is nul-terminated */
602 i = input;
603 p = path;
604
605 if (*input != '/' || len < 3)
606 return (NULL);
607
608 start = p;
609 end = p + (len - 1);
610
611 while (*i != '\0') {
612 /* Detect truncation */
613 if (p >= end)
614 return (NULL);
615
616 /* 1. check for special path elements */
617 if (i[0] == '/') {
618 if (i[1] == '/') {
619 /* a) skip repeating '//' slashes */
620 while (i[1] == '/')
621 i++;
622 continue;
623 } else if (i[1] == '.' && i[2] == '.' &&
624 (i[3] == '/' || i[3] == '\0')) {
625 /* b) revert '..' to previous directory */
626 i += 3;
627 while (p > start && *p != '/')
628 p--;
629 *p = '\0';
630 continue;
631 } else if (i[1] == '.' &&
632 (i[2] == '/' || i[2] == '\0')) {
633 /* c) skip unnecessary '.' current dir */
634 i += 2;
635 continue;
636 }
637 }
638
639 /* 2. copy any other characters */
640 *p++ = *i;
641 i++;
642 }
643 if (p == start)
644 *p++ = '/';
645 *p++ = '\0';
646
647 return (path);
648 }
649
650 size_t
path_info(char * path)651 path_info(char *path)
652 {
653 char *p, *start, *end, ch;
654 struct stat st;
655 int ret;
656
657 start = path;
658 end = start + strlen(path);
659
660 for (p = end; p > start; p--) {
661 /* Scan every path component from the end and at each '/' */
662 if (p < end && *p != '/')
663 continue;
664
665 /* Temporarily cut the path component out */
666 ch = *p;
667 *p = '\0';
668 ret = stat(path, &st);
669 *p = ch;
670
671 /* Break if the initial path component was found */
672 if (ret == 0)
673 break;
674 }
675
676 return (p - start);
677 }
678
679 char *
url_encode(const char * src)680 url_encode(const char *src)
681 {
682 static char hex[] = "0123456789ABCDEF";
683 char *dp, *dst;
684 unsigned char c;
685
686 /* We need 3 times the memory if every letter is encoded. */
687 if ((dst = calloc(3, strlen(src) + 1)) == NULL)
688 return (NULL);
689
690 for (dp = dst; *src != 0; src++) {
691 c = (unsigned char) *src;
692 if (c == ' ' || c == '#' || c == '%' || c == '?' || c == '"' ||
693 c == '&' || c == '<' || c <= 0x1f || c >= 0x7f) {
694 *dp++ = '%';
695 *dp++ = hex[c >> 4];
696 *dp++ = hex[c & 0x0f];
697 } else
698 *dp++ = *src;
699 }
700 return (dst);
701 }
702
703 char*
escape_html(const char * src)704 escape_html(const char* src)
705 {
706 char *dp, *dst;
707
708 /* We need 5 times the memory if every letter is "&" */
709 if ((dst = calloc(5, strlen(src) + 1)) == NULL)
710 return NULL;
711
712 for (dp = dst; *src != 0; src++) {
713 if (*src == '<') {
714 *dp++ = '&';
715 *dp++ = 'l';
716 *dp++ = 't';
717 *dp++ = ';';
718 } else if (*src == '>') {
719 *dp++ = '&';
720 *dp++ = 'g';
721 *dp++ = 't';
722 *dp++ = ';';
723 } else if (*src == '&') {
724 *dp++ = '&';
725 *dp++ = 'a';
726 *dp++ = 'm';
727 *dp++ = 'p';
728 *dp++ = ';';
729 } else
730 *dp++ = *src;
731 }
732 return (dst);
733 }
734
735 void
socket_rlimit(int maxfd)736 socket_rlimit(int maxfd)
737 {
738 struct rlimit rl;
739
740 if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
741 fatal("%s: failed to get resource limit", __func__);
742 log_debug("%s: max open files %llu", __func__, rl.rlim_max);
743
744 /*
745 * Allow the maximum number of open file descriptors for this
746 * login class (which should be the class "daemon" by default).
747 */
748 if (maxfd == -1)
749 rl.rlim_cur = rl.rlim_max;
750 else
751 rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd);
752 if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
753 fatal("%s: failed to set resource limit", __func__);
754 }
755
756 char *
evbuffer_getline(struct evbuffer * evb)757 evbuffer_getline(struct evbuffer *evb)
758 {
759 uint8_t *ptr = EVBUFFER_DATA(evb);
760 size_t len = EVBUFFER_LENGTH(evb);
761 char *str;
762 size_t i;
763
764 /* Safe version of evbuffer_readline() */
765 if ((str = get_string(ptr, len)) == NULL)
766 return (NULL);
767
768 for (i = 0; str[i] != '\0'; i++) {
769 if (str[i] == '\r' || str[i] == '\n')
770 break;
771 }
772
773 if (i == len) {
774 free(str);
775 return (NULL);
776 }
777
778 str[i] = '\0';
779
780 if ((i + 1) < len) {
781 if (ptr[i] == '\r' && ptr[i + 1] == '\n')
782 i++;
783 }
784
785 evbuffer_drain(evb, ++i);
786
787 return (str);
788 }
789
790 char *
get_string(uint8_t * ptr,size_t len)791 get_string(uint8_t *ptr, size_t len)
792 {
793 size_t i;
794
795 for (i = 0; i < len; i++)
796 if (!(isprint((unsigned char)ptr[i]) ||
797 isspace((unsigned char)ptr[i])))
798 break;
799
800 return strndup(ptr, i);
801 }
802
803 void *
get_data(uint8_t * ptr,size_t len)804 get_data(uint8_t *ptr, size_t len)
805 {
806 uint8_t *data;
807
808 if ((data = malloc(len)) == NULL)
809 return (NULL);
810 memcpy(data, ptr, len);
811
812 return (data);
813 }
814
815 int
sockaddr_cmp(struct sockaddr * a,struct sockaddr * b,int prefixlen)816 sockaddr_cmp(struct sockaddr *a, struct sockaddr *b, int prefixlen)
817 {
818 struct sockaddr_in *a4, *b4;
819 struct sockaddr_in6 *a6, *b6;
820 uint32_t av[4], bv[4], mv[4];
821
822 if (a->sa_family == AF_UNSPEC || b->sa_family == AF_UNSPEC)
823 return (0);
824 else if (a->sa_family > b->sa_family)
825 return (1);
826 else if (a->sa_family < b->sa_family)
827 return (-1);
828
829 if (prefixlen == -1)
830 memset(&mv, 0xff, sizeof(mv));
831
832 switch (a->sa_family) {
833 case AF_INET:
834 a4 = (struct sockaddr_in *)a;
835 b4 = (struct sockaddr_in *)b;
836
837 av[0] = a4->sin_addr.s_addr;
838 bv[0] = b4->sin_addr.s_addr;
839 if (prefixlen != -1)
840 mv[0] = prefixlen2mask(prefixlen);
841
842 if ((av[0] & mv[0]) > (bv[0] & mv[0]))
843 return (1);
844 if ((av[0] & mv[0]) < (bv[0] & mv[0]))
845 return (-1);
846 break;
847 case AF_INET6:
848 a6 = (struct sockaddr_in6 *)a;
849 b6 = (struct sockaddr_in6 *)b;
850
851 memcpy(&av, &a6->sin6_addr.s6_addr, 16);
852 memcpy(&bv, &b6->sin6_addr.s6_addr, 16);
853 if (prefixlen != -1)
854 prefixlen2mask6(prefixlen, mv);
855
856 if ((av[3] & mv[3]) > (bv[3] & mv[3]))
857 return (1);
858 if ((av[3] & mv[3]) < (bv[3] & mv[3]))
859 return (-1);
860 if ((av[2] & mv[2]) > (bv[2] & mv[2]))
861 return (1);
862 if ((av[2] & mv[2]) < (bv[2] & mv[2]))
863 return (-1);
864 if ((av[1] & mv[1]) > (bv[1] & mv[1]))
865 return (1);
866 if ((av[1] & mv[1]) < (bv[1] & mv[1]))
867 return (-1);
868 if ((av[0] & mv[0]) > (bv[0] & mv[0]))
869 return (1);
870 if ((av[0] & mv[0]) < (bv[0] & mv[0]))
871 return (-1);
872 break;
873 }
874
875 return (0);
876 }
877
878 uint32_t
prefixlen2mask(uint8_t prefixlen)879 prefixlen2mask(uint8_t prefixlen)
880 {
881 if (prefixlen == 0)
882 return (0);
883
884 if (prefixlen > 32)
885 prefixlen = 32;
886
887 return (htonl(0xffffffff << (32 - prefixlen)));
888 }
889
890 struct in6_addr *
prefixlen2mask6(uint8_t prefixlen,uint32_t * mask)891 prefixlen2mask6(uint8_t prefixlen, uint32_t *mask)
892 {
893 static struct in6_addr s6;
894 int i;
895
896 if (prefixlen > 128)
897 prefixlen = 128;
898
899 memset(&s6, 0, sizeof(s6));
900 for (i = 0; i < prefixlen / 8; i++)
901 s6.s6_addr[i] = 0xff;
902 i = prefixlen % 8;
903 if (i)
904 s6.s6_addr[prefixlen / 8] = 0xff00 >> i;
905
906 memcpy(mask, &s6, sizeof(s6));
907
908 return (&s6);
909 }
910
911 int
accept_reserve(int sockfd,struct sockaddr * addr,socklen_t * addrlen,int reserve,volatile int * counter)912 accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
913 int reserve, volatile int *counter)
914 {
915 int ret;
916 if (getdtablecount() + reserve +
917 *counter >= getdtablesize()) {
918 errno = EMFILE;
919 return (-1);
920 }
921
922 if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK)) > -1) {
923 (*counter)++;
924 DPRINTF("%s: inflight incremented, now %d",__func__, *counter);
925 }
926 return (ret);
927 }
928
929 struct kv *
kv_add(struct kvtree * keys,char * key,char * value)930 kv_add(struct kvtree *keys, char *key, char *value)
931 {
932 struct kv *kv, *oldkv;
933
934 if (key == NULL)
935 return (NULL);
936 if ((kv = calloc(1, sizeof(*kv))) == NULL)
937 return (NULL);
938 if ((kv->kv_key = strdup(key)) == NULL) {
939 free(kv);
940 return (NULL);
941 }
942 if (value != NULL &&
943 (kv->kv_value = strdup(value)) == NULL) {
944 free(kv->kv_key);
945 free(kv);
946 return (NULL);
947 }
948 TAILQ_INIT(&kv->kv_children);
949
950 if ((oldkv = RB_INSERT(kvtree, keys, kv)) != NULL) {
951 TAILQ_INSERT_TAIL(&oldkv->kv_children, kv, kv_entry);
952 kv->kv_parent = oldkv;
953 }
954
955 return (kv);
956 }
957
958 int
kv_set(struct kv * kv,char * fmt,...)959 kv_set(struct kv *kv, char *fmt, ...)
960 {
961 va_list ap;
962 char *value = NULL;
963 struct kv *ckv;
964 int ret;
965
966 va_start(ap, fmt);
967 ret = vasprintf(&value, fmt, ap);
968 va_end(ap);
969 if (ret == -1)
970 return (-1);
971
972 /* Remove all children */
973 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) {
974 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry);
975 kv_free(ckv);
976 free(ckv);
977 }
978
979 /* Set the new value */
980 free(kv->kv_value);
981 kv->kv_value = value;
982
983 return (0);
984 }
985
986 int
kv_setkey(struct kv * kv,char * fmt,...)987 kv_setkey(struct kv *kv, char *fmt, ...)
988 {
989 va_list ap;
990 char *key = NULL;
991 int ret;
992
993 va_start(ap, fmt);
994 ret = vasprintf(&key, fmt, ap);
995 va_end(ap);
996 if (ret == -1)
997 return (-1);
998
999 free(kv->kv_key);
1000 kv->kv_key = key;
1001
1002 return (0);
1003 }
1004
1005 void
kv_delete(struct kvtree * keys,struct kv * kv)1006 kv_delete(struct kvtree *keys, struct kv *kv)
1007 {
1008 struct kv *ckv;
1009
1010 RB_REMOVE(kvtree, keys, kv);
1011
1012 /* Remove all children */
1013 while ((ckv = TAILQ_FIRST(&kv->kv_children)) != NULL) {
1014 TAILQ_REMOVE(&kv->kv_children, ckv, kv_entry);
1015 kv_free(ckv);
1016 free(ckv);
1017 }
1018
1019 kv_free(kv);
1020 free(kv);
1021 }
1022
1023 struct kv *
kv_extend(struct kvtree * keys,struct kv * kv,char * value)1024 kv_extend(struct kvtree *keys, struct kv *kv, char *value)
1025 {
1026 char *newvalue;
1027
1028 if (kv == NULL) {
1029 return (NULL);
1030 } else if (kv->kv_value != NULL) {
1031 if (asprintf(&newvalue, "%s%s", kv->kv_value, value) == -1)
1032 return (NULL);
1033
1034 free(kv->kv_value);
1035 kv->kv_value = newvalue;
1036 } else if ((kv->kv_value = strdup(value)) == NULL)
1037 return (NULL);
1038
1039 return (kv);
1040 }
1041
1042 void
kv_purge(struct kvtree * keys)1043 kv_purge(struct kvtree *keys)
1044 {
1045 struct kv *kv;
1046
1047 while ((kv = RB_MIN(kvtree, keys)) != NULL)
1048 kv_delete(keys, kv);
1049 }
1050
1051 void
kv_free(struct kv * kv)1052 kv_free(struct kv *kv)
1053 {
1054 free(kv->kv_key);
1055 kv->kv_key = NULL;
1056 free(kv->kv_value);
1057 kv->kv_value = NULL;
1058 memset(kv, 0, sizeof(*kv));
1059 }
1060
1061 struct kv *
kv_find(struct kvtree * keys,struct kv * kv)1062 kv_find(struct kvtree *keys, struct kv *kv)
1063 {
1064 return (RB_FIND(kvtree, keys, kv));
1065 }
1066
1067 int
kv_cmp(struct kv * a,struct kv * b)1068 kv_cmp(struct kv *a, struct kv *b)
1069 {
1070 return (strcasecmp(a->kv_key, b->kv_key));
1071 }
1072
1073 RB_GENERATE(kvtree, kv, kv_node, kv_cmp);
1074
1075 struct media_type *
media_add(struct mediatypes * types,struct media_type * media)1076 media_add(struct mediatypes *types, struct media_type *media)
1077 {
1078 struct media_type *entry;
1079
1080 if ((entry = RB_FIND(mediatypes, types, media)) != NULL) {
1081 log_debug("%s: entry overwritten for \"%s\"", __func__,
1082 media->media_name);
1083 media_delete(types, entry);
1084 }
1085
1086 if ((entry = malloc(sizeof(*media))) == NULL)
1087 return (NULL);
1088
1089 memcpy(entry, media, sizeof(*entry));
1090 if (media->media_encoding != NULL &&
1091 (entry->media_encoding = strdup(media->media_encoding)) == NULL) {
1092 free(entry);
1093 return (NULL);
1094 }
1095 RB_INSERT(mediatypes, types, entry);
1096
1097 return (entry);
1098 }
1099
1100 void
media_delete(struct mediatypes * types,struct media_type * media)1101 media_delete(struct mediatypes *types, struct media_type *media)
1102 {
1103 RB_REMOVE(mediatypes, types, media);
1104
1105 free(media->media_encoding);
1106 free(media);
1107 }
1108
1109 void
media_purge(struct mediatypes * types)1110 media_purge(struct mediatypes *types)
1111 {
1112 struct media_type *media;
1113
1114 while ((media = RB_MIN(mediatypes, types)) != NULL)
1115 media_delete(types, media);
1116 }
1117
1118 struct media_type *
media_find(struct mediatypes * types,const char * file)1119 media_find(struct mediatypes *types, const char *file)
1120 {
1121 struct media_type *match, media;
1122 char *p;
1123
1124 /* Last component of the file name */
1125 p = strchr(file, '\0');
1126 while (p > file && p[-1] != '.' && p[-1] != '/')
1127 p--;
1128 if (*p == '\0')
1129 return (NULL);
1130
1131 if (strlcpy(media.media_name, p,
1132 sizeof(media.media_name)) >=
1133 sizeof(media.media_name)) {
1134 return (NULL);
1135 }
1136
1137 /* Find media type by extension name */
1138 match = RB_FIND(mediatypes, types, &media);
1139
1140 return (match);
1141 }
1142
1143 struct media_type *
media_find_config(struct httpd * env,struct server_config * srv_conf,const char * file)1144 media_find_config(struct httpd *env, struct server_config *srv_conf,
1145 const char *file)
1146 {
1147 struct media_type *match;
1148
1149 if ((match = media_find(env->sc_mediatypes, file)) != NULL)
1150 return (match);
1151 else if (srv_conf->flags & SRVFLAG_DEFAULT_TYPE)
1152 return (&srv_conf->default_type);
1153
1154 /* fallback to the global default type */
1155 return (&env->sc_default_type);
1156 }
1157
1158 int
media_cmp(struct media_type * a,struct media_type * b)1159 media_cmp(struct media_type *a, struct media_type *b)
1160 {
1161 return (strcasecmp(a->media_name, b->media_name));
1162 }
1163
1164 RB_GENERATE(mediatypes, media_type, media_entry, media_cmp);
1165
1166 struct auth *
auth_add(struct serverauth * serverauth,struct auth * auth)1167 auth_add(struct serverauth *serverauth, struct auth *auth)
1168 {
1169 struct auth *entry;
1170
1171 TAILQ_FOREACH(entry, serverauth, auth_entry) {
1172 if (strcmp(entry->auth_htpasswd, auth->auth_htpasswd) == 0)
1173 return (entry);
1174 }
1175
1176 if ((entry = calloc(1, sizeof(*entry))) == NULL)
1177 return (NULL);
1178
1179 memcpy(entry, auth, sizeof(*entry));
1180
1181 TAILQ_INSERT_TAIL(serverauth, entry, auth_entry);
1182
1183 return (entry);
1184 }
1185
1186 struct auth *
auth_byid(struct serverauth * serverauth,uint32_t id)1187 auth_byid(struct serverauth *serverauth, uint32_t id)
1188 {
1189 struct auth *auth;
1190
1191 TAILQ_FOREACH(auth, serverauth, auth_entry) {
1192 if (auth->auth_id == id)
1193 return (auth);
1194 }
1195
1196 return (NULL);
1197 }
1198
1199 void
auth_free(struct serverauth * serverauth,struct auth * auth)1200 auth_free(struct serverauth *serverauth, struct auth *auth)
1201 {
1202 TAILQ_REMOVE(serverauth, auth, auth_entry);
1203 }
1204
1205
1206 const char *
print_host(struct sockaddr_storage * ss,char * buf,size_t len)1207 print_host(struct sockaddr_storage *ss, char *buf, size_t len)
1208 {
1209 if (getnameinfo((struct sockaddr *)ss, ss->ss_len,
1210 buf, len, NULL, 0, NI_NUMERICHOST) != 0) {
1211 buf[0] = '\0';
1212 return (NULL);
1213 }
1214 return (buf);
1215 }
1216
1217 const char *
printb_flags(const uint32_t v,const char * bits)1218 printb_flags(const uint32_t v, const char *bits)
1219 {
1220 static char buf[2][BUFSIZ];
1221 static int idx = 0;
1222 int i, any = 0;
1223 char c, *p, *r;
1224
1225 p = r = buf[++idx % 2];
1226 memset(p, 0, BUFSIZ);
1227
1228 if (bits) {
1229 bits++;
1230 while ((i = *bits++)) {
1231 if (v & (1 << (i - 1))) {
1232 if (any) {
1233 *p++ = ',';
1234 *p++ = ' ';
1235 }
1236 any = 1;
1237 for (; (c = *bits) > 32; bits++) {
1238 if (c == '_')
1239 *p++ = ' ';
1240 else
1241 *p++ =
1242 tolower((unsigned char)c);
1243 }
1244 } else
1245 for (; *bits > 32; bits++)
1246 ;
1247 }
1248 }
1249
1250 return (r);
1251 }
1252
1253 void
getmonotime(struct timeval * tv)1254 getmonotime(struct timeval *tv)
1255 {
1256 struct timespec ts;
1257
1258 if (clock_gettime(CLOCK_MONOTONIC, &ts))
1259 fatal("clock_gettime");
1260
1261 TIMESPEC_TO_TIMEVAL(tv, &ts);
1262 }
1263