GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/slowcgi/slowcgi.c Lines: 0 552 0.0 %
Date: 2017-11-07 Branches: 0 294 0.0 %

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