2 8ad1c570 2021-05-09 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
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.
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.
17 8ad1c570 2021-05-09 op #include "gmid.h"
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>
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.
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
31 8ad1c570 2021-05-09 op * rm -f debug.sock ; nc -Ulk ./debug.sock | hexdump -C
33 8ad1c570 2021-05-09 op * NB: the sandbox must be disabled for this to work.
35 8ad1c570 2021-05-09 op #define DEBUG_FCGI 0
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;
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;
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.
57 8ad1c570 2021-05-09 op #define FCGI_HEADER_LEN 8
60 8ad1c570 2021-05-09 op * values for the version component
62 8ad1c570 2021-05-09 op #define FCGI_VERSION_1 1
65 8ad1c570 2021-05-09 op * values for the type component
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)
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];
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;
93 8ad1c570 2021-05-09 op * mask for flags;
95 8ad1c570 2021-05-09 op #define FCGI_KEEP_CONN 1
98 8ad1c570 2021-05-09 op * values for the role
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
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];
114 8ad1c570 2021-05-09 op * values for proto_status
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
122 8ad1c570 2021-05-09 op * Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT
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"
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)
133 8ad1c570 2021-05-09 op memset(h, 0, sizeof(*h));
136 8ad1c570 2021-05-09 op * id=0 is reserved for status messages.
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;
152 741b69be 2021-09-26 op fcgi_begin_request(struct bufferevent *bev, int id)
154 8ad1c570 2021-05-09 op struct fcgi_begin_req_record r;
156 8ad1c570 2021-05-09 op if (id > UINT16_MAX)
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);
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;
168 741b69be 2021-09-26 op if (bufferevent_write(bev, &r, sizeof(r)) == -1)
174 741b69be 2021-09-26 op fcgi_send_param(struct bufferevent *bev, int id, const char *name,
175 741b69be 2021-09-26 op const char *value)
177 8ad1c570 2021-05-09 op struct fcgi_header h;
178 8ad1c570 2021-05-09 op uint32_t namlen, vallen, padlen;
179 8ad1c570 2021-05-09 op uint8_t s[8];
181 8ad1c570 2021-05-09 op char padding[8] = { 0 };
183 8ad1c570 2021-05-09 op namlen = strlen(name);
184 8ad1c570 2021-05-09 op vallen = strlen(value);
185 8ad1c570 2021-05-09 op size = namlen + vallen + 8; /* 4 for the sizes */
186 8ad1c570 2021-05-09 op padlen = (8 - (size & 0x7)) & 0x7;
188 8ad1c570 2021-05-09 op s[0] = ( namlen >> 24) | 0x80;
189 8ad1c570 2021-05-09 op s[1] = ((namlen >> 16) & 0xFF);
190 8ad1c570 2021-05-09 op s[2] = ((namlen >> 8) & 0xFF);
191 8ad1c570 2021-05-09 op s[3] = ( namlen & 0xFF);
193 8ad1c570 2021-05-09 op s[4] = ( vallen >> 24) | 0x80;
194 8ad1c570 2021-05-09 op s[5] = ((vallen >> 16) & 0xFF);
195 8ad1c570 2021-05-09 op s[6] = ((vallen >> 8) & 0xFF);
196 8ad1c570 2021-05-09 op s[7] = ( vallen & 0xFF);
198 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_PARAMS, id, size, padlen);
200 741b69be 2021-09-26 op if (bufferevent_write(bev, &h, sizeof(h)) == -1 ||
201 741b69be 2021-09-26 op bufferevent_write(bev, s, sizeof(s)) == -1 ||
202 741b69be 2021-09-26 op bufferevent_write(bev, name, namlen) == -1 ||
203 741b69be 2021-09-26 op bufferevent_write(bev, value, vallen) == -1 ||
204 741b69be 2021-09-26 op bufferevent_write(bev, padding, padlen) == -1)
211 741b69be 2021-09-26 op fcgi_end_param(struct bufferevent *bev, int id)
213 8ad1c570 2021-05-09 op struct fcgi_header h;
215 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_PARAMS, id, 0, 0);
216 741b69be 2021-09-26 op if (bufferevent_write(bev, &h, sizeof(h)) == -1)
219 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_STDIN, id, 0, 0);
220 741b69be 2021-09-26 op if (bufferevent_write(bev, &h, sizeof(h)) == -1)
227 741b69be 2021-09-26 op fcgi_abort_request(struct bufferevent *bev, int id)
229 8ad1c570 2021-05-09 op struct fcgi_header h;
231 8ad1c570 2021-05-09 op prepare_header(&h, FCGI_ABORT_REQUEST, id, 0, 0);
232 741b69be 2021-09-26 op if (bufferevent_write(bev, &h, sizeof(h)) == -1)
238 8ad1c570 2021-05-09 op static inline int
239 8ad1c570 2021-05-09 op recid(struct fcgi_header *h)
241 8ad1c570 2021-05-09 op return h->req_id0 + (h->req_id1 << 8) - 1;
244 8ad1c570 2021-05-09 op static inline int
245 8ad1c570 2021-05-09 op reclen(struct fcgi_header *h)
247 8ad1c570 2021-05-09 op return h->content_len0 + (h->content_len1 << 8);
251 8ad1c570 2021-05-09 op copy_mbuf(int fd, short ev, void *d)
253 8ad1c570 2021-05-09 op struct client *c = d;
254 8ad1c570 2021-05-09 op struct mbuf *mbuf;
260 8ad1c570 2021-05-09 op mbuf = TAILQ_FIRST(&c->mbufhead);
261 8ad1c570 2021-05-09 op if (mbuf == NULL)
264 8ad1c570 2021-05-09 op len = mbuf->len - mbuf->off;
265 8ad1c570 2021-05-09 op data = mbuf->data + mbuf->off;
266 8ad1c570 2021-05-09 op switch (r = tls_write(c->ctx, data, len)) {
269 8ad1c570 2021-05-09 op * Can't close_conn here. The application
270 8ad1c570 2021-05-09 op * needs to be informed first, otherwise it
271 8ad1c570 2021-05-09 op * can interfere with future connections.
272 8ad1c570 2021-05-09 op * Check also that we're not doing recursion
273 8ad1c570 2021-05-09 op * (copy_mbuf -> handle_fcgi -> copy_mbuf ...)
275 8ad1c570 2021-05-09 op if (c->next != NULL)
277 8ad1c570 2021-05-09 op fcgi_abort_request(0, c->id);
279 8ad1c570 2021-05-09 op case TLS_WANT_POLLIN:
280 8ad1c570 2021-05-09 op event_once(c->fd, EV_READ, ©_mbuf, c, NULL);
282 8ad1c570 2021-05-09 op case TLS_WANT_POLLOUT:
283 8ad1c570 2021-05-09 op event_once(c->fd, EV_WRITE, ©_mbuf, c, NULL);
286 8ad1c570 2021-05-09 op mbuf->off += r;
288 8ad1c570 2021-05-09 op if (mbuf->off == mbuf->len) {
289 8ad1c570 2021-05-09 op TAILQ_REMOVE(&c->mbufhead, mbuf, mbufs);
295 8ad1c570 2021-05-09 op if (c->next != NULL)
296 8ad1c570 2021-05-09 op c->next(0, 0, c);
300 090b8a89 2021-07-06 op fcgi_close_backend(struct fcgi *f)
302 741b69be 2021-09-26 op bufferevent_free(f->bev);
303 741b69be 2021-09-26 op f->bev = NULL;
304 741b69be 2021-09-26 op close(fcgi->fd);
305 741b69be 2021-09-26 op fcgi->fd = -1;
306 741b69be 2021-09-26 op fcgi->pending = 0;
307 741b69be 2021-09-26 op fcgi->s = FCGI_OFF;
311 741b69be 2021-09-26 op fcgi_read(struct bufferevent *bev, void *d)
313 741b69be 2021-09-26 op struct fcgi *fcgi = d;
314 741b69be 2021-09-26 op struct evbuffer *src = EVBUFFER_INPUT(bev);
315 741b69be 2021-09-26 op struct fcgi_header hdr;
316 8ad1c570 2021-05-09 op struct fcgi_end_req_body end;
317 8ad1c570 2021-05-09 op struct client *c;
318 8ad1c570 2021-05-09 op struct mbuf *mbuf;
321 741b69be 2021-09-26 op #if DEBUG_FCGI
322 741b69be 2021-09-26 op if (debug_socket == -1) {
323 741b69be 2021-09-26 op struct sockaddr_un addr;
325 741b69be 2021-09-26 op if ((debug_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
326 741b69be 2021-09-26 op err(1, "socket");
328 741b69be 2021-09-26 op memset(&addr, 0, sizeof(addr));
329 741b69be 2021-09-26 op addr.sun_family = AF_UNIX;
330 741b69be 2021-09-26 op strlcpy(addr.sun_path, "./debug.sock", sizeof(addr.sun_path));
331 741b69be 2021-09-26 op if (connect(debug_socket, (struct sockaddr*)&addr, sizeof(addr))
333 741b69be 2021-09-26 op err(1, "connect");
338 741b69be 2021-09-26 op if (EVBUFFER_LENGTH(src) < sizeof(hdr))
341 741b69be 2021-09-26 op memcpy(&hdr, EVBUFFER_DATA(src), sizeof(hdr));
343 741b69be 2021-09-26 op c = try_client_by_id(recid(&hdr));
344 741b69be 2021-09-26 op if (c == NULL) {
345 741b69be 2021-09-26 op log_err(NULL,
346 741b69be 2021-09-26 op "got invalid client id from fcgi backend %d",
347 741b69be 2021-09-26 op recid(&hdr));
351 741b69be 2021-09-26 op len = reclen(&hdr);
353 741b69be 2021-09-26 op if (EVBUFFER_LENGTH(src) < sizeof(hdr) + len + hdr.padding)
356 741b69be 2021-09-26 op #if DEBUG_FCGI
357 c016b65c 2021-10-02 op write(debug_socket, EVBUFFER_DATA(src),
358 741b69be 2021-09-26 op sizeof(hdr) + len + hdr.padding);
361 741b69be 2021-09-26 op evbuffer_drain(src, sizeof(hdr));
363 741b69be 2021-09-26 op switch (hdr.type) {
364 741b69be 2021-09-26 op case FCGI_END_REQUEST:
365 741b69be 2021-09-26 op if (len != sizeof(end)) {
366 741b69be 2021-09-26 op log_err(NULL,
367 741b69be 2021-09-26 op "got invalid end request record size");
370 741b69be 2021-09-26 op bufferevent_read(bev, &end, sizeof(end));
372 741b69be 2021-09-26 op /* TODO: do something with the status? */
373 741b69be 2021-09-26 op fcgi->pending--;
374 741b69be 2021-09-26 op c->fcgi = -1;
375 741b69be 2021-09-26 op c->next = close_conn;
376 8ad1c570 2021-05-09 op event_once(c->fd, EV_WRITE, ©_mbuf, c, NULL);
379 741b69be 2021-09-26 op case FCGI_STDERR:
380 741b69be 2021-09-26 op /* discard stderr (for now) */
381 741b69be 2021-09-26 op evbuffer_drain(src, len);
384 741b69be 2021-09-26 op case FCGI_STDOUT:
385 741b69be 2021-09-26 op if ((mbuf = calloc(1, sizeof(*mbuf) + len)) == NULL)
386 741b69be 2021-09-26 op fatal("calloc");
387 741b69be 2021-09-26 op mbuf->len = len;
388 741b69be 2021-09-26 op bufferevent_read(bev, mbuf->data, len);
390 741b69be 2021-09-26 op if (TAILQ_EMPTY(&c->mbufhead))
391 741b69be 2021-09-26 op event_once(c->fd, EV_WRITE, ©_mbuf,
394 8ad1c570 2021-05-09 op TAILQ_INSERT_TAIL(&c->mbufhead, mbuf, mbufs);
398 741b69be 2021-09-26 op log_err(NULL, "got invalid fcgi record (type=%d)",
403 741b69be 2021-09-26 op evbuffer_drain(src, hdr.padding);
405 741b69be 2021-09-26 op if (fcgi->pending == 0 && shutting_down) {
406 741b69be 2021-09-26 op fcgi_error(bev, EVBUFFER_EOF, fcgi);
412 741b69be 2021-09-26 op fcgi_error(bev, EVBUFFER_ERROR, fcgi);
416 741b69be 2021-09-26 op fcgi_write(struct bufferevent *bev, void *d)
419 741b69be 2021-09-26 op * There's no much use for the write callback.
425 741b69be 2021-09-26 op fcgi_error(struct bufferevent *bev, short err, void *d)
427 741b69be 2021-09-26 op struct fcgi *fcgi = d;
428 741b69be 2021-09-26 op struct client *c;
431 741b69be 2021-09-26 op if (!(err & EVBUFFER_ERROR) ||
432 741b69be 2021-09-26 op !(err & EVBUFFER_EOF))
433 741b69be 2021-09-26 op log_warn(NULL, "unknown event error (%x)",
436 741b69be 2021-09-26 op for (i = 0; i < MAX_USERS; ++i) {
437 741b69be 2021-09-26 op c = &clients[i];
439 741b69be 2021-09-26 op if (c->fcgi != fcgi->id)
442 741b69be 2021-09-26 op if (c->code != 0)
443 741b69be 2021-09-26 op close_conn(0, 0, 0);
445 741b69be 2021-09-26 op start_reply(c, CGI_ERROR, "CGI error");
448 741b69be 2021-09-26 op fcgi_close_backend(fcgi);
452 741b69be 2021-09-26 op fcgi_req(struct fcgi *f, struct client *c)
454 f740b61b 2021-06-11 op char addr[NI_MAXHOST], buf[22];
457 f740b61b 2021-06-11 op struct tm tminfo;
458 f740b61b 2021-06-11 op struct envlist *p;
460 090b8a89 2021-07-06 op f->pending++;
462 59c7ee13 2021-07-06 op e = getnameinfo((struct sockaddr*)&c->addr, sizeof(c->addr),
463 d1051bfa 2021-05-15 op addr, sizeof(addr),
465 d1051bfa 2021-05-15 op NI_NUMERICHOST);
467 d1051bfa 2021-05-15 op fatal("getnameinfo failed");
469 8ad1c570 2021-05-09 op c->next = NULL;
471 741b69be 2021-09-26 op fcgi_begin_request(f->bev, c->id);
472 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "GATEWAY_INTERFACE", "CGI/1.1");
473 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "GEMINI_URL_PATH", c->iri.path);
474 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "QUERY_STRING", c->iri.query);
475 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "REMOTE_ADDR", addr);
476 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "REMOTE_HOST", addr);
477 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "REQUEST_METHOD", "");
478 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "SERVER_NAME", c->iri.host);
479 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "SERVER_PROTOCOL", "GEMINI");
480 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "SERVER_SOFTWARE", GMID_VERSION);
482 f740b61b 2021-06-11 op if (tls_peer_cert_provided(c->ctx)) {
483 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "AUTH_TYPE", "CERTIFICATE");
484 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "REMOTE_USER",
485 f740b61b 2021-06-11 op tls_peer_cert_subject(c->ctx));
486 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "TLS_CLIENT_ISSUER",
487 f740b61b 2021-06-11 op tls_peer_cert_issuer(c->ctx));
488 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "TLS_CLIENT_HASH",
489 f740b61b 2021-06-11 op tls_peer_cert_hash(c->ctx));
490 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "TLS_VERSION",
491 f740b61b 2021-06-11 op tls_conn_version(c->ctx));
492 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "TLS_CIPHER",
493 f740b61b 2021-06-11 op tls_conn_cipher(c->ctx));
495 f740b61b 2021-06-11 op snprintf(buf, sizeof(buf), "%d",
496 f740b61b 2021-06-11 op tls_conn_cipher_strength(c->ctx));
497 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "TLS_CIPHER_STRENGTH", buf);
499 f740b61b 2021-06-11 op tim = tls_peer_cert_notbefore(c->ctx);
500 f740b61b 2021-06-11 op strftime(buf, sizeof(buf), "%FT%TZ",
501 f740b61b 2021-06-11 op gmtime_r(&tim, &tminfo));
502 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "TLS_CLIENT_NOT_BEFORE", buf);
504 f740b61b 2021-06-11 op tim = tls_peer_cert_notafter(c->ctx);
505 f740b61b 2021-06-11 op strftime(buf, sizeof(buf), "%FT%TZ",
506 f740b61b 2021-06-11 op gmtime_r(&tim, &tminfo));
507 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "TLS_CLIENT_NOT_AFTER", buf);
509 f740b61b 2021-06-11 op TAILQ_FOREACH(p, &c->host->params, envs) {
510 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, p->name, p->value);
513 741b69be 2021-09-26 op fcgi_send_param(f->bev, c->id, "AUTH_TYPE", "");
515 741b69be 2021-09-26 op if (fcgi_end_param(f->bev, c->id) == -1)
516 741b69be 2021-09-26 op fcgi_error(f->bev, EVBUFFER_ERROR, f);