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