xref: /openbsd/usr.sbin/slowcgi/slowcgi.c (revision 76d0caae)
1 /*	$OpenBSD: slowcgi.c,v 1.62 2021/09/02 14:14:44 jmc Exp $ */
2 /*
3  * Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
4  * Copyright (c) 2013 Florian Obser <florian@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/ioctl.h>
21 #include <sys/queue.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/time.h>
25 #include <sys/un.h>
26 #include <sys/wait.h>
27 #include <arpa/inet.h>
28 #include <err.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <event.h>
32 #include <limits.h>
33 #include <pwd.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <syslog.h>
40 #include <unistd.h>
41 
42 #define TIMEOUT_DEFAULT		 120
43 #define SLOWCGI_USER		 "www"
44 
45 #define FCGI_CONTENT_SIZE	 65535
46 #define FCGI_PADDING_SIZE	 255
47 #define FCGI_RECORD_SIZE	 \
48     (sizeof(struct fcgi_record_header) + FCGI_CONTENT_SIZE + FCGI_PADDING_SIZE)
49 
50 #define FCGI_ALIGNMENT		 8
51 #define FCGI_ALIGN(n)		 \
52     (((n) + (FCGI_ALIGNMENT - 1)) & ~(FCGI_ALIGNMENT - 1))
53 
54 #define STDOUT_DONE		 1
55 #define STDERR_DONE		 2
56 #define SCRIPT_DONE		 4
57 
58 #define FCGI_BEGIN_REQUEST	 1
59 #define FCGI_ABORT_REQUEST	 2
60 #define FCGI_END_REQUEST	 3
61 #define FCGI_PARAMS		 4
62 #define FCGI_STDIN		 5
63 #define FCGI_STDOUT		 6
64 #define FCGI_STDERR		 7
65 #define FCGI_DATA		 8
66 #define FCGI_GET_VALUES		 9
67 #define FCGI_GET_VALUES_RESULT	10
68 #define FCGI_UNKNOWN_TYPE	11
69 #define FCGI_MAXTYPE		(FCGI_UNKNOWN_TYPE)
70 
71 #define FCGI_REQUEST_COMPLETE	0
72 #define FCGI_CANT_MPX_CONN	1
73 #define FCGI_OVERLOADED		2
74 #define FCGI_UNKNOWN_ROLE	3
75 
76 #define FD_RESERVE		5
77 #define FD_NEEDED		6
78 int cgi_inflight = 0;
79 
80 struct listener {
81 	struct event	ev, pause;
82 };
83 
84 struct env_val {
85 	SLIST_ENTRY(env_val)	 entry;
86 	char			*val;
87 };
88 SLIST_HEAD(env_head, env_val);
89 
90 struct fcgi_record_header {
91 	uint8_t		version;
92 	uint8_t		type;
93 	uint16_t	id;
94 	uint16_t	content_len;
95 	uint8_t		padding_len;
96 	uint8_t		reserved;
97 }__packed;
98 
99 struct fcgi_response {
100 	TAILQ_ENTRY(fcgi_response)	entry;
101 	uint8_t				data[FCGI_RECORD_SIZE];
102 	size_t				data_pos;
103 	size_t				data_len;
104 };
105 TAILQ_HEAD(fcgi_response_head, fcgi_response);
106 
107 struct fcgi_stdin {
108 	TAILQ_ENTRY(fcgi_stdin)	entry;
109 	uint8_t			data[FCGI_RECORD_SIZE];
110 	size_t			data_pos;
111 	size_t			data_len;
112 };
113 TAILQ_HEAD(fcgi_stdin_head, fcgi_stdin);
114 
115 struct request {
116 	LIST_ENTRY(request)		entry;
117 	struct event			ev;
118 	struct event			resp_ev;
119 	struct event			tmo;
120 	int				fd;
121 	uint8_t				buf[FCGI_RECORD_SIZE];
122 	size_t				buf_pos;
123 	size_t				buf_len;
124 	struct fcgi_response_head	response_head;
125 	struct fcgi_stdin_head		stdin_head;
126 	uint16_t			id;
127 	char				script_name[PATH_MAX];
128 	struct env_head			env;
129 	int				env_count;
130 	pid_t				script_pid;
131 	int				script_status;
132 	struct event			script_ev;
133 	struct event			script_err_ev;
134 	struct event			script_stdin_ev;
135 	int				stdin_fd_closed;
136 	int				stdout_fd_closed;
137 	int				stderr_fd_closed;
138 	uint8_t				script_flags;
139 	uint8_t				request_started;
140 	int				inflight_fds_accounted;
141 };
142 
143 LIST_HEAD(requests_head, request);
144 
145 struct slowcgi_proc {
146 	struct requests_head	requests;
147 	struct event		ev_sigchld;
148 };
149 
150 struct fcgi_begin_request_body {
151 	uint16_t	role;
152 	uint8_t		flags;
153 	uint8_t		reserved[5];
154 }__packed;
155 
156 struct fcgi_end_request_body {
157 	uint32_t	app_status;
158 	uint8_t		protocol_status;
159 	uint8_t		reserved[3];
160 }__packed;
161 
162 __dead void	usage(void);
163 int		slowcgi_listen(char *, struct passwd *);
164 void		slowcgi_paused(int, short, void *);
165 int		accept_reserve(int, struct sockaddr *, socklen_t *, int, int *);
166 void		slowcgi_accept(int, short, void *);
167 void		slowcgi_request(int, short, void *);
168 void		slowcgi_response(int, short, void *);
169 void		slowcgi_add_response(struct request *, struct fcgi_response *);
170 void		slowcgi_timeout(int, short, void *);
171 void		slowcgi_sig_handler(int, short, void *);
172 size_t		parse_record(uint8_t * , size_t, struct request *);
173 void		parse_begin_request(uint8_t *, uint16_t, struct request *,
174 		    uint16_t);
175 void		parse_params(uint8_t *, uint16_t, struct request *, uint16_t);
176 void		parse_stdin(uint8_t *, uint16_t, struct request *, uint16_t);
177 void		exec_cgi(struct request *);
178 void		script_in(int, struct event *, struct request *, uint8_t);
179 void		script_std_in(int, short, void *);
180 void		script_err_in(int, short, void *);
181 void		script_out(int, short, void *);
182 void		create_end_record(struct request *);
183 void		dump_fcgi_record(const char *,
184 		    struct fcgi_record_header *);
185 void		dump_fcgi_record_header(const char *,
186 		    struct fcgi_record_header *);
187 void		dump_fcgi_begin_request_body(const char *,
188 		    struct fcgi_begin_request_body *);
189 void		dump_fcgi_end_request_body(const char *,
190 		    struct fcgi_end_request_body *);
191 void		cleanup_request(struct request *);
192 
193 struct loggers {
194 	__dead void (*err)(int, const char *, ...)
195 	    __attribute__((__format__ (printf, 2, 3)));
196 	__dead void (*errx)(int, const char *, ...)
197 	    __attribute__((__format__ (printf, 2, 3)));
198 	void (*warn)(const char *, ...)
199 	    __attribute__((__format__ (printf, 1, 2)));
200 	void (*warnx)(const char *, ...)
201 	    __attribute__((__format__ (printf, 1, 2)));
202 	void (*info)(const char *, ...)
203 	    __attribute__((__format__ (printf, 1, 2)));
204 	void (*debug)(const char *, ...)
205 	    __attribute__((__format__ (printf, 1, 2)));
206 };
207 
208 const struct loggers conslogger = {
209 	err,
210 	errx,
211 	warn,
212 	warnx,
213 	warnx, /* info */
214 	warnx /* debug */
215 };
216 
217 __dead void	syslog_err(int, const char *, ...)
218 		    __attribute__((__format__ (printf, 2, 3)));
219 __dead void	syslog_errx(int, const char *, ...)
220 		    __attribute__((__format__ (printf, 2, 3)));
221 void		syslog_warn(const char *, ...)
222 		    __attribute__((__format__ (printf, 1, 2)));
223 void		syslog_warnx(const char *, ...)
224 		    __attribute__((__format__ (printf, 1, 2)));
225 void		syslog_info(const char *, ...)
226 		    __attribute__((__format__ (printf, 1, 2)));
227 void		syslog_debug(const char *, ...)
228 		    __attribute__((__format__ (printf, 1, 2)));
229 void		syslog_vstrerror(int, int, const char *, va_list)
230 		    __attribute__((__format__ (printf, 3, 0)));
231 
232 const struct loggers syslogger = {
233 	syslog_err,
234 	syslog_errx,
235 	syslog_warn,
236 	syslog_warnx,
237 	syslog_info,
238 	syslog_debug
239 };
240 
241 const struct loggers *logger = &conslogger;
242 
243 #define lerr(_e, _f...) logger->err((_e), _f)
244 #define lerrx(_e, _f...) logger->errx((_e), _f)
245 #define lwarn(_f...) logger->warn(_f)
246 #define lwarnx(_f...) logger->warnx(_f)
247 #define linfo(_f...) logger->info(_f)
248 #define ldebug(_f...) logger->debug(_f)
249 
250 __dead void
251 usage(void)
252 {
253 	extern char *__progname;
254 	fprintf(stderr,
255 	    "usage: %s [-dv] [-p path] [-s socket] [-U user] [-u user]\n",
256 	    __progname);
257 	exit(1);
258 }
259 
260 struct timeval		timeout = { TIMEOUT_DEFAULT, 0 };
261 struct slowcgi_proc	slowcgi_proc;
262 int			debug = 0;
263 int			verbose = 0;
264 int			on = 1;
265 char			*fcgi_socket = "/var/www/run/slowcgi.sock";
266 
267 int
268 main(int argc, char *argv[])
269 {
270 	extern char *__progname;
271 	struct listener	*l = NULL;
272 	struct passwd	*pw;
273 	struct stat	 sb;
274 	int		 c, fd;
275 	const char	*chrootpath = NULL;
276 	const char	*sock_user = SLOWCGI_USER;
277 	const char	*slowcgi_user = SLOWCGI_USER;
278 
279 	/*
280 	 * Ensure we have fds 0-2 open so that we have no fd overlaps
281 	 * in exec_cgi() later. Just exit on error, we don't have enough
282 	 * fds open to output an error message anywhere.
283 	 */
284 	for (c=0; c < 3; c++) {
285 		if (fstat(c, &sb) == -1) {
286 			if ((fd = open("/dev/null", O_RDWR)) != -1) {
287 				if (dup2(fd, c) == -1)
288 					exit(1);
289 				if (fd > c)
290 					close(fd);
291 			} else
292 				exit(1);
293 		}
294 	}
295 
296 	while ((c = getopt(argc, argv, "dp:s:U:u:v")) != -1) {
297 		switch (c) {
298 		case 'd':
299 			debug++;
300 			break;
301 		case 'p':
302 			chrootpath = optarg;
303 			break;
304 		case 's':
305 			fcgi_socket = optarg;
306 			break;
307 		case 'U':
308 			sock_user = optarg;
309 			break;
310 		case 'u':
311 			slowcgi_user = optarg;
312 			break;
313 		case 'v':
314 			verbose++;
315 			break;
316 		default:
317 			usage();
318 			/* NOTREACHED */
319 		}
320 	}
321 
322 	if (geteuid() != 0)
323 		errx(1, "need root privileges");
324 
325 	if (!debug && daemon(0, 0) == -1)
326 		err(1, "daemon");
327 
328 	if (!debug) {
329 		openlog(__progname, LOG_PID|LOG_NDELAY, LOG_DAEMON);
330 		logger = &syslogger;
331 	}
332 
333 	ldebug("sock_user: %s", sock_user);
334 	pw = getpwnam(sock_user);
335 	if (pw == NULL)
336 		lerrx(1, "no %s user", sock_user);
337 
338 	fd = slowcgi_listen(fcgi_socket, pw);
339 
340 	ldebug("slowcgi_user: %s", slowcgi_user);
341 	pw = getpwnam(slowcgi_user);
342 	if (pw == NULL)
343 		lerrx(1, "no %s user", slowcgi_user);
344 
345 	if (chrootpath == NULL)
346 		chrootpath = pw->pw_dir;
347 
348 	if (chroot(chrootpath) == -1)
349 		lerr(1, "chroot(%s)", chrootpath);
350 
351 	ldebug("chroot: %s", chrootpath);
352 
353 	if (chdir("/") == -1)
354 		lerr(1, "chdir(/)");
355 
356 	if (setgroups(1, &pw->pw_gid) ||
357 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
358 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
359 		lerr(1, "unable to revoke privs");
360 
361 	if (pledge("stdio rpath unix proc exec", NULL) == -1)
362 		lerr(1, "pledge");
363 
364 	LIST_INIT(&slowcgi_proc.requests);
365 	event_init();
366 
367 	l = calloc(1, sizeof(*l));
368 	if (l == NULL)
369 		lerr(1, "listener ev alloc");
370 
371 	event_set(&l->ev, fd, EV_READ | EV_PERSIST, slowcgi_accept, l);
372 	event_add(&l->ev, NULL);
373 	evtimer_set(&l->pause, slowcgi_paused, l);
374 
375 	signal_set(&slowcgi_proc.ev_sigchld, SIGCHLD, slowcgi_sig_handler,
376 	    &slowcgi_proc);
377 	signal(SIGPIPE, SIG_IGN);
378 
379 	signal_add(&slowcgi_proc.ev_sigchld, NULL);
380 
381 	event_dispatch();
382 	return (0);
383 }
384 
385 int
386 slowcgi_listen(char *path, struct passwd *pw)
387 {
388 	struct sockaddr_un	 sun;
389 	mode_t			 old_umask;
390 	int			 fd;
391 
392 	if ((fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
393 	    0)) == -1)
394 		lerr(1, "slowcgi_listen: socket");
395 
396 	bzero(&sun, sizeof(sun));
397 	sun.sun_family = AF_UNIX;
398 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
399 	    sizeof(sun.sun_path))
400 		lerrx(1, "socket path too long");
401 
402 	if (unlink(path) == -1)
403 		if (errno != ENOENT)
404 			lerr(1, "slowcgi_listen: unlink %s", path);
405 
406 	old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
407 
408 	if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1)
409 		lerr(1,"slowcgi_listen: bind: %s", path);
410 
411 	umask(old_umask);
412 
413 	if (chown(path, pw->pw_uid, pw->pw_gid) == -1)
414 		lerr(1, "slowcgi_listen: chown: %s", path);
415 
416 	if (listen(fd, 5) == -1)
417 		lerr(1, "listen");
418 
419 	ldebug("socket: %s", path);
420 	return fd;
421 }
422 
423 void
424 slowcgi_paused(int fd, short events, void *arg)
425 {
426 	struct listener	*l = arg;
427 	event_add(&l->ev, NULL);
428 }
429 
430 int
431 accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
432     int reserve, int *counter)
433 {
434 	int ret;
435 	if (getdtablecount() + reserve +
436 	    ((*counter + 1) * FD_NEEDED) >= getdtablesize()) {
437 		ldebug("inflight fds exceeded");
438 		errno = EMFILE;
439 		return -1;
440 	}
441 
442 	if ((ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC))
443 	    > -1) {
444 		(*counter)++;
445 		ldebug("inflight incremented, now %d", *counter);
446 	}
447 	return ret;
448 }
449 
450 void
451 slowcgi_accept(int fd, short events, void *arg)
452 {
453 	struct listener		*l;
454 	struct sockaddr_storage	 ss;
455 	struct timeval		 backoff;
456 	struct request		*c;
457 	socklen_t		 len;
458 	int			 s;
459 
460 	l = arg;
461 	backoff.tv_sec = 1;
462 	backoff.tv_usec = 0;
463 	c = NULL;
464 
465 	len = sizeof(ss);
466 	if ((s = accept_reserve(fd, (struct sockaddr *)&ss,
467 	    &len, FD_RESERVE, &cgi_inflight)) == -1) {
468 		switch (errno) {
469 		case EINTR:
470 		case EWOULDBLOCK:
471 		case ECONNABORTED:
472 			return;
473 		case EMFILE:
474 		case ENFILE:
475 			event_del(&l->ev);
476 			evtimer_add(&l->pause, &backoff);
477 			return;
478 		default:
479 			lerr(1, "accept");
480 		}
481 	}
482 
483 	c = calloc(1, sizeof(*c));
484 	if (c == NULL) {
485 		lwarn("cannot calloc request");
486 		close(s);
487 		cgi_inflight--;
488 		return;
489 	}
490 	c->fd = s;
491 	c->buf_pos = 0;
492 	c->buf_len = 0;
493 	c->request_started = 0;
494 	c->stdin_fd_closed = c->stdout_fd_closed = c->stderr_fd_closed = 0;
495 	c->inflight_fds_accounted = 0;
496 	TAILQ_INIT(&c->response_head);
497 	TAILQ_INIT(&c->stdin_head);
498 
499 	event_set(&c->ev, s, EV_READ | EV_PERSIST, slowcgi_request, c);
500 	event_add(&c->ev, NULL);
501 	event_set(&c->resp_ev, s, EV_WRITE | EV_PERSIST, slowcgi_response, c);
502 	evtimer_set(&c->tmo, slowcgi_timeout, c);
503 	evtimer_add(&c->tmo, &timeout);
504 	LIST_INSERT_HEAD(&slowcgi_proc.requests, c, entry);
505 }
506 
507 void
508 slowcgi_timeout(int fd, short events, void *arg)
509 {
510 	cleanup_request((struct request*) arg);
511 }
512 
513 void
514 slowcgi_sig_handler(int sig, short event, void *arg)
515 {
516 	struct request		*c;
517 	struct slowcgi_proc	*p;
518 	pid_t			 pid;
519 	int			 status;
520 
521 	p = arg;
522 
523 	switch (sig) {
524 	case SIGCHLD:
525 		while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
526 			LIST_FOREACH(c, &p->requests, entry)
527 				if (c->script_pid == pid)
528 					break;
529 			if (c == NULL) {
530 				lwarnx("caught exit of unknown child %i", pid);
531 				continue;
532 			}
533 
534 			if (WIFSIGNALED(status))
535 				c->script_status = WTERMSIG(status);
536 			else
537 				c->script_status = WEXITSTATUS(status);
538 
539 			if (c->script_flags == (STDOUT_DONE | STDERR_DONE))
540 				create_end_record(c);
541 			c->script_flags |= SCRIPT_DONE;
542 
543 			ldebug("wait: %s", c->script_name);
544 		}
545 		if (pid == -1 && errno != ECHILD)
546 			lwarn("waitpid");
547 		break;
548 	default:
549 		lerr(1, "unexpected signal: %d", sig);
550 		break;
551 	}
552 }
553 
554 void
555 slowcgi_add_response(struct request *c, struct fcgi_response *resp)
556 {
557 	struct fcgi_record_header	*header;
558 	size_t				 padded_len;
559 
560 	header = (struct fcgi_record_header*)resp->data;
561 
562 	/* The FastCGI spec suggests to align the output buffer */
563 	padded_len = FCGI_ALIGN(resp->data_len);
564 	if (padded_len > resp->data_len) {
565 		/* There should always be FCGI_PADDING_SIZE bytes left */
566 		if (padded_len > FCGI_RECORD_SIZE)
567 			lerr(1, "response too long");
568 		header->padding_len = padded_len - resp->data_len;
569 		resp->data_len = padded_len;
570 	}
571 
572 	TAILQ_INSERT_TAIL(&c->response_head, resp, entry);
573 	event_add(&c->resp_ev, NULL);
574 }
575 
576 void
577 slowcgi_response(int fd, short events, void *arg)
578 {
579 	struct request			*c;
580 	struct fcgi_record_header	*header;
581 	struct fcgi_response		*resp;
582 	ssize_t				 n;
583 
584 	c = arg;
585 
586 	while ((resp = TAILQ_FIRST(&c->response_head))) {
587 		header = (struct fcgi_record_header*) resp->data;
588 		if (debug > 1)
589 			dump_fcgi_record("resp ", header);
590 
591 		n = write(fd, resp->data + resp->data_pos, resp->data_len);
592 		if (n == -1) {
593 			if (errno == EAGAIN || errno == EINTR)
594 				return;
595 			cleanup_request(c);
596 			return;
597 		}
598 		resp->data_pos += n;
599 		resp->data_len -= n;
600 		if (resp->data_len == 0) {
601 			TAILQ_REMOVE(&c->response_head, resp, entry);
602 			free(resp);
603 		}
604 	}
605 
606 	if (TAILQ_EMPTY(&c->response_head)) {
607 		if (c->script_flags == (STDOUT_DONE | STDERR_DONE |
608 		    SCRIPT_DONE))
609 			cleanup_request(c);
610 		else
611 			event_del(&c->resp_ev);
612 	}
613 }
614 
615 void
616 slowcgi_request(int fd, short events, void *arg)
617 {
618 	struct request	*c;
619 	ssize_t		 n;
620 	size_t		 parsed;
621 
622 	c = arg;
623 
624 	n = read(fd, c->buf + c->buf_pos + c->buf_len,
625 	    FCGI_RECORD_SIZE - c->buf_pos-c->buf_len);
626 
627 	switch (n) {
628 	case -1:
629 		switch (errno) {
630 		case EINTR:
631 		case EAGAIN:
632 			return;
633 		default:
634 			goto fail;
635 		}
636 		break;
637 
638 	case 0:
639 		ldebug("closed connection");
640 		goto fail;
641 	default:
642 		break;
643 	}
644 
645 	c->buf_len += n;
646 
647 	/*
648 	 * Parse the records as they are received. Per the FastCGI
649 	 * specification, the server need only receive the FastCGI
650 	 * parameter records in full; it is free to begin execution
651 	 * at that point, which is what happens here.
652 	 */
653 	do {
654 		parsed = parse_record(c->buf + c->buf_pos, c->buf_len, c);
655 		c->buf_pos += parsed;
656 		c->buf_len -= parsed;
657 	} while (parsed > 0 && c->buf_len > 0);
658 
659 	/* Make space for further reads */
660 	if (c->buf_len > 0) {
661 		bcopy(c->buf + c->buf_pos, c->buf, c->buf_len);
662 		c->buf_pos = 0;
663 	}
664 	return;
665 fail:
666 	cleanup_request(c);
667 }
668 
669 void
670 parse_begin_request(uint8_t *buf, uint16_t n, struct request *c, uint16_t id)
671 {
672 	/* XXX -- FCGI_CANT_MPX_CONN */
673 	if (c->request_started) {
674 		lwarnx("unexpected FCGI_BEGIN_REQUEST, ignoring");
675 		return;
676 	}
677 
678 	if (n != sizeof(struct fcgi_begin_request_body)) {
679 		lwarnx("wrong size %d != %lu", n,
680 		    sizeof(struct fcgi_begin_request_body));
681 		return;
682 	}
683 
684 	c->request_started = 1;
685 
686 	c->id = id;
687 	SLIST_INIT(&c->env);
688 	c->env_count = 0;
689 }
690 
691 void
692 parse_params(uint8_t *buf, uint16_t n, struct request *c, uint16_t id)
693 {
694 	struct env_val			*env_entry;
695 	uint32_t			 name_len, val_len;
696 
697 	if (!c->request_started) {
698 		lwarnx("FCGI_PARAMS without FCGI_BEGIN_REQUEST, ignoring");
699 		return;
700 	}
701 
702 	if (c->id != id) {
703 		lwarnx("unexpected id, ignoring");
704 		return;
705 	}
706 
707 	/*
708 	 * If this is the last FastCGI parameter record,
709 	 * begin execution of the CGI script.
710 	 */
711 	if (n == 0) {
712 		exec_cgi(c);
713 		return;
714 	}
715 
716 	while (n > 0) {
717 		if (buf[0] >> 7 == 0) {
718 			name_len = buf[0];
719 			n--;
720 			buf++;
721 		} else {
722 			if (n > 3) {
723 				name_len = ((buf[0] & 0x7f) << 24) +
724 				    (buf[1] << 16) + (buf[2] << 8) + buf[3];
725 				n -= 4;
726 				buf += 4;
727 			} else
728 				return;
729 		}
730 
731 		if (n > 0) {
732 			if (buf[0] >> 7 == 0) {
733 				val_len = buf[0];
734 				n--;
735 				buf++;
736 			} else {
737 				if (n > 3) {
738 					val_len = ((buf[0] & 0x7f) << 24) +
739 					    (buf[1] << 16) + (buf[2] << 8) +
740 					     buf[3];
741 					n -= 4;
742 					buf += 4;
743 				} else
744 					return;
745 			}
746 		} else
747 			return;
748 
749 		if (n < name_len + val_len)
750 			return;
751 
752 		if ((env_entry = malloc(sizeof(struct env_val))) == NULL) {
753 			lwarnx("cannot allocate env_entry");
754 			return;
755 		}
756 
757 		if ((env_entry->val = calloc(sizeof(char), name_len + val_len +
758 		    2)) == NULL) {
759 			lwarnx("cannot allocate env_entry->val");
760 			free(env_entry);
761 			return;
762 		}
763 
764 		bcopy(buf, env_entry->val, name_len);
765 		buf += name_len;
766 		n -= name_len;
767 
768 		env_entry->val[name_len] = '\0';
769 		if (val_len < PATH_MAX && strcmp(env_entry->val,
770 		    "SCRIPT_NAME") == 0 && c->script_name[0] == '\0') {
771 			bcopy(buf, c->script_name, val_len);
772 			c->script_name[val_len] = '\0';
773 		} else if (val_len < PATH_MAX && strcmp(env_entry->val,
774 		    "SCRIPT_FILENAME") == 0) {
775 			bcopy(buf, c->script_name, val_len);
776 			c->script_name[val_len] = '\0';
777 		}
778 		env_entry->val[name_len] = '=';
779 
780 		bcopy(buf, (env_entry->val) + name_len + 1, val_len);
781 		buf += val_len;
782 		n -= val_len;
783 
784 		SLIST_INSERT_HEAD(&c->env, env_entry, entry);
785 		ldebug("env[%d], %s", c->env_count, env_entry->val);
786 		c->env_count++;
787 	}
788 }
789 
790 void
791 parse_stdin(uint8_t *buf, uint16_t n, struct request *c, uint16_t id)
792 {
793 	struct fcgi_stdin	*node;
794 
795 	if (c->id != id) {
796 		lwarnx("unexpected id, ignoring");
797 		return;
798 	}
799 
800 	if ((node = calloc(1, sizeof(struct fcgi_stdin))) == NULL) {
801 		lwarnx("cannot calloc stdin node");
802 		return;
803 	}
804 
805 	bcopy(buf, node->data, n);
806 	node->data_pos = 0;
807 	node->data_len = n;
808 
809 	TAILQ_INSERT_TAIL(&c->stdin_head, node, entry);
810 
811 	if (event_initialized(&c->script_stdin_ev))
812 		event_add(&c->script_stdin_ev, NULL);
813 }
814 
815 size_t
816 parse_record(uint8_t *buf, size_t n, struct request *c)
817 {
818 	struct fcgi_record_header	*h;
819 
820 	if (n < sizeof(struct fcgi_record_header))
821 		return (0);
822 
823 	h = (struct fcgi_record_header*) buf;
824 
825 	if (debug > 1)
826 		dump_fcgi_record("", h);
827 
828 	if (n < sizeof(struct fcgi_record_header) + ntohs(h->content_len)
829 	    + h->padding_len)
830 		return (0);
831 
832 	if (h->version != 1)
833 		lerrx(1, "wrong version");
834 
835 	switch (h->type) {
836 	case FCGI_BEGIN_REQUEST:
837 		parse_begin_request(buf + sizeof(struct fcgi_record_header),
838 		    ntohs(h->content_len), c, ntohs(h->id));
839 		break;
840 	case FCGI_PARAMS:
841 		parse_params(buf + sizeof(struct fcgi_record_header),
842 		    ntohs(h->content_len), c, ntohs(h->id));
843 		break;
844 	case FCGI_STDIN:
845 		parse_stdin(buf + sizeof(struct fcgi_record_header),
846 		    ntohs(h->content_len), c, ntohs(h->id));
847 		break;
848 	default:
849 		lwarnx("unimplemented type %d", h->type);
850 		break;
851 	}
852 
853 	return (sizeof(struct fcgi_record_header) + ntohs(h->content_len)
854 	    + h->padding_len);
855 }
856 
857 /*
858  * Fork a new CGI process to handle the request, translating
859  * between FastCGI parameter records and CGI's environment variables,
860  * as well as between the CGI process' stdin/stdout and the
861  * corresponding FastCGI records.
862  */
863 void
864 exec_cgi(struct request *c)
865 {
866 	struct env_val	*env_entry;
867 	int		 s_in[2], s_out[2], s_err[2], i;
868 	pid_t		 pid;
869 	char		*argv[2];
870 	char		**env;
871 	char		*path;
872 
873 	i = 0;
874 
875 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s_in) == -1)
876 		lerr(1, "socketpair");
877 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s_out) == -1)
878 		lerr(1, "socketpair");
879 	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s_err) == -1)
880 		lerr(1, "socketpair");
881 	cgi_inflight--;
882 	c->inflight_fds_accounted = 1;
883 	ldebug("fork: %s", c->script_name);
884 
885 	switch (pid = fork()) {
886 	case -1:
887 		c->script_status = errno;
888 
889 		lwarn("fork");
890 
891 		close(s_in[0]);
892 		close(s_out[0]);
893 		close(s_err[0]);
894 
895 		close(s_in[1]);
896 		close(s_out[1]);
897 		close(s_err[1]);
898 
899 		c->stdin_fd_closed = c->stdout_fd_closed =
900 		    c->stderr_fd_closed = 1;
901 		c->script_flags = (STDOUT_DONE | STDERR_DONE | SCRIPT_DONE);
902 
903 		create_end_record(c);
904 		return;
905 	case 0:
906 		/* Child process */
907 		if (pledge("stdio rpath exec", NULL) == -1)
908 			lerr(1, "pledge");
909 		close(s_in[0]);
910 		close(s_out[0]);
911 		close(s_err[0]);
912 
913 		if (dup2(s_in[1], STDIN_FILENO) == -1)
914 			_exit(1);
915 		if (dup2(s_out[1], STDOUT_FILENO) == -1)
916 			_exit(1);
917 		if (dup2(s_err[1], STDERR_FILENO) == -1)
918 			_exit(1);
919 
920 		close(s_in[1]);
921 		close(s_out[1]);
922 		close(s_err[1]);
923 
924 		signal(SIGPIPE, SIG_DFL);
925 
926 		path = strrchr(c->script_name, '/');
927 		if (path != NULL) {
928 			if (path != c->script_name) {
929 				*path = '\0';
930 				if (chdir(c->script_name) == -1)
931 					lwarn("cannot chdir to %s",
932 					    c->script_name);
933 				*path = '/';
934 			} else
935 				if (chdir("/") == -1)
936 					lwarn("cannot chdir to /");
937 		}
938 
939 		argv[0] = c->script_name;
940 		argv[1] = NULL;
941 		if ((env = calloc(c->env_count + 1, sizeof(char*))) == NULL)
942 			_exit(1);
943 		SLIST_FOREACH(env_entry, &c->env, entry)
944 			env[i++] = env_entry->val;
945 		env[i++] = NULL;
946 		execve(c->script_name, argv, env);
947 		lwarn("execve %s", c->script_name);
948 		_exit(1);
949 
950 	}
951 
952 	/* Parent process*/
953 	close(s_in[1]);
954 	close(s_out[1]);
955 	close(s_err[1]);
956 
957 	fcntl(s_in[0], F_SETFD, FD_CLOEXEC);
958 	fcntl(s_out[0], F_SETFD, FD_CLOEXEC);
959 	fcntl(s_err[0], F_SETFD, FD_CLOEXEC);
960 
961 	if (ioctl(s_in[0], FIONBIO, &on) == -1)
962 		lerr(1, "script ioctl(FIONBIO)");
963 	if (ioctl(s_out[0], FIONBIO, &on) == -1)
964 		lerr(1, "script ioctl(FIONBIO)");
965 	if (ioctl(s_err[0], FIONBIO, &on) == -1)
966 		lerr(1, "script ioctl(FIONBIO)");
967 
968 	c->script_pid = pid;
969 	event_set(&c->script_stdin_ev, s_in[0], EV_WRITE | EV_PERSIST,
970 	    script_out, c);
971 	event_add(&c->script_stdin_ev, NULL);
972 	event_set(&c->script_ev, s_out[0], EV_READ | EV_PERSIST,
973 	    script_std_in, c);
974 	event_add(&c->script_ev, NULL);
975 	event_set(&c->script_err_ev, s_err[0], EV_READ | EV_PERSIST,
976 	    script_err_in, c);
977 	event_add(&c->script_err_ev, NULL);
978 }
979 
980 void
981 create_end_record(struct request *c)
982 {
983 	struct fcgi_response		*resp;
984 	struct fcgi_record_header	*header;
985 	struct fcgi_end_request_body	*end_request;
986 
987 	if ((resp = calloc(1, sizeof(struct fcgi_response))) == NULL) {
988 		lwarnx("cannot malloc fcgi_response");
989 		return;
990 	}
991 	header = (struct fcgi_record_header*) resp->data;
992 	header->version = 1;
993 	header->type = FCGI_END_REQUEST;
994 	header->id = htons(c->id);
995 	header->content_len = htons(sizeof(struct
996 	    fcgi_end_request_body));
997 	header->padding_len = 0;
998 	header->reserved = 0;
999 	end_request = (struct fcgi_end_request_body *) (resp->data +
1000 	    sizeof(struct fcgi_record_header));
1001 	end_request->app_status = htonl(c->script_status);
1002 	end_request->protocol_status = FCGI_REQUEST_COMPLETE;
1003 	end_request->reserved[0] = 0;
1004 	end_request->reserved[1] = 0;
1005 	end_request->reserved[2] = 0;
1006 	resp->data_pos = 0;
1007 	resp->data_len = sizeof(struct fcgi_end_request_body) +
1008 	    sizeof(struct fcgi_record_header);
1009 	slowcgi_add_response(c, resp);
1010 }
1011 
1012 void
1013 script_in(int fd, struct event *ev, struct request *c, uint8_t type)
1014 {
1015 	struct fcgi_response		*resp;
1016 	struct fcgi_record_header	*header;
1017 	ssize_t				 n;
1018 
1019 	if ((resp = calloc(1, sizeof(struct fcgi_response))) == NULL) {
1020 		lwarnx("cannot malloc fcgi_response");
1021 		return;
1022 	}
1023 	header = (struct fcgi_record_header*) resp->data;
1024 	header->version = 1;
1025 	header->type = type;
1026 	header->id = htons(c->id);
1027 	header->padding_len = 0;
1028 	header->reserved = 0;
1029 
1030 	n = read(fd, resp->data + sizeof(struct fcgi_record_header),
1031 	    FCGI_CONTENT_SIZE);
1032 
1033 	if (n == -1) {
1034 		switch (errno) {
1035 		case EINTR:
1036 		case EAGAIN:
1037 			free(resp);
1038 			return;
1039 		default:
1040 			n = 0; /* fake empty FCGI_STD{OUT,ERR} response */
1041 		}
1042 	}
1043 	header->content_len = htons(n);
1044 	resp->data_pos = 0;
1045 	resp->data_len = n + sizeof(struct fcgi_record_header);
1046 	slowcgi_add_response(c, resp);
1047 
1048 	if (n == 0) {
1049 		if (type == FCGI_STDOUT)
1050 			c->script_flags |= STDOUT_DONE;
1051 		else
1052 			c->script_flags |= STDERR_DONE;
1053 
1054 		if (c->script_flags == (STDOUT_DONE | STDERR_DONE |
1055 		    SCRIPT_DONE)) {
1056 			create_end_record(c);
1057 		}
1058 		event_del(ev);
1059 		close(fd);
1060 		if (type == FCGI_STDOUT)
1061 			c->stdout_fd_closed = 1;
1062 		else
1063 			c->stderr_fd_closed = 1;
1064 	}
1065 }
1066 
1067 void
1068 script_std_in(int fd, short events, void *arg)
1069 {
1070 	struct request *c = arg;
1071 	script_in(fd, &c->script_ev, c, FCGI_STDOUT);
1072 }
1073 
1074 void
1075 script_err_in(int fd, short events, void *arg)
1076 {
1077 	struct request *c = arg;
1078 	script_in(fd, &c->script_err_ev, c, FCGI_STDERR);
1079 }
1080 
1081 void
1082 script_out(int fd, short events, void *arg)
1083 {
1084 	struct request		*c;
1085 	struct fcgi_stdin	*node;
1086 	ssize_t			 n;
1087 
1088 	c = arg;
1089 
1090 	while ((node = TAILQ_FIRST(&c->stdin_head))) {
1091 		if (node->data_len == 0) { /* end of stdin marker */
1092 			close(fd);
1093 			c->stdin_fd_closed = 1;
1094 			break;
1095 		}
1096 		n = write(fd, node->data + node->data_pos, node->data_len);
1097 		if (n == -1) {
1098 			if (errno == EAGAIN || errno == EINTR)
1099 				return;
1100 			event_del(&c->script_stdin_ev);
1101 			return;
1102 		}
1103 		node->data_pos += n;
1104 		node->data_len -= n;
1105 		if (node->data_len == 0) {
1106 			TAILQ_REMOVE(&c->stdin_head, node, entry);
1107 			free(node);
1108 		}
1109 	}
1110 	event_del(&c->script_stdin_ev);
1111 }
1112 
1113 void
1114 cleanup_request(struct request *c)
1115 {
1116 	struct fcgi_response	*resp;
1117 	struct fcgi_stdin	*stdin_node;
1118 	struct env_val		*env_entry;
1119 
1120 	evtimer_del(&c->tmo);
1121 	if (event_initialized(&c->ev))
1122 		event_del(&c->ev);
1123 	if (event_initialized(&c->resp_ev))
1124 		event_del(&c->resp_ev);
1125 	if (event_initialized(&c->script_ev)) {
1126 		if (!c->stdout_fd_closed)
1127 			close(EVENT_FD(&c->script_ev));
1128 		event_del(&c->script_ev);
1129 	}
1130 	if (event_initialized(&c->script_err_ev)) {
1131 		if (!c->stderr_fd_closed)
1132 			close(EVENT_FD(&c->script_err_ev));
1133 		event_del(&c->script_err_ev);
1134 	}
1135 	if (event_initialized(&c->script_stdin_ev)) {
1136 		if (!c->stdin_fd_closed)
1137 			close(EVENT_FD(&c->script_stdin_ev));
1138 		event_del(&c->script_stdin_ev);
1139 	}
1140 	close(c->fd);
1141 	while (!SLIST_EMPTY(&c->env)) {
1142 		env_entry = SLIST_FIRST(&c->env);
1143 		SLIST_REMOVE_HEAD(&c->env, entry);
1144 		free(env_entry->val);
1145 		free(env_entry);
1146 	}
1147 
1148 	while ((resp = TAILQ_FIRST(&c->response_head))) {
1149 		TAILQ_REMOVE(&c->response_head, resp, entry);
1150 		free(resp);
1151 	}
1152 	while ((stdin_node = TAILQ_FIRST(&c->stdin_head))) {
1153 		TAILQ_REMOVE(&c->stdin_head, stdin_node, entry);
1154 		free(stdin_node);
1155 	}
1156 	LIST_REMOVE(c, entry);
1157 	if (! c->inflight_fds_accounted)
1158 		cgi_inflight--;
1159 	free(c);
1160 }
1161 
1162 void
1163 dump_fcgi_record(const char *p, struct fcgi_record_header *h)
1164 {
1165 	dump_fcgi_record_header(p, h);
1166 
1167 	if (h->type == FCGI_BEGIN_REQUEST)
1168 		dump_fcgi_begin_request_body(p,
1169 		    (struct fcgi_begin_request_body *)(h + 1));
1170 	else if (h->type == FCGI_END_REQUEST)
1171 		dump_fcgi_end_request_body(p,
1172 		    (struct fcgi_end_request_body *)(h + 1));
1173 }
1174 
1175 void
1176 dump_fcgi_record_header(const char* p, struct fcgi_record_header *h)
1177 {
1178 	ldebug("%sversion:         %d", p, h->version);
1179 	ldebug("%stype:            %d", p, h->type);
1180 	ldebug("%srequestId:       %d", p, ntohs(h->id));
1181 	ldebug("%scontentLength:   %d", p, ntohs(h->content_len));
1182 	ldebug("%spaddingLength:   %d", p, h->padding_len);
1183 	ldebug("%sreserved:        %d", p, h->reserved);
1184 }
1185 
1186 void
1187 dump_fcgi_begin_request_body(const char *p, struct fcgi_begin_request_body *b)
1188 {
1189 	ldebug("%srole             %d", p, ntohs(b->role));
1190 	ldebug("%sflags            %d", p, b->flags);
1191 }
1192 
1193 void
1194 dump_fcgi_end_request_body(const char *p, struct fcgi_end_request_body *b)
1195 {
1196 	ldebug("%sappStatus:       %d", p, ntohl(b->app_status));
1197 	ldebug("%sprotocolStatus:  %d", p, b->protocol_status);
1198 }
1199 
1200 void
1201 syslog_vstrerror(int e, int priority, const char *fmt, va_list ap)
1202 {
1203 	char *s;
1204 
1205 	if (vasprintf(&s, fmt, ap) == -1) {
1206 		syslog(LOG_EMERG, "unable to alloc in syslog_vstrerror");
1207 		exit(1);
1208 	}
1209 	syslog(priority, "%s: %s", s, strerror(e));
1210 	free(s);
1211 }
1212 
1213 __dead void
1214 syslog_err(int ecode, const char *fmt, ...)
1215 {
1216 	va_list ap;
1217 
1218 	va_start(ap, fmt);
1219 	syslog_vstrerror(errno, LOG_CRIT, fmt, ap);
1220 	va_end(ap);
1221 	exit(ecode);
1222 }
1223 
1224 __dead void
1225 syslog_errx(int ecode, const char *fmt, ...)
1226 {
1227 	va_list ap;
1228 
1229 	va_start(ap, fmt);
1230 	vsyslog(LOG_CRIT, fmt, ap);
1231 	va_end(ap);
1232 	exit(ecode);
1233 }
1234 
1235 void
1236 syslog_warn(const char *fmt, ...)
1237 {
1238 	va_list ap;
1239 
1240 	va_start(ap, fmt);
1241 	syslog_vstrerror(errno, LOG_ERR, fmt, ap);
1242 	va_end(ap);
1243 }
1244 
1245 void
1246 syslog_warnx(const char *fmt, ...)
1247 {
1248 	va_list ap;
1249 
1250 	va_start(ap, fmt);
1251 	vsyslog(LOG_ERR, fmt, ap);
1252 	va_end(ap);
1253 }
1254 
1255 void
1256 syslog_info(const char *fmt, ...)
1257 {
1258 	va_list ap;
1259 
1260 	va_start(ap, fmt);
1261 	vsyslog(LOG_INFO, fmt, ap);
1262 	va_end(ap);
1263 }
1264 
1265 void
1266 syslog_debug(const char *fmt, ...)
1267 {
1268 	if (verbose > 0) {
1269 		va_list ap;
1270 		va_start(ap, fmt);
1271 		vsyslog(LOG_DEBUG, fmt, ap);
1272 		va_end(ap);
1273 	}
1274 }
1275