Blame


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