1 /*-
2  * Copyright (c) 2006 Verdens Gang AS
3  * Copyright (c) 2006-2015 Varnish Software AS
4  * All rights reserved.
5  *
6  * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7  *
8  * SPDX-License-Identifier: BSD-2-Clause
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * Runtime support for compiled VCL programs
32  */
33 
34 #include "config.h"
35 
36 #include <stdlib.h>
37 
38 #include "cache_varnishd.h"
39 
40 #include "cache_objhead.h"
41 #include "vav.h"
42 #include "vcl.h"
43 #include "vct.h"
44 #include "venc.h"
45 #include "vend.h"
46 #include "vrt_obj.h"
47 #include "vsa.h"
48 #include "vsha256.h"
49 #include "vtcp.h"
50 #include "vtim.h"
51 #include "vcc_interface.h"
52 
53 #include "common/heritage.h"
54 #include "common/vsmw.h"
55 #include "proxy/cache_proxy.h"
56 
57 const void * const vrt_magic_string_end = &vrt_magic_string_end;
58 const void * const vrt_magic_string_unset = &vrt_magic_string_unset;
59 
60 /*--------------------------------------------------------------------*/
61 
62 VCL_VOID
VRT_synth(VRT_CTX,VCL_INT code,VCL_STRING reason)63 VRT_synth(VRT_CTX, VCL_INT code, VCL_STRING reason)
64 {
65 	const char *ret;
66 
67 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
68 	assert(ctx->req != NULL || ctx->bo != NULL);
69 
70 	ret = ctx->req == NULL ? "error" : "synth";
71 	if (code < 0) {
72 		VRT_fail(ctx, "return(%s()) status code (%jd) is negative",
73 		    ret, (intmax_t)code);
74 		return;
75 	}
76 	if (code > 65535) {
77 		VRT_fail(ctx, "return(%s()) status code (%jd) > 65535",
78 		    ret, (intmax_t)code);
79 		return;
80 	}
81 	if ((code % 1000) < 100) {
82 		VRT_fail(ctx,
83 		    "illegal return(%s()) status code (%jd) (..0##)",
84 		    ret, (intmax_t)code);
85 		return;
86 	}
87 
88 	if (reason && !WS_Inside(ctx->ws, reason, NULL)) {
89 		reason = WS_Copy(ctx->ws, reason, -1);
90 		if (!reason) {
91 			VRT_fail(ctx, "Workspace overflow");
92 			return;
93 		}
94 	}
95 
96 	if (ctx->req == NULL) {
97 		CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
98 		ctx->bo->err_code = (uint16_t)code;
99 		ctx->bo->err_reason = reason ? reason
100 		    : http_Status2Reason(ctx->bo->err_code % 1000, NULL);
101 		return;
102 	}
103 
104 	ctx->req->err_code = (uint16_t)code;
105 	ctx->req->err_reason = reason ? reason
106 	    : http_Status2Reason(ctx->req->err_code % 1000, NULL);
107 }
108 
109 /*--------------------------------------------------------------------*/
110 
111 void
VPI_acl_log(VRT_CTX,const char * msg)112 VPI_acl_log(VRT_CTX, const char *msg)
113 {
114 
115 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
116 	AN(msg);
117 	if (ctx->vsl != NULL)
118 		VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg);
119 	else
120 		VSL(SLT_VCL_acl, 0, "%s", msg);
121 }
122 
123 int
VRT_acl_match(VRT_CTX,VCL_ACL acl,VCL_IP ip)124 VRT_acl_match(VRT_CTX, VCL_ACL acl, VCL_IP ip)
125 {
126 
127 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
128 	CHECK_OBJ_NOTNULL(acl, VRT_ACL_MAGIC);
129 	if (ip == NULL) {
130 		VRT_fail(ctx, "Cannot match a null IP address");
131 		return (0);
132 	}
133 	assert(VSA_Sane(ip));
134 	return (acl->match(ctx, ip));
135 }
136 
137 /*--------------------------------------------------------------------*/
138 
139 VCL_VOID
VRT_hit_for_pass(VRT_CTX,VCL_DURATION d)140 VRT_hit_for_pass(VRT_CTX, VCL_DURATION d)
141 {
142 	struct objcore *oc;
143 
144 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
145 	if (ctx->bo == NULL) {
146 		VSLb(ctx->vsl, SLT_Error,
147 		    "Note: Ignoring DURATION argument to return(pass);");
148 		return;
149 	}
150 	CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
151 	oc = ctx->bo->fetch_objcore;
152 	oc->ttl = d;
153 	oc->grace = 0.0;
154 	oc->keep = 0.0;
155 	VSLb(ctx->vsl, SLT_TTL, "HFP %.0f %.0f %.0f %.0f uncacheable",
156 	    oc->ttl, oc->grace, oc->keep, oc->t_origin);
157 }
158 
159 /*--------------------------------------------------------------------*/
160 
161 VCL_HTTP
VRT_selecthttp(VRT_CTX,enum gethdr_e where)162 VRT_selecthttp(VRT_CTX, enum gethdr_e where)
163 {
164 	VCL_HTTP hp;
165 
166 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
167 	switch (where) {
168 	case HDR_REQ:
169 		hp = ctx->http_req;
170 		break;
171 	case HDR_REQ_TOP:
172 		hp = ctx->http_req_top;
173 		break;
174 	case HDR_BEREQ:
175 		hp = ctx->http_bereq;
176 		break;
177 	case HDR_BERESP:
178 		hp = ctx->http_beresp;
179 		break;
180 	case HDR_RESP:
181 		hp = ctx->http_resp;
182 		break;
183 	default:
184 		WRONG("VRT_selecthttp 'where' invalid");
185 	}
186 	return (hp);
187 }
188 
189 /*--------------------------------------------------------------------*/
190 
191 VCL_STRING
VRT_GetHdr(VRT_CTX,VCL_HEADER hs)192 VRT_GetHdr(VRT_CTX, VCL_HEADER hs)
193 {
194 	VCL_HTTP hp;
195 	const char *p;
196 
197 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
198 	if (hs->where == HDR_OBJ) {
199 		CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
200 		CHECK_OBJ_NOTNULL(ctx->req->objcore, OBJCORE_MAGIC);
201 		return (HTTP_GetHdrPack(ctx->req->wrk, ctx->req->objcore,
202 		    hs->what));
203 	}
204 	hp = VRT_selecthttp(ctx, hs->where);
205 	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
206 	if (!http_GetHdr(hp, hs->what, &p))
207 		return (NULL);
208 	return (p);
209 }
210 
211 /*--------------------------------------------------------------------
212  * Alloc Strands with space for n elements on workspace
213  *
214  * Error handling is deliberately left to the caller
215  */
216 
217 struct strands *
VRT_AllocStrandsWS(struct ws * ws,int n)218 VRT_AllocStrandsWS(struct ws *ws, int n)
219 {
220 	struct strands *s;
221 	const char **p;
222 
223 	s = WS_Alloc(ws, sizeof *s);
224 	p = WS_Alloc(ws, n * sizeof *p);
225 
226 	if (s == NULL || p == NULL)
227 		return (NULL);
228 
229 	s->n = n;
230 	s->p = p;
231 
232 	return (s);
233 }
234 
235 /*--------------------------------------------------------------------
236  * Compare two STRANDS
237  */
238 
239 int
VRT_CompareStrands(VCL_STRANDS a,VCL_STRANDS b)240 VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b)
241 {
242 	const char *pa = NULL, *pb = NULL;
243 	int na = 0, nb = 0;
244 
245 	while (1) {
246 		if (pa != NULL && *pa == '\0')
247 			pa = NULL;
248 		if (pb != NULL && *pb == '\0')
249 			pb = NULL;
250 		if (pa == NULL && na < a->n)
251 			pa = a->p[na++];
252 		else if (pb == NULL && nb < b->n)
253 			pb = b->p[nb++];
254 		else if (pa == NULL && pb == NULL)
255 			return (0);
256 		else if (pa == NULL)
257 			return (-1);
258 		else if (pb == NULL)
259 			return (1);
260 		else if (*pa == '\0')
261 			pa = NULL;
262 		else if (*pb == '\0')
263 			pb = NULL;
264 		else if (*pa != *pb)
265 			return (*pa - *pb);
266 		else {
267 			pa++;
268 			pb++;
269 		}
270 	}
271 }
272 
273 /*--------------------------------------------------------------------
274  * STRANDS to BOOL
275  */
276 
277 VCL_BOOL
VRT_Strands2Bool(VCL_STRANDS s)278 VRT_Strands2Bool(VCL_STRANDS s)
279 {
280 	int i;
281 
282 	AN(s);
283 	for (i = 0; i < s->n; i++)
284 		if (s->p[i] != NULL)
285 			return (1);
286 	return (0);
287 }
288 
289 /*--------------------------------------------------------------------
290  * Hash a STRANDS
291  */
292 
293 uint32_t
VRT_HashStrands32(VCL_STRANDS s)294 VRT_HashStrands32(VCL_STRANDS s)
295 {
296 	struct VSHA256Context sha_ctx;
297 	unsigned char sha256[VSHA256_LEN];
298 	const char *p;
299 	int i;
300 
301 	AN(s);
302 	VSHA256_Init(&sha_ctx);
303 	for (i = 0; i < s->n; i++) {
304 		p = s->p[i];
305 		if (p != NULL && *p != '\0')
306 			VSHA256_Update(&sha_ctx, p, strlen(p));
307 	}
308 	VSHA256_Final(sha256, &sha_ctx);
309 
310 	/* NB: for some reason vmod_director's shard director specifically
311 	 * relied on little-endian decoding of the last 4 octets. In order
312 	 * to maintain a stable hash function to share across consumers we
313 	 * need to stick to that.
314 	 */
315 	return (vle32dec(sha256 + VSHA256_LEN - 4));
316 }
317 
318 /*--------------------------------------------------------------------
319  * Collapse a STRING_LIST in the space provided, or return NULL
320  */
321 
322 char *
VRT_StringList(char * d,unsigned dl,const char * p,va_list ap)323 VRT_StringList(char *d, unsigned dl, const char *p, va_list ap)
324 {
325 	char *b, *e;
326 	unsigned x;
327 
328 	b = d;
329 	e = b + dl;
330 	while (p != vrt_magic_string_end && b < e) {
331 		if (p != NULL && *p != '\0') {
332 			x = strlen(p);
333 			if (b + x < e)
334 				memcpy(b, p, x);
335 			b += x;
336 		}
337 		p = va_arg(ap, const char *);
338 	}
339 	if (b >= e)
340 		return (NULL);
341 	*b++ = '\0';
342 	return (b);
343 }
344 
345 /*--------------------------------------------------------------------
346  * Copy and merge a STRING_LIST into a workspace.
347  */
348 
349 const char *
VRT_String(struct ws * ws,const char * h,const char * p,va_list ap)350 VRT_String(struct ws *ws, const char *h, const char *p, va_list ap)
351 {
352 	char *b, *e;
353 	const char *q;
354 	unsigned u, x;
355 	va_list aq;
356 
357 	u = WS_ReserveAll(ws);
358 	e = b = WS_Reservation(ws);
359 	e += u;
360 
361 	va_copy(aq, ap);
362 	do
363 		q = va_arg(aq, const char *);
364 	while (q == NULL || (q != vrt_magic_string_end && *q == '\0'));
365 
366 	if (h != NULL && p == NULL && q == vrt_magic_string_end &&
367 	    WS_Inside(ws, h, NULL)) {
368 		va_end(aq);
369 		WS_Release(ws, 0);
370 		return (h);
371 	}
372 
373 	if (h == NULL && p != NULL && q == vrt_magic_string_end &&
374 	    WS_Inside(ws, p, NULL)) {
375 		va_end(aq);
376 		WS_Release(ws, 0);
377 		return (p);
378 	}
379 
380 	if (h == NULL && p == NULL) {
381 		if (q == vrt_magic_string_end) {
382 			va_end(aq);
383 			WS_Release(ws, 0);
384 			return ("");
385 		}
386 		do
387 			p = va_arg(aq, const char *);
388 		while (p == NULL || (p != vrt_magic_string_end && *p == '\0'));
389 		if (p == vrt_magic_string_end && WS_Inside(ws, q, NULL)) {
390 			va_end(aq);
391 			WS_Release(ws, 0);
392 			return (q);
393 		}
394 		p = NULL;
395 		va_end(aq);
396 	}
397 
398 	if (h != NULL) {
399 		x = strlen(h);
400 		if (b + x < e)
401 			memcpy(b, h, x);
402 		b += x;
403 		if (b < e)
404 			*b = ' ';
405 		b++;
406 	}
407 	b = VRT_StringList(b, e > b ? e - b : 0, p, ap);
408 	if (b == NULL || b == e) {
409 		WS_MarkOverflow(ws);
410 		WS_Release(ws, 0);
411 		return (NULL);
412 	}
413 	e = b;
414 	b = WS_Reservation(ws);
415 	WS_Release(ws, e - b);
416 	return (b);
417 }
418 
419 /*--------------------------------------------------------------------
420  * Copy and merge a STRING_LIST on the current workspace
421  */
422 
423 VCL_STRING
VRT_CollectString(VRT_CTX,const char * p,...)424 VRT_CollectString(VRT_CTX, const char *p, ...)
425 {
426 	va_list ap;
427 	const char *b;
428 
429 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
430 	CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
431 	va_start(ap, p);
432 	b = VRT_String(ctx->ws, NULL, p, ap);
433 	va_end(ap);
434 	if (b == NULL)
435 		VRT_fail(ctx, "Workspace overflow");
436 	return (b);
437 }
438 
439 /*--------------------------------------------------------------------
440  * Collapse STRANDS into the space provided, or return NULL
441  */
442 
443 char *
VRT_Strands(char * d,size_t dl,VCL_STRANDS s)444 VRT_Strands(char *d, size_t dl, VCL_STRANDS s)
445 {
446 	char *b;
447 	const char *e;
448 	unsigned x;
449 
450 	AN(d);
451 	AN(s);
452 	b = d;
453 	e = b + dl;
454 	for (int i = 0; i < s->n; i++)
455 		if (s->p[i] != NULL && *s->p[i] != '\0') {
456 			x = strlen(s->p[i]);
457 			if (b + x >= e)
458 				return (NULL);
459 			memcpy(b, s->p[i], x);
460 			b += x;
461 		}
462 	assert(b < e);
463 	*b++ = '\0';
464 	return (b);
465 }
466 
467 /*--------------------------------------------------------------------
468  * Copy and merge STRANDS into a workspace.
469  */
470 
471 VCL_STRING
VRT_StrandsWS(struct ws * ws,const char * h,VCL_STRANDS s)472 VRT_StrandsWS(struct ws *ws, const char *h, VCL_STRANDS s)
473 {
474 	const char *q = NULL;
475 	struct vsb vsb[1];
476 	int i;
477 
478 	WS_Assert(ws);
479 	AN(s);
480 
481 	for (i = 0; i < s->n; i++) {
482 		if (s->p[i] != NULL && *s->p[i] != '\0') {
483 			q = s->p[i];
484 			break;
485 		}
486 	}
487 
488 	if (q == NULL) {
489 		if (h == NULL)
490 			return ("");
491 		if (WS_Inside(ws, h, NULL))
492 			return (h);
493 	} else if (h == NULL && WS_Inside(ws, q, NULL)) {
494 		for (i++; i < s->n; i++)
495 			if (s->p[i] != NULL && *s->p[i] != '\0')
496 				break;
497 		if (i == s->n)
498 			return (q);
499 	}
500 
501 	WS_VSB_new(vsb, ws);
502 	if (h != NULL)
503 		VSB_cat(vsb, h);
504 	for (i = 0; i < s->n; i++) {
505 		if (s->p[i] != NULL && *s->p[i] != '\0')
506 			VSB_cat(vsb, s->p[i]);
507 	}
508 	return (WS_VSB_finish(vsb, ws, NULL));
509 }
510 
511 /*--------------------------------------------------------------------
512  * Copy and merge STRANDS on the current workspace
513  */
514 
515 VCL_STRING
VRT_CollectStrands(VRT_CTX,VCL_STRANDS s)516 VRT_CollectStrands(VRT_CTX, VCL_STRANDS s)
517 {
518 	const char *b;
519 
520 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
521 	CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
522 	b = VRT_StrandsWS(ctx->ws, NULL, s);
523 	if (b == NULL)
524 		VRT_fail(ctx, "Workspace overflow");
525 	return (b);
526 }
527 
528 /*--------------------------------------------------------------------
529  * upper/lower-case STRANDS (onto workspace)
530  */
531 
532 #include <stdio.h>
533 
534 VCL_STRING
VRT_UpperLowerStrands(VRT_CTX,VCL_STRANDS s,int up)535 VRT_UpperLowerStrands(VRT_CTX, VCL_STRANDS s, int up)
536 {
537 	unsigned u;
538 	char *b, *e, *r;
539 	const char *p, *q = NULL;
540 	int i, copy = 0;
541 
542 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
543 	CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
544 	AN(s);
545 	u = WS_ReserveAll(ctx->ws);
546 	r = b = WS_Reservation(ctx->ws);
547 	e = b + u;
548 	for (i = 0; i < s->n; i++) {
549 		if (s->p[i] == NULL || s->p[i][0] == '\0')
550 			continue;
551 		if (q != NULL)
552 			copy = 1;
553 		for(p = q = s->p[i]; *p != '\0'; p++) {
554 			if ((up && vct_islower(*p)) ||
555 			    (!up && vct_isupper(*p))) {
556 				*b++ = *p ^ 0x20;
557 				copy = 1;
558 			} else if (b < e) {
559 				*b++ = *p;
560 			}
561 			if (copy && b == e)
562 				break;
563 		}
564 		if (copy && b == e) {
565 			WS_Release(ctx->ws, 0);
566 			VRT_fail(ctx, "Workspace overflow");
567 			return (NULL);
568 		}
569 	}
570 	assert(b <= e);
571 	if (!copy) {
572 		WS_Release(ctx->ws, 0);
573 		return (q);
574 	}
575 	assert(b < e);
576 	*b++ = '\0';
577 	assert(b <= e);
578 	WS_ReleaseP(ctx->ws, b);
579 	return (r);
580 }
581 
582 // rfc7230,l,1243,1244
583 // ASCII VCHAR + TAB + obs-text (0x80-ff)
584 static inline VCL_BOOL
validhdr(const char * p)585 validhdr(const char *p)
586 {
587 	AN(p);
588 	for(;*p != '\0'; p++)
589 		if (! vct_ishdrval(*p))
590 			return (0);
591 	return (1);
592 }
593 
594 /*--------------------------------------------------------------------*/
595 VCL_BOOL
VRT_ValidHdr(VRT_CTX,VCL_STRANDS s)596 VRT_ValidHdr(VRT_CTX, VCL_STRANDS s)
597 {
598 	int i;
599 
600 	(void) ctx;
601 
602 	for (i = 0; i < s->n; i++) {
603 		if (s->p[i] == NULL || s->p[i][0] == '\0')
604 			continue;
605 		if (! validhdr(s->p[i]))
606 			return (0);
607 	}
608 
609 	return (1);
610 }
611 /*--------------------------------------------------------------------*/
612 
613 VCL_VOID
VRT_SetHdr(VRT_CTX,VCL_HEADER hs,const char * p,...)614 VRT_SetHdr(VRT_CTX , VCL_HEADER hs, const char *p, ...)
615 {
616 	VCL_HTTP hp;
617 	va_list ap;
618 	const char *b;
619 
620 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
621 	AN(hs);
622 	AN(hs->what);
623 	hp = VRT_selecthttp(ctx, hs->where);
624 	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
625 	if (p == vrt_magic_string_unset) {
626 		http_Unset(hp, hs->what);
627 	} else {
628 		va_start(ap, p);
629 		b = VRT_String(hp->ws, hs->what + 1, p, ap);
630 		va_end(ap);
631 		if (b == NULL) {
632 			VSLb(ctx->vsl, SLT_LostHeader, "%s", hs->what + 1);
633 			return;
634 		}
635 		if (FEATURE(FEATURE_VALIDATE_HEADERS) && ! validhdr(b)) {
636 			VRT_fail(ctx, "Bad header %s", b);
637 			return;
638 		}
639 		http_Unset(hp, hs->what);
640 		http_SetHeader(hp, b);
641 	}
642 }
643 
644 /*--------------------------------------------------------------------*/
645 
646 VCL_VOID
VRT_handling(VRT_CTX,unsigned hand)647 VRT_handling(VRT_CTX, unsigned hand)
648 {
649 
650 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
651 	assert(hand != VCL_RET_FAIL);
652 	AN(ctx->handling);
653 	AZ(*ctx->handling);
654 	assert(hand > 0);
655 	assert(hand < VCL_RET_MAX);
656 	*ctx->handling = hand;
657 }
658 
659 unsigned
VRT_handled(VRT_CTX)660 VRT_handled(VRT_CTX)
661 {
662 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
663 	AN(ctx->handling);
664 	return (*ctx->handling);
665 }
666 
667 /*--------------------------------------------------------------------*/
668 
669 VCL_VOID
VRT_fail(VRT_CTX,const char * fmt,...)670 VRT_fail(VRT_CTX, const char *fmt, ...)
671 {
672 	va_list ap;
673 
674 	assert(ctx->vsl != NULL || ctx->msg != NULL);
675 	AN(ctx->handling);
676 	if (*ctx->handling == VCL_RET_FAIL)
677 		return;
678 	AZ(*ctx->handling);
679 	AN(fmt);
680 	AZ(strchr(fmt, '\n'));
681 	va_start(ap, fmt);
682 	if (ctx->vsl != NULL) {
683 		VSLbv(ctx->vsl, SLT_VCL_Error, fmt, ap);
684 	} else {
685 		AN(ctx->msg);
686 		VSB_vprintf(ctx->msg, fmt, ap);
687 		VSB_putc(ctx->msg, '\n');
688 	}
689 	va_end(ap);
690 	*ctx->handling = VCL_RET_FAIL;
691 }
692 
693 /*--------------------------------------------------------------------
694  * Feed data into the hash calculation
695  */
696 
697 VCL_VOID
VRT_hashdata(VRT_CTX,VCL_STRANDS s)698 VRT_hashdata(VRT_CTX, VCL_STRANDS s)
699 {
700 	int i;
701 
702 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
703 	CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
704 	AN(ctx->specific);
705 	AN(s);
706 	for (i = 0; i < s->n; i++)
707 		HSH_AddString(ctx->req, ctx->specific, s->p[i]);
708 	/*
709 	 * Add a 'field-separator' to make it more difficult to
710 	 * manipulate the hash.
711 	 */
712 	HSH_AddString(ctx->req, ctx->specific, NULL);
713 }
714 
715 /*--------------------------------------------------------------------*/
716 
717 VCL_TIME
VRT_r_now(VRT_CTX)718 VRT_r_now(VRT_CTX)
719 {
720 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
721 	return (ctx->now);
722 }
723 
724 /*--------------------------------------------------------------------*/
725 
v_matchproto_()726 VCL_STRING v_matchproto_()
727 VRT_IP_string(VRT_CTX, VCL_IP ip)
728 {
729 	char *p;
730 	unsigned len;
731 
732 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
733 	if (ip == NULL) {
734 		VRT_fail(ctx, "%s: Illegal IP", __func__);
735 		return (NULL);
736 	}
737 	len = WS_ReserveAll(ctx->ws);
738 	if (len == 0) {
739 		WS_Release(ctx->ws, 0);
740 		return (NULL);
741 	}
742 	p = WS_Reservation(ctx->ws);
743 	VTCP_name(ip, p, len, NULL, 0);
744 	WS_Release(ctx->ws, strlen(p) + 1);
745 	return (p);
746 }
747 
v_matchproto_()748 VCL_STRING v_matchproto_()
749 VRT_INT_string(VRT_CTX, VCL_INT num)
750 {
751 
752 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
753 	return (WS_Printf(ctx->ws, "%jd", (intmax_t)num));
754 }
755 
v_matchproto_()756 VCL_STRING v_matchproto_()
757 VRT_REAL_string(VRT_CTX, VCL_REAL num)
758 {
759 
760 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
761 	return (WS_Printf(ctx->ws, "%.3f", num));
762 }
763 
v_matchproto_()764 VCL_STRING v_matchproto_()
765 VRT_TIME_string(VRT_CTX, VCL_TIME t)
766 {
767 	char *p;
768 
769 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
770 	p = WS_Alloc(ctx->ws, VTIM_FORMAT_SIZE);
771 	if (p != NULL)
772 		VTIM_format(t, p);
773 	return (p);
774 }
775 
v_matchproto_()776 VCL_STRING v_matchproto_()
777 VRT_BACKEND_string(VCL_BACKEND d)
778 {
779 	if (d == NULL)
780 		return (NULL);
781 	CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
782 	return (d->vcl_name);
783 }
784 
v_matchproto_()785 VCL_STRING v_matchproto_()
786 VRT_BOOL_string(VCL_BOOL val)
787 {
788 
789 	return (val ? "true" : "false");
790 }
791 
v_matchproto_()792 VCL_STRING v_matchproto_()
793 VRT_BLOB_string(VRT_CTX, VCL_BLOB val)
794 {
795 	struct vsb vsb[1];
796 	const char *s;
797 
798 	if (val == NULL)
799 		return (NULL);
800 	WS_VSB_new(vsb, ctx->ws);
801 	VSB_putc(vsb, ':');
802 	VENC_Encode_Base64(vsb, val->blob, val->len);
803 	VSB_putc(vsb, ':');
804 	s = WS_VSB_finish(vsb, ctx->ws, NULL);
805 	return (s);
806 }
807 
808 /*--------------------------------------------------------------------*/
809 
810 VCL_VOID
VRT_Rollback(VRT_CTX,VCL_HTTP hp)811 VRT_Rollback(VRT_CTX, VCL_HTTP hp)
812 {
813 
814 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
815 	CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
816 	if (ctx->method & VCL_MET_PIPE) {
817 		VRT_fail(ctx, "Cannot rollback in vcl_pipe {}");
818 		return;
819 	}
820 	if (hp == ctx->http_req) {
821 		CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
822 		Req_Rollback(ctx);
823 		if (ctx->method & VCL_MET_DELIVER)
824 			XXXAZ(Resp_Setup_Deliver(ctx->req));
825 		if (ctx->method & VCL_MET_SYNTH)
826 			Resp_Setup_Synth(ctx->req);
827 	} else if (hp == ctx->http_bereq) {
828 		Bereq_Rollback(ctx);
829 	} else
830 		WRONG("VRT_Rollback 'hp' invalid");
831 }
832 
833 /*--------------------------------------------------------------------*/
834 
835 VCL_VOID
VRT_synth_strands(VRT_CTX,VCL_STRANDS s)836 VRT_synth_strands(VRT_CTX, VCL_STRANDS s)
837 {
838 	struct vsb *vsb;
839 	int i;
840 
841 	CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);
842 	AN(s);
843 	for (i = 0; i < s->n; i++) {
844 		if (s->p[i] != NULL)
845 			VSB_cat(vsb, s->p[i]);
846 		else
847 			VSB_cat(vsb, "(null)");
848 	}
849 }
850 
851 VCL_VOID
VRT_synth_blob(VRT_CTX,VCL_BLOB b)852 VRT_synth_blob(VRT_CTX, VCL_BLOB b)
853 {
854 	struct vsb *vsb;
855 	CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);
856 
857 	if (b->len > 0 && b->blob != NULL)
858 		VSB_bcat(vsb, b->blob, b->len);
859 }
860 
861 VCL_VOID
VRT_synth_page(VRT_CTX,VCL_STRANDS s)862 VRT_synth_page(VRT_CTX, VCL_STRANDS s)
863 {
864 	VRT_synth_strands(ctx, s);
865 }
866 
867 /*--------------------------------------------------------------------*/
868 
869 static VCL_STRING
vrt_ban_error(VRT_CTX,VCL_STRING err)870 vrt_ban_error(VRT_CTX, VCL_STRING err)
871 {
872 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
873 	AN(ctx->vsl);
874 	AN(err);
875 
876 	VSLb(ctx->vsl, SLT_VCL_Error, "ban(): %s", err);
877 	return (err);
878 }
879 
880 VCL_STRING
VRT_ban_string(VRT_CTX,VCL_STRING str)881 VRT_ban_string(VRT_CTX, VCL_STRING str)
882 {
883 	char *a1, *a2, *a3;
884 	char **av;
885 	struct ban_proto *bp;
886 	const char *err = NULL, *berr = NULL;
887 	int i;
888 
889 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
890 
891 	if (str == NULL)
892 		return (vrt_ban_error(ctx, "Null argument"));
893 
894 	bp = BAN_Build();
895 	if (bp == NULL)
896 		return (vrt_ban_error(ctx, "Out of Memory"));
897 
898 	av = VAV_Parse(str, NULL, ARGV_NOESC);
899 	AN(av);
900 	if (av[0] != NULL) {
901 		err = av[0];
902 		VAV_Free(av);
903 		BAN_Abandon(bp);
904 		return (vrt_ban_error(ctx, err));
905 	}
906 	for (i = 0; ;) {
907 		a1 = av[++i];
908 		if (a1 == NULL) {
909 			err = "No ban conditions found.";
910 			break;
911 		}
912 		a2 = av[++i];
913 		if (a2 == NULL) {
914 			err = "Expected comparison operator.";
915 			break;
916 		}
917 		a3 = av[++i];
918 		if (a3 == NULL) {
919 			err = "Expected second operand.";
920 			break;
921 		}
922 		berr = BAN_AddTest(bp, a1, a2, a3);
923 		if (berr != NULL)
924 			break;
925 
926 		if (av[++i] == NULL) {
927 			berr = BAN_Commit(bp);
928 			if (berr == NULL)
929 				bp = NULL;
930 			break;
931 		}
932 		if (strcmp(av[i], "&&")) {
933 			err = WS_Printf(ctx->ws, "Expected && between "
934 			    "conditions, found \"%s\"", av[i]);
935 			if (err == NULL)
936 				err = "Expected && between conditions "
937 				    "(workspace overflow)";
938 			break;
939 		}
940 	}
941 	if (berr != NULL) {
942 		AZ(err);
943 		err = WS_Copy(ctx->ws, berr, -1);
944 		if (err == NULL)
945 			err = "Unknown error (workspace overflow)";
946 		berr = NULL;
947 	}
948 	AZ(berr);
949 	if (bp != NULL)
950 		BAN_Abandon(bp);
951 	VAV_Free(av);
952 	if (err == NULL)
953 		return (NULL);
954 	return (vrt_ban_error(ctx, err));
955 }
956 
957 VCL_BYTES
VRT_CacheReqBody(VRT_CTX,VCL_BYTES maxsize)958 VRT_CacheReqBody(VRT_CTX, VCL_BYTES maxsize)
959 {
960 
961 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
962 	CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
963 	if (ctx->method != VCL_MET_RECV) {
964 		VSLb(ctx->vsl, SLT_VCL_Error,
965 		    "req.body can only be cached in vcl_recv{}");
966 		return (-1);
967 	}
968 	return (VRB_Cache(ctx->req, maxsize));
969 }
970 
971 /*--------------------------------------------------------------------
972  * purges
973  */
974 
975 VCL_INT
VRT_purge(VRT_CTX,VCL_DURATION ttl,VCL_DURATION grace,VCL_DURATION keep)976 VRT_purge(VRT_CTX, VCL_DURATION ttl, VCL_DURATION grace, VCL_DURATION keep)
977 {
978 
979 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
980 
981 	if ((ctx->method & (VCL_MET_HIT|VCL_MET_MISS)) == 0) {
982 		VRT_fail(ctx,
983 		    "purge can only happen in vcl_hit{} or vcl_miss{}");
984 		return (0);
985 	}
986 
987 	CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
988 	CHECK_OBJ_NOTNULL(ctx->req->wrk, WORKER_MAGIC);
989 	return (HSH_Purge(ctx->req->wrk, ctx->req->objcore->objhead,
990 	    ctx->req->t_req, ttl, grace, keep));
991 }
992 
993 /*--------------------------------------------------------------------
994  */
995 
v_matchproto_()996 struct vsmw_cluster * v_matchproto_()
997 VRT_VSM_Cluster_New(VRT_CTX, size_t sz)
998 {
999 	struct vsmw_cluster *vc;
1000 
1001 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1002 	assert(sz > 0);
1003 	AN(vsc_lock);
1004 	AN(vsc_unlock);
1005 	AN(heritage.proc_vsmw);
1006 	vsc_lock();
1007 	vc = VSMW_NewCluster(heritage.proc_vsmw, sz, "VSC_cluster");
1008 	vsc_unlock();
1009 	return (vc);
1010 }
1011 
v_matchproto_()1012 void v_matchproto_()
1013 VRT_VSM_Cluster_Destroy(VRT_CTX, struct vsmw_cluster **vsmcp)
1014 {
1015 
1016 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1017 	AN(vsmcp);
1018 	VSMW_DestroyCluster(heritage.proc_vsmw, vsmcp);
1019 }
1020 
1021 /*--------------------------------------------------------------------
1022  * Simple stuff
1023  */
1024 
1025 int
VRT_strcmp(const char * s1,const char * s2)1026 VRT_strcmp(const char *s1, const char *s2)
1027 {
1028 	if (s1 == NULL || s2 == NULL)
1029 		return (1);
1030 	return (strcmp(s1, s2));
1031 }
1032 
1033 void
VRT_memmove(void * dst,const void * src,unsigned len)1034 VRT_memmove(void *dst, const void *src, unsigned len)
1035 {
1036 
1037 	(void)memmove(dst, src, len);
1038 }
1039 
1040 VCL_BOOL
VRT_ipcmp(VRT_CTX,VCL_IP sua1,VCL_IP sua2)1041 VRT_ipcmp(VRT_CTX, VCL_IP sua1, VCL_IP sua2)
1042 {
1043 
1044 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1045 
1046 	if (sua1 == NULL || sua2 == NULL) {
1047 		VRT_fail(ctx, "%s: Illegal IP", __func__);
1048 		return (1);
1049 	}
1050 	return (VSA_Compare_IP(sua1, sua2));
1051 }
1052 
1053 /*
1054  * the pointer passed as src must have at least VCL_TASK lifetime
1055  */
1056 VCL_BLOB
VRT_blob(VRT_CTX,const char * err,const void * src,size_t len,unsigned type)1057 VRT_blob(VRT_CTX, const char *err, const void *src, size_t len, unsigned type)
1058 {
1059 	struct vrt_blob *p;
1060 
1061 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1062 	CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
1063 
1064 	p = (void *)WS_Alloc(ctx->ws, sizeof *p);
1065 	if (p == NULL) {
1066 		VRT_fail(ctx, "Workspace overflow (%s)", err);
1067 		return (NULL);
1068 	}
1069 
1070 	p->type = type;
1071 	p->len = len;
1072 	p->blob = src;
1073 
1074 	return (p);
1075 }
1076 
1077 int
VRT_VSA_GetPtr(VRT_CTX,const struct suckaddr * sua,const unsigned char ** dst)1078 VRT_VSA_GetPtr(VRT_CTX, const struct suckaddr *sua, const unsigned char ** dst)
1079 {
1080 
1081 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
1082 	AN(dst);
1083 
1084 	if (sua == NULL) {
1085 		VRT_fail(ctx, "%s: Illegal IP", __func__);
1086 		*dst = NULL;
1087 		return (-1);
1088 	}
1089 	return (VSA_GetPtr(sua, dst));
1090 }
1091 
1092 void
VRT_Format_Proxy(struct vsb * vsb,VCL_INT version,VCL_IP sac,VCL_IP sas,VCL_STRING auth)1093 VRT_Format_Proxy(struct vsb *vsb, VCL_INT version, VCL_IP sac, VCL_IP sas,
1094     VCL_STRING auth)
1095 {
1096 	VPX_Format_Proxy(vsb, (int)version, sac, sas, auth);
1097 }
1098 
1099 /*
1100  * Clone a struct vrt_endpoint in a single malloc() allocation
1101  */
1102 
1103 //lint -e{662}  Possible of out-of-bounds pointer (___ beyond end of data)
1104 //lint -e{826}  Suspicious pointer-to-pointer conversion (area to o small
1105 struct vrt_endpoint *
VRT_Endpoint_Clone(const struct vrt_endpoint * const vep)1106 VRT_Endpoint_Clone(const struct vrt_endpoint * const vep)
1107 {
1108 	size_t sz;
1109 	struct vrt_endpoint *nvep;
1110 	struct vrt_blob *blob = NULL;
1111 	struct suckaddr *sa;
1112 	size_t uds_len = 0;
1113 	char *p, *e;
1114 
1115 	CHECK_OBJ_NOTNULL(vep, VRT_ENDPOINT_MAGIC);
1116 	sz = sizeof *nvep;
1117 	if (vep->ipv4)
1118 		sz += vsa_suckaddr_len;
1119 	if (vep->ipv6)
1120 		sz += vsa_suckaddr_len;
1121 	if (vep->uds_path != NULL) {
1122 		uds_len = strlen(vep->uds_path) + 1;
1123 		sz += uds_len;
1124 	}
1125 	if (vep->preamble != NULL && vep->preamble->len) {
1126 		sz += sizeof(*blob);
1127 		sz += vep->preamble->len;
1128 	}
1129 	p = calloc(1, sz);
1130 	AN(p);
1131 	e = p + sz;
1132 	nvep = (void*)p;
1133 	p += sizeof *nvep;
1134 	INIT_OBJ(nvep, VRT_ENDPOINT_MAGIC);
1135 	if (vep->ipv4) {
1136 		sa = (void*)p;
1137 		memcpy(sa, vep->ipv4, vsa_suckaddr_len);
1138 		nvep->ipv4 = sa;
1139 		p += vsa_suckaddr_len;
1140 	}
1141 	if (vep->ipv6) {
1142 		sa = (void*)p;
1143 		memcpy(sa, vep->ipv6, vsa_suckaddr_len);
1144 		nvep->ipv6 = sa;
1145 		p += vsa_suckaddr_len;
1146 	}
1147 	if (vep->preamble != NULL && vep->preamble->len) {
1148 		/* Before uds because we need p to be aligned still */
1149 		blob = (void*)p;
1150 		p += sizeof(*blob);
1151 		nvep->preamble = blob;
1152 		memcpy(p, vep->preamble->blob, vep->preamble->len);
1153 		blob->len = vep->preamble->len;
1154 		blob->blob = p;
1155 		p += vep->preamble->len;
1156 	}
1157 	if (uds_len) {
1158 		memcpy(p, vep->uds_path, uds_len);
1159 		nvep->uds_path = p;
1160 		p += uds_len;
1161 	}
1162 	assert(p == e);
1163 	return (nvep);
1164 }
1165