Bug Summary

File:src/usr.sbin/httpd/server.c
Warning:line 449, column 3
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name server.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/httpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/httpd -I /usr/src/usr.sbin/httpd/obj -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/httpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/httpd/server.c
1/* $OpenBSD: server.c,v 1.129 2023/11/08 19:19:10 millert Exp $ */
2
3/*
4 * Copyright (c) 2006 - 2015 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/time.h>
22#include <sys/stat.h>
23#include <sys/socket.h>
24#include <sys/uio.h>
25#include <sys/tree.h>
26
27#include <netinet/in.h>
28#include <netinet/tcp.h>
29#include <arpa/inet.h>
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <stdarg.h>
34#include <limits.h>
35#include <errno(*__errno()).h>
36#include <fcntl.h>
37#include <string.h>
38#include <syslog.h>
39#include <unistd.h>
40#include <event.h>
41#include <imsg.h>
42#include <tls.h>
43#include <vis.h>
44
45#include "httpd.h"
46
47#define MINIMUM(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
48
49int server_dispatch_parent(int, struct privsep_proc *,
50 struct imsg *);
51int server_dispatch_logger(int, struct privsep_proc *,
52 struct imsg *);
53void server_shutdown(void);
54
55void server_init(struct privsep *, struct privsep_proc *p, void *);
56void server_launch(void);
57int server_socket(struct sockaddr_storage *, in_port_t,
58 struct server_config *, int, int);
59int server_socket_listen(struct sockaddr_storage *, in_port_t,
60 struct server_config *);
61struct server *server_byid(uint32_t);
62
63int server_tls_init(struct server *);
64void server_tls_readcb(int, short, void *);
65void server_tls_writecb(int, short, void *);
66void server_tls_handshake(int, short, void *);
67
68void server_accept(int, short, void *);
69void server_input(struct client *);
70void server_inflight_dec(struct client *, const char *);
71
72extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t,
73 size_t, void *);
74
75volatile int server_clients;
76volatile int server_inflight = 0;
77uint32_t server_cltid;
78
79static struct privsep_proc procs[] = {
80 { "parent", PROC_PARENT, server_dispatch_parent },
81 { "logger", PROC_LOGGER, server_dispatch_logger }
82};
83
84void
85server(struct privsep *ps, struct privsep_proc *p)
86{
87 proc_run(ps, p, procs, nitems(procs)(sizeof((procs)) / sizeof((procs)[0])), server_init, NULL((void *)0));
88 server_http();
89}
90
91void
92server_shutdown(void)
93{
94 config_purge(httpd_env, CONFIG_ALL0xff);
95 usleep(200); /* XXX server needs to shutdown last */
96}
97
98int
99server_privinit(struct server *srv)
100{
101 struct server *s;
102
103 if (srv->srv_conf.flags & SRVFLAG_LOCATION0x00000020)
104 return (0);
105
106 log_debug("%s: adding server %s", __func__, srv->srv_conf.name);
107
108 /*
109 * There's no need to open a new socket if a server with the
110 * same address already exists.
111 */
112 TAILQ_FOREACH(s, httpd_env->sc_servers, srv_entry)for((s) = ((httpd_env->sc_servers)->tqh_first); (s) != (
(void *)0); (s) = ((s)->srv_entry.tqe_next))
{
113 if (s != srv && s->srv_s != -1 &&
114 s->srv_conf.port == srv->srv_conf.port &&
115 sockaddr_cmp((struct sockaddr *)&s->srv_conf.ss,
116 (struct sockaddr *)&srv->srv_conf.ss,
117 s->srv_conf.prefixlen) == 0)
118 return (0);
119 }
120
121 /* Open listening socket in the privileged process */
122 if ((srv->srv_s = server_socket_listen(&srv->srv_conf.ss,
123 srv->srv_conf.port, &srv->srv_conf)) == -1)
124 return (-1);
125
126 return (0);
127}
128
129int
130server_tls_cmp(struct server *s1, struct server *s2)
131{
132 struct server_config *sc1, *sc2;
133
134 sc1 = &s1->srv_conf;
135 sc2 = &s2->srv_conf;
136
137 if (sc1->tls_flags != sc2->tls_flags)
138 return (-1);
139 if (sc1->tls_protocols != sc2->tls_protocols)
140 return (-1);
141 if (sc1->tls_ticket_lifetime != sc2->tls_ticket_lifetime)
142 return (-1);
143 if (strcmp(sc1->tls_ciphers, sc2->tls_ciphers) != 0)
144 return (-1);
145 if (strcmp(sc1->tls_dhe_params, sc2->tls_dhe_params) != 0)
146 return (-1);
147 if (strcmp(sc1->tls_ecdhe_curves, sc2->tls_ecdhe_curves) != 0)
148 return (-1);
149
150 return (0);
151}
152
153int
154server_tls_load_keypair(struct server *srv)
155{
156 if ((srv->srv_conf.flags & SRVFLAG_TLS0x00002000) == 0)
157 return (0);
158
159 if ((srv->srv_conf.tls_cert = tls_load_file(srv->srv_conf.tls_cert_file,
160 &srv->srv_conf.tls_cert_len, NULL((void *)0))) == NULL((void *)0))
161 return (-1);
162 log_debug("%s: using certificate %s", __func__,
163 srv->srv_conf.tls_cert_file);
164
165 /* XXX allow to specify password for encrypted key */
166 if ((srv->srv_conf.tls_key = tls_load_file(srv->srv_conf.tls_key_file,
167 &srv->srv_conf.tls_key_len, NULL((void *)0))) == NULL((void *)0))
168 return (-1);
169 log_debug("%s: using private key %s", __func__,
170 srv->srv_conf.tls_key_file);
171
172 return (0);
173}
174
175int
176server_tls_load_ocsp(struct server *srv)
177{
178 if ((srv->srv_conf.flags & SRVFLAG_TLS0x00002000) == 0)
179 return (0);
180
181 if (srv->srv_conf.tls_ocsp_staple_file == NULL((void *)0))
182 return (0);
183
184 if ((srv->srv_conf.tls_ocsp_staple = tls_load_file(
185 srv->srv_conf.tls_ocsp_staple_file,
186 &srv->srv_conf.tls_ocsp_staple_len, NULL((void *)0))) == NULL((void *)0)) {
187 log_warnx("%s: Failed to load ocsp staple from %s", __func__,
188 srv->srv_conf.tls_ocsp_staple_file);
189 return (-1);
190 }
191
192 if (srv->srv_conf.tls_ocsp_staple_len == 0) {
193 log_warnx("%s: ignoring 0 length ocsp staple from %s", __func__,
194 srv->srv_conf.tls_ocsp_staple_file);
195 return (0);
196 }
197
198 log_debug("%s: using ocsp staple from %s", __func__,
199 srv->srv_conf.tls_ocsp_staple_file);
200
201 return (0);
202}
203
204int
205server_tls_load_ca(struct server *srv)
206{
207 if ((srv->srv_conf.tls_flags & TLSFLAG_CA0x01) == 0 ||
208 srv->srv_conf.tls_ca_file == NULL((void *)0))
209 return (0);
210
211 if ((srv->srv_conf.tls_ca = tls_load_file(
212 srv->srv_conf.tls_ca_file,
213 &srv->srv_conf.tls_ca_len, NULL((void *)0))) == NULL((void *)0))
214 return (-1);
215 log_debug("%s: using ca cert(s) from %s", __func__,
216 srv->srv_conf.tls_ca_file);
217
218 return (0);
219}
220
221int
222server_tls_load_crl(struct server *srv)
223{
224 if ((srv->srv_conf.tls_flags & TLSFLAG_CA0x01) == 0 ||
225 srv->srv_conf.tls_crl_file == NULL((void *)0))
226 return (0);
227
228 if ((srv->srv_conf.tls_crl = tls_load_file(
229 srv->srv_conf.tls_crl_file,
230 &srv->srv_conf.tls_crl_len, NULL((void *)0))) == NULL((void *)0))
231 return (-1);
232 log_debug("%s: using crl(s) from %s", __func__,
233 srv->srv_conf.tls_crl_file);
234
235 return (0);
236}
237
238int
239server_tls_init(struct server *srv)
240{
241 struct server_config *srv_conf;
242
243 if ((srv->srv_conf.flags & SRVFLAG_TLS0x00002000) == 0)
244 return (0);
245
246 log_debug("%s: setting up tls for %s", __func__, srv->srv_conf.name);
247
248 if ((srv->srv_tls_config = tls_config_new()) == NULL((void *)0)) {
249 log_warnx("%s: failed to get tls config", __func__);
250 return (-1);
251 }
252 if ((srv->srv_tls_ctx = tls_server()) == NULL((void *)0)) {
253 log_warnx("%s: failed to get tls server", __func__);
254 return (-1);
255 }
256
257 if (tls_config_set_protocols(srv->srv_tls_config,
258 srv->srv_conf.tls_protocols) != 0) {
259 log_warnx("%s: failed to set tls protocols: %s",
260 __func__, tls_config_error(srv->srv_tls_config));
261 return (-1);
262 }
263 if (tls_config_set_ciphers(srv->srv_tls_config,
264 srv->srv_conf.tls_ciphers) != 0) {
265 log_warnx("%s: failed to set tls ciphers: %s",
266 __func__, tls_config_error(srv->srv_tls_config));
267 return (-1);
268 }
269 if (tls_config_set_dheparams(srv->srv_tls_config,
270 srv->srv_conf.tls_dhe_params) != 0) {
271 log_warnx("%s: failed to set tls dhe params: %s",
272 __func__, tls_config_error(srv->srv_tls_config));
273 return (-1);
274 }
275 if (tls_config_set_ecdhecurves(srv->srv_tls_config,
276 srv->srv_conf.tls_ecdhe_curves) != 0) {
277 log_warnx("%s: failed to set tls ecdhe curves: %s",
278 __func__, tls_config_error(srv->srv_tls_config));
279 return (-1);
280 }
281
282 if (tls_config_set_keypair_ocsp_mem(srv->srv_tls_config,
283 srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len,
284 srv->srv_conf.tls_key, srv->srv_conf.tls_key_len,
285 srv->srv_conf.tls_ocsp_staple,
286 srv->srv_conf.tls_ocsp_staple_len) != 0) {
287 log_warnx("%s: failed to set tls certificate/key: %s",
288 __func__, tls_config_error(srv->srv_tls_config));
289 return (-1);
290 }
291
292 if (srv->srv_conf.tls_ca != NULL((void *)0)) {
293 if (tls_config_set_ca_mem(srv->srv_tls_config,
294 srv->srv_conf.tls_ca, srv->srv_conf.tls_ca_len) != 0) {
295 log_warnx("%s: failed to add ca cert(s)", __func__);
296 return (-1);
297 }
298 if (tls_config_set_crl_mem(srv->srv_tls_config,
299 srv->srv_conf.tls_crl, srv->srv_conf.tls_crl_len) != 0) {
300 log_warnx("%s: failed to add crl(s)", __func__);
301 return (-1);
302 }
303 if (srv->srv_conf.tls_flags & TLSFLAG_OPTIONAL0x04)
304 tls_config_verify_client_optional(srv->srv_tls_config);
305 else
306 tls_config_verify_client(srv->srv_tls_config);
307 }
308
309 TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry)for((srv_conf) = ((&srv->srv_hosts)->tqh_first); (srv_conf
) != ((void *)0); (srv_conf) = ((srv_conf)->entry.tqe_next
))
{
310 if (srv_conf->tls_cert == NULL((void *)0) || srv_conf->tls_key == NULL((void *)0))
311 continue;
312 log_debug("%s: adding keypair for server %s", __func__,
313 srv->srv_conf.name);
314 if (tls_config_add_keypair_ocsp_mem(srv->srv_tls_config,
315 srv_conf->tls_cert, srv_conf->tls_cert_len,
316 srv_conf->tls_key, srv_conf->tls_key_len,
317 srv_conf->tls_ocsp_staple,
318 srv_conf->tls_ocsp_staple_len) != 0) {
319 log_warnx("%s: failed to add tls keypair", __func__);
320 return (-1);
321 }
322 }
323
324 /* set common session ID among all processes */
325 if (tls_config_set_session_id(srv->srv_tls_config,
326 httpd_env->sc_tls_sid, sizeof(httpd_env->sc_tls_sid)) == -1) {
327 log_warnx("%s: could not set the TLS session ID: %s",
328 __func__, tls_config_error(srv->srv_tls_config));
329 return (-1);
330 }
331
332 /* ticket support */
333 if (srv->srv_conf.tls_ticket_lifetime) {
334 if (tls_config_set_session_lifetime(srv->srv_tls_config,
335 srv->srv_conf.tls_ticket_lifetime) == -1) {
336 log_warnx("%s: could not set the TLS session lifetime: "
337 "%s", __func__,
338 tls_config_error(srv->srv_tls_config));
339 return (-1);
340 }
341 tls_config_add_ticket_key(srv->srv_tls_config,
342 srv->srv_conf.tls_ticket_key.tt_keyrev,
343 srv->srv_conf.tls_ticket_key.tt_key,
344 sizeof(srv->srv_conf.tls_ticket_key.tt_key));
345 explicit_bzero(&srv->srv_conf.tls_ticket_key,
346 sizeof(srv->srv_conf.tls_ticket_key));
347 }
348
349 if (tls_configure(srv->srv_tls_ctx, srv->srv_tls_config) != 0) {
350 log_warnx("%s: failed to configure tls - %s", __func__,
351 tls_error(srv->srv_tls_ctx));
352 return (-1);
353 }
354
355 /* We're now done with the public/private key & ca/crl... */
356 tls_config_clear_keys(srv->srv_tls_config);
357 freezero(srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len);
358 freezero(srv->srv_conf.tls_key, srv->srv_conf.tls_key_len);
359 free(srv->srv_conf.tls_ca);
360 free(srv->srv_conf.tls_crl);
361 srv->srv_conf.tls_ca = NULL((void *)0);
362 srv->srv_conf.tls_cert = NULL((void *)0);
363 srv->srv_conf.tls_crl = NULL((void *)0);
364 srv->srv_conf.tls_key = NULL((void *)0);
365 srv->srv_conf.tls_ca_len = 0;
366 srv->srv_conf.tls_cert_len = 0;
367 srv->srv_conf.tls_crl_len = 0;
368 srv->srv_conf.tls_key_len = 0;
369
370 return (0);
371}
372
373void
374server_generate_ticket_key(struct server_config *srv_conf)
375{
376 struct server_tls_ticket *key = &srv_conf->tls_ticket_key;
377
378 key->tt_id = srv_conf->id;
379 key->tt_keyrev = arc4random();
380 arc4random_buf(key->tt_key, sizeof(key->tt_key));
381}
382
383void
384server_init(struct privsep *ps, struct privsep_proc *p, void *arg)
385{
386 server_http();
387
388 if (config_init(ps->ps_env) == -1)
389 fatal("failed to initialize configuration");
390
391 /* We use a custom shutdown callback */
392 p->p_shutdown = server_shutdown;
393
394 /* Unlimited file descriptors (use system limits) */
395 socket_rlimit(-1);
396
397 if (pledge("stdio rpath inet unix recvfd", NULL((void *)0)) == -1)
398 fatal("pledge");
399
400#if 0
401 /* Schedule statistics timer */
402 evtimer_set(&ps->ps_env->sc_statev, server_statistics, NULL)event_set(&ps->ps_env->sc_statev, -1, 0, server_statistics
, ((void *)0))
;
403 memcpy(&tv, &ps->ps_env->sc_statinterval, sizeof(tv));
404 evtimer_add(&ps->ps_env->sc_statev, &tv)event_add(&ps->ps_env->sc_statev, &tv);
405#endif
406}
407
408void
409server_launch(void)
410{
411 struct server *srv;
412
413 TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry)for((srv) = ((httpd_env->sc_servers)->tqh_first); (srv)
!= ((void *)0); (srv) = ((srv)->srv_entry.tqe_next))
{
414 log_debug("%s: configuring server %s", __func__,
415 srv->srv_conf.name);
416
417 server_tls_init(srv);
418 server_http_init(srv);
419
420 log_debug("%s: running server %s", __func__,
421 srv->srv_conf.name);
422
423 event_set(&srv->srv_ev, srv->srv_s, EV_READ0x02,
424 server_accept, srv);
425 event_add(&srv->srv_ev, NULL((void *)0));
426 evtimer_set(&srv->srv_evt, server_accept, srv)event_set(&srv->srv_evt, -1, 0, server_accept, srv);
427 }
428}
429
430void
431server_purge(struct server *srv)
432{
433 struct client *clt;
434 struct server_config *srv_conf;
435
436 /* shutdown and remove server */
437 if (event_initialized(&srv->srv_ev)((&srv->srv_ev)->ev_flags & 0x80))
1
Assuming the condition is false
2
Taking false branch
438 event_del(&srv->srv_ev);
439 if (evtimer_initialized(&srv->srv_evt)((&srv->srv_evt)->ev_flags & 0x80))
3
Assuming the condition is false
4
Taking false branch
440 evtimer_del(&srv->srv_evt)event_del(&srv->srv_evt);
441
442 if (srv->srv_s != -1)
5
Assuming the condition is false
6
Taking false branch
443 close(srv->srv_s);
444 TAILQ_REMOVE(httpd_env->sc_servers, srv, srv_entry)do { if (((srv)->srv_entry.tqe_next) != ((void *)0)) (srv)
->srv_entry.tqe_next->srv_entry.tqe_prev = (srv)->srv_entry
.tqe_prev; else (httpd_env->sc_servers)->tqh_last = (srv
)->srv_entry.tqe_prev; *(srv)->srv_entry.tqe_prev = (srv
)->srv_entry.tqe_next; ; ; } while (0)
;
7
Assuming field 'tqe_next' is equal to null
8
Taking false branch
9
Loop condition is false. Exiting loop
445
446 /* cleanup sessions */
447 while ((clt =
10
Assuming the condition is true
11
Loop condition is true. Entering loop body
37
Loop condition is true. Entering loop body
448 SPLAY_ROOT(&srv->srv_clients)(&srv->srv_clients)->sph_root) != NULL((void *)0))
449 server_close(clt, NULL((void *)0));
12
Calling 'server_close'
36
Returning; memory was released via 1st parameter
38
Use of memory after it is freed
450
451 /* cleanup hosts */
452 while ((srv_conf =
453 TAILQ_FIRST(&srv->srv_hosts)((&srv->srv_hosts)->tqh_first)) != NULL((void *)0)) {
454 TAILQ_REMOVE(&srv->srv_hosts, srv_conf, entry)do { if (((srv_conf)->entry.tqe_next) != ((void *)0)) (srv_conf
)->entry.tqe_next->entry.tqe_prev = (srv_conf)->entry
.tqe_prev; else (&srv->srv_hosts)->tqh_last = (srv_conf
)->entry.tqe_prev; *(srv_conf)->entry.tqe_prev = (srv_conf
)->entry.tqe_next; ; ; } while (0)
;
455
456 /* It might point to our own "default" entry */
457 if (srv_conf != &srv->srv_conf) {
458 serverconfig_free(srv_conf);
459 free(srv_conf);
460 }
461 }
462
463 tls_config_free(srv->srv_tls_config);
464 tls_free(srv->srv_tls_ctx);
465
466 free(srv);
467}
468
469void
470serverconfig_free(struct server_config *srv_conf)
471{
472 struct fastcgi_param *param, *tparam;
473
474 free(srv_conf->return_uri);
475 free(srv_conf->tls_ca_file);
476 free(srv_conf->tls_ca);
477 free(srv_conf->tls_cert_file);
478 free(srv_conf->tls_crl_file);
479 free(srv_conf->tls_crl);
480 free(srv_conf->tls_key_file);
481 free(srv_conf->tls_ocsp_staple_file);
482 free(srv_conf->tls_ocsp_staple);
483 freezero(srv_conf->tls_cert, srv_conf->tls_cert_len);
484 freezero(srv_conf->tls_key, srv_conf->tls_key_len);
485
486 TAILQ_FOREACH_SAFE(param, &srv_conf->fcgiparams, entry, tparam)for ((param) = ((&srv_conf->fcgiparams)->tqh_first)
; (param) != ((void *)0) && ((tparam) = ((param)->
entry.tqe_next), 1); (param) = (tparam))
487 free(param);
488}
489
490void
491serverconfig_reset(struct server_config *srv_conf)
492{
493 srv_conf->auth = NULL((void *)0);
494 srv_conf->return_uri = NULL((void *)0);
495 srv_conf->tls_ca = NULL((void *)0);
496 srv_conf->tls_ca_file = NULL((void *)0);
497 srv_conf->tls_cert = NULL((void *)0);
498 srv_conf->tls_cert_file = NULL((void *)0);
499 srv_conf->tls_crl = NULL((void *)0);
500 srv_conf->tls_crl_file = NULL((void *)0);
501 srv_conf->tls_key = NULL((void *)0);
502 srv_conf->tls_key_file = NULL((void *)0);
503 srv_conf->tls_ocsp_staple = NULL((void *)0);
504 srv_conf->tls_ocsp_staple_file = NULL((void *)0);
505 TAILQ_INIT(&srv_conf->fcgiparams)do { (&srv_conf->fcgiparams)->tqh_first = ((void *)
0); (&srv_conf->fcgiparams)->tqh_last = &(&
srv_conf->fcgiparams)->tqh_first; } while (0)
;
506}
507
508struct server *
509server_byaddr(struct sockaddr *addr, in_port_t port)
510{
511 struct server *srv;
512
513 TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry)for((srv) = ((httpd_env->sc_servers)->tqh_first); (srv)
!= ((void *)0); (srv) = ((srv)->srv_entry.tqe_next))
{
514 if (port == srv->srv_conf.port &&
515 sockaddr_cmp((struct sockaddr *)&srv->srv_conf.ss,
516 addr, srv->srv_conf.prefixlen) == 0)
517 return (srv);
518 }
519
520 return (NULL((void *)0));
521}
522
523struct server_config *
524serverconfig_byid(uint32_t id)
525{
526 struct server *srv;
527 struct server_config *srv_conf;
528
529 TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry)for((srv) = ((httpd_env->sc_servers)->tqh_first); (srv)
!= ((void *)0); (srv) = ((srv)->srv_entry.tqe_next))
{
530 if (srv->srv_conf.id == id)
531 return (&srv->srv_conf);
532 TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry)for((srv_conf) = ((&srv->srv_hosts)->tqh_first); (srv_conf
) != ((void *)0); (srv_conf) = ((srv_conf)->entry.tqe_next
))
{
533 if (srv_conf->id == id)
534 return (srv_conf);
535 }
536 }
537
538 return (NULL((void *)0));
539}
540
541struct server *
542server_byid(uint32_t id)
543{
544 struct server *srv;
545
546 TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry)for((srv) = ((httpd_env->sc_servers)->tqh_first); (srv)
!= ((void *)0); (srv) = ((srv)->srv_entry.tqe_next))
{
547 if (srv->srv_conf.id == id)
548 return (srv);
549 }
550 return (NULL((void *)0));
551}
552
553int
554server_foreach(int (*srv_cb)(struct server *,
555 struct server_config *, void *), void *arg)
556{
557 struct server *srv;
558 struct server_config *srv_conf;
559
560 TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry)for((srv) = ((httpd_env->sc_servers)->tqh_first); (srv)
!= ((void *)0); (srv) = ((srv)->srv_entry.tqe_next))
{
561 if ((srv_cb)(srv, &srv->srv_conf, arg) == -1)
562 return (-1);
563 TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry)for((srv_conf) = ((&srv->srv_hosts)->tqh_first); (srv_conf
) != ((void *)0); (srv_conf) = ((srv_conf)->entry.tqe_next
))
{
564 if ((srv_cb)(srv, srv_conf, arg) == -1)
565 return (-1);
566 }
567 }
568
569 return (0);
570}
571
572struct server *
573server_match(struct server *s2, int match_name)
574{
575 struct server *s1;
576
577 /* Attempt to find matching server. */
578 TAILQ_FOREACH(s1, httpd_env->sc_servers, srv_entry)for((s1) = ((httpd_env->sc_servers)->tqh_first); (s1) !=
((void *)0); (s1) = ((s1)->srv_entry.tqe_next))
{
579 if ((s1->srv_conf.flags & SRVFLAG_LOCATION0x00000020) != 0)
580 continue;
581 if (match_name) {
582 if (strcmp(s1->srv_conf.name, s2->srv_conf.name) != 0)
583 continue;
584 }
585 if (s1->srv_conf.port != s2->srv_conf.port)
586 continue;
587 if (sockaddr_cmp(
588 (struct sockaddr *)&s1->srv_conf.ss,
589 (struct sockaddr *)&s2->srv_conf.ss,
590 s1->srv_conf.prefixlen) != 0)
591 continue;
592
593 return (s1);
594 }
595
596 return (NULL((void *)0));
597}
598
599int
600server_socket_af(struct sockaddr_storage *ss, in_port_t port)
601{
602 switch (ss->ss_family) {
603 case AF_INET2:
604 ((struct sockaddr_in *)ss)->sin_port = port;
605 ((struct sockaddr_in *)ss)->sin_len =
606 sizeof(struct sockaddr_in);
607 break;
608 case AF_INET624:
609 ((struct sockaddr_in6 *)ss)->sin6_port = port;
610 ((struct sockaddr_in6 *)ss)->sin6_len =
611 sizeof(struct sockaddr_in6);
612 break;
613 default:
614 return (-1);
615 }
616
617 return (0);
618}
619
620in_port_t
621server_socket_getport(struct sockaddr_storage *ss)
622{
623 switch (ss->ss_family) {
624 case AF_INET2:
625 return (((struct sockaddr_in *)ss)->sin_port);
626 case AF_INET624:
627 return (((struct sockaddr_in6 *)ss)->sin6_port);
628 default:
629 return (0);
630 }
631
632 /* NOTREACHED */
633 return (0);
634}
635
636int
637server_socket(struct sockaddr_storage *ss, in_port_t port,
638 struct server_config *srv_conf, int fd, int reuseport)
639{
640 struct linger lng;
641 int s = -1, val;
642
643 if (server_socket_af(ss, port) == -1)
644 goto bad;
645
646 s = fd == -1 ? socket(ss->ss_family, SOCK_STREAM1 | SOCK_NONBLOCK0x4000,
647 IPPROTO_TCP6) : fd;
648 if (s == -1)
649 goto bad;
650
651 /*
652 * Socket options
653 */
654 memset(&lng, 0, sizeof(lng));
655 if (setsockopt(s, SOL_SOCKET0xffff, SO_LINGER0x0080, &lng, sizeof(lng)) == -1)
656 goto bad;
657 if (reuseport) {
658 val = 1;
659 if (setsockopt(s, SOL_SOCKET0xffff, SO_REUSEPORT0x0200, &val,
660 sizeof(int)) == -1)
661 goto bad;
662 }
663 if (srv_conf->tcpflags & TCPFLAG_BUFSIZ0x10) {
664 val = srv_conf->tcpbufsiz;
665 if (setsockopt(s, SOL_SOCKET0xffff, SO_RCVBUF0x1002,
666 &val, sizeof(val)) == -1)
667 goto bad;
668 val = srv_conf->tcpbufsiz;
669 if (setsockopt(s, SOL_SOCKET0xffff, SO_SNDBUF0x1001,
670 &val, sizeof(val)) == -1)
671 goto bad;
672 }
673
674 /*
675 * IP options
676 */
677 if (srv_conf->tcpflags & TCPFLAG_IPTTL0x20) {
678 val = (int)srv_conf->tcpipttl;
679 switch (ss->ss_family) {
680 case AF_INET2:
681 if (setsockopt(s, IPPROTO_IP0, IP_TTL4,
682 &val, sizeof(val)) == -1)
683 goto bad;
684 break;
685 case AF_INET624:
686 if (setsockopt(s, IPPROTO_IPV641, IPV6_UNICAST_HOPS4,
687 &val, sizeof(val)) == -1)
688 goto bad;
689 break;
690 }
691 }
692 if (srv_conf->tcpflags & TCPFLAG_IPMINTTL0x40) {
693 val = (int)srv_conf->tcpipminttl;
694 switch (ss->ss_family) {
695 case AF_INET2:
696 if (setsockopt(s, IPPROTO_IP0, IP_MINTTL32,
697 &val, sizeof(val)) == -1)
698 goto bad;
699 break;
700 case AF_INET624:
701 if (setsockopt(s, IPPROTO_IPV641, IPV6_MINHOPCOUNT65,
702 &val, sizeof(val)) == -1)
703 goto bad;
704 break;
705 }
706 }
707
708 /*
709 * TCP options
710 */
711 if (srv_conf->tcpflags & (TCPFLAG_NODELAY0x01|TCPFLAG_NNODELAY0x02)) {
712 if (srv_conf->tcpflags & TCPFLAG_NNODELAY0x02)
713 val = 0;
714 else
715 val = 1;
716 if (setsockopt(s, IPPROTO_TCP6, TCP_NODELAY0x01,
717 &val, sizeof(val)) == -1)
718 goto bad;
719 }
720 if (srv_conf->tcpflags & (TCPFLAG_SACK0x04|TCPFLAG_NSACK0x08)) {
721 if (srv_conf->tcpflags & TCPFLAG_NSACK0x08)
722 val = 0;
723 else
724 val = 1;
725 if (setsockopt(s, IPPROTO_TCP6, TCP_SACK_ENABLE0x08,
726 &val, sizeof(val)) == -1)
727 goto bad;
728 }
729
730 return (s);
731
732 bad:
733 if (s != -1)
734 close(s);
735 return (-1);
736}
737
738int
739server_socket_listen(struct sockaddr_storage *ss, in_port_t port,
740 struct server_config *srv_conf)
741{
742 int s;
743
744 if ((s = server_socket(ss, port, srv_conf, -1, 1)) == -1)
745 return (-1);
746
747 if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1)
748 goto bad;
749 if (listen(s, srv_conf->tcpbacklog) == -1)
750 goto bad;
751
752 return (s);
753
754 bad:
755 close(s);
756 return (-1);
757}
758
759int
760server_socket_connect(struct sockaddr_storage *ss, in_port_t port,
761 struct server_config *srv_conf)
762{
763 int s;
764
765 if ((s = server_socket(ss, port, srv_conf, -1, 0)) == -1)
766 return (-1);
767
768 if (connect(s, (struct sockaddr *)ss, ss->ss_len) == -1) {
769 if (errno(*__errno()) != EINPROGRESS36)
770 goto bad;
771 }
772
773 return (s);
774
775 bad:
776 close(s);
777 return (-1);
778}
779
780void
781server_tls_readcb(int fd, short event, void *arg)
782{
783 struct bufferevent *bufev = arg;
784 struct client *clt = bufev->cbarg;
785 char rbuf[IBUF_READ_SIZE65535];
786 int what = EVBUFFER_READ0x01;
787 int howmuch = IBUF_READ_SIZE65535;
788 ssize_t ret;
789 size_t len;
790
791 if (event == EV_TIMEOUT0x01) {
792 what |= EVBUFFER_TIMEOUT0x40;
793 goto err;
794 }
795
796 if (bufev->wm_read.high != 0)
797 howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high)(((sizeof(rbuf)) < (bufev->wm_read.high)) ? (sizeof(rbuf
)) : (bufev->wm_read.high))
;
798
799 ret = tls_read(clt->clt_tls_ctx, rbuf, howmuch);
800 if (ret == TLS_WANT_POLLIN-2 || ret == TLS_WANT_POLLOUT-3) {
801 goto retry;
802 } else if (ret == -1) {
803 what |= EVBUFFER_ERROR0x20;
804 goto err;
805 }
806 len = ret;
807
808 if (len == 0) {
809 what |= EVBUFFER_EOF0x10;
810 goto err;
811 }
812
813 if (evbuffer_add(bufev->input, rbuf, len) == -1) {
814 what |= EVBUFFER_ERROR0x20;
815 goto err;
816 }
817
818 server_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
819
820 len = EVBUFFER_LENGTH(bufev->input)(bufev->input)->off;
821 if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
822 return;
823 if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) {
824 struct evbuffer *buf = bufev->input;
825 event_del(&bufev->ev_read);
826 evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
827 return;
828 }
829
830 if (bufev->readcb != NULL((void *)0))
831 (*bufev->readcb)(bufev, bufev->cbarg);
832 return;
833
834 retry:
835 server_bufferevent_add(&bufev->ev_read, bufev->timeout_read);
836 return;
837
838 err:
839 (*bufev->errorcb)(bufev, what, bufev->cbarg);
840}
841
842void
843server_tls_writecb(int fd, short event, void *arg)
844{
845 struct bufferevent *bufev = arg;
846 struct client *clt = bufev->cbarg;
847 ssize_t ret;
848 short what = EVBUFFER_WRITE0x02;
849 size_t len;
850
851 if (event == EV_TIMEOUT0x01) {
852 what |= EVBUFFER_TIMEOUT0x40;
853 goto err;
854 }
855
856 if (EVBUFFER_LENGTH(bufev->output)(bufev->output)->off) {
857 ret = tls_write(clt->clt_tls_ctx,
858 EVBUFFER_DATA(bufev->output)(bufev->output)->buffer,
859 EVBUFFER_LENGTH(bufev->output)(bufev->output)->off);
860 if (ret == TLS_WANT_POLLIN-2 || ret == TLS_WANT_POLLOUT-3) {
861 goto retry;
862 } else if (ret == -1) {
863 what |= EVBUFFER_ERROR0x20;
864 goto err;
865 }
866 len = ret;
867 evbuffer_drain(bufev->output, len);
868 }
869
870 if (EVBUFFER_LENGTH(bufev->output)(bufev->output)->off != 0)
871 server_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
872
873 if (bufev->writecb != NULL((void *)0) &&
874 EVBUFFER_LENGTH(bufev->output)(bufev->output)->off <= bufev->wm_write.low)
875 (*bufev->writecb)(bufev, bufev->cbarg);
876 return;
877
878 retry:
879 server_bufferevent_add(&bufev->ev_write, bufev->timeout_write);
880 return;
881
882 err:
883 (*bufev->errorcb)(bufev, what, bufev->cbarg);
884}
885
886void
887server_input(struct client *clt)
888{
889 struct server_config *srv_conf = clt->clt_srv_conf;
890 evbuffercb inrd = server_read;
891 evbuffercb inwr = server_write;
892 socklen_t slen;
893
894 if (server_httpdesc_init(clt) == -1) {
895 server_close(clt, "failed to allocate http descriptor");
896 return;
897 }
898
899 clt->clt_toread = TOREAD_HTTP_HEADER;
900 inrd = server_read_http;
901
902 slen = sizeof(clt->clt_sndbufsiz);
903 if (getsockopt(clt->clt_s, SOL_SOCKET0xffff, SO_SNDBUF0x1001,
904 &clt->clt_sndbufsiz, &slen) == -1) {
905 server_close(clt, "failed to get send buffer size");
906 return;
907 }
908
909 /*
910 * Client <-> Server
911 */
912 clt->clt_bev = bufferevent_new(clt->clt_s, inrd, inwr,
913 server_error, clt);
914 if (clt->clt_bev == NULL((void *)0)) {
915 server_close(clt, "failed to allocate input buffer event");
916 return;
917 }
918
919 if (srv_conf->flags & SRVFLAG_TLS0x00002000) {
920 event_set(&clt->clt_bev->ev_read, clt->clt_s, EV_READ0x02,
921 server_tls_readcb, clt->clt_bev);
922 event_set(&clt->clt_bev->ev_write, clt->clt_s, EV_WRITE0x04,
923 server_tls_writecb, clt->clt_bev);
924 }
925
926 /* Adjust write watermark to the socket buffer output size */
927 bufferevent_setwatermark(clt->clt_bev, EV_WRITE0x04,
928 SERVER_MIN_PREFETCHED32 * clt->clt_sndbufsiz, 0);
929 /* Read at most amount of data that fits in one fcgi record. */
930 bufferevent_setwatermark(clt->clt_bev, EV_READ0x02, 0, FCGI_CONTENT_SIZE65535);
931
932 bufferevent_settimeout(clt->clt_bev,
933 srv_conf->requesttimeout.tv_sec, srv_conf->requesttimeout.tv_sec);
934 bufferevent_enable(clt->clt_bev, EV_READ0x02|EV_WRITE0x04);
935}
936
937void
938server_write(struct bufferevent *bev, void *arg)
939{
940 struct client *clt = arg;
941 struct evbuffer *dst = EVBUFFER_OUTPUT(bev)(bev)->output;
942
943 if (EVBUFFER_LENGTH(dst)(dst)->off == 0 &&
944 clt->clt_toread == TOREAD_HTTP_NONE)
945 goto done;
946
947 getmonotime(&clt->clt_tv_last);
948
949 if (clt->clt_done)
950 goto done;
951
952 if (clt->clt_srvbev && clt->clt_srvbev_throttled) {
953 bufferevent_enable(clt->clt_srvbev, EV_READ0x02);
954 clt->clt_srvbev_throttled = 0;
955 }
956
957 return;
958 done:
959 (*bev->errorcb)(bev, EVBUFFER_WRITE0x02, bev->cbarg);
960 return;
961}
962
963void
964server_dump(struct client *clt, const void *buf, size_t len)
965{
966 if (!len)
967 return;
968
969 /*
970 * This function will dump the specified message directly
971 * to the underlying client, without waiting for success
972 * of non-blocking events etc. This is useful to print an
973 * error message before gracefully closing the client.
974 */
975 if (clt->clt_tls_ctx != NULL((void *)0))
976 (void)tls_write(clt->clt_tls_ctx, buf, len);
977 else
978 (void)write(clt->clt_s, buf, len);
979}
980
981void
982server_read(struct bufferevent *bev, void *arg)
983{
984 struct client *clt = arg;
985 struct evbuffer *src = EVBUFFER_INPUT(bev)(bev)->input;
986
987 getmonotime(&clt->clt_tv_last);
988
989 if (!EVBUFFER_LENGTH(src)(src)->off)
990 return;
991 if (server_bufferevent_write_buffer(clt, src) == -1)
992 goto fail;
993 if (clt->clt_done)
994 goto done;
995
996 if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(clt->clt_bev))((clt->clt_bev)->output)->off > (size_t)
997 SERVER_MAX_PREFETCH256 * clt->clt_sndbufsiz) {
998 bufferevent_disable(clt->clt_srvbev, EV_READ0x02);
999 clt->clt_srvbev_throttled = 1;
1000 }
1001
1002 return;
1003 done:
1004 (*bev->errorcb)(bev, EVBUFFER_READ0x01, bev->cbarg);
1005 return;
1006 fail:
1007 server_close(clt, strerror(errno(*__errno())));
1008}
1009
1010void
1011server_error(struct bufferevent *bev, short error, void *arg)
1012{
1013 struct client *clt = arg;
1014 struct evbuffer *dst;
1015
1016 if (error & EVBUFFER_TIMEOUT0x40) {
1017 if (!clt->clt_headersdone && clt->clt_line > 0)
1018 server_abort_http(clt, 408, "timeout");
1019 else
1020 server_close(clt, "timeout");
1021 return;
1022 }
1023 if (error & EVBUFFER_ERROR0x20) {
1024 if (errno(*__errno()) == EFBIG27) {
1025 bufferevent_enable(bev, EV_READ0x02);
1026 return;
1027 }
1028 server_close(clt, "buffer event error");
1029 return;
1030 }
1031 if (error & EVBUFFER_EOF0x10) {
1032 server_close(clt, "closed");
1033 return;
1034 }
1035 if (error & (EVBUFFER_READ0x01|EVBUFFER_WRITE0x02)) {
1036 bufferevent_disable(bev, EV_READ0x02|EV_WRITE0x04);
1037
1038 clt->clt_done = 1;
1039
1040 dst = EVBUFFER_OUTPUT(clt->clt_bev)(clt->clt_bev)->output;
1041 if (EVBUFFER_LENGTH(dst)(dst)->off) {
1042 /* Finish writing all data first */
1043 bufferevent_enable(clt->clt_bev, EV_WRITE0x04);
1044 return;
1045 }
1046
1047 server_close(clt, "done");
1048 return;
1049 }
1050 server_close(clt, "unknown event error");
1051 return;
1052}
1053
1054void
1055server_accept(int fd, short event, void *arg)
1056{
1057 struct server *srv = arg;
1058 struct client *clt = NULL((void *)0);
1059 socklen_t slen;
1060 struct sockaddr_storage ss;
1061 int s = -1;
1062
1063 event_add(&srv->srv_ev, NULL((void *)0));
1064 if ((event & EV_TIMEOUT0x01))
1065 return;
1066
1067 slen = sizeof(ss);
1068 if ((s = accept_reserve(fd, (struct sockaddr *)&ss,
1069 &slen, FD_RESERVE5, &server_inflight)) == -1) {
1070 /*
1071 * Pause accept if we are out of file descriptors, or
1072 * libevent will haunt us here too.
1073 */
1074 if (errno(*__errno()) == ENFILE23 || errno(*__errno()) == EMFILE24) {
1075 struct timeval evtpause = { 1, 0 };
1076
1077 event_del(&srv->srv_ev);
1078 evtimer_add(&srv->srv_evt, &evtpause)event_add(&srv->srv_evt, &evtpause);
1079 log_debug("%s: deferring connections", __func__);
1080 }
1081 return;
1082 }
1083 if (server_clients >= SERVER_MAX_CLIENTS1024)
1084 goto err;
1085
1086 if ((clt = calloc(1, sizeof(*clt))) == NULL((void *)0))
1087 goto err;
1088
1089 /* Pre-allocate log buffer */
1090 clt->clt_log = evbuffer_new();
1091 if (clt->clt_log == NULL((void *)0))
1092 goto err;
1093
1094 clt->clt_s = s;
1095 clt->clt_fd = -1;
1096 clt->clt_toread = TOREAD_UNLIMITED;
1097 clt->clt_srv = srv;
1098 clt->clt_srv_conf = &srv->srv_conf;
1099 clt->clt_id = ++server_cltid;
1100 clt->clt_srv_id = srv->srv_conf.id;
1101 clt->clt_pid = getpid();
1102 clt->clt_inflight = 1;
1103
1104 /* get local address */
1105 slen = sizeof(clt->clt_srv_ss);
1106 if (getsockname(s, (struct sockaddr *)&clt->clt_srv_ss,
1107 &slen) == -1) {
1108 server_close(clt, "listen address lookup failed");
1109 return;
1110 }
1111
1112 /* get client address */
1113 memcpy(&clt->clt_ss, &ss, sizeof(clt->clt_ss));
1114
1115 /* get ports */
1116 switch (ss.ss_family) {
1117 case AF_INET2:
1118 clt->clt_port = ((struct sockaddr_in *)&ss)->sin_port;
1119 break;
1120 case AF_INET624:
1121 clt->clt_port = ((struct sockaddr_in6 *)&ss)->sin6_port;
1122 break;
1123 }
1124
1125 getmonotime(&clt->clt_tv_start);
1126 memcpy(&clt->clt_tv_last, &clt->clt_tv_start, sizeof(clt->clt_tv_last));
1127
1128 server_clients++;
1129 SPLAY_INSERT(client_tree, &srv->srv_clients, clt)client_tree_SPLAY_INSERT(&srv->srv_clients, clt);
1130
1131 /* Pre-allocate output buffer */
1132 clt->clt_output = evbuffer_new();
1133 if (clt->clt_output == NULL((void *)0)) {
1134 server_close(clt, "failed to allocate output buffer");
1135 return;
1136 }
1137
1138 if (srv->srv_conf.flags & SRVFLAG_TLS0x00002000) {
1139 if (tls_accept_socket(srv->srv_tls_ctx, &clt->clt_tls_ctx,
1140 clt->clt_s) != 0) {
1141 server_close(clt, "failed to accept tls socket");
1142 return;
1143 }
1144 event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT0x01|EV_READ0x02,
1145 server_tls_handshake, &clt->clt_tv_start,
1146 &srv->srv_conf.timeout, clt);
1147 return;
1148 }
1149
1150 server_input(clt);
1151 return;
1152
1153 err:
1154 if (s != -1) {
1155 close(s);
1156 free(clt);
1157 /*
1158 * the client struct was not completely set up, but still
1159 * counted as an inflight client. account for this.
1160 */
1161 server_inflight_dec(NULL((void *)0), __func__);
1162 }
1163}
1164
1165void
1166server_tls_handshake(int fd, short event, void *arg)
1167{
1168 struct client *clt = (struct client *)arg;
1169 struct server *srv = (struct server *)clt->clt_srv;
1170 int ret;
1171
1172 if (event == EV_TIMEOUT0x01) {
1173 server_close(clt, "tls handshake timeout");
1174 return;
1175 }
1176
1177 if (srv->srv_tls_ctx == NULL((void *)0) || clt->clt_tls_ctx == NULL((void *)0))
1178 fatalx("NULL tls context");
1179
1180 ret = tls_handshake(clt->clt_tls_ctx);
1181 if (ret == 0) {
1182 server_input(clt);
1183 } else if (ret == TLS_WANT_POLLIN-2) {
1184 event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT0x01|EV_READ0x02,
1185 server_tls_handshake, &clt->clt_tv_start,
1186 &srv->srv_conf.timeout, clt);
1187 } else if (ret == TLS_WANT_POLLOUT-3) {
1188 event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT0x01|EV_WRITE0x04,
1189 server_tls_handshake, &clt->clt_tv_start,
1190 &srv->srv_conf.timeout, clt);
1191 } else {
1192 log_debug("%s: tls handshake failed - %s", __func__,
1193 tls_error(clt->clt_tls_ctx));
1194 server_close(clt, "tls handshake failed");
1195 }
1196}
1197
1198void
1199server_inflight_dec(struct client *clt, const char *why)
1200{
1201 if (clt != NULL((void *)0)) {
1202 /* the flight already left inflight mode. */
1203 if (clt->clt_inflight == 0)
1204 return;
1205 clt->clt_inflight = 0;
1206 }
1207
1208 /* the file was never opened, thus this was an inflight client. */
1209 server_inflight--;
1210 DPRINTF("%s: inflight decremented, now %d, %s",do {} while(0)
1211 __func__, server_inflight, why)do {} while(0);
1212}
1213
1214void
1215server_sendlog(struct server_config *srv_conf, int cmd, const char *emsg, ...)
1216{
1217 va_list ap;
1218 char *msg;
1219 int ret;
1220 struct iovec iov[2];
1221
1222 if (srv_conf->flags & SRVFLAG_SYSLOG0x00000800) {
1223 va_start(ap, emsg)__builtin_va_start((ap), emsg);
1224 if (cmd == IMSG_LOG_ACCESS)
1225 vlog(LOG_INFO6, emsg, ap);
1226 else
1227 vlog(LOG_DEBUG7, emsg, ap);
1228 va_end(ap)__builtin_va_end((ap));
1229 return;
1230 }
1231
1232 va_start(ap, emsg)__builtin_va_start((ap), emsg);
1233 ret = vasprintf(&msg, emsg, ap);
1234 va_end(ap)__builtin_va_end((ap));
1235 if (ret == -1) {
1236 log_warn("%s: vasprintf", __func__);
1237 return;
1238 }
1239
1240 iov[0].iov_base = &srv_conf->id;
1241 iov[0].iov_len = sizeof(srv_conf->id);
1242 iov[1].iov_base = msg;
1243 iov[1].iov_len = ret + 1;
1244
1245 if (proc_composev(httpd_env->sc_ps, PROC_LOGGER, cmd, iov, 2) != 0) {
1246 log_warn("%s: failed to compose imsg", __func__);
1247 free(msg);
1248 return;
1249 }
1250 free(msg);
1251}
1252
1253void
1254server_log(struct client *clt, const char *msg)
1255{
1256 char ibuf[HOST_NAME_MAX255+1], obuf[HOST_NAME_MAX255+1];
1257 struct server_config *srv_conf = clt->clt_srv_conf;
1258 char *ptr = NULL((void *)0), *vmsg = NULL((void *)0);
1259 int debug_cmd = -1;
1260
1261 switch (srv_conf->logformat) {
1262 case LOG_FORMAT_CONNECTION:
1263 debug_cmd = IMSG_LOG_ACCESS;
1264 break;
1265 default:
1266 if (log_getverbose() > 1)
1267 debug_cmd = IMSG_LOG_ERROR;
1268 if (EVBUFFER_LENGTH(clt->clt_log)(clt->clt_log)->off) {
1269 while ((ptr =
1270 evbuffer_readline(clt->clt_log)) != NULL((void *)0)) {
1271 server_sendlog(srv_conf,
1272 IMSG_LOG_ACCESS, "%s", ptr);
1273 free(ptr);
1274 }
1275 }
1276 break;
1277 }
1278
1279 if (debug_cmd != -1 && msg != NULL((void *)0)) {
1280 memset(ibuf, 0, sizeof(ibuf));
1281 memset(obuf, 0, sizeof(obuf));
1282 (void)print_host(&clt->clt_ss, ibuf, sizeof(ibuf));
1283 (void)server_http_host(&clt->clt_srv_ss, obuf, sizeof(obuf));
1284 if (EVBUFFER_LENGTH(clt->clt_log)(clt->clt_log)->off &&
1285 evbuffer_add_printf(clt->clt_log, "\n") != -1)
1286 ptr = evbuffer_readline(clt->clt_log);
1287 (void)stravis(&vmsg, msg, HTTPD_LOGVIS0x10|0x08|0x02);
1288 server_sendlog(srv_conf, debug_cmd, "server %s, "
1289 "client %d (%d active), %s:%u -> %s, "
1290 "%s%s%s", srv_conf->name, clt->clt_id, server_clients,
1291 ibuf, ntohs(clt->clt_port)(__uint16_t)(__builtin_constant_p(clt->clt_port) ? (__uint16_t
)(((__uint16_t)(clt->clt_port) & 0xffU) << 8 | (
(__uint16_t)(clt->clt_port) & 0xff00U) >> 8) : __swap16md
(clt->clt_port))
, obuf, vmsg == NULL((void *)0) ? "" : vmsg,
1292 ptr == NULL((void *)0) ? "" : ",", ptr == NULL((void *)0) ? "" : ptr);
1293 free(vmsg);
1294 free(ptr);
1295 }
1296}
1297
1298void
1299server_close(struct client *clt, const char *msg)
1300{
1301 struct server *srv = clt->clt_srv;
1302
1303 if (clt->clt_fcgi_count-- > 0) {
13
Assuming the condition is false
14
Taking false branch
1304 clt->clt_fcgi_error = msg;
1305 return;
1306 }
1307
1308 SPLAY_REMOVE(client_tree, &srv->srv_clients, clt)client_tree_SPLAY_REMOVE(&srv->srv_clients, clt);
1309
1310 /* free the HTTP descriptors incl. headers */
1311 server_close_http(clt);
1312
1313 /* tls_close must be called before the underlying socket is closed. */
1314 if (clt->clt_tls_ctx != NULL((void *)0))
15
Assuming field 'clt_tls_ctx' is equal to NULL
16
Taking false branch
1315 tls_close(clt->clt_tls_ctx); /* XXX - error handling */
1316 tls_free(clt->clt_tls_ctx);
1317
1318 event_del(&clt->clt_ev);
1319 if (clt->clt_bev != NULL((void *)0))
17
Assuming field 'clt_bev' is equal to NULL
18
Taking false branch
1320 bufferevent_disable(clt->clt_bev, EV_READ0x02|EV_WRITE0x04);
1321 if (clt->clt_srvbev != NULL((void *)0))
19
Assuming field 'clt_srvbev' is equal to NULL
20
Taking false branch
1322 bufferevent_disable(clt->clt_srvbev, EV_READ0x02|EV_WRITE0x04);
1323
1324 server_log(clt, msg);
1325
1326 if (clt->clt_bev != NULL((void *)0))
21
Assuming field 'clt_bev' is equal to NULL
22
Taking false branch
1327 bufferevent_free(clt->clt_bev);
1328 if (clt->clt_output != NULL((void *)0))
23
Assuming field 'clt_output' is equal to NULL
24
Taking false branch
1329 evbuffer_free(clt->clt_output);
1330 if (clt->clt_srvevb != NULL((void *)0))
25
Assuming field 'clt_srvevb' is equal to NULL
26
Taking false branch
1331 evbuffer_free(clt->clt_srvevb);
1332
1333 if (clt->clt_srvbev != NULL((void *)0))
27
Assuming field 'clt_srvbev' is equal to NULL
28
Taking false branch
1334 bufferevent_free(clt->clt_srvbev);
1335
1336 if (clt->clt_fd != -1)
29
Assuming the condition is false
30
Taking false branch
1337 close(clt->clt_fd);
1338 if (clt->clt_s != -1)
31
Assuming the condition is false
32
Taking false branch
1339 close(clt->clt_s);
1340
1341 server_inflight_dec(clt, __func__);
1342
1343 if (clt->clt_log != NULL((void *)0))
33
Assuming field 'clt_log' is equal to NULL
34
Taking false branch
1344 evbuffer_free(clt->clt_log);
1345
1346 free(clt);
35
Memory is released
1347 server_clients--;
1348}
1349
1350int
1351server_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)
1352{
1353 struct server *srv;
1354 struct server_tls_ticket key;
1355
1356 switch (imsg->hdr.type) {
1357 case IMSG_CFG_MEDIA:
1358 config_getmedia(httpd_env, imsg);
1359 break;
1360 case IMSG_CFG_AUTH:
1361 config_getauth(httpd_env, imsg);
1362 break;
1363 case IMSG_CFG_SERVER:
1364 config_getserver(httpd_env, imsg);
1365 break;
1366 case IMSG_CFG_TLS:
1367 config_getserver_tls(httpd_env, imsg);
1368 break;
1369 case IMSG_CFG_FCGI:
1370 config_getserver_fcgiparams(httpd_env, imsg);
1371 break;
1372 case IMSG_CFG_DONE:
1373 config_getcfg(httpd_env, imsg);
1374 break;
1375 case IMSG_CTL_START:
1376 server_launch();
1377 break;
1378 case IMSG_CTL_RESET:
1379 config_getreset(httpd_env, imsg);
1380 break;
1381 case IMSG_TLSTICKET_REKEY:
1382 IMSG_SIZE_CHECK(imsg, (&key))do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof
(*(&key))) fatalx("bad length imsg received"); } while (0
)
;
1383 memcpy(&key, imsg->data, sizeof(key));
1384 /* apply to the right server */
1385 srv = server_byid(key.tt_id);
1386 if (srv) {
1387 tls_config_add_ticket_key(srv->srv_tls_config,
1388 key.tt_keyrev, key.tt_key, sizeof(key.tt_key));
1389 }
1390 break;
1391 default:
1392 return (-1);
1393 }
1394
1395 return (0);
1396}
1397
1398int
1399server_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg)
1400{
1401 switch (imsg->hdr.type) {
1402 default:
1403 return (-1);
1404 }
1405
1406 return (0);
1407}
1408
1409int
1410server_bufferevent_add(struct event *ev, int timeout)
1411{
1412 struct timeval tv, *ptv = NULL((void *)0);
1413
1414 if (timeout) {
1415 timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0;
1416 tv.tv_sec = timeout;
1417 ptv = &tv;
1418 }
1419
1420 return (event_add(ev, ptv));
1421}
1422
1423int
1424server_bufferevent_printf(struct client *clt, const char *fmt, ...)
1425{
1426 int ret;
1427 va_list ap;
1428 char *str;
1429
1430 va_start(ap, fmt)__builtin_va_start((ap), fmt);
1431 ret = vasprintf(&str, fmt, ap);
1432 va_end(ap)__builtin_va_end((ap));
1433
1434 if (ret == -1)
1435 return (ret);
1436
1437 ret = server_bufferevent_print(clt, str);
1438 free(str);
1439
1440 return (ret);
1441}
1442
1443int
1444server_bufferevent_print(struct client *clt, const char *str)
1445{
1446 if (clt->clt_bev == NULL((void *)0))
1447 return (evbuffer_add(clt->clt_output, str, strlen(str)));
1448 return (bufferevent_write(clt->clt_bev, str, strlen(str)));
1449}
1450
1451int
1452server_bufferevent_write_buffer(struct client *clt, struct evbuffer *buf)
1453{
1454 if (clt->clt_bev == NULL((void *)0))
1455 return (evbuffer_add_buffer(clt->clt_output, buf));
1456 return (bufferevent_write_buffer(clt->clt_bev, buf));
1457}
1458
1459int
1460server_bufferevent_write_chunk(struct client *clt,
1461 struct evbuffer *buf, size_t size)
1462{
1463 int ret;
1464 ret = server_bufferevent_write(clt, EVBUFFER_DATA(buf)(buf)->buffer, size);
1465 if (ret != -1)
1466 evbuffer_drain(buf, size);
1467 return (ret);
1468}
1469
1470int
1471server_bufferevent_write(struct client *clt, void *data, size_t size)
1472{
1473 if (clt->clt_bev == NULL((void *)0))
1474 return (evbuffer_add(clt->clt_output, data, size));
1475 return (bufferevent_write(clt->clt_bev, data, size));
1476}
1477
1478int
1479server_client_cmp(struct client *a, struct client *b)
1480{
1481 return ((int)a->clt_id - b->clt_id);
1482}
1483
1484SPLAY_GENERATE(client_tree, client, clt_nodes, server_client_cmp)struct client * client_tree_SPLAY_INSERT(struct client_tree *
head, struct client *elm) { if (((head)->sph_root == ((void
*)0))) { (elm)->clt_nodes.spe_left = (elm)->clt_nodes.
spe_right = ((void *)0); } else { int __comp; client_tree_SPLAY
(head, elm); __comp = (server_client_cmp)(elm, (head)->sph_root
); if(__comp < 0) { (elm)->clt_nodes.spe_left = ((head)
->sph_root)->clt_nodes.spe_left; (elm)->clt_nodes.spe_right
= (head)->sph_root; ((head)->sph_root)->clt_nodes.spe_left
= ((void *)0); } else if (__comp > 0) { (elm)->clt_nodes
.spe_right = ((head)->sph_root)->clt_nodes.spe_right; (
elm)->clt_nodes.spe_left = (head)->sph_root; ((head)->
sph_root)->clt_nodes.spe_right = ((void *)0); } else return
((head)->sph_root); } (head)->sph_root = (elm); return
(((void *)0)); } struct client * client_tree_SPLAY_REMOVE(struct
client_tree *head, struct client *elm) { struct client *__tmp
; if (((head)->sph_root == ((void *)0))) return (((void *)
0)); client_tree_SPLAY(head, elm); if ((server_client_cmp)(elm
, (head)->sph_root) == 0) { if (((head)->sph_root)->
clt_nodes.spe_left == ((void *)0)) { (head)->sph_root = ((
head)->sph_root)->clt_nodes.spe_right; } else { __tmp =
((head)->sph_root)->clt_nodes.spe_right; (head)->sph_root
= ((head)->sph_root)->clt_nodes.spe_left; client_tree_SPLAY
(head, elm); ((head)->sph_root)->clt_nodes.spe_right = __tmp
; } return (elm); } return (((void *)0)); } void client_tree_SPLAY
(struct client_tree *head, struct client *elm) { struct client
__node, *__left, *__right, *__tmp; int __comp; (&__node)
->clt_nodes.spe_left = (&__node)->clt_nodes.spe_right
= ((void *)0); __left = __right = &__node; while ((__comp
= (server_client_cmp)(elm, (head)->sph_root))) { if (__comp
< 0) { __tmp = ((head)->sph_root)->clt_nodes.spe_left
; if (__tmp == ((void *)0)) break; if ((server_client_cmp)(elm
, __tmp) < 0){ do { ((head)->sph_root)->clt_nodes.spe_left
= (__tmp)->clt_nodes.spe_right; (__tmp)->clt_nodes.spe_right
= (head)->sph_root; (head)->sph_root = __tmp; } while (
0); if (((head)->sph_root)->clt_nodes.spe_left == ((void
*)0)) break; } do { (__right)->clt_nodes.spe_left = (head
)->sph_root; __right = (head)->sph_root; (head)->sph_root
= ((head)->sph_root)->clt_nodes.spe_left; } while (0);
} else if (__comp > 0) { __tmp = ((head)->sph_root)->
clt_nodes.spe_right; if (__tmp == ((void *)0)) break; if ((server_client_cmp
)(elm, __tmp) > 0){ do { ((head)->sph_root)->clt_nodes
.spe_right = (__tmp)->clt_nodes.spe_left; (__tmp)->clt_nodes
.spe_left = (head)->sph_root; (head)->sph_root = __tmp;
} while (0); if (((head)->sph_root)->clt_nodes.spe_right
== ((void *)0)) break; } do { (__left)->clt_nodes.spe_right
= (head)->sph_root; __left = (head)->sph_root; (head)->
sph_root = ((head)->sph_root)->clt_nodes.spe_right; } while
(0); } } do { (__left)->clt_nodes.spe_right = ((head)->
sph_root)->clt_nodes.spe_left; (__right)->clt_nodes.spe_left
= ((head)->sph_root)->clt_nodes.spe_right; ((head)->
sph_root)->clt_nodes.spe_left = (&__node)->clt_nodes
.spe_right; ((head)->sph_root)->clt_nodes.spe_right = (
&__node)->clt_nodes.spe_left; } while (0); } void client_tree_SPLAY_MINMAX
(struct client_tree *head, int __comp) { struct client __node
, *__left, *__right, *__tmp; (&__node)->clt_nodes.spe_left
= (&__node)->clt_nodes.spe_right = ((void *)0); __left
= __right = &__node; while (1) { if (__comp < 0) { __tmp
= ((head)->sph_root)->clt_nodes.spe_left; if (__tmp ==
((void *)0)) break; if (__comp < 0){ do { ((head)->sph_root
)->clt_nodes.spe_left = (__tmp)->clt_nodes.spe_right; (
__tmp)->clt_nodes.spe_right = (head)->sph_root; (head)->
sph_root = __tmp; } while (0); if (((head)->sph_root)->
clt_nodes.spe_left == ((void *)0)) break; } do { (__right)->
clt_nodes.spe_left = (head)->sph_root; __right = (head)->
sph_root; (head)->sph_root = ((head)->sph_root)->clt_nodes
.spe_left; } while (0); } else if (__comp > 0) { __tmp = (
(head)->sph_root)->clt_nodes.spe_right; if (__tmp == ((
void *)0)) break; if (__comp > 0) { do { ((head)->sph_root
)->clt_nodes.spe_right = (__tmp)->clt_nodes.spe_left; (
__tmp)->clt_nodes.spe_left = (head)->sph_root; (head)->
sph_root = __tmp; } while (0); if (((head)->sph_root)->
clt_nodes.spe_right == ((void *)0)) break; } do { (__left)->
clt_nodes.spe_right = (head)->sph_root; __left = (head)->
sph_root; (head)->sph_root = ((head)->sph_root)->clt_nodes
.spe_right; } while (0); } } do { (__left)->clt_nodes.spe_right
= ((head)->sph_root)->clt_nodes.spe_left; (__right)->
clt_nodes.spe_left = ((head)->sph_root)->clt_nodes.spe_right
; ((head)->sph_root)->clt_nodes.spe_left = (&__node
)->clt_nodes.spe_right; ((head)->sph_root)->clt_nodes
.spe_right = (&__node)->clt_nodes.spe_left; } while (0
); }
;