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