1 /*	$Id$ */
2 /*
3  * Copyright (c) 2015, 2016, 2020 Kristaps Dzonsons <kristaps@bsd.lv>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include "config.h"
18 
19 #include <arpa/inet.h>
20 
21 #include <assert.h>
22 #include <ctype.h>
23 #include <inttypes.h>
24 #include <stdarg.h>
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <zlib.h>
31 
32 #include "kcgi.h"
33 #include "extern.h"
34 
35 /*
36  * The state of our HTTP response.
37  * We can be in KSTATE_HEAD, where we're printing HTTP headers; or
38  * KSTATE_BODY, where we're printing the body parts.
39  * So if we try to print a header when we're supposed to be in the body,
40  * this will be caught.
41  */
42 enum	kstate {
43 	KSTATE_HEAD = 0,
44 	KSTATE_BODY
45 };
46 
47 /*
48  * Interior data.
49  * This is used for managing HTTP compression.
50  */
51 struct	kdata {
52 	int		 debugging; /* debugging flags */
53 	int		 fcgi; /* file descriptor or -1 */
54 	int		 control; /* control socket or -1 */
55 	char		 linebuf[80]; /* debugging output line buffer */
56 	size_t		 linebufpos; /* position in line buffer */
57 	uint64_t	 bytes; /* total bytes written */
58 	uint16_t	 requestId; /* current requestId or 0 */
59 	enum kstate	 state;
60 	gzFile		 gz;
61 	char		*outbuf;
62 	size_t		 outbufpos;
63 	size_t		 outbufsz;
64 	int		 disabled;
65 };
66 
67 /*
68  * A writer is allocated for use by a front-end formatter.
69  * It is basically the bridge between the back-end writer (currently
70  * operated by kdata_write) and the front-ends like kcgijson.
71  */
72 struct	kcgi_writer {
73 	struct kdata	*kdata; /* the back-end writer context */
74 	int		 type; /* currently unused */
75 };
76 
77 static char *
fcgi_header(uint8_t type,uint16_t requestId,uint16_t contentLength,uint8_t paddingLength)78 fcgi_header(uint8_t type, uint16_t requestId,
79 	uint16_t contentLength, uint8_t paddingLength)
80 {
81 	static uint8_t	header[8];
82 
83 	/* Masking probably not necessary: truncation. */
84 
85 	header[0] = 1;
86 	header[1] = type;
87 	header[2] = (requestId >> 8) & 0xff;
88 	header[3] = requestId & 0xff;
89 	header[4] = (contentLength >> 8) & 0xff;
90 	header[5] = contentLength & 0xff;
91 	header[6] = paddingLength;
92 	header[7] = 0;
93 	return((char *)header);
94 }
95 
96 /*
97  * Write a `stdout' FastCGI packet.
98  * This involves writing the header, then the data itself, then padding.
99  * Returns KCGI_OK, KCGI_SYSTEM, or KCGI_HUP.
100  */
101 static enum kcgi_err
fcgi_write(uint8_t type,const struct kdata * p,const char * buf,size_t sz)102 fcgi_write(uint8_t type, const struct kdata *p, const char *buf, size_t sz)
103 {
104 	const char	*pad = "\0\0\0\0\0\0\0\0";
105 	char		*head;
106 	size_t	 	 rsz, padlen;
107 	enum kcgi_err	 er = KCGI_OK;
108 
109 	/*
110 	 * Break up the data stream into FastCGI-capable chunks of at
111 	 * most UINT16_MAX bytes.
112 	 * Send each of these in its own FastCGI frame.
113 	 * Pad to 8-byte boundary.
114 	 */
115 
116 	do {
117 		rsz = sz > UINT16_MAX ? UINT16_MAX : sz;
118 		padlen = -rsz % 8;
119 		head = fcgi_header(type, p->requestId, rsz, padlen);
120 		if ((er = fullwritenoerr(p->fcgi, head, 8)) != KCGI_OK)
121 			break;
122 		if ((er = fullwritenoerr(p->fcgi, buf, rsz)) != KCGI_OK)
123 			break;
124 		if ((er = fullwritenoerr(p->fcgi, pad, padlen)) != KCGI_OK)
125 			break;
126 		sz -= rsz;
127 		buf += rsz;
128 	} while (sz > 0);
129 
130 	return er;
131 }
132 
133 /*
134  * Flushes a buffer "buf" of size "sz" to the wire (stdout in the case
135  * of CGI, the socket for FastCGI, and a gz stream for compression IFF
136  * in body parts).
137  * If sz is zero or buf is NULL, this is a no-op.
138  * Return zero on failure (system error writing to output) or non-zero
139  * on success.
140  */
141 static enum kcgi_err
kdata_flush(struct kdata * p,const char * buf,size_t sz)142 kdata_flush(struct kdata *p, const char *buf, size_t sz)
143 {
144 
145 	if (sz == 0 || buf == NULL)
146 		return KCGI_OK;
147 
148 	/*
149 	 * FIXME: make this work properly on all systems.
150 	 * This is known (?) to break on FreeBSD: we may need to break
151 	 * the uncompressed buffer into chunks that will not cause
152 	 * EAGAIN to be raised.
153 	 */
154 
155 	if (p->gz != NULL && p->state != KSTATE_HEAD) {
156 		if (gzwrite(p->gz, buf, sz) == 0) {
157 			kutil_warnx(NULL, NULL, "gzwrite");
158 			return KCGI_SYSTEM;
159 		}
160 		return KCGI_OK;
161 	}
162 
163 	return (p->fcgi == -1) ?
164 		fullwritenoerr(STDOUT_FILENO, buf, sz) :
165 		fcgi_write(6, p, buf, sz);
166 }
167 
168 /*
169  * Drain the output buffer with kdata_flush().
170  * Returns KCGI_OK, KCGI_SYSTEM, or KCGI_HUP.
171  * XXX: if errors occur, outbufpos is zeroed as if we wrote the data.
172  */
173 static enum kcgi_err
kdata_drain(struct kdata * p)174 kdata_drain(struct kdata *p)
175 {
176 	enum kcgi_err	 er;
177 
178 	er = kdata_flush(p, p->outbuf, p->outbufpos);
179 	p->outbufpos = 0;
180 	return er;
181 }
182 
183 /*
184  * In this function, we handle arbitrary writes of data to the output.
185  * In the event of CGI, this will be to stdout; in the event of FastCGI,
186  * this is to the wire.
187  * We want to handle buffering of output, so we maintain an output
188  * buffer that we fill and drain as needed.
189  * This will end up calling kdata_flush(), directly or indirectly.
190  * This will also handle debugging.
191  * Returns KCGI_ENOMEM if any allocation failures occur during the
192  * sequence, KCGI_SYSTEM if any errors occur writing to the output
193  * channel, KCGI_HUP on channel hangup, or KCGI_OK on success.
194  */
195 static enum kcgi_err
kdata_write(struct kdata * p,const char * buf,size_t sz)196 kdata_write(struct kdata *p, const char *buf, size_t sz)
197 {
198 	size_t	 	 i, max;
199 	int		 newln;
200 	enum kcgi_err	 er = KCGI_OK;
201 
202 	assert(p != NULL);
203 
204 	if (sz == 0 || buf == NULL)
205 		return er;
206 
207 	/*
208 	 * If we're debugging writes, first copy as many bytes as
209 	 * possible into the output line buffer, stopping when it's full
210 	 * or when we have a newline.  Keep flushing in these cases til
211 	 * we have nothing left to add.  We'll flush any stray bytes
212 	 * when we get back here or close the connection.
213 	 */
214 
215 	if (sz && (p->debugging & KREQ_DEBUG_WRITE))
216 		for (i = 0, max = sizeof(p->linebuf); i < sz; ) {
217 			newln = 0;
218 			while (i < sz && p->linebufpos < max) {
219 				p->linebuf[p->linebufpos] = buf[i++];
220 				p->bytes++;
221 				if (p->linebuf[p->linebufpos] == '\n') {
222 					newln = 1;
223 					break;
224 				}
225 				p->linebufpos++;
226 			}
227 			if (newln) {
228 				kutil_info(NULL, NULL, "%lu-tx: %.*s",
229 					(unsigned long)getpid(),
230 					(int)p->linebufpos, p->linebuf);
231 				p->linebufpos = 0;
232 			} else if (p->linebufpos == max) {
233 				kutil_info(NULL, NULL, "%lu-tx: %.*s...",
234 					(unsigned long)getpid(),
235 					(int)p->linebufpos, p->linebuf);
236 				p->linebufpos = 0;
237 			}
238 		}
239 
240 	/*
241 	 * Short-circuit: if we have no output buffer, flush directly to
242 	 * the wire.
243 	 */
244 
245 	if (p->outbufsz == 0)
246 		return kdata_flush(p, buf, sz);
247 
248 	/*
249 	 * If we want to accept new data and it exceeds the buffer size,
250 	 * push out the entire existing buffer to start.
251 	 * Then re-check if we exceed our buffer size.
252 	 * If we do, then instead of filling into the temporary buffer
253 	 * and looping until the new buffer is exhausted, just push the
254 	 * whole thing out.
255 	 * If we don't, then copy it into the buffer.
256 	 */
257 
258 	if (p->outbufpos + sz > p->outbufsz) {
259 		if ((er = kdata_drain(p)) != KCGI_OK)
260 			return er;
261 		if (sz > p->outbufsz)
262 			return kdata_flush(p, buf, sz);
263 	}
264 
265 	assert(p->outbufpos + sz <= p->outbufsz);
266 	assert(p->outbuf != NULL);
267 	memcpy(p->outbuf + p->outbufpos, buf, sz);
268 	p->outbufpos += sz;
269 	return er;
270 }
271 
272 enum kcgi_err
khttp_write(struct kreq * req,const char * buf,size_t sz)273 khttp_write(struct kreq *req, const char *buf, size_t sz)
274 {
275 
276 	assert(req->kdata != NULL);
277 	if (req->kdata->state != KSTATE_BODY)
278 		return KCGI_FORM;
279 	assert(!req->kdata->disabled);
280 
281 	/* This protects against buf == NULL or sz == 0. */
282 
283 	return kdata_write(req->kdata, buf, sz);
284 }
285 
286 enum kcgi_err
khttp_printf(struct kreq * req,const char * fmt,...)287 khttp_printf(struct kreq *req, const char *fmt, ...)
288 {
289 	char		*buf;
290 	int		 len;
291 	va_list		 ap;
292 	enum kcgi_err	 er;
293 
294 	if (fmt == NULL)
295 		return KCGI_OK;
296 
297 	va_start(ap, fmt);
298 	len = kxvasprintf(&buf, fmt, ap);
299 	va_end(ap);
300 
301 	if (len == -1)
302 		return KCGI_ENOMEM;
303 
304 	er = khttp_write(req, buf, (size_t)len);
305 	free(buf);
306 	return er;
307 }
308 
309 enum kcgi_err
khttp_puts(struct kreq * req,const char * cp)310 khttp_puts(struct kreq *req, const char *cp)
311 {
312 
313 	if (cp == NULL)
314 		return KCGI_OK;
315 	return khttp_write(req, cp, strlen(cp));
316 }
317 
318 enum kcgi_err
khttp_putc(struct kreq * req,int c)319 khttp_putc(struct kreq *req, int c)
320 {
321 	unsigned char	cc = c;
322 
323 	return khttp_write(req, (char *)&cc, 1);
324 }
325 
326 enum kcgi_err
khttp_head(struct kreq * req,const char * key,const char * fmt,...)327 khttp_head(struct kreq *req, const char *key, const char *fmt, ...)
328 {
329 	va_list		 ap;
330 	char		*buf;
331 	size_t		 ksz;
332 	int		 len;
333 	enum kcgi_err	 er;
334 
335 	assert(req->kdata != NULL);
336 	assert(req->kdata->state == KSTATE_HEAD);
337 
338 	va_start(ap, fmt);
339 	len = kxvasprintf(&buf, fmt, ap);
340 	va_end(ap);
341 
342 	if (len == -1)
343 		return KCGI_ENOMEM;
344 
345 	ksz = strlen(key);
346 	if ((er = kdata_write(req->kdata, key, ksz)) != KCGI_OK)
347 		goto out;
348 	if ((er = kdata_write(req->kdata, ": ", 2)) != KCGI_OK)
349 		goto out;
350 	if ((er = kdata_write(req->kdata, buf, len)) != KCGI_OK)
351 		goto out;
352 	if ((er = kdata_write(req->kdata, "\r\n", 2)) != KCGI_OK)
353 		goto out;
354 out:
355 	free(buf);
356 	return er;
357 }
358 
359 /*
360  * Allocate our output data.
361  * We accept the file descriptor for the FastCGI stream, if there's any.
362  */
363 struct kdata *
kdata_alloc(int control,int fcgi,uint16_t requestId,unsigned int debugging,const struct kopts * opts)364 kdata_alloc(int control, int fcgi, uint16_t requestId,
365 	unsigned int debugging, const struct kopts *opts)
366 {
367 	struct kdata	*p;
368 
369 	if ((p = kxcalloc(1, sizeof(struct kdata))) == NULL)
370 		return NULL;
371 
372 	p->debugging = debugging;
373 	p->fcgi = fcgi;
374 	p->control = control;
375 	p->requestId = requestId;
376 
377 	if (opts->sndbufsz > 0) {
378 		p->outbufsz = opts->sndbufsz;
379 		if ((p->outbuf = kxmalloc(p->outbufsz)) == NULL) {
380 			free(p);
381 			return NULL;
382 		}
383 	}
384 
385 	return p;
386 }
387 
388 /*
389  * Two ways of doing this: with or without "flush".
390  * If we're flushing, then we drain our output buffers to the output.
391  * Either way, we then release all of our internal memory.
392  */
393 void
kdata_free(struct kdata * p,int flush)394 kdata_free(struct kdata *p, int flush)
395 {
396 	char	 	 buf[8];
397 	uint32_t 	 appStatus;
398 
399 	if (p == NULL)
400 		return;
401 
402 	/* Debugging messages. */
403 
404 	if (flush && (p->debugging & KREQ_DEBUG_WRITE)) {
405 		if (p->linebufpos)
406 			kutil_info(NULL, NULL, "%lu-tx: %.*s",
407 				(unsigned long)getpid(),
408 				(int)p->linebufpos, p->linebuf);
409 		p->linebufpos = 0;
410 		kutil_info(NULL, NULL, "%lu-tx: %" PRIu64 " B",
411 			(unsigned long)getpid(), p->bytes);
412 	}
413 
414 	/* Remaining buffered data. */
415 
416 	if (flush)
417 		kdata_drain(p);
418 
419 	free(p->outbuf);
420 
421 	/*
422 	 * If we're not FastCGI and we're not going to flush, then close
423 	 * the file descriptors outright: we don't want gzclose()
424 	 * flushing anything to the wire.
425 	 */
426 
427 	if (!flush && p->fcgi == -1) {
428 		close(STDOUT_FILENO);
429 		close(STDIN_FILENO);
430 	}
431 
432 	if (p->gz != NULL)
433 		gzclose(p->gz);
434 
435 	if (p->fcgi == -1) {
436 		free(p);
437 		return;
438 	}
439 
440 	/*
441 	 * If flushing, end the stream.
442 	 * Note that we've already flushed our last FastCGI record to
443 	 * the stream, but the standard implies that we need a blank
444 	 * record to really shut this thing down.
445 	 */
446 
447 	if (flush) {
448 		fcgi_write(6, p, "", 0);
449 		appStatus = htonl(EXIT_SUCCESS);
450 		memset(buf, 0, 8);
451 		memcpy(buf, &appStatus, sizeof(uint32_t));
452 
453 		/* End of request. */
454 
455 		fcgi_write(3, p, buf, 8);
456 
457 		/* Close out. */
458 
459 		close(p->fcgi);
460 		fullwrite(p->control, &p->requestId, sizeof(uint16_t));
461 	} else
462 		close(p->fcgi);
463 
464 	free(p);
465 }
466 
467 /*
468  * Try to enable compression on the output stream itself.
469  * This function is only available with zlib.
470  * We disallow compression on FastCGI streams because I don't yet have
471  * the structure in place to copy the compressed data into a buffer then
472  * write that out.
473  * Set "ret" to zero if compression is not enabled, non-zero if enabled.
474  * Returns zero if allocation errors occured (via gzdopen(3)), non-zero
475  * otherwise.
476  * On failure, "ret" is always zero.
477  */
478 static int
kdata_compress(struct kdata * p,int * ret)479 kdata_compress(struct kdata *p, int *ret)
480 {
481 
482 	*ret = 0;
483 	assert(p->state == KSTATE_HEAD);
484 
485 	if (p->fcgi != -1)
486 		return 1;
487 
488 	assert(p->gz == NULL);
489 	if ((p->gz = gzdopen(STDOUT_FILENO, "w")) == NULL) {
490 		kutil_warn(NULL, NULL, "gzdopen");
491 		return 0;
492 	}
493 	*ret = 1;
494 	return 1;
495 }
496 
497 /*
498  * Begin the body sequence by draining the headers to the wire and
499  * marking that the body has begun.
500  * Returns KCGI_OK on success, KCGI_ENOMEM on memory exhaustion, and
501  * KCGI_SYSTEM on wire-writing failure.
502  */
503 static enum kcgi_err
kdata_body(struct kdata * p)504 kdata_body(struct kdata *p)
505 {
506 	enum kcgi_err	 er;
507 
508 	assert(p->state == KSTATE_HEAD);
509 
510 	if ((er = kdata_write(p, "\r\n", 2)) != KCGI_OK)
511 		return er;
512 
513 	/*
514 	 * XXX: we always drain our buffer after the headers have been
515 	 * written.
516 	 * This incurs more chat on the wire, but also ensures that our
517 	 * response gets to the server as quickly as possible.
518 	 * Should an option be added to disable this?
519 	 */
520 
521 	if ((er = kdata_drain(p)) != KCGI_OK)
522 		return er;
523 
524 	if (p->fcgi == -1)
525 		if (fflush(stdout) != 0) {
526 			kutil_warn(NULL, NULL, "fflush");
527 			return KCGI_SYSTEM;
528 		}
529 
530 	p->state = KSTATE_BODY;
531 	return KCGI_OK;
532 }
533 
534 enum kcgi_err
khttp_body(struct kreq * req)535 khttp_body(struct kreq *req)
536 {
537 	int	 	 hasreq = 0;
538 	enum kcgi_err	 er;
539 	const char	*cp;
540 
541 	/*
542 	 * First determine if the request wants HTTP compression.
543 	 * Use RFC 2616 14.3 as a guide for checking this: if we have
544 	 * the "gzip" accept encoding and a non-zero quality, then use
545 	 * compression.
546 	 */
547 
548 	if (req->reqmap[KREQU_ACCEPT_ENCODING] != NULL) {
549 		cp = req->reqmap[KREQU_ACCEPT_ENCODING]->val;
550 		if ((cp = strstr(cp, "gzip")) != NULL) {
551 			hasreq = 1;
552 			cp += 4;
553 			if (strncmp(cp, ";q=0", 4) == 0)
554 				hasreq = '.' == cp[4];
555 		}
556 	}
557 
558 	/*
559 	 * Note: the underlying writing functions will not do any
560 	 * compression even if we have compression enabled when in
561 	 * header mode, so the order of these operations (enable
562 	 * compression then write headers) is ok.
563 	 */
564 
565 	if (hasreq) {
566 		/*
567 		 * We could just ignore this error, which means gzdopen
568 		 * failed, and just continue with hasreq=0.
569 		 * However, if gzdopen fails (memory allocation), it
570 		 * probably means other things are going to fail, so we
571 		 * might as well just die now.
572 		 */
573 
574 		if (!kdata_compress(req->kdata, &hasreq))
575 			return KCGI_ENOMEM;
576 		if (hasreq) {
577 			er = khttp_head(req,
578 				kresps[KRESP_CONTENT_ENCODING], "gzip");
579 			if (er != KCGI_OK)
580 				return er;
581 		}
582 	}
583 
584 	return kdata_body(req->kdata);
585 }
586 
587 enum kcgi_err
khttp_body_compress(struct kreq * req,int comp)588 khttp_body_compress(struct kreq *req, int comp)
589 {
590 	int	 didcomp;
591 
592 	/*
593 	 * First, if we didn't request compression, go directly into the
594 	 * body of the document.
595 	 */
596 
597 	if (!comp)
598 		return kdata_body(req->kdata);
599 
600 	/*
601 	 * If we do have compression requested, try enabling it on the
602 	 * output stream.
603 	 */
604 
605 	if (!kdata_compress(req->kdata, &didcomp))
606 		return KCGI_ENOMEM;
607 	else if (!didcomp)
608 		return KCGI_FORM;
609 
610 	return kdata_body(req->kdata);
611 }
612 
613 /*
614  * Allocate a writer.
615  * This only works if we haven't disabled allocation of writers yet via
616  * kcgi_writer_disable(), otherwise we abort().
617  * Returns the writer or NULL on allocation (memory) failure.
618  */
619 struct kcgi_writer *
kcgi_writer_get(struct kreq * r,int type)620 kcgi_writer_get(struct kreq *r, int type)
621 {
622 	struct kcgi_writer	*p;
623 
624 	if (r->kdata->disabled) {
625 		kutil_warnx(NULL, NULL,
626 			"kcgi_writer_get after kcgi_writer_disable");
627 		abort();
628 	}
629 
630 	if ((p = kxmalloc(sizeof(struct kcgi_writer))) != NULL)
631 		p->kdata = r->kdata;
632 
633 	return p;
634 }
635 
636 /*
637  * Disable further allocation of writers with kcgi_writer_get().
638  * Following this, kcgi_writer_get() will abort.
639  * This may be called as many times as desired: only the first time
640  * makes a difference.
641  */
642 void
kcgi_writer_disable(struct kreq * r)643 kcgi_writer_disable(struct kreq *r)
644 {
645 
646 	r->kdata->disabled = 1;
647 }
648 
649 /*
650  * Release an allocation by kcgi_writer_get().
651  * May be called with a NULL-valued "p".
652  */
653 void
kcgi_writer_free(struct kcgi_writer * p)654 kcgi_writer_free(struct kcgi_writer *p)
655 {
656 
657 	free(p);
658 }
659 
660 /*
661  * Write "sz" bytes of "buf" into the output.
662  * This doesn't necessarily mean that the output has been written: it
663  * may be further buffered.
664  * Returns KCGI_OK, KCGI_ENOMEM, or KCGI_SYSTEM.
665  */
666 enum kcgi_err
kcgi_writer_write(struct kcgi_writer * p,const void * buf,size_t sz)667 kcgi_writer_write(struct kcgi_writer *p, const void *buf, size_t sz)
668 {
669 
670 	if (p->kdata->state != KSTATE_BODY)
671 		return KCGI_FORM;
672 	return kdata_write(p->kdata, buf, sz);
673 }
674 
675 /*
676  * Like kcgi_writer_write but for the NUL-terminated string.
677  */
678 enum kcgi_err
kcgi_writer_puts(struct kcgi_writer * p,const char * cp)679 kcgi_writer_puts(struct kcgi_writer *p, const char *cp)
680 {
681 
682 	return kcgi_writer_write(p, cp, strlen(cp));
683 }
684 
685 /*
686  * Like kcgi_writer_write but for a single character.
687  */
688 enum kcgi_err
kcgi_writer_putc(struct kcgi_writer * p,char c)689 kcgi_writer_putc(struct kcgi_writer *p, char c)
690 {
691 
692 	return kcgi_writer_write(p, &c, 1);
693 }
694