1 |
|
|
/* $OpenBSD: server.c,v 1.111 2017/08/11 18:48:56 jsing 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.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)) |
48 |
|
|
|
49 |
|
|
int server_dispatch_parent(int, struct privsep_proc *, |
50 |
|
|
struct imsg *); |
51 |
|
|
int server_dispatch_logger(int, struct privsep_proc *, |
52 |
|
|
struct imsg *); |
53 |
|
|
void server_shutdown(void); |
54 |
|
|
|
55 |
|
|
void server_init(struct privsep *, struct privsep_proc *p, void *); |
56 |
|
|
void server_launch(void); |
57 |
|
|
int server_socket(struct sockaddr_storage *, in_port_t, |
58 |
|
|
struct server_config *, int, int); |
59 |
|
|
int server_socket_listen(struct sockaddr_storage *, in_port_t, |
60 |
|
|
struct server_config *); |
61 |
|
|
struct server *server_byid(uint32_t); |
62 |
|
|
|
63 |
|
|
int server_tls_init(struct server *); |
64 |
|
|
void server_tls_readcb(int, short, void *); |
65 |
|
|
void server_tls_writecb(int, short, void *); |
66 |
|
|
void server_tls_handshake(int, short, void *); |
67 |
|
|
|
68 |
|
|
void server_accept(int, short, void *); |
69 |
|
|
void server_input(struct client *); |
70 |
|
|
void server_inflight_dec(struct client *, const char *); |
71 |
|
|
|
72 |
|
|
extern void bufferevent_read_pressure_cb(struct evbuffer *, size_t, |
73 |
|
|
size_t, void *); |
74 |
|
|
|
75 |
|
|
volatile int server_clients; |
76 |
|
|
volatile int server_inflight = 0; |
77 |
|
|
uint32_t server_cltid; |
78 |
|
|
|
79 |
|
|
static struct privsep_proc procs[] = { |
80 |
|
|
{ "parent", PROC_PARENT, server_dispatch_parent }, |
81 |
|
|
{ "logger", PROC_LOGGER, server_dispatch_logger } |
82 |
|
|
}; |
83 |
|
|
|
84 |
|
|
void |
85 |
|
|
server(struct privsep *ps, struct privsep_proc *p) |
86 |
|
|
{ |
87 |
|
|
proc_run(ps, p, procs, nitems(procs), server_init, NULL); |
88 |
|
|
server_http(); |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
void |
92 |
|
|
server_shutdown(void) |
93 |
|
|
{ |
94 |
|
|
config_purge(httpd_env, CONFIG_ALL); |
95 |
|
|
usleep(200); /* XXX server needs to shutdown last */ |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
int |
99 |
|
|
server_privinit(struct server *srv) |
100 |
|
|
{ |
101 |
|
|
struct server *s; |
102 |
|
|
|
103 |
✗✓ |
96 |
if (srv->srv_conf.flags & SRVFLAG_LOCATION) |
104 |
|
|
return (0); |
105 |
|
|
|
106 |
|
48 |
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 |
✓✓ |
192 |
TAILQ_FOREACH(s, httpd_env->sc_servers, srv_entry) { |
113 |
✗✓✗✗ ✗✗ |
48 |
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 |
✗✓ |
144 |
if ((srv->srv_s = server_socket_listen(&srv->srv_conf.ss, |
123 |
|
96 |
srv->srv_conf.port, &srv->srv_conf)) == -1) |
124 |
|
|
return (-1); |
125 |
|
|
|
126 |
|
48 |
return (0); |
127 |
|
48 |
} |
128 |
|
|
|
129 |
|
|
int |
130 |
|
|
server_tls_cmp(struct server *s1, struct server *s2, int match_keypair) |
131 |
|
|
{ |
132 |
|
|
struct server_config *sc1, *sc2; |
133 |
|
|
|
134 |
|
|
sc1 = &s1->srv_conf; |
135 |
|
|
sc2 = &s2->srv_conf; |
136 |
|
|
|
137 |
|
|
if (sc1->tls_protocols != sc2->tls_protocols) |
138 |
|
|
return (-1); |
139 |
|
|
if (sc1->tls_ticket_lifetime != sc2->tls_ticket_lifetime) |
140 |
|
|
return (-1); |
141 |
|
|
if (strcmp(sc1->tls_ciphers, sc2->tls_ciphers) != 0) |
142 |
|
|
return (-1); |
143 |
|
|
if (strcmp(sc1->tls_dhe_params, sc2->tls_dhe_params) != 0) |
144 |
|
|
return (-1); |
145 |
|
|
if (strcmp(sc1->tls_ecdhe_curves, sc2->tls_ecdhe_curves) != 0) |
146 |
|
|
return (-1); |
147 |
|
|
|
148 |
|
|
if (match_keypair) { |
149 |
|
|
if (strcmp(sc1->tls_cert_file, sc2->tls_cert_file) != 0) |
150 |
|
|
return (-1); |
151 |
|
|
if (strcmp(sc1->tls_key_file, sc2->tls_key_file) != 0) |
152 |
|
|
return (-1); |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
return (0); |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
int |
159 |
|
|
server_tls_load_keypair(struct server *srv) |
160 |
|
|
{ |
161 |
✓✓ |
96 |
if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0) |
162 |
|
32 |
return (0); |
163 |
|
|
|
164 |
✗✓ |
48 |
if ((srv->srv_conf.tls_cert = tls_load_file(srv->srv_conf.tls_cert_file, |
165 |
|
32 |
&srv->srv_conf.tls_cert_len, NULL)) == NULL) |
166 |
|
|
return (-1); |
167 |
|
16 |
log_debug("%s: using certificate %s", __func__, |
168 |
|
16 |
srv->srv_conf.tls_cert_file); |
169 |
|
|
|
170 |
|
|
/* XXX allow to specify password for encrypted key */ |
171 |
✗✓ |
48 |
if ((srv->srv_conf.tls_key = tls_load_file(srv->srv_conf.tls_key_file, |
172 |
|
32 |
&srv->srv_conf.tls_key_len, NULL)) == NULL) |
173 |
|
|
return (-1); |
174 |
|
16 |
log_debug("%s: using private key %s", __func__, |
175 |
|
16 |
srv->srv_conf.tls_key_file); |
176 |
|
|
|
177 |
|
16 |
return (0); |
178 |
|
48 |
} |
179 |
|
|
|
180 |
|
|
int |
181 |
|
|
server_tls_load_ocsp(struct server *srv) |
182 |
|
|
{ |
183 |
✓✓ |
96 |
if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0) |
184 |
|
32 |
return (0); |
185 |
|
|
|
186 |
✓✗ |
16 |
if (srv->srv_conf.tls_ocsp_staple_file == NULL) |
187 |
|
16 |
return (0); |
188 |
|
|
|
189 |
|
|
if ((srv->srv_conf.tls_ocsp_staple = tls_load_file( |
190 |
|
|
srv->srv_conf.tls_ocsp_staple_file, |
191 |
|
|
&srv->srv_conf.tls_ocsp_staple_len, NULL)) == NULL) |
192 |
|
|
return (-1); |
193 |
|
|
log_debug("%s: using ocsp staple from %s", __func__, |
194 |
|
|
srv->srv_conf.tls_ocsp_staple_file); |
195 |
|
|
|
196 |
|
|
return (0); |
197 |
|
48 |
} |
198 |
|
|
|
199 |
|
|
int |
200 |
|
|
server_tls_init(struct server *srv) |
201 |
|
|
{ |
202 |
|
|
struct server_config *srv_conf; |
203 |
|
|
|
204 |
|
|
if ((srv->srv_conf.flags & SRVFLAG_TLS) == 0) |
205 |
|
|
return (0); |
206 |
|
|
|
207 |
|
|
log_debug("%s: setting up tls for %s", __func__, srv->srv_conf.name); |
208 |
|
|
|
209 |
|
|
if (tls_init() != 0) { |
210 |
|
|
log_warnx("%s: failed to initialise tls", __func__); |
211 |
|
|
return (-1); |
212 |
|
|
} |
213 |
|
|
if ((srv->srv_tls_config = tls_config_new()) == NULL) { |
214 |
|
|
log_warnx("%s: failed to get tls config", __func__); |
215 |
|
|
return (-1); |
216 |
|
|
} |
217 |
|
|
if ((srv->srv_tls_ctx = tls_server()) == NULL) { |
218 |
|
|
log_warnx("%s: failed to get tls server", __func__); |
219 |
|
|
return (-1); |
220 |
|
|
} |
221 |
|
|
|
222 |
|
|
if (tls_config_set_protocols(srv->srv_tls_config, |
223 |
|
|
srv->srv_conf.tls_protocols) != 0) { |
224 |
|
|
log_warnx("%s: failed to set tls protocols: %s", |
225 |
|
|
__func__, tls_config_error(srv->srv_tls_config)); |
226 |
|
|
return (-1); |
227 |
|
|
} |
228 |
|
|
if (tls_config_set_ciphers(srv->srv_tls_config, |
229 |
|
|
srv->srv_conf.tls_ciphers) != 0) { |
230 |
|
|
log_warnx("%s: failed to set tls ciphers: %s", |
231 |
|
|
__func__, tls_config_error(srv->srv_tls_config)); |
232 |
|
|
return (-1); |
233 |
|
|
} |
234 |
|
|
if (tls_config_set_dheparams(srv->srv_tls_config, |
235 |
|
|
srv->srv_conf.tls_dhe_params) != 0) { |
236 |
|
|
log_warnx("%s: failed to set tls dhe params: %s", |
237 |
|
|
__func__, tls_config_error(srv->srv_tls_config)); |
238 |
|
|
return (-1); |
239 |
|
|
} |
240 |
|
|
if (tls_config_set_ecdhecurves(srv->srv_tls_config, |
241 |
|
|
srv->srv_conf.tls_ecdhe_curves) != 0) { |
242 |
|
|
log_warnx("%s: failed to set tls ecdhe curves: %s", |
243 |
|
|
__func__, tls_config_error(srv->srv_tls_config)); |
244 |
|
|
return (-1); |
245 |
|
|
} |
246 |
|
|
|
247 |
|
|
if (tls_config_set_keypair_ocsp_mem(srv->srv_tls_config, |
248 |
|
|
srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len, |
249 |
|
|
srv->srv_conf.tls_key, srv->srv_conf.tls_key_len, |
250 |
|
|
srv->srv_conf.tls_ocsp_staple, |
251 |
|
|
srv->srv_conf.tls_ocsp_staple_len) != 0) { |
252 |
|
|
log_warnx("%s: failed to set tls certificate/key: %s", |
253 |
|
|
__func__, tls_config_error(srv->srv_tls_config)); |
254 |
|
|
return (-1); |
255 |
|
|
} |
256 |
|
|
|
257 |
|
|
TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) { |
258 |
|
|
if (srv_conf->tls_cert == NULL || srv_conf->tls_key == NULL) |
259 |
|
|
continue; |
260 |
|
|
log_debug("%s: adding keypair for server %s", __func__, |
261 |
|
|
srv->srv_conf.name); |
262 |
|
|
if (tls_config_add_keypair_ocsp_mem(srv->srv_tls_config, |
263 |
|
|
srv_conf->tls_cert, srv_conf->tls_cert_len, |
264 |
|
|
srv_conf->tls_key, srv_conf->tls_key_len, |
265 |
|
|
srv_conf->tls_ocsp_staple, |
266 |
|
|
srv_conf->tls_ocsp_staple_len) != 0) { |
267 |
|
|
log_warnx("%s: failed to add tls keypair", __func__); |
268 |
|
|
return (-1); |
269 |
|
|
} |
270 |
|
|
} |
271 |
|
|
|
272 |
|
|
/* set common session ID among all processes */ |
273 |
|
|
if (tls_config_set_session_id(srv->srv_tls_config, |
274 |
|
|
httpd_env->sc_tls_sid, sizeof(httpd_env->sc_tls_sid)) == -1) { |
275 |
|
|
log_warnx("%s: could not set the TLS session ID: %s", |
276 |
|
|
__func__, tls_config_error(srv->srv_tls_config)); |
277 |
|
|
return (-1); |
278 |
|
|
} |
279 |
|
|
|
280 |
|
|
/* ticket support */ |
281 |
|
|
if (srv->srv_conf.tls_ticket_lifetime) { |
282 |
|
|
if (tls_config_set_session_lifetime(srv->srv_tls_config, |
283 |
|
|
srv->srv_conf.tls_ticket_lifetime) == -1) { |
284 |
|
|
log_warnx("%s: could not set the TLS session lifetime: " |
285 |
|
|
"%s", __func__, |
286 |
|
|
tls_config_error(srv->srv_tls_config)); |
287 |
|
|
return (-1); |
288 |
|
|
} |
289 |
|
|
tls_config_add_ticket_key(srv->srv_tls_config, |
290 |
|
|
srv->srv_conf.tls_ticket_key.tt_keyrev, |
291 |
|
|
srv->srv_conf.tls_ticket_key.tt_key, |
292 |
|
|
sizeof(srv->srv_conf.tls_ticket_key.tt_key)); |
293 |
|
|
explicit_bzero(&srv->srv_conf.tls_ticket_key, |
294 |
|
|
sizeof(srv->srv_conf.tls_ticket_key)); |
295 |
|
|
} |
296 |
|
|
|
297 |
|
|
if (tls_configure(srv->srv_tls_ctx, srv->srv_tls_config) != 0) { |
298 |
|
|
log_warnx("%s: failed to configure tls - %s", __func__, |
299 |
|
|
tls_error(srv->srv_tls_ctx)); |
300 |
|
|
return (-1); |
301 |
|
|
} |
302 |
|
|
|
303 |
|
|
/* We're now done with the public/private key... */ |
304 |
|
|
tls_config_clear_keys(srv->srv_tls_config); |
305 |
|
|
freezero(srv->srv_conf.tls_cert, srv->srv_conf.tls_cert_len); |
306 |
|
|
freezero(srv->srv_conf.tls_key, srv->srv_conf.tls_key_len); |
307 |
|
|
srv->srv_conf.tls_cert = NULL; |
308 |
|
|
srv->srv_conf.tls_key = NULL; |
309 |
|
|
srv->srv_conf.tls_cert_len = 0; |
310 |
|
|
srv->srv_conf.tls_key_len = 0; |
311 |
|
|
|
312 |
|
|
return (0); |
313 |
|
|
} |
314 |
|
|
|
315 |
|
|
void |
316 |
|
|
server_generate_ticket_key(struct server_config *srv_conf) |
317 |
|
|
{ |
318 |
|
|
struct server_tls_ticket *key = &srv_conf->tls_ticket_key; |
319 |
|
|
|
320 |
|
|
key->tt_id = srv_conf->id; |
321 |
|
|
key->tt_keyrev = arc4random(); |
322 |
|
|
arc4random_buf(key->tt_key, sizeof(key->tt_key)); |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
void |
326 |
|
|
server_init(struct privsep *ps, struct privsep_proc *p, void *arg) |
327 |
|
|
{ |
328 |
|
|
server_http(); |
329 |
|
|
|
330 |
|
|
if (config_init(ps->ps_env) == -1) |
331 |
|
|
fatal("failed to initialize configuration"); |
332 |
|
|
|
333 |
|
|
/* We use a custom shutdown callback */ |
334 |
|
|
p->p_shutdown = server_shutdown; |
335 |
|
|
|
336 |
|
|
/* Unlimited file descriptors (use system limits) */ |
337 |
|
|
socket_rlimit(-1); |
338 |
|
|
|
339 |
|
|
if (pledge("stdio rpath inet unix recvfd flock cpath wpath", NULL) == -1) |
340 |
|
|
fatal("pledge"); |
341 |
|
|
|
342 |
|
|
#if 0 |
343 |
|
|
/* Schedule statistics timer */ |
344 |
|
|
evtimer_set(&ps->ps_env->sc_statev, server_statistics, NULL); |
345 |
|
|
memcpy(&tv, &ps->ps_env->sc_statinterval, sizeof(tv)); |
346 |
|
|
evtimer_add(&ps->ps_env->sc_statev, &tv); |
347 |
|
|
#endif |
348 |
|
|
} |
349 |
|
|
|
350 |
|
|
void |
351 |
|
|
server_launch(void) |
352 |
|
|
{ |
353 |
|
|
struct server *srv; |
354 |
|
|
|
355 |
|
|
TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry) { |
356 |
|
|
log_debug("%s: configuring server %s", __func__, |
357 |
|
|
srv->srv_conf.name); |
358 |
|
|
|
359 |
|
|
server_tls_init(srv); |
360 |
|
|
server_http_init(srv); |
361 |
|
|
|
362 |
|
|
log_debug("%s: running server %s", __func__, |
363 |
|
|
srv->srv_conf.name); |
364 |
|
|
|
365 |
|
|
event_set(&srv->srv_ev, srv->srv_s, EV_READ, |
366 |
|
|
server_accept, srv); |
367 |
|
|
event_add(&srv->srv_ev, NULL); |
368 |
|
|
evtimer_set(&srv->srv_evt, server_accept, srv); |
369 |
|
|
} |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
void |
373 |
|
|
server_purge(struct server *srv) |
374 |
|
|
{ |
375 |
|
|
struct client *clt; |
376 |
|
|
struct server_config *srv_conf; |
377 |
|
|
|
378 |
|
|
/* shutdown and remove server */ |
379 |
✗✓ |
96 |
if (event_initialized(&srv->srv_ev)) |
380 |
|
|
event_del(&srv->srv_ev); |
381 |
✗✓ |
48 |
if (evtimer_initialized(&srv->srv_evt)) |
382 |
|
|
evtimer_del(&srv->srv_evt); |
383 |
|
|
|
384 |
✗✓ |
48 |
if (srv->srv_s != -1) |
385 |
|
|
close(srv->srv_s); |
386 |
✗✓ |
144 |
TAILQ_REMOVE(httpd_env->sc_servers, srv, srv_entry); |
387 |
|
|
|
388 |
|
|
/* cleanup sessions */ |
389 |
✗✓ |
96 |
while ((clt = |
390 |
|
48 |
SPLAY_ROOT(&srv->srv_clients)) != NULL) |
391 |
|
|
server_close(clt, NULL); |
392 |
|
|
|
393 |
|
|
/* cleanup hosts */ |
394 |
✗✓ |
96 |
while ((srv_conf = |
395 |
|
48 |
TAILQ_FIRST(&srv->srv_hosts)) != NULL) { |
396 |
|
|
TAILQ_REMOVE(&srv->srv_hosts, srv_conf, entry); |
397 |
|
|
|
398 |
|
|
/* It might point to our own "default" entry */ |
399 |
|
|
if (srv_conf != &srv->srv_conf) { |
400 |
|
|
serverconfig_free(srv_conf); |
401 |
|
|
free(srv_conf); |
402 |
|
|
} |
403 |
|
|
} |
404 |
|
|
|
405 |
|
48 |
tls_config_free(srv->srv_tls_config); |
406 |
|
48 |
tls_free(srv->srv_tls_ctx); |
407 |
|
|
|
408 |
|
48 |
free(srv); |
409 |
|
48 |
} |
410 |
|
|
|
411 |
|
|
void |
412 |
|
|
serverconfig_free(struct server_config *srv_conf) |
413 |
|
|
{ |
414 |
|
|
free(srv_conf->return_uri); |
415 |
|
|
free(srv_conf->tls_cert_file); |
416 |
|
|
free(srv_conf->tls_key_file); |
417 |
|
|
free(srv_conf->tls_ocsp_staple_file); |
418 |
|
|
free(srv_conf->tls_ocsp_staple); |
419 |
|
|
freezero(srv_conf->tls_cert, srv_conf->tls_cert_len); |
420 |
|
|
freezero(srv_conf->tls_key, srv_conf->tls_key_len); |
421 |
|
|
} |
422 |
|
|
|
423 |
|
|
void |
424 |
|
|
serverconfig_reset(struct server_config *srv_conf) |
425 |
|
|
{ |
426 |
|
|
srv_conf->auth = NULL; |
427 |
|
|
srv_conf->return_uri = NULL; |
428 |
|
|
srv_conf->tls_cert = NULL; |
429 |
|
|
srv_conf->tls_cert_file = NULL; |
430 |
|
|
srv_conf->tls_key = NULL; |
431 |
|
|
srv_conf->tls_key_file = NULL; |
432 |
|
|
srv_conf->tls_ocsp_staple = NULL; |
433 |
|
|
srv_conf->tls_ocsp_staple_file = NULL; |
434 |
|
|
} |
435 |
|
|
|
436 |
|
|
struct server * |
437 |
|
|
server_byaddr(struct sockaddr *addr, in_port_t port) |
438 |
|
|
{ |
439 |
|
|
struct server *srv; |
440 |
|
|
|
441 |
|
|
TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry) { |
442 |
|
|
if (port == srv->srv_conf.port && |
443 |
|
|
sockaddr_cmp((struct sockaddr *)&srv->srv_conf.ss, |
444 |
|
|
addr, srv->srv_conf.prefixlen) == 0) |
445 |
|
|
return (srv); |
446 |
|
|
} |
447 |
|
|
|
448 |
|
|
return (NULL); |
449 |
|
|
} |
450 |
|
|
|
451 |
|
|
struct server_config * |
452 |
|
|
serverconfig_byid(uint32_t id) |
453 |
|
|
{ |
454 |
|
|
struct server *srv; |
455 |
|
|
struct server_config *srv_conf; |
456 |
|
|
|
457 |
|
|
TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry) { |
458 |
|
|
if (srv->srv_conf.id == id) |
459 |
|
|
return (&srv->srv_conf); |
460 |
|
|
TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) { |
461 |
|
|
if (srv_conf->id == id) |
462 |
|
|
return (srv_conf); |
463 |
|
|
} |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
return (NULL); |
467 |
|
|
} |
468 |
|
|
|
469 |
|
|
struct server * |
470 |
|
|
server_byid(uint32_t id) |
471 |
|
|
{ |
472 |
|
|
struct server *srv; |
473 |
|
|
|
474 |
|
|
TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry) { |
475 |
|
|
if (srv->srv_conf.id == id) |
476 |
|
|
return (srv); |
477 |
|
|
} |
478 |
|
|
return (NULL); |
479 |
|
|
} |
480 |
|
|
|
481 |
|
|
int |
482 |
|
|
server_foreach(int (*srv_cb)(struct server *, |
483 |
|
|
struct server_config *, void *), void *arg) |
484 |
|
|
{ |
485 |
|
|
struct server *srv; |
486 |
|
|
struct server_config *srv_conf; |
487 |
|
|
|
488 |
|
|
TAILQ_FOREACH(srv, httpd_env->sc_servers, srv_entry) { |
489 |
|
|
if ((srv_cb)(srv, &srv->srv_conf, arg) == -1) |
490 |
|
|
return (-1); |
491 |
|
|
TAILQ_FOREACH(srv_conf, &srv->srv_hosts, entry) { |
492 |
|
|
if ((srv_cb)(srv, srv_conf, arg) == -1) |
493 |
|
|
return (-1); |
494 |
|
|
} |
495 |
|
|
} |
496 |
|
|
|
497 |
|
|
return (0); |
498 |
|
|
} |
499 |
|
|
|
500 |
|
|
struct server * |
501 |
|
|
server_match(struct server *s2, int match_name) |
502 |
|
|
{ |
503 |
|
|
struct server *s1; |
504 |
|
|
|
505 |
|
|
/* Attempt to find matching server. */ |
506 |
✗✓ |
288 |
TAILQ_FOREACH(s1, httpd_env->sc_servers, srv_entry) { |
507 |
|
|
if ((s1->srv_conf.flags & SRVFLAG_LOCATION) != 0) |
508 |
|
|
continue; |
509 |
|
|
if (match_name) { |
510 |
|
|
if (strcmp(s1->srv_conf.name, s2->srv_conf.name) != 0) |
511 |
|
|
continue; |
512 |
|
|
} |
513 |
|
|
if (s1->srv_conf.port != s2->srv_conf.port) |
514 |
|
|
continue; |
515 |
|
|
if (sockaddr_cmp( |
516 |
|
|
(struct sockaddr *)&s1->srv_conf.ss, |
517 |
|
|
(struct sockaddr *)&s2->srv_conf.ss, |
518 |
|
|
s1->srv_conf.prefixlen) != 0) |
519 |
|
|
continue; |
520 |
|
|
|
521 |
|
|
return (s1); |
522 |
|
|
} |
523 |
|
|
|
524 |
|
96 |
return (NULL); |
525 |
|
96 |
} |
526 |
|
|
|
527 |
|
|
int |
528 |
|
|
server_socket_af(struct sockaddr_storage *ss, in_port_t port) |
529 |
|
|
{ |
530 |
✓✗✗ |
96 |
switch (ss->ss_family) { |
531 |
|
|
case AF_INET: |
532 |
|
48 |
((struct sockaddr_in *)ss)->sin_port = port; |
533 |
|
48 |
((struct sockaddr_in *)ss)->sin_len = |
534 |
|
|
sizeof(struct sockaddr_in); |
535 |
|
48 |
break; |
536 |
|
|
case AF_INET6: |
537 |
|
|
((struct sockaddr_in6 *)ss)->sin6_port = port; |
538 |
|
|
((struct sockaddr_in6 *)ss)->sin6_len = |
539 |
|
|
sizeof(struct sockaddr_in6); |
540 |
|
|
break; |
541 |
|
|
default: |
542 |
|
|
return (-1); |
543 |
|
|
} |
544 |
|
|
|
545 |
|
48 |
return (0); |
546 |
|
48 |
} |
547 |
|
|
|
548 |
|
|
in_port_t |
549 |
|
|
server_socket_getport(struct sockaddr_storage *ss) |
550 |
|
|
{ |
551 |
|
|
switch (ss->ss_family) { |
552 |
|
|
case AF_INET: |
553 |
|
|
return (((struct sockaddr_in *)ss)->sin_port); |
554 |
|
|
case AF_INET6: |
555 |
|
|
return (((struct sockaddr_in6 *)ss)->sin6_port); |
556 |
|
|
default: |
557 |
|
|
return (0); |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
/* NOTREACHED */ |
561 |
|
|
return (0); |
562 |
|
|
} |
563 |
|
|
|
564 |
|
|
int |
565 |
|
|
server_socket(struct sockaddr_storage *ss, in_port_t port, |
566 |
|
|
struct server_config *srv_conf, int fd, int reuseport) |
567 |
|
|
{ |
568 |
|
96 |
struct linger lng; |
569 |
|
48 |
int s = -1, val; |
570 |
|
|
|
571 |
✓✗ |
48 |
if (server_socket_af(ss, port) == -1) |
572 |
|
|
goto bad; |
573 |
|
|
|
574 |
✓✗ |
144 |
s = fd == -1 ? socket(ss->ss_family, SOCK_STREAM | SOCK_NONBLOCK, |
575 |
|
|
IPPROTO_TCP) : fd; |
576 |
✓✗ |
48 |
if (s == -1) |
577 |
|
|
goto bad; |
578 |
|
|
|
579 |
|
|
/* |
580 |
|
|
* Socket options |
581 |
|
|
*/ |
582 |
|
48 |
memset(&lng, 0, sizeof(lng)); |
583 |
✓✗ |
48 |
if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1) |
584 |
|
|
goto bad; |
585 |
✓✗ |
48 |
if (reuseport) { |
586 |
|
48 |
val = 1; |
587 |
✓✗ |
96 |
if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &val, |
588 |
|
48 |
sizeof(int)) == -1) |
589 |
|
|
goto bad; |
590 |
|
|
} |
591 |
✗✓ |
48 |
if (srv_conf->tcpflags & TCPFLAG_BUFSIZ) { |
592 |
|
|
val = srv_conf->tcpbufsiz; |
593 |
|
|
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, |
594 |
|
|
&val, sizeof(val)) == -1) |
595 |
|
|
goto bad; |
596 |
|
|
val = srv_conf->tcpbufsiz; |
597 |
|
|
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, |
598 |
|
|
&val, sizeof(val)) == -1) |
599 |
|
|
goto bad; |
600 |
|
|
} |
601 |
|
|
|
602 |
|
|
/* |
603 |
|
|
* IP options |
604 |
|
|
*/ |
605 |
✗✓ |
48 |
if (srv_conf->tcpflags & TCPFLAG_IPTTL) { |
606 |
|
|
val = (int)srv_conf->tcpipttl; |
607 |
|
|
switch (ss->ss_family) { |
608 |
|
|
case AF_INET: |
609 |
|
|
if (setsockopt(s, IPPROTO_IP, IP_TTL, |
610 |
|
|
&val, sizeof(val)) == -1) |
611 |
|
|
goto bad; |
612 |
|
|
break; |
613 |
|
|
case AF_INET6: |
614 |
|
|
if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, |
615 |
|
|
&val, sizeof(val)) == -1) |
616 |
|
|
goto bad; |
617 |
|
|
break; |
618 |
|
|
} |
619 |
|
|
} |
620 |
✗✓ |
48 |
if (srv_conf->tcpflags & TCPFLAG_IPMINTTL) { |
621 |
|
|
val = (int)srv_conf->tcpipminttl; |
622 |
|
|
switch (ss->ss_family) { |
623 |
|
|
case AF_INET: |
624 |
|
|
if (setsockopt(s, IPPROTO_IP, IP_MINTTL, |
625 |
|
|
&val, sizeof(val)) == -1) |
626 |
|
|
goto bad; |
627 |
|
|
break; |
628 |
|
|
case AF_INET6: |
629 |
|
|
if (setsockopt(s, IPPROTO_IPV6, IPV6_MINHOPCOUNT, |
630 |
|
|
&val, sizeof(val)) == -1) |
631 |
|
|
goto bad; |
632 |
|
|
break; |
633 |
|
|
} |
634 |
|
|
} |
635 |
|
|
|
636 |
|
|
/* |
637 |
|
|
* TCP options |
638 |
|
|
*/ |
639 |
✗✓ |
48 |
if (srv_conf->tcpflags & (TCPFLAG_NODELAY|TCPFLAG_NNODELAY)) { |
640 |
|
|
if (srv_conf->tcpflags & TCPFLAG_NNODELAY) |
641 |
|
|
val = 0; |
642 |
|
|
else |
643 |
|
|
val = 1; |
644 |
|
|
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, |
645 |
|
|
&val, sizeof(val)) == -1) |
646 |
|
|
goto bad; |
647 |
|
|
} |
648 |
✗✓ |
48 |
if (srv_conf->tcpflags & (TCPFLAG_SACK|TCPFLAG_NSACK)) { |
649 |
|
|
if (srv_conf->tcpflags & TCPFLAG_NSACK) |
650 |
|
|
val = 0; |
651 |
|
|
else |
652 |
|
|
val = 1; |
653 |
|
|
if (setsockopt(s, IPPROTO_TCP, TCP_SACK_ENABLE, |
654 |
|
|
&val, sizeof(val)) == -1) |
655 |
|
|
goto bad; |
656 |
|
|
} |
657 |
|
|
|
658 |
|
48 |
return (s); |
659 |
|
|
|
660 |
|
|
bad: |
661 |
|
|
if (s != -1) |
662 |
|
|
close(s); |
663 |
|
|
return (-1); |
664 |
|
48 |
} |
665 |
|
|
|
666 |
|
|
int |
667 |
|
|
server_socket_listen(struct sockaddr_storage *ss, in_port_t port, |
668 |
|
|
struct server_config *srv_conf) |
669 |
|
|
{ |
670 |
|
|
int s; |
671 |
|
|
|
672 |
✗✓ |
96 |
if ((s = server_socket(ss, port, srv_conf, -1, 1)) == -1) |
673 |
|
|
return (-1); |
674 |
|
|
|
675 |
✓✗ |
48 |
if (bind(s, (struct sockaddr *)ss, ss->ss_len) == -1) |
676 |
|
|
goto bad; |
677 |
✓✗ |
48 |
if (listen(s, srv_conf->tcpbacklog) == -1) |
678 |
|
|
goto bad; |
679 |
|
|
|
680 |
|
48 |
return (s); |
681 |
|
|
|
682 |
|
|
bad: |
683 |
|
|
close(s); |
684 |
|
|
return (-1); |
685 |
|
48 |
} |
686 |
|
|
|
687 |
|
|
int |
688 |
|
|
server_socket_connect(struct sockaddr_storage *ss, in_port_t port, |
689 |
|
|
struct server_config *srv_conf) |
690 |
|
|
{ |
691 |
|
|
int s; |
692 |
|
|
|
693 |
|
|
if ((s = server_socket(ss, port, srv_conf, -1, 0)) == -1) |
694 |
|
|
return (-1); |
695 |
|
|
|
696 |
|
|
if (connect(s, (struct sockaddr *)ss, ss->ss_len) == -1) { |
697 |
|
|
if (errno != EINPROGRESS) |
698 |
|
|
goto bad; |
699 |
|
|
} |
700 |
|
|
|
701 |
|
|
return (s); |
702 |
|
|
|
703 |
|
|
bad: |
704 |
|
|
close(s); |
705 |
|
|
return (-1); |
706 |
|
|
} |
707 |
|
|
|
708 |
|
|
void |
709 |
|
|
server_tls_readcb(int fd, short event, void *arg) |
710 |
|
|
{ |
711 |
|
|
struct bufferevent *bufev = arg; |
712 |
|
|
struct client *clt = bufev->cbarg; |
713 |
|
|
char rbuf[IBUF_READ_SIZE]; |
714 |
|
|
int what = EVBUFFER_READ; |
715 |
|
|
int howmuch = IBUF_READ_SIZE; |
716 |
|
|
ssize_t ret; |
717 |
|
|
size_t len; |
718 |
|
|
|
719 |
|
|
if (event == EV_TIMEOUT) { |
720 |
|
|
what |= EVBUFFER_TIMEOUT; |
721 |
|
|
goto err; |
722 |
|
|
} |
723 |
|
|
|
724 |
|
|
if (bufev->wm_read.high != 0) |
725 |
|
|
howmuch = MINIMUM(sizeof(rbuf), bufev->wm_read.high); |
726 |
|
|
|
727 |
|
|
ret = tls_read(clt->clt_tls_ctx, rbuf, howmuch); |
728 |
|
|
if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) { |
729 |
|
|
goto retry; |
730 |
|
|
} else if (ret < 0) { |
731 |
|
|
what |= EVBUFFER_ERROR; |
732 |
|
|
goto err; |
733 |
|
|
} |
734 |
|
|
len = ret; |
735 |
|
|
|
736 |
|
|
if (len == 0) { |
737 |
|
|
what |= EVBUFFER_EOF; |
738 |
|
|
goto err; |
739 |
|
|
} |
740 |
|
|
|
741 |
|
|
if (evbuffer_add(bufev->input, rbuf, len) == -1) { |
742 |
|
|
what |= EVBUFFER_ERROR; |
743 |
|
|
goto err; |
744 |
|
|
} |
745 |
|
|
|
746 |
|
|
server_bufferevent_add(&bufev->ev_read, bufev->timeout_read); |
747 |
|
|
|
748 |
|
|
len = EVBUFFER_LENGTH(bufev->input); |
749 |
|
|
if (bufev->wm_read.low != 0 && len < bufev->wm_read.low) |
750 |
|
|
return; |
751 |
|
|
if (bufev->wm_read.high != 0 && len > bufev->wm_read.high) { |
752 |
|
|
struct evbuffer *buf = bufev->input; |
753 |
|
|
event_del(&bufev->ev_read); |
754 |
|
|
evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev); |
755 |
|
|
return; |
756 |
|
|
} |
757 |
|
|
|
758 |
|
|
if (bufev->readcb != NULL) |
759 |
|
|
(*bufev->readcb)(bufev, bufev->cbarg); |
760 |
|
|
return; |
761 |
|
|
|
762 |
|
|
retry: |
763 |
|
|
server_bufferevent_add(&bufev->ev_read, bufev->timeout_read); |
764 |
|
|
return; |
765 |
|
|
|
766 |
|
|
err: |
767 |
|
|
(*bufev->errorcb)(bufev, what, bufev->cbarg); |
768 |
|
|
} |
769 |
|
|
|
770 |
|
|
void |
771 |
|
|
server_tls_writecb(int fd, short event, void *arg) |
772 |
|
|
{ |
773 |
|
|
struct bufferevent *bufev = arg; |
774 |
|
|
struct client *clt = bufev->cbarg; |
775 |
|
|
ssize_t ret; |
776 |
|
|
short what = EVBUFFER_WRITE; |
777 |
|
|
size_t len; |
778 |
|
|
|
779 |
|
|
if (event == EV_TIMEOUT) { |
780 |
|
|
what |= EVBUFFER_TIMEOUT; |
781 |
|
|
goto err; |
782 |
|
|
} |
783 |
|
|
|
784 |
|
|
if (EVBUFFER_LENGTH(bufev->output)) { |
785 |
|
|
ret = tls_write(clt->clt_tls_ctx, |
786 |
|
|
EVBUFFER_DATA(bufev->output), |
787 |
|
|
EVBUFFER_LENGTH(bufev->output)); |
788 |
|
|
if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) { |
789 |
|
|
goto retry; |
790 |
|
|
} else if (ret < 0) { |
791 |
|
|
what |= EVBUFFER_ERROR; |
792 |
|
|
goto err; |
793 |
|
|
} |
794 |
|
|
len = ret; |
795 |
|
|
evbuffer_drain(bufev->output, len); |
796 |
|
|
} |
797 |
|
|
|
798 |
|
|
if (EVBUFFER_LENGTH(bufev->output) != 0) |
799 |
|
|
server_bufferevent_add(&bufev->ev_write, bufev->timeout_write); |
800 |
|
|
|
801 |
|
|
if (bufev->writecb != NULL && |
802 |
|
|
EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low) |
803 |
|
|
(*bufev->writecb)(bufev, bufev->cbarg); |
804 |
|
|
return; |
805 |
|
|
|
806 |
|
|
retry: |
807 |
|
|
server_bufferevent_add(&bufev->ev_write, bufev->timeout_write); |
808 |
|
|
return; |
809 |
|
|
|
810 |
|
|
err: |
811 |
|
|
(*bufev->errorcb)(bufev, what, bufev->cbarg); |
812 |
|
|
} |
813 |
|
|
|
814 |
|
|
void |
815 |
|
|
server_input(struct client *clt) |
816 |
|
|
{ |
817 |
|
|
struct server_config *srv_conf = clt->clt_srv_conf; |
818 |
|
|
evbuffercb inrd = server_read; |
819 |
|
|
evbuffercb inwr = server_write; |
820 |
|
|
socklen_t slen; |
821 |
|
|
|
822 |
|
|
if (server_httpdesc_init(clt) == -1) { |
823 |
|
|
server_close(clt, "failed to allocate http descriptor"); |
824 |
|
|
return; |
825 |
|
|
} |
826 |
|
|
|
827 |
|
|
clt->clt_toread = TOREAD_HTTP_HEADER; |
828 |
|
|
inrd = server_read_http; |
829 |
|
|
|
830 |
|
|
slen = sizeof(clt->clt_sndbufsiz); |
831 |
|
|
if (getsockopt(clt->clt_s, SOL_SOCKET, SO_SNDBUF, |
832 |
|
|
&clt->clt_sndbufsiz, &slen) == -1) { |
833 |
|
|
server_close(clt, "failed to get send buffer size"); |
834 |
|
|
return; |
835 |
|
|
} |
836 |
|
|
|
837 |
|
|
/* |
838 |
|
|
* Client <-> Server |
839 |
|
|
*/ |
840 |
|
|
clt->clt_bev = bufferevent_new(clt->clt_s, inrd, inwr, |
841 |
|
|
server_error, clt); |
842 |
|
|
if (clt->clt_bev == NULL) { |
843 |
|
|
server_close(clt, "failed to allocate input buffer event"); |
844 |
|
|
return; |
845 |
|
|
} |
846 |
|
|
|
847 |
|
|
if (srv_conf->flags & SRVFLAG_TLS) { |
848 |
|
|
event_set(&clt->clt_bev->ev_read, clt->clt_s, EV_READ, |
849 |
|
|
server_tls_readcb, clt->clt_bev); |
850 |
|
|
event_set(&clt->clt_bev->ev_write, clt->clt_s, EV_WRITE, |
851 |
|
|
server_tls_writecb, clt->clt_bev); |
852 |
|
|
} |
853 |
|
|
|
854 |
|
|
/* Adjust write watermark to the socket buffer output size */ |
855 |
|
|
bufferevent_setwatermark(clt->clt_bev, EV_WRITE, |
856 |
|
|
SERVER_MIN_PREFETCHED * clt->clt_sndbufsiz, 0); |
857 |
|
|
/* Read at most amount of data that fits in one fcgi record. */ |
858 |
|
|
bufferevent_setwatermark(clt->clt_bev, EV_READ, 0, FCGI_CONTENT_SIZE); |
859 |
|
|
|
860 |
|
|
bufferevent_settimeout(clt->clt_bev, |
861 |
|
|
srv_conf->requesttimeout.tv_sec, srv_conf->requesttimeout.tv_sec); |
862 |
|
|
bufferevent_enable(clt->clt_bev, EV_READ|EV_WRITE); |
863 |
|
|
} |
864 |
|
|
|
865 |
|
|
void |
866 |
|
|
server_write(struct bufferevent *bev, void *arg) |
867 |
|
|
{ |
868 |
|
|
struct client *clt = arg; |
869 |
|
|
struct evbuffer *dst = EVBUFFER_OUTPUT(bev); |
870 |
|
|
|
871 |
|
|
if (EVBUFFER_LENGTH(dst) == 0 && |
872 |
|
|
clt->clt_toread == TOREAD_HTTP_NONE) |
873 |
|
|
goto done; |
874 |
|
|
|
875 |
|
|
getmonotime(&clt->clt_tv_last); |
876 |
|
|
|
877 |
|
|
if (clt->clt_done) |
878 |
|
|
goto done; |
879 |
|
|
|
880 |
|
|
if (clt->clt_srvbev && clt->clt_srvbev_throttled) { |
881 |
|
|
bufferevent_enable(clt->clt_srvbev, EV_READ); |
882 |
|
|
clt->clt_srvbev_throttled = 0; |
883 |
|
|
} |
884 |
|
|
|
885 |
|
|
return; |
886 |
|
|
done: |
887 |
|
|
(*bev->errorcb)(bev, EVBUFFER_WRITE, bev->cbarg); |
888 |
|
|
return; |
889 |
|
|
} |
890 |
|
|
|
891 |
|
|
void |
892 |
|
|
server_dump(struct client *clt, const void *buf, size_t len) |
893 |
|
|
{ |
894 |
|
|
if (!len) |
895 |
|
|
return; |
896 |
|
|
|
897 |
|
|
/* |
898 |
|
|
* This function will dump the specified message directly |
899 |
|
|
* to the underlying client, without waiting for success |
900 |
|
|
* of non-blocking events etc. This is useful to print an |
901 |
|
|
* error message before gracefully closing the client. |
902 |
|
|
*/ |
903 |
|
|
if (clt->clt_tls_ctx != NULL) |
904 |
|
|
(void)tls_write(clt->clt_tls_ctx, buf, len); |
905 |
|
|
else |
906 |
|
|
(void)write(clt->clt_s, buf, len); |
907 |
|
|
} |
908 |
|
|
|
909 |
|
|
void |
910 |
|
|
server_read(struct bufferevent *bev, void *arg) |
911 |
|
|
{ |
912 |
|
|
struct client *clt = arg; |
913 |
|
|
struct evbuffer *src = EVBUFFER_INPUT(bev); |
914 |
|
|
|
915 |
|
|
getmonotime(&clt->clt_tv_last); |
916 |
|
|
|
917 |
|
|
if (!EVBUFFER_LENGTH(src)) |
918 |
|
|
return; |
919 |
|
|
if (server_bufferevent_write_buffer(clt, src) == -1) |
920 |
|
|
goto fail; |
921 |
|
|
if (clt->clt_done) |
922 |
|
|
goto done; |
923 |
|
|
|
924 |
|
|
if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(clt->clt_bev)) > (size_t) |
925 |
|
|
SERVER_MAX_PREFETCH * clt->clt_sndbufsiz) { |
926 |
|
|
bufferevent_disable(clt->clt_srvbev, EV_READ); |
927 |
|
|
clt->clt_srvbev_throttled = 1; |
928 |
|
|
} |
929 |
|
|
|
930 |
|
|
return; |
931 |
|
|
done: |
932 |
|
|
(*bev->errorcb)(bev, EVBUFFER_READ, bev->cbarg); |
933 |
|
|
return; |
934 |
|
|
fail: |
935 |
|
|
server_close(clt, strerror(errno)); |
936 |
|
|
} |
937 |
|
|
|
938 |
|
|
void |
939 |
|
|
server_error(struct bufferevent *bev, short error, void *arg) |
940 |
|
|
{ |
941 |
|
|
struct client *clt = arg; |
942 |
|
|
struct evbuffer *dst; |
943 |
|
|
|
944 |
|
|
if (error & EVBUFFER_TIMEOUT) { |
945 |
|
|
server_abort_http(clt, 408, "timeout"); |
946 |
|
|
return; |
947 |
|
|
} |
948 |
|
|
if (error & EVBUFFER_ERROR) { |
949 |
|
|
if (errno == EFBIG) { |
950 |
|
|
bufferevent_enable(bev, EV_READ); |
951 |
|
|
return; |
952 |
|
|
} |
953 |
|
|
server_close(clt, "buffer event error"); |
954 |
|
|
return; |
955 |
|
|
} |
956 |
|
|
if (error & EVBUFFER_EOF) { |
957 |
|
|
server_close(clt, "closed"); |
958 |
|
|
return; |
959 |
|
|
} |
960 |
|
|
if (error & (EVBUFFER_READ|EVBUFFER_WRITE)) { |
961 |
|
|
bufferevent_disable(bev, EV_READ|EV_WRITE); |
962 |
|
|
|
963 |
|
|
clt->clt_done = 1; |
964 |
|
|
|
965 |
|
|
dst = EVBUFFER_OUTPUT(clt->clt_bev); |
966 |
|
|
if (EVBUFFER_LENGTH(dst)) { |
967 |
|
|
/* Finish writing all data first */ |
968 |
|
|
bufferevent_enable(clt->clt_bev, EV_WRITE); |
969 |
|
|
return; |
970 |
|
|
} |
971 |
|
|
|
972 |
|
|
server_close(clt, "done"); |
973 |
|
|
return; |
974 |
|
|
} |
975 |
|
|
server_close(clt, "unknown event error"); |
976 |
|
|
return; |
977 |
|
|
} |
978 |
|
|
|
979 |
|
|
void |
980 |
|
|
server_accept(int fd, short event, void *arg) |
981 |
|
|
{ |
982 |
|
|
struct server *srv = arg; |
983 |
|
|
struct client *clt = NULL; |
984 |
|
|
socklen_t slen; |
985 |
|
|
struct sockaddr_storage ss; |
986 |
|
|
int s = -1; |
987 |
|
|
|
988 |
|
|
event_add(&srv->srv_ev, NULL); |
989 |
|
|
if ((event & EV_TIMEOUT)) |
990 |
|
|
return; |
991 |
|
|
|
992 |
|
|
slen = sizeof(ss); |
993 |
|
|
if ((s = accept_reserve(fd, (struct sockaddr *)&ss, |
994 |
|
|
&slen, FD_RESERVE, &server_inflight)) == -1) { |
995 |
|
|
/* |
996 |
|
|
* Pause accept if we are out of file descriptors, or |
997 |
|
|
* libevent will haunt us here too. |
998 |
|
|
*/ |
999 |
|
|
if (errno == ENFILE || errno == EMFILE) { |
1000 |
|
|
struct timeval evtpause = { 1, 0 }; |
1001 |
|
|
|
1002 |
|
|
event_del(&srv->srv_ev); |
1003 |
|
|
evtimer_add(&srv->srv_evt, &evtpause); |
1004 |
|
|
log_debug("%s: deferring connections", __func__); |
1005 |
|
|
} |
1006 |
|
|
return; |
1007 |
|
|
} |
1008 |
|
|
if (server_clients >= SERVER_MAX_CLIENTS) |
1009 |
|
|
goto err; |
1010 |
|
|
|
1011 |
|
|
if ((clt = calloc(1, sizeof(*clt))) == NULL) |
1012 |
|
|
goto err; |
1013 |
|
|
|
1014 |
|
|
/* Pre-allocate log buffer */ |
1015 |
|
|
clt->clt_log = evbuffer_new(); |
1016 |
|
|
if (clt->clt_log == NULL) |
1017 |
|
|
goto err; |
1018 |
|
|
|
1019 |
|
|
clt->clt_s = s; |
1020 |
|
|
clt->clt_fd = -1; |
1021 |
|
|
clt->clt_toread = TOREAD_UNLIMITED; |
1022 |
|
|
clt->clt_srv = srv; |
1023 |
|
|
clt->clt_srv_conf = &srv->srv_conf; |
1024 |
|
|
clt->clt_id = ++server_cltid; |
1025 |
|
|
clt->clt_srv_id = srv->srv_conf.id; |
1026 |
|
|
clt->clt_pid = getpid(); |
1027 |
|
|
clt->clt_inflight = 1; |
1028 |
|
|
|
1029 |
|
|
/* get local address */ |
1030 |
|
|
slen = sizeof(clt->clt_srv_ss); |
1031 |
|
|
if (getsockname(s, (struct sockaddr *)&clt->clt_srv_ss, |
1032 |
|
|
&slen) == -1) { |
1033 |
|
|
server_close(clt, "listen address lookup failed"); |
1034 |
|
|
return; |
1035 |
|
|
} |
1036 |
|
|
|
1037 |
|
|
/* get client address */ |
1038 |
|
|
memcpy(&clt->clt_ss, &ss, sizeof(clt->clt_ss)); |
1039 |
|
|
|
1040 |
|
|
/* get ports */ |
1041 |
|
|
switch (ss.ss_family) { |
1042 |
|
|
case AF_INET: |
1043 |
|
|
clt->clt_port = ((struct sockaddr_in *)&ss)->sin_port; |
1044 |
|
|
break; |
1045 |
|
|
case AF_INET6: |
1046 |
|
|
clt->clt_port = ((struct sockaddr_in6 *)&ss)->sin6_port; |
1047 |
|
|
break; |
1048 |
|
|
} |
1049 |
|
|
|
1050 |
|
|
getmonotime(&clt->clt_tv_start); |
1051 |
|
|
memcpy(&clt->clt_tv_last, &clt->clt_tv_start, sizeof(clt->clt_tv_last)); |
1052 |
|
|
|
1053 |
|
|
server_clients++; |
1054 |
|
|
SPLAY_INSERT(client_tree, &srv->srv_clients, clt); |
1055 |
|
|
|
1056 |
|
|
/* Pre-allocate output buffer */ |
1057 |
|
|
clt->clt_output = evbuffer_new(); |
1058 |
|
|
if (clt->clt_output == NULL) { |
1059 |
|
|
server_close(clt, "failed to allocate output buffer"); |
1060 |
|
|
return; |
1061 |
|
|
} |
1062 |
|
|
|
1063 |
|
|
if (srv->srv_conf.flags & SRVFLAG_TLS) { |
1064 |
|
|
if (tls_accept_socket(srv->srv_tls_ctx, &clt->clt_tls_ctx, |
1065 |
|
|
clt->clt_s) != 0) { |
1066 |
|
|
server_close(clt, "failed to setup tls context"); |
1067 |
|
|
return; |
1068 |
|
|
} |
1069 |
|
|
event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT|EV_READ, |
1070 |
|
|
server_tls_handshake, &clt->clt_tv_start, |
1071 |
|
|
&srv->srv_conf.timeout, clt); |
1072 |
|
|
return; |
1073 |
|
|
} |
1074 |
|
|
|
1075 |
|
|
server_input(clt); |
1076 |
|
|
return; |
1077 |
|
|
|
1078 |
|
|
err: |
1079 |
|
|
if (s != -1) { |
1080 |
|
|
close(s); |
1081 |
|
|
free(clt); |
1082 |
|
|
/* |
1083 |
|
|
* the client struct was not completely set up, but still |
1084 |
|
|
* counted as an inflight client. account for this. |
1085 |
|
|
*/ |
1086 |
|
|
server_inflight_dec(NULL, __func__); |
1087 |
|
|
} |
1088 |
|
|
} |
1089 |
|
|
|
1090 |
|
|
void |
1091 |
|
|
server_tls_handshake(int fd, short event, void *arg) |
1092 |
|
|
{ |
1093 |
|
|
struct client *clt = (struct client *)arg; |
1094 |
|
|
struct server *srv = (struct server *)clt->clt_srv; |
1095 |
|
|
int ret; |
1096 |
|
|
|
1097 |
|
|
if (event == EV_TIMEOUT) { |
1098 |
|
|
server_close(clt, "tls handshake timeout"); |
1099 |
|
|
return; |
1100 |
|
|
} |
1101 |
|
|
|
1102 |
|
|
if (srv->srv_tls_ctx == NULL || clt->clt_tls_ctx == NULL) |
1103 |
|
|
fatalx("NULL tls context"); |
1104 |
|
|
|
1105 |
|
|
ret = tls_handshake(clt->clt_tls_ctx); |
1106 |
|
|
if (ret == 0) { |
1107 |
|
|
server_input(clt); |
1108 |
|
|
} else if (ret == TLS_WANT_POLLIN) { |
1109 |
|
|
event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT|EV_READ, |
1110 |
|
|
server_tls_handshake, &clt->clt_tv_start, |
1111 |
|
|
&srv->srv_conf.timeout, clt); |
1112 |
|
|
} else if (ret == TLS_WANT_POLLOUT) { |
1113 |
|
|
event_again(&clt->clt_ev, clt->clt_s, EV_TIMEOUT|EV_WRITE, |
1114 |
|
|
server_tls_handshake, &clt->clt_tv_start, |
1115 |
|
|
&srv->srv_conf.timeout, clt); |
1116 |
|
|
} else { |
1117 |
|
|
log_debug("%s: tls handshake failed - %s", __func__, |
1118 |
|
|
tls_error(clt->clt_tls_ctx)); |
1119 |
|
|
server_close(clt, "tls handshake failed"); |
1120 |
|
|
} |
1121 |
|
|
} |
1122 |
|
|
|
1123 |
|
|
void |
1124 |
|
|
server_inflight_dec(struct client *clt, const char *why) |
1125 |
|
|
{ |
1126 |
|
|
if (clt != NULL) { |
1127 |
|
|
/* the flight already left inflight mode. */ |
1128 |
|
|
if (clt->clt_inflight == 0) |
1129 |
|
|
return; |
1130 |
|
|
clt->clt_inflight = 0; |
1131 |
|
|
} |
1132 |
|
|
|
1133 |
|
|
/* the file was never opened, thus this was an inflight client. */ |
1134 |
|
|
server_inflight--; |
1135 |
|
|
DPRINTF("%s: inflight decremented, now %d, %s", |
1136 |
|
|
__func__, server_inflight, why); |
1137 |
|
|
} |
1138 |
|
|
|
1139 |
|
|
void |
1140 |
|
|
server_sendlog(struct server_config *srv_conf, int cmd, const char *emsg, ...) |
1141 |
|
|
{ |
1142 |
|
|
va_list ap; |
1143 |
|
|
char *msg; |
1144 |
|
|
int ret; |
1145 |
|
|
struct iovec iov[2]; |
1146 |
|
|
|
1147 |
|
|
if (srv_conf->flags & SRVFLAG_SYSLOG) { |
1148 |
|
|
va_start(ap, emsg); |
1149 |
|
|
if (cmd == IMSG_LOG_ACCESS) |
1150 |
|
|
vlog(LOG_INFO, emsg, ap); |
1151 |
|
|
else |
1152 |
|
|
vlog(LOG_DEBUG, emsg, ap); |
1153 |
|
|
va_end(ap); |
1154 |
|
|
return; |
1155 |
|
|
} |
1156 |
|
|
|
1157 |
|
|
va_start(ap, emsg); |
1158 |
|
|
ret = vasprintf(&msg, emsg, ap); |
1159 |
|
|
va_end(ap); |
1160 |
|
|
if (ret == -1) { |
1161 |
|
|
log_warn("%s: vasprintf", __func__); |
1162 |
|
|
return; |
1163 |
|
|
} |
1164 |
|
|
|
1165 |
|
|
iov[0].iov_base = &srv_conf->id; |
1166 |
|
|
iov[0].iov_len = sizeof(srv_conf->id); |
1167 |
|
|
iov[1].iov_base = msg; |
1168 |
|
|
iov[1].iov_len = strlen(msg) + 1; |
1169 |
|
|
|
1170 |
|
|
if (proc_composev(httpd_env->sc_ps, PROC_LOGGER, cmd, iov, 2) != 0) { |
1171 |
|
|
log_warn("%s: failed to compose imsg", __func__); |
1172 |
|
|
return; |
1173 |
|
|
} |
1174 |
|
|
} |
1175 |
|
|
|
1176 |
|
|
void |
1177 |
|
|
server_log(struct client *clt, const char *msg) |
1178 |
|
|
{ |
1179 |
|
|
char ibuf[HOST_NAME_MAX+1], obuf[HOST_NAME_MAX+1]; |
1180 |
|
|
struct server_config *srv_conf = clt->clt_srv_conf; |
1181 |
|
|
char *ptr = NULL, *vmsg = NULL; |
1182 |
|
|
int debug_cmd = -1; |
1183 |
|
|
|
1184 |
|
|
switch (srv_conf->logformat) { |
1185 |
|
|
case LOG_FORMAT_CONNECTION: |
1186 |
|
|
debug_cmd = IMSG_LOG_ACCESS; |
1187 |
|
|
break; |
1188 |
|
|
default: |
1189 |
|
|
if (log_getverbose() > 1) |
1190 |
|
|
debug_cmd = IMSG_LOG_ERROR; |
1191 |
|
|
if (EVBUFFER_LENGTH(clt->clt_log)) { |
1192 |
|
|
while ((ptr = |
1193 |
|
|
evbuffer_readline(clt->clt_log)) != NULL) { |
1194 |
|
|
server_sendlog(srv_conf, |
1195 |
|
|
IMSG_LOG_ACCESS, "%s", ptr); |
1196 |
|
|
free(ptr); |
1197 |
|
|
} |
1198 |
|
|
} |
1199 |
|
|
break; |
1200 |
|
|
} |
1201 |
|
|
|
1202 |
|
|
if (debug_cmd != -1 && msg != NULL) { |
1203 |
|
|
memset(ibuf, 0, sizeof(ibuf)); |
1204 |
|
|
memset(obuf, 0, sizeof(obuf)); |
1205 |
|
|
(void)print_host(&clt->clt_ss, ibuf, sizeof(ibuf)); |
1206 |
|
|
(void)server_http_host(&clt->clt_srv_ss, obuf, sizeof(obuf)); |
1207 |
|
|
if (EVBUFFER_LENGTH(clt->clt_log) && |
1208 |
|
|
evbuffer_add_printf(clt->clt_log, "\n") != -1) |
1209 |
|
|
ptr = evbuffer_readline(clt->clt_log); |
1210 |
|
|
(void)stravis(&vmsg, msg, HTTPD_LOGVIS); |
1211 |
|
|
server_sendlog(srv_conf, debug_cmd, "server %s, " |
1212 |
|
|
"client %d (%d active), %s:%u -> %s, " |
1213 |
|
|
"%s%s%s", srv_conf->name, clt->clt_id, server_clients, |
1214 |
|
|
ibuf, ntohs(clt->clt_port), obuf, vmsg == NULL ? "" : vmsg, |
1215 |
|
|
ptr == NULL ? "" : ",", ptr == NULL ? "" : ptr); |
1216 |
|
|
free(vmsg); |
1217 |
|
|
free(ptr); |
1218 |
|
|
} |
1219 |
|
|
} |
1220 |
|
|
|
1221 |
|
|
void |
1222 |
|
|
server_close(struct client *clt, const char *msg) |
1223 |
|
|
{ |
1224 |
|
|
struct server *srv = clt->clt_srv; |
1225 |
|
|
|
1226 |
|
|
SPLAY_REMOVE(client_tree, &srv->srv_clients, clt); |
1227 |
|
|
|
1228 |
|
|
/* free the HTTP descriptors incl. headers */ |
1229 |
|
|
server_close_http(clt); |
1230 |
|
|
|
1231 |
|
|
event_del(&clt->clt_ev); |
1232 |
|
|
if (clt->clt_bev != NULL) |
1233 |
|
|
bufferevent_disable(clt->clt_bev, EV_READ|EV_WRITE); |
1234 |
|
|
if (clt->clt_srvbev != NULL) |
1235 |
|
|
bufferevent_disable(clt->clt_srvbev, EV_READ|EV_WRITE); |
1236 |
|
|
|
1237 |
|
|
server_log(clt, msg); |
1238 |
|
|
|
1239 |
|
|
if (clt->clt_bev != NULL) |
1240 |
|
|
bufferevent_free(clt->clt_bev); |
1241 |
|
|
if (clt->clt_output != NULL) |
1242 |
|
|
evbuffer_free(clt->clt_output); |
1243 |
|
|
if (clt->clt_srvevb != NULL) |
1244 |
|
|
evbuffer_free(clt->clt_srvevb); |
1245 |
|
|
|
1246 |
|
|
if (clt->clt_srvbev != NULL) |
1247 |
|
|
bufferevent_free(clt->clt_srvbev); |
1248 |
|
|
if (clt->clt_fd != -1) |
1249 |
|
|
close(clt->clt_fd); |
1250 |
|
|
if (clt->clt_s != -1) |
1251 |
|
|
close(clt->clt_s); |
1252 |
|
|
|
1253 |
|
|
if (clt->clt_tls_ctx != NULL) |
1254 |
|
|
tls_close(clt->clt_tls_ctx); |
1255 |
|
|
tls_free(clt->clt_tls_ctx); |
1256 |
|
|
|
1257 |
|
|
server_inflight_dec(clt, __func__); |
1258 |
|
|
|
1259 |
|
|
if (clt->clt_log != NULL) |
1260 |
|
|
evbuffer_free(clt->clt_log); |
1261 |
|
|
|
1262 |
|
|
free(clt); |
1263 |
|
|
server_clients--; |
1264 |
|
|
} |
1265 |
|
|
|
1266 |
|
|
int |
1267 |
|
|
server_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) |
1268 |
|
|
{ |
1269 |
|
|
struct server *srv; |
1270 |
|
|
struct server_tls_ticket key; |
1271 |
|
|
|
1272 |
|
|
switch (imsg->hdr.type) { |
1273 |
|
|
case IMSG_CFG_MEDIA: |
1274 |
|
|
config_getmedia(httpd_env, imsg); |
1275 |
|
|
break; |
1276 |
|
|
case IMSG_CFG_AUTH: |
1277 |
|
|
config_getauth(httpd_env, imsg); |
1278 |
|
|
break; |
1279 |
|
|
case IMSG_CFG_SERVER: |
1280 |
|
|
config_getserver(httpd_env, imsg); |
1281 |
|
|
break; |
1282 |
|
|
case IMSG_CFG_TLS: |
1283 |
|
|
config_getserver_tls(httpd_env, imsg); |
1284 |
|
|
break; |
1285 |
|
|
case IMSG_CFG_DONE: |
1286 |
|
|
config_getcfg(httpd_env, imsg); |
1287 |
|
|
break; |
1288 |
|
|
case IMSG_CTL_START: |
1289 |
|
|
server_launch(); |
1290 |
|
|
break; |
1291 |
|
|
case IMSG_CTL_RESET: |
1292 |
|
|
config_getreset(httpd_env, imsg); |
1293 |
|
|
break; |
1294 |
|
|
case IMSG_TLSTICKET_REKEY: |
1295 |
|
|
IMSG_SIZE_CHECK(imsg, (&key)); |
1296 |
|
|
memcpy(&key, imsg->data, sizeof(key)); |
1297 |
|
|
/* apply to the right server */ |
1298 |
|
|
srv = server_byid(key.tt_id); |
1299 |
|
|
if (srv) { |
1300 |
|
|
tls_config_add_ticket_key(srv->srv_tls_config, |
1301 |
|
|
key.tt_keyrev, key.tt_key, sizeof(key.tt_key)); |
1302 |
|
|
} |
1303 |
|
|
break; |
1304 |
|
|
default: |
1305 |
|
|
return (-1); |
1306 |
|
|
} |
1307 |
|
|
|
1308 |
|
|
return (0); |
1309 |
|
|
} |
1310 |
|
|
|
1311 |
|
|
int |
1312 |
|
|
server_dispatch_logger(int fd, struct privsep_proc *p, struct imsg *imsg) |
1313 |
|
|
{ |
1314 |
|
|
switch (imsg->hdr.type) { |
1315 |
|
|
default: |
1316 |
|
|
return (-1); |
1317 |
|
|
} |
1318 |
|
|
|
1319 |
|
|
return (0); |
1320 |
|
|
} |
1321 |
|
|
|
1322 |
|
|
int |
1323 |
|
|
server_bufferevent_add(struct event *ev, int timeout) |
1324 |
|
|
{ |
1325 |
|
|
struct timeval tv, *ptv = NULL; |
1326 |
|
|
|
1327 |
|
|
if (timeout) { |
1328 |
|
|
timerclear(&tv); |
1329 |
|
|
tv.tv_sec = timeout; |
1330 |
|
|
ptv = &tv; |
1331 |
|
|
} |
1332 |
|
|
|
1333 |
|
|
return (event_add(ev, ptv)); |
1334 |
|
|
} |
1335 |
|
|
|
1336 |
|
|
int |
1337 |
|
|
server_bufferevent_printf(struct client *clt, const char *fmt, ...) |
1338 |
|
|
{ |
1339 |
|
|
int ret; |
1340 |
|
|
va_list ap; |
1341 |
|
|
char *str; |
1342 |
|
|
|
1343 |
|
|
va_start(ap, fmt); |
1344 |
|
|
ret = vasprintf(&str, fmt, ap); |
1345 |
|
|
va_end(ap); |
1346 |
|
|
|
1347 |
|
|
if (ret == -1) |
1348 |
|
|
return (ret); |
1349 |
|
|
|
1350 |
|
|
ret = server_bufferevent_print(clt, str); |
1351 |
|
|
free(str); |
1352 |
|
|
|
1353 |
|
|
return (ret); |
1354 |
|
|
} |
1355 |
|
|
|
1356 |
|
|
int |
1357 |
|
|
server_bufferevent_print(struct client *clt, const char *str) |
1358 |
|
|
{ |
1359 |
|
|
if (clt->clt_bev == NULL) |
1360 |
|
|
return (evbuffer_add(clt->clt_output, str, strlen(str))); |
1361 |
|
|
return (bufferevent_write(clt->clt_bev, str, strlen(str))); |
1362 |
|
|
} |
1363 |
|
|
|
1364 |
|
|
int |
1365 |
|
|
server_bufferevent_write_buffer(struct client *clt, struct evbuffer *buf) |
1366 |
|
|
{ |
1367 |
|
|
if (clt->clt_bev == NULL) |
1368 |
|
|
return (evbuffer_add_buffer(clt->clt_output, buf)); |
1369 |
|
|
return (bufferevent_write_buffer(clt->clt_bev, buf)); |
1370 |
|
|
} |
1371 |
|
|
|
1372 |
|
|
int |
1373 |
|
|
server_bufferevent_write_chunk(struct client *clt, |
1374 |
|
|
struct evbuffer *buf, size_t size) |
1375 |
|
|
{ |
1376 |
|
|
int ret; |
1377 |
|
|
ret = server_bufferevent_write(clt, buf->buffer, size); |
1378 |
|
|
if (ret != -1) |
1379 |
|
|
evbuffer_drain(buf, size); |
1380 |
|
|
return (ret); |
1381 |
|
|
} |
1382 |
|
|
|
1383 |
|
|
int |
1384 |
|
|
server_bufferevent_write(struct client *clt, void *data, size_t size) |
1385 |
|
|
{ |
1386 |
|
|
if (clt->clt_bev == NULL) |
1387 |
|
|
return (evbuffer_add(clt->clt_output, data, size)); |
1388 |
|
|
return (bufferevent_write(clt->clt_bev, data, size)); |
1389 |
|
|
} |
1390 |
|
|
|
1391 |
|
|
int |
1392 |
|
|
server_client_cmp(struct client *a, struct client *b) |
1393 |
|
|
{ |
1394 |
|
|
return ((int)a->clt_id - b->clt_id); |
1395 |
|
|
} |
1396 |
|
|
|
1397 |
|
|
SPLAY_GENERATE(client_tree, client, clt_nodes, server_client_cmp); |