Blame


1 8ad1c570 2021-05-09 op /*
2 8ad1c570 2021-05-09 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
3 8ad1c570 2021-05-09 op *
4 8ad1c570 2021-05-09 op * Permission to use, copy, modify, and distribute this software for any
5 8ad1c570 2021-05-09 op * purpose with or without fee is hereby granted, provided that the above
6 8ad1c570 2021-05-09 op * copyright notice and this permission notice appear in all copies.
7 8ad1c570 2021-05-09 op *
8 8ad1c570 2021-05-09 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 8ad1c570 2021-05-09 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 8ad1c570 2021-05-09 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 8ad1c570 2021-05-09 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 8ad1c570 2021-05-09 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 8ad1c570 2021-05-09 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 8ad1c570 2021-05-09 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 8ad1c570 2021-05-09 op */
16 8ad1c570 2021-05-09 op
17 8ad1c570 2021-05-09 op #include "gmid.h"
18 8ad1c570 2021-05-09 op
19 8ad1c570 2021-05-09 op #include <assert.h>
20 8ad1c570 2021-05-09 op #include <errno.h>
21 8ad1c570 2021-05-09 op #include <string.h>
22 8ad1c570 2021-05-09 op
23 8ad1c570 2021-05-09 op /*
24 8ad1c570 2021-05-09 op * Sometimes it can be useful to inspect the fastcgi traffic as
25 8ad1c570 2021-05-09 op * received by gmid.
26 8ad1c570 2021-05-09 op *
27 8ad1c570 2021-05-09 op * This will make gmid connect to a `debug.sock' socket (that must
28 8ad1c570 2021-05-09 op * exists) in the current directory and send there a copy of what gets
29 8ad1c570 2021-05-09 op * read. The socket can be created and monitored e.g. with
30 8ad1c570 2021-05-09 op *
31 8ad1c570 2021-05-09 op * rm -f debug.sock ; nc -Ulk ./debug.sock | hexdump -C
32 8ad1c570 2021-05-09 op *
33 8ad1c570 2021-05-09 op * NB: the sandbox must be disabled for this to work.
34 8ad1c570 2021-05-09 op */
35 8ad1c570 2021-05-09 op #define DEBUG_FCGI 0
36 8ad1c570 2021-05-09 op
37 f740b61b 2021-06-11 op #if DEBUG_FCGI
38 8ad1c570 2021-05-09 op # include <sys/un.h>
39 8ad1c570 2021-05-09 op static int debug_socket = -1;
40 8ad1c570 2021-05-09 op #endif
41 8ad1c570 2021-05-09 op
42 8ad1c570 2021-05-09 op struct fcgi_header {
43 8ad1c570 2021-05-09 op unsigned char version;
44 8ad1c570 2021-05-09 op unsigned char type;
45 8ad1c570 2021-05-09 op unsigned char req_id1;
46 8ad1c570 2021-05-09 op unsigned char req_id0;
47 8ad1c570 2021-05-09 op unsigned char content_len1;
48 8ad1c570 2021-05-09 op unsigned char content_len0;
49 8ad1c570 2021-05-09 op unsigned char padding;
50 8ad1c570 2021-05-09 op unsigned char reserved;
51 8ad1c570 2021-05-09 op };
52 8ad1c570 2021-05-09 op
53 8ad1c570 2021-05-09 op /*
54 8ad1c570 2021-05-09 op * number of bytes in a FCGI_HEADER. Future version of the protocol
55 8ad1c570 2021-05-09 op * will not reduce this number.
56 8ad1c570 2021-05-09 op */
57 8ad1c570 2021-05-09 op #define FCGI_HEADER_LEN 8
58 8ad1c570 2021-05-09 op
59 8ad1c570 2021-05-09 op /*
60 8ad1c570 2021-05-09 op * values for the version component
61 8ad1c570 2021-05-09 op */
62 8ad1c570 2021-05-09 op #define FCGI_VERSION_1 1
63 8ad1c570 2021-05-09 op
64 8ad1c570 2021-05-09 op /*
65 8ad1c570 2021-05-09 op * values for the type component
66 8ad1c570 2021-05-09 op */
67 8ad1c570 2021-05-09 op #define FCGI_BEGIN_REQUEST 1
68 8ad1c570 2021-05-09 op #define FCGI_ABORT_REQUEST 2
69 8ad1c570 2021-05-09 op #define FCGI_END_REQUEST 3
70 8ad1c570 2021-05-09 op #define FCGI_PARAMS 4
71 8ad1c570 2021-05-09 op #define FCGI_STDIN 5
72 8ad1c570 2021-05-09 op #define FCGI_STDOUT 6
73 8ad1c570 2021-05-09 op #define FCGI_STDERR 7
74 8ad1c570 2021-05-09 op #define FCGI_DATA 8
75 8ad1c570 2021-05-09 op #define FCGI_GET_VALUES 9
76 8ad1c570 2021-05-09 op #define FCGI_GET_VALUES_RESULT 10
77 8ad1c570 2021-05-09 op #define FCGI_UNKNOWN_TYPE 11
78 8ad1c570 2021-05-09 op #define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
79 8ad1c570 2021-05-09 op
80 8ad1c570 2021-05-09 op struct fcgi_begin_req {
81 8ad1c570 2021-05-09 op unsigned char role1;
82 8ad1c570 2021-05-09 op unsigned char role0;
83 8ad1c570 2021-05-09 op unsigned char flags;
84 8ad1c570 2021-05-09 op unsigned char reserved[5];
85 8ad1c570 2021-05-09 op };
86 8ad1c570 2021-05-09 op
87 8ad1c570 2021-05-09 op struct fcgi_begin_req_record {
88 8ad1c570 2021-05-09 op struct fcgi_header header;
89 8ad1c570 2021-05-09 op struct fcgi_begin_req body;
90 8ad1c570 2021-05-09 op };
91 8ad1c570 2021-05-09 op
92 8ad1c570 2021-05-09 op /*
93 8ad1c570 2021-05-09 op * mask for flags;
94 8ad1c570 2021-05-09 op */
95 8ad1c570 2021-05-09 op #define FCGI_KEEP_CONN 1
96 8ad1c570 2021-05-09 op
97 8ad1c570 2021-05-09 op /*
98 8ad1c570 2021-05-09 op * values for the role
99 8ad1c570 2021-05-09 op */
100 8ad1c570 2021-05-09 op #define FCGI_RESPONDER 1
101 8ad1c570 2021-05-09 op #define FCGI_AUTHORIZER 2
102 8ad1c570 2021-05-09 op #define FCGI_FILTER 3
103 8ad1c570 2021-05-09 op
104 8ad1c570 2021-05-09 op struct fcgi_end_req_body {
105 8ad1c570 2021-05-09 op unsigned char app_status3;
106 8ad1c570 2021-05-09 op unsigned char app_status2;
107 8ad1c570 2021-05-09 op unsigned char app_status1;
108 8ad1c570 2021-05-09 op unsigned char app_status0;
109 8ad1c570 2021-05-09 op unsigned char proto_status;
110 8ad1c570 2021-05-09 op unsigned char reserved[3];
111 8ad1c570 2021-05-09 op };
112 8ad1c570 2021-05-09 op
113 8ad1c570 2021-05-09 op /*
114 8ad1c570 2021-05-09 op * values for proto_status
115 8ad1c570 2021-05-09 op */
116 8ad1c570 2021-05-09 op #define FCGI_REQUEST_COMPLETE 0
117 8ad1c570 2021-05-09 op #define FCGI_CANT_MPX_CONN 1
118 8ad1c570 2021-05-09 op #define FCGI_OVERLOADED 2
119 8ad1c570 2021-05-09 op #define FCGI_UNKNOWN_ROLE 3
120 8ad1c570 2021-05-09 op
121 8ad1c570 2021-05-09 op /*
122 8ad1c570 2021-05-09 op * Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT
123 8ad1c570 2021-05-09 op * records.
124 8ad1c570 2021-05-09 op */
125 8ad1c570 2021-05-09 op #define FCGI_MAX_CONNS "FCGI_MAX_CONNS"
126 8ad1c570 2021-05-09 op #define FCGI_MAX_REQS "FCGI_MAX_REQS"
127 8ad1c570 2021-05-09 op #define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"
128 8ad1c570 2021-05-09 op
129 8ad1c570 2021-05-09 op static int
130 8ad1c570 2021-05-09 op prepare_header(struct fcgi_header *h, int type, int id, size_t size,
131 8ad1c570 2021-05-09 op size_t padding)
132 8ad1c570 2021-05-09 op {
133 8ad1c570 2021-05-09 op memset(h, 0, sizeof(*h));
134 8ad1c570 2021-05-09 op
135 8ad1c570 2021-05-09 op /*
136 8ad1c570 2021-05-09 op * id=0 is reserved for status messages.
137 8ad1c570 2021-05-09 op */
138 8ad1c570 2021-05-09 op id++;
139 8ad1c570 2021-05-09 op
140 8ad1c570 2021-05-09 op h->version = FCGI_VERSION_1;
141 8ad1c570 2021-05-09 op h->type = type;
142 8ad1c570 2021-05-09 op h->req_id1 = (id >> 8);
143 8ad1c570 2021-05-09 op h->req_id0 = (id & 0xFF);
144 8ad1c570 2021-05-09 op h->content_len1 = (size >> 8);
145 8ad1c570 2021-05-09 op h->content_len0 = (size & 0xFF);
146 8ad1c570 2021-05-09 op h->padding = padding;
147 8ad1c570 2021-05-09 op
148 8ad1c570 2021-05-09 op return 0;
149 8ad1c570 2021-05-09 op }
150 8ad1c570 2021-05-09 op
151 8ad1c570 2021-05-09 op static int
152 8ad1c570 2021-05-09 op fcgi_begin_request(int sock, int id)
153 8ad1c570 2021-05-09 op {
154 8ad1c570 2021-05-09 op struct fcgi_begin_req_record r;
155 8ad1c570 2021-05-09 op
156 8ad1c570 2021-05-09 op if (id > UINT16_MAX)
157 8ad1c570 2021-05-09 op return -1;
158 8ad1c570 2021-05-09 op
159 8ad1c570 2021-05-09 op memset(&r, 0, sizeof(r));
160 8ad1c570 2021-05-09 op prepare_header(&r.header, FCGI_BEGIN_REQUEST, id,
161 8ad1c570 2021-05-09 op sizeof(r.body), 0);
162 8ad1c570 2021-05-09 op assert(sizeof(r.body) == FCGI_HEADER_LEN);
163 8ad1c570 2021-05-09 op
164 8ad1c570 2021-05-09 op r.body.role1 = 0;
165 8ad1c570 2021-05-09 op r.body.role0 = FCGI_RESPONDER;
166 8ad1c570 2021-05-09 op r.body.flags = FCGI_KEEP_CONN;
167 8ad1c570 2021-05-09 op
168 e18b070d 2021-06-12 op if (write(sock, &r, sizeof(r)) != sizeof(r))
169 8ad1c570 2021-05-09 op return -1;
170 8ad1c570 2021-05-09 op return 0;
171 8ad1c570 2021-05-09 op }
172 8ad1c570 2021-05-09 op
173 8ad1c570 2021-05-09 op static int
174 8ad1c570 2021-05-09 op fcgi_send_param(int sock, int id, const char *name, const char *value)
175 8ad1c570 2021-05-09 op {
176 8ad1c570 2021-05-09 op struct fcgi_header h;
177 8ad1c570 2021-05-09 op uint32_t namlen, vallen, padlen;
178 8ad1c570 2021-05-09 op uint8_t s[8];
179 8ad1c570 2021-05-09 op size_t size;
180 8ad1c570 2021-05-09 op char padding[8] = { 0 };
181 8ad1c570 2021-05-09 op
182 8ad1c570 2021-05-09 op namlen = strlen(name);
183 8ad1c570 2021-05-09 op vallen = strlen(value);
184 8ad1c570 2021-05-09 op size = namlen + vallen + 8; /* 4 for the sizes */
185 8ad1c570 2021-05-09 op padlen = (8 - (size & 0x7)) & 0x7;
186 8ad1c570 2021-05-09 op
187 8ad1c570 2021-05-09 op s[0] = ( namlen >> 24) | 0x80;
188 8ad1c570 2021-05-09 op s[1] = ((namlen >> 16) & 0xFF);
189 8ad1c570 2021-05-09 op s[2] = ((namlen >> 8) & 0xFF);
190 8ad1c570 2021-05-09 op s[3] = ( namlen & 0xFF);
191 8ad1c570 2021-05-09 op
192 8ad1c570 2021-05-09 op s[4] = ( vallen >> 24) | 0x80;
193 8ad1c570 2021-05-09 op s[5] = ((vallen >> 16) & 0xFF);
194 8ad1c570 2021-05-09 op s[6] = ((vallen >> 8) & 0xFF);
195 8ad1c570 2021-05-09 op s[7] = ( vallen & 0xFF);
196 8ad1c570 2021-05-09 op
197 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_PARAMS, id, size, padlen);
198 8ad1c570 2021-05-09 op
199 8ad1c570 2021-05-09 op if (write(sock, &h, sizeof(h)) != sizeof(h) ||
200 8ad1c570 2021-05-09 op write(sock, s, sizeof(s)) != sizeof(s) ||
201 8ad1c570 2021-05-09 op write(sock, name, namlen) != namlen ||
202 8ad1c570 2021-05-09 op write(sock, value, vallen) != vallen ||
203 8ad1c570 2021-05-09 op write(sock, padding, padlen) != padlen)
204 8ad1c570 2021-05-09 op return -1;
205 8ad1c570 2021-05-09 op
206 8ad1c570 2021-05-09 op return 0;
207 8ad1c570 2021-05-09 op }
208 8ad1c570 2021-05-09 op
209 8ad1c570 2021-05-09 op static int
210 8ad1c570 2021-05-09 op fcgi_end_param(int sock, int id)
211 8ad1c570 2021-05-09 op {
212 8ad1c570 2021-05-09 op struct fcgi_header h;
213 8ad1c570 2021-05-09 op
214 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_PARAMS, id, 0, 0);
215 8ad1c570 2021-05-09 op if (write(sock, &h, sizeof(h)) != sizeof(h))
216 8ad1c570 2021-05-09 op return -1;
217 8ad1c570 2021-05-09 op
218 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_STDIN, id, 0, 0);
219 8ad1c570 2021-05-09 op if (write(sock, &h, sizeof(h)) != sizeof(h))
220 8ad1c570 2021-05-09 op return -1;
221 8ad1c570 2021-05-09 op
222 8ad1c570 2021-05-09 op return 0;
223 8ad1c570 2021-05-09 op }
224 8ad1c570 2021-05-09 op
225 8ad1c570 2021-05-09 op static int
226 8ad1c570 2021-05-09 op fcgi_abort_request(int sock, int id)
227 8ad1c570 2021-05-09 op {
228 8ad1c570 2021-05-09 op struct fcgi_header h;
229 8ad1c570 2021-05-09 op
230 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_ABORT_REQUEST, id, 0, 0);
231 8ad1c570 2021-05-09 op if (write(sock, &h, sizeof(h)) != sizeof(h))
232 8ad1c570 2021-05-09 op return -1;
233 8ad1c570 2021-05-09 op
234 8ad1c570 2021-05-09 op return 0;
235 8ad1c570 2021-05-09 op }
236 8ad1c570 2021-05-09 op
237 8ad1c570 2021-05-09 op static int
238 8ad1c570 2021-05-09 op must_read(int sock, char *d, size_t len)
239 8ad1c570 2021-05-09 op {
240 8ad1c570 2021-05-09 op ssize_t r;
241 8ad1c570 2021-05-09 op
242 8ad1c570 2021-05-09 op #if DEBUG_FCGI
243 8ad1c570 2021-05-09 op if (debug_socket == -1) {
244 8ad1c570 2021-05-09 op struct sockaddr_un addr;
245 8ad1c570 2021-05-09 op
246 8ad1c570 2021-05-09 op if ((debug_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
247 8ad1c570 2021-05-09 op err(1, "socket");
248 8ad1c570 2021-05-09 op
249 8ad1c570 2021-05-09 op memset(&addr, 0, sizeof(addr));
250 8ad1c570 2021-05-09 op addr.sun_family = AF_UNIX;
251 8ad1c570 2021-05-09 op strlcpy(addr.sun_path, "./debug.sock", sizeof(addr.sun_path));
252 8ad1c570 2021-05-09 op if (connect(debug_socket, (struct sockaddr*)&addr, sizeof(addr))
253 8ad1c570 2021-05-09 op == -1)
254 8ad1c570 2021-05-09 op err(1, "connect");
255 8ad1c570 2021-05-09 op }
256 8ad1c570 2021-05-09 op #endif
257 8ad1c570 2021-05-09 op
258 8ad1c570 2021-05-09 op for (;;) {
259 8ad1c570 2021-05-09 op switch (r = read(sock, d, len)) {
260 8ad1c570 2021-05-09 op case -1:
261 8ad1c570 2021-05-09 op case 0:
262 8ad1c570 2021-05-09 op return -1;
263 8ad1c570 2021-05-09 op default:
264 8ad1c570 2021-05-09 op #if DEBUG_FCGI
265 8ad1c570 2021-05-09 op write(debug_socket, d, r);
266 8ad1c570 2021-05-09 op #endif
267 8ad1c570 2021-05-09 op
268 8ad1c570 2021-05-09 op if (r == (ssize_t)len)
269 8ad1c570 2021-05-09 op return 0;
270 8ad1c570 2021-05-09 op len -= r;
271 8ad1c570 2021-05-09 op d += r;
272 8ad1c570 2021-05-09 op }
273 8ad1c570 2021-05-09 op }
274 8ad1c570 2021-05-09 op }
275 8ad1c570 2021-05-09 op
276 8ad1c570 2021-05-09 op static int
277 8ad1c570 2021-05-09 op fcgi_read_header(int sock, struct fcgi_header *h)
278 8ad1c570 2021-05-09 op {
279 8ad1c570 2021-05-09 op if (must_read(sock, (char*)h, sizeof(*h)) == -1)
280 8ad1c570 2021-05-09 op return -1;
281 8ad1c570 2021-05-09 op if (h->version != FCGI_VERSION_1) {
282 8ad1c570 2021-05-09 op errno = EINVAL;
283 8ad1c570 2021-05-09 op return -1;
284 8ad1c570 2021-05-09 op }
285 8ad1c570 2021-05-09 op return 0;
286 8ad1c570 2021-05-09 op }
287 8ad1c570 2021-05-09 op
288 8ad1c570 2021-05-09 op static inline int
289 8ad1c570 2021-05-09 op recid(struct fcgi_header *h)
290 8ad1c570 2021-05-09 op {
291 8ad1c570 2021-05-09 op return h->req_id0 + (h->req_id1 << 8) - 1;
292 8ad1c570 2021-05-09 op }
293 8ad1c570 2021-05-09 op
294 8ad1c570 2021-05-09 op static inline int
295 8ad1c570 2021-05-09 op reclen(struct fcgi_header *h)
296 8ad1c570 2021-05-09 op {
297 8ad1c570 2021-05-09 op return h->content_len0 + (h->content_len1 << 8);
298 8ad1c570 2021-05-09 op }
299 8ad1c570 2021-05-09 op
300 8ad1c570 2021-05-09 op static void
301 8ad1c570 2021-05-09 op copy_mbuf(int fd, short ev, void *d)
302 8ad1c570 2021-05-09 op {
303 8ad1c570 2021-05-09 op struct client *c = d;
304 8ad1c570 2021-05-09 op struct mbuf *mbuf;
305 8ad1c570 2021-05-09 op size_t len;
306 8ad1c570 2021-05-09 op ssize_t r;
307 8ad1c570 2021-05-09 op char *data;
308 8ad1c570 2021-05-09 op
309 8ad1c570 2021-05-09 op for (;;) {
310 8ad1c570 2021-05-09 op mbuf = TAILQ_FIRST(&c->mbufhead);
311 8ad1c570 2021-05-09 op if (mbuf == NULL)
312 8ad1c570 2021-05-09 op break;
313 8ad1c570 2021-05-09 op
314 8ad1c570 2021-05-09 op len = mbuf->len - mbuf->off;
315 8ad1c570 2021-05-09 op data = mbuf->data + mbuf->off;
316 8ad1c570 2021-05-09 op switch (r = tls_write(c->ctx, data, len)) {
317 8ad1c570 2021-05-09 op case -1:
318 8ad1c570 2021-05-09 op /*
319 8ad1c570 2021-05-09 op * Can't close_conn here. The application
320 8ad1c570 2021-05-09 op * needs to be informed first, otherwise it
321 8ad1c570 2021-05-09 op * can interfere with future connections.
322 8ad1c570 2021-05-09 op * Check also that we're not doing recursion
323 8ad1c570 2021-05-09 op * (copy_mbuf -> handle_fcgi -> copy_mbuf ...)
324 8ad1c570 2021-05-09 op */
325 8ad1c570 2021-05-09 op if (c->next != NULL)
326 8ad1c570 2021-05-09 op goto end;
327 8ad1c570 2021-05-09 op fcgi_abort_request(0, c->id);
328 8ad1c570 2021-05-09 op return;
329 8ad1c570 2021-05-09 op case TLS_WANT_POLLIN:
330 8ad1c570 2021-05-09 op event_once(c->fd, EV_READ, &copy_mbuf, c, NULL);
331 8ad1c570 2021-05-09 op return;
332 8ad1c570 2021-05-09 op case TLS_WANT_POLLOUT:
333 8ad1c570 2021-05-09 op event_once(c->fd, EV_WRITE, &copy_mbuf, c, NULL);
334 8ad1c570 2021-05-09 op return;
335 8ad1c570 2021-05-09 op }
336 8ad1c570 2021-05-09 op mbuf->off += r;
337 8ad1c570 2021-05-09 op
338 8ad1c570 2021-05-09 op if (mbuf->off == mbuf->len) {
339 8ad1c570 2021-05-09 op TAILQ_REMOVE(&c->mbufhead, mbuf, mbufs);
340 8ad1c570 2021-05-09 op free(mbuf);
341 8ad1c570 2021-05-09 op }
342 8ad1c570 2021-05-09 op }
343 8ad1c570 2021-05-09 op
344 8ad1c570 2021-05-09 op end:
345 8ad1c570 2021-05-09 op if (c->next != NULL)
346 8ad1c570 2021-05-09 op c->next(0, 0, c);
347 8ad1c570 2021-05-09 op }
348 8ad1c570 2021-05-09 op
349 8ad1c570 2021-05-09 op static int
350 8ad1c570 2021-05-09 op consume(int fd, size_t len)
351 8ad1c570 2021-05-09 op {
352 8ad1c570 2021-05-09 op size_t l;
353 8ad1c570 2021-05-09 op char buf[64];
354 8ad1c570 2021-05-09 op
355 8ad1c570 2021-05-09 op while (len != 0) {
356 8ad1c570 2021-05-09 op if ((l = len) > sizeof(buf))
357 8ad1c570 2021-05-09 op l = sizeof(buf);
358 8ad1c570 2021-05-09 op if (must_read(fd, buf, l) == -1)
359 8ad1c570 2021-05-09 op return 0;
360 8ad1c570 2021-05-09 op len -= l;
361 8ad1c570 2021-05-09 op }
362 8ad1c570 2021-05-09 op
363 8ad1c570 2021-05-09 op return 1;
364 8ad1c570 2021-05-09 op }
365 8ad1c570 2021-05-09 op
366 8ad1c570 2021-05-09 op static void
367 8ad1c570 2021-05-09 op close_all(struct fcgi *f)
368 8ad1c570 2021-05-09 op {
369 8ad1c570 2021-05-09 op size_t i;
370 8ad1c570 2021-05-09 op struct client *c;
371 8ad1c570 2021-05-09 op
372 8ad1c570 2021-05-09 op for (i = 0; i < MAX_USERS; i++) {
373 8ad1c570 2021-05-09 op c = &clients[i];
374 8ad1c570 2021-05-09 op
375 8ad1c570 2021-05-09 op if (c->fcgi != f->id)
376 8ad1c570 2021-05-09 op continue;
377 8ad1c570 2021-05-09 op
378 8ad1c570 2021-05-09 op if (c->code != 0)
379 8ad1c570 2021-05-09 op close_conn(0, 0, c);
380 8ad1c570 2021-05-09 op else
381 8ad1c570 2021-05-09 op start_reply(c, CGI_ERROR, "CGI error");
382 8ad1c570 2021-05-09 op }
383 8ad1c570 2021-05-09 op
384 090b8a89 2021-07-06 op fcgi_close_backend(f);
385 090b8a89 2021-07-06 op }
386 090b8a89 2021-07-06 op
387 090b8a89 2021-07-06 op void
388 090b8a89 2021-07-06 op fcgi_close_backend(struct fcgi *f)
389 090b8a89 2021-07-06 op {
390 8ad1c570 2021-05-09 op event_del(&f->e);
391 8ad1c570 2021-05-09 op close(f->fd);
392 8ad1c570 2021-05-09 op f->fd = -1;
393 090b8a89 2021-07-06 op f->pending = 0;
394 8ad1c570 2021-05-09 op f->s = FCGI_OFF;
395 8ad1c570 2021-05-09 op }
396 8ad1c570 2021-05-09 op
397 8ad1c570 2021-05-09 op void
398 8ad1c570 2021-05-09 op handle_fcgi(int sock, short event, void *d)
399 8ad1c570 2021-05-09 op {
400 8ad1c570 2021-05-09 op struct fcgi *f = d;
401 8ad1c570 2021-05-09 op struct fcgi_header h;
402 8ad1c570 2021-05-09 op struct fcgi_end_req_body end;
403 8ad1c570 2021-05-09 op struct client *c;
404 8ad1c570 2021-05-09 op struct mbuf *mbuf;
405 8ad1c570 2021-05-09 op size_t len;
406 8ad1c570 2021-05-09 op
407 8ad1c570 2021-05-09 op if (fcgi_read_header(sock, &h) == -1)
408 8ad1c570 2021-05-09 op goto err;
409 8ad1c570 2021-05-09 op
410 8ad1c570 2021-05-09 op c = try_client_by_id(recid(&h));
411 8ad1c570 2021-05-09 op if (c == NULL || c->fcgi != f->id)
412 8ad1c570 2021-05-09 op goto err;
413 8ad1c570 2021-05-09 op
414 8ad1c570 2021-05-09 op len = reclen(&h);
415 8ad1c570 2021-05-09 op
416 8ad1c570 2021-05-09 op switch (h.type) {
417 8ad1c570 2021-05-09 op case FCGI_END_REQUEST:
418 8ad1c570 2021-05-09 op if (len != sizeof(end))
419 8ad1c570 2021-05-09 op goto err;
420 8ad1c570 2021-05-09 op if (must_read(sock, (char*)&end, sizeof(end)) == -1)
421 8ad1c570 2021-05-09 op goto err;
422 8ad1c570 2021-05-09 op /* TODO: do something with the status? */
423 090b8a89 2021-07-06 op
424 090b8a89 2021-07-06 op f->pending--;
425 8ad1c570 2021-05-09 op c->fcgi = -1;
426 8ad1c570 2021-05-09 op c->next = close_conn;
427 8ad1c570 2021-05-09 op event_once(c->fd, EV_WRITE, &copy_mbuf, c, NULL);
428 8ad1c570 2021-05-09 op break;
429 8ad1c570 2021-05-09 op
430 8ad1c570 2021-05-09 op case FCGI_STDERR:
431 8ad1c570 2021-05-09 op /* discard stderr (for now) */
432 8ad1c570 2021-05-09 op if (!consume(sock, len))
433 8ad1c570 2021-05-09 op goto err;
434 8ad1c570 2021-05-09 op break;
435 8ad1c570 2021-05-09 op
436 8ad1c570 2021-05-09 op case FCGI_STDOUT:
437 8ad1c570 2021-05-09 op if ((mbuf = calloc(1, sizeof(*mbuf) + len)) == NULL)
438 8ad1c570 2021-05-09 op fatal("calloc");
439 8ad1c570 2021-05-09 op mbuf->len = len;
440 8ad1c570 2021-05-09 op if (must_read(sock, mbuf->data, len) == -1) {
441 8ad1c570 2021-05-09 op free(mbuf);
442 8ad1c570 2021-05-09 op goto err;
443 8ad1c570 2021-05-09 op }
444 8ad1c570 2021-05-09 op
445 8ad1c570 2021-05-09 op if (TAILQ_EMPTY(&c->mbufhead)) {
446 8ad1c570 2021-05-09 op TAILQ_INSERT_HEAD(&c->mbufhead, mbuf, mbufs);
447 8ad1c570 2021-05-09 op event_once(c->fd, EV_WRITE, &copy_mbuf, c, NULL);
448 8ad1c570 2021-05-09 op } else
449 8ad1c570 2021-05-09 op TAILQ_INSERT_TAIL(&c->mbufhead, mbuf, mbufs);
450 8ad1c570 2021-05-09 op break;
451 8ad1c570 2021-05-09 op
452 8ad1c570 2021-05-09 op default:
453 8ad1c570 2021-05-09 op log_err(NULL, "got invalid fcgi record (type=%d)", h.type);
454 8ad1c570 2021-05-09 op goto err;
455 8ad1c570 2021-05-09 op }
456 8ad1c570 2021-05-09 op
457 8ad1c570 2021-05-09 op if (!consume(sock, h.padding))
458 8ad1c570 2021-05-09 op goto err;
459 090b8a89 2021-07-06 op
460 090b8a89 2021-07-06 op if (f->pending == 0 && shutting_down)
461 090b8a89 2021-07-06 op fcgi_close_backend(f);
462 090b8a89 2021-07-06 op
463 8ad1c570 2021-05-09 op return;
464 8ad1c570 2021-05-09 op
465 8ad1c570 2021-05-09 op err:
466 8ad1c570 2021-05-09 op close_all(f);
467 8ad1c570 2021-05-09 op }
468 8ad1c570 2021-05-09 op
469 8ad1c570 2021-05-09 op void
470 8ad1c570 2021-05-09 op send_fcgi_req(struct fcgi *f, struct client *c)
471 8ad1c570 2021-05-09 op {
472 f740b61b 2021-06-11 op char addr[NI_MAXHOST], buf[22];
473 d1051bfa 2021-05-15 op int e;
474 f740b61b 2021-06-11 op time_t tim;
475 f740b61b 2021-06-11 op struct tm tminfo;
476 f740b61b 2021-06-11 op struct envlist *p;
477 d1051bfa 2021-05-15 op
478 090b8a89 2021-07-06 op f->pending++;
479 090b8a89 2021-07-06 op
480 59c7ee13 2021-07-06 op e = getnameinfo((struct sockaddr*)&c->addr, sizeof(c->addr),
481 d1051bfa 2021-05-15 op addr, sizeof(addr),
482 d1051bfa 2021-05-15 op NULL, 0,
483 d1051bfa 2021-05-15 op NI_NUMERICHOST);
484 d1051bfa 2021-05-15 op if (e != 0)
485 d1051bfa 2021-05-15 op fatal("getnameinfo failed");
486 d1051bfa 2021-05-15 op
487 8ad1c570 2021-05-09 op c->next = NULL;
488 8ad1c570 2021-05-09 op
489 8ad1c570 2021-05-09 op fcgi_begin_request(f->fd, c->id);
490 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "GATEWAY_INTERFACE", "CGI/1.1");
491 8ad1c570 2021-05-09 op fcgi_send_param(f->fd, c->id, "GEMINI_URL_PATH", c->iri.path);
492 d1051bfa 2021-05-15 op fcgi_send_param(f->fd, c->id, "QUERY_STRING", c->iri.query);
493 d1051bfa 2021-05-15 op fcgi_send_param(f->fd, c->id, "REMOTE_ADDR", addr);
494 d1051bfa 2021-05-15 op fcgi_send_param(f->fd, c->id, "REMOTE_HOST", addr);
495 d1051bfa 2021-05-15 op fcgi_send_param(f->fd, c->id, "REQUEST_METHOD", "");
496 d1051bfa 2021-05-15 op fcgi_send_param(f->fd, c->id, "SERVER_NAME", c->iri.host);
497 d1051bfa 2021-05-15 op fcgi_send_param(f->fd, c->id, "SERVER_PROTOCOL", "GEMINI");
498 ce2c9edb 2021-05-15 op fcgi_send_param(f->fd, c->id, "SERVER_SOFTWARE", GMID_VERSION);
499 f740b61b 2021-06-11 op
500 f740b61b 2021-06-11 op if (tls_peer_cert_provided(c->ctx)) {
501 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "AUTH_TYPE", "CERTIFICATE");
502 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "REMOTE_USER",
503 f740b61b 2021-06-11 op tls_peer_cert_subject(c->ctx));
504 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "TLS_CLIENT_ISSUER",
505 f740b61b 2021-06-11 op tls_peer_cert_issuer(c->ctx));
506 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "TLS_CLIENT_HASH",
507 f740b61b 2021-06-11 op tls_peer_cert_hash(c->ctx));
508 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "TLS_VERSION",
509 f740b61b 2021-06-11 op tls_conn_version(c->ctx));
510 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "TLS_CIPHER",
511 f740b61b 2021-06-11 op tls_conn_cipher(c->ctx));
512 8ad1c570 2021-05-09 op
513 f740b61b 2021-06-11 op snprintf(buf, sizeof(buf), "%d",
514 f740b61b 2021-06-11 op tls_conn_cipher_strength(c->ctx));
515 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "TLS_CIPHER_STRENGTH", buf);
516 f740b61b 2021-06-11 op
517 f740b61b 2021-06-11 op tim = tls_peer_cert_notbefore(c->ctx);
518 f740b61b 2021-06-11 op strftime(buf, sizeof(buf), "%FT%TZ",
519 f740b61b 2021-06-11 op gmtime_r(&tim, &tminfo));
520 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "TLS_CLIENT_NOT_BEFORE", buf);
521 f740b61b 2021-06-11 op
522 f740b61b 2021-06-11 op tim = tls_peer_cert_notafter(c->ctx);
523 f740b61b 2021-06-11 op strftime(buf, sizeof(buf), "%FT%TZ",
524 f740b61b 2021-06-11 op gmtime_r(&tim, &tminfo));
525 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "TLS_CLIENT_NOT_AFTER", buf);
526 f740b61b 2021-06-11 op
527 f740b61b 2021-06-11 op TAILQ_FOREACH(p, &c->host->params, envs) {
528 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, p->name, p->value);
529 f740b61b 2021-06-11 op }
530 f740b61b 2021-06-11 op } else
531 f740b61b 2021-06-11 op fcgi_send_param(f->fd, c->id, "AUTH_TYPE", "");
532 f740b61b 2021-06-11 op
533 8ad1c570 2021-05-09 op if (fcgi_end_param(f->fd, c->id) == -1)
534 8ad1c570 2021-05-09 op close_all(f);
535 8ad1c570 2021-05-09 op }