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