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