Hi,

Once again related to my work on dynamic backends, but also probably
useful in other cases, checking ACLs in VMODs. Unlike my similar patch
for probes[1], this one is already tested. I'll first give some background,
then the rationale, and finally the caveats.

Background:
The DNS director from Varnish 3 used to take IP addresses and ranges
to generate static backends, and would enable/disable the backends
after DNS lookups. The director would also ignore DNS entries that
don't match the static list of IP addresses. DNS director backends
don't have probes, probably because the backends always exist, and
that they'd be marked as sick when no DNS entry match them.

Please correct me if I'm wrong, I'm basing my DNS director for Varnish
4.1 on this understanding.

Rationale:
In Varnish 4.1, provided that we introduce dynamic backends, we don't
need that at all. We can simply create/destroy backends after lookups.
However, I see two reasons for keeping IP addresses around:
- it's familiar to Varnish 3 users
- it may mitigate DNS spoofing (I am no security expert)

I don't want to rewrite this logic, especially since we already have a
good "data structure" in Varnish for that. So I thought it could benefit
VMOD writers to have access to the named ACLs.

Caveats:
The ACL declaration ends up being a function, so that would be the
first VCL type exposed as a function to VMODs (I don't see that as a
problem). Because of the way code is generated, I had to move things
around and put an ugly comment to circumvent spurious code generation.
With this patch, its "probe" sibling[1] and the existing backend
handling, code duplication is emerging in libvcc.

This email is probably^W bigger than the patch, comments ?

Best Regards,
Dridi

[1] 
https://www.varnish-cache.org/lists/pipermail/varnish-dev/2015-June/008357.html
From b04761dfeb8d033e3d224ee5c0e44486e31fbdc2 Mon Sep 17 00:00:00 2001
From: Dridi Boukelmoune <[email protected]>
Date: Thu, 18 Jun 2015 19:00:09 +0200
Subject: [PATCH] Allow ACL references in VMODs

Only log ACL results when the check happens during a transaction.
---
 bin/varnishd/cache/cache_vrt.c |  6 ++++--
 include/vrt.h                  |  9 +++++++--
 lib/libvcc/vcc_acl.c           | 17 ++++++++++++-----
 lib/libvcc/vcc_compile.h       |  1 +
 lib/libvcc/vcc_expr.c          | 21 +++++++++++++++++++++
 lib/libvcc/vmodtool.py         |  1 +
 lib/libvmod_debug/vmod.vcc     |  4 ++++
 lib/libvmod_debug/vmod_debug.c | 10 ++++++++++
 8 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index df6bb96..81b87ba 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -68,8 +68,10 @@ void
 VRT_acl_log(VRT_CTX, const char *msg)
 {
 
-	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
-	VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg);
+	CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
+	AN(msg);
+	if (ctx != NULL && ctx->vsl != NULL)
+		VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg);
 }
 
 /*--------------------------------------------------------------------*/
diff --git a/include/vrt.h b/include/vrt.h
index 27e738e..c29d5a1 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -54,13 +54,17 @@ struct busyobj;
 struct director;
 struct http;
 struct req;
+struct sess;
 struct suckaddr;
 struct vcl;
+struct vrt_ctx;
 struct vmod;
 struct vsb;
 struct vsl_log;
 struct ws;
 
+#define VRT_CTX		const struct vrt_ctx *ctx
+
 /***********************************************************************
  * This is the central definition of the mapping from VCL types to
  * C-types.  The python scripts read these from here.
@@ -82,6 +86,9 @@ typedef const char *			VCL_STRING;
 typedef double				VCL_TIME;
 typedef void				VCL_VOID;
 
+typedef int (acl_f) (VRT_CTX, const VCL_IP /* hack */ );
+typedef acl_f *				VCL_ACL;
+
 /***********************************************************************
  * This is the composite argument we pass to compiled VCL and VRT
  * functions.
@@ -118,8 +125,6 @@ struct vrt_ctx {
 	void				*specific;
 };
 
-#define VRT_CTX		const struct vrt_ctx *ctx
-
 /***********************************************************************/
 
 struct vmod_data {
diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c
index 72dd304..15264be 100644
--- a/lib/libvcc/vcc_acl.c
+++ b/lib/libvcc/vcc_acl.c
@@ -352,7 +352,7 @@ vcc_acl_emit(struct vcc *tl, const char *acln, int anon)
 	struct token *t;
 	struct inifin *ifp;
 
-	Fh(tl, 0, "\nstatic int\n");
+	Fh(tl, 0, "\nstatic int __match_proto__(acl_f)\n");
 	Fh(tl, 0,
 	    "match_acl_%s_%s(VRT_CTX, const VCL_IP p)\n",
 	    anon ? "anon" : "named", acln);
@@ -470,7 +470,7 @@ void
 vcc_ParseAcl(struct vcc *tl)
 {
 	struct token *an;
-	int i;
+	struct symbol *sym;
 	char acln[1024];
 
 	vcc_NextToken(tl);
@@ -486,13 +486,20 @@ vcc_ParseAcl(struct vcc *tl)
 	an = tl->t;
 	vcc_NextToken(tl);
 
-	i = vcc_AddDef(tl, an, SYM_ACL);
-	if (i > 1) {
+	bprintf(acln, "%.*s", PF(an));
+
+	sym = VCC_GetSymbolTok(tl, an, SYM_ACL);
+	AN(sym);
+	if (sym->ndef > 0) {
 		VSB_printf(tl->sb, "ACL %.*s redefined\n", PF(an));
 		vcc_ErrWhere(tl, an);
 		return;
 	}
-	bprintf(acln, "%.*s", PF(an));
+	sym->fmt = ACL;
+	sym->eval = vcc_Eval_Acl;
+	sym->eval_priv = TlDup(tl, acln);
+	sym->ndef++;
+	ERRCHK(tl);
 
 	SkipToken(tl, '{');
 
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index a222b9b..9908104 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -278,6 +278,7 @@ sym_expr_t vcc_Eval_Var;
 sym_expr_t vcc_Eval_SymFunc;
 void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra,
     const char *name, const char *args);
+sym_expr_t vcc_Eval_Acl;
 sym_expr_t vcc_Eval_Backend;
 
 /* vcc_obj.c */
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index df5aa43..f6648b8 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -501,10 +501,28 @@ vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym)
  */
 
 void
+vcc_Eval_Acl(struct vcc *tl, struct expr **e, const struct symbol *sym)
+{
+
+	assert(sym->kind == SYM_ACL);
+	AN(sym->eval_priv);
+
+	vcc_ExpectCid(tl);
+	vcc_AddRef(tl, tl->t, SYM_ACL);
+	*e = vcc_mk_expr(ACL, "&match_acl_named_%s",
+	    (const char *)sym->eval_priv);
+	(*e)->constant = EXPR_VAR;	/* XXX ? */
+	vcc_NextToken(tl);
+}
+/*--------------------------------------------------------------------
+ */
+
+void
 vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym)
 {
 
 	assert(sym->kind == SYM_BACKEND);
+	AN(sym->eval_priv);
 
 	vcc_ExpectCid(tl);
 	vcc_AddRef(tl, tl->t, SYM_BACKEND);
@@ -809,6 +827,8 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
 		 * XXX: look for SYM_VAR first for consistency ?
 		 */
 		sym = NULL;
+		if (fmt == ACL)
+			sym = VCC_FindSymbol(tl, tl->t, SYM_ACL);
 		if (fmt == BACKEND)
 			sym = VCC_FindSymbol(tl, tl->t, SYM_BACKEND);
 		if (sym == NULL)
@@ -829,6 +849,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
 		switch(sym->kind) {
 		case SYM_VAR:
 		case SYM_FUNC:
+		case SYM_ACL:
 		case SYM_BACKEND:
 			AN(sym->eval);
 			AZ(*e);
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index a5eb8bb..b27eb23 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -46,6 +46,7 @@ from os.path import dirname, realpath, exists
 from pprint import pprint, pformat
 
 ctypes = {
+	'ACL':  	"VCL_ACL",
 	'BACKEND':	"VCL_BACKEND",
 	'BLOB':		"VCL_BLOB",
 	'BOOL':		"VCL_BOOL",
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index 67edd62..e4e1706 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -105,3 +105,7 @@ Register the vmod to receive expiry callbacks
 $Function VOID init_fail()
 
 Function to fail vcl_init{}
+
+$Function VOID match_acl(ACL acl, IP ip)
+
+Panic if ip doesn't match acl.
diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c
index f9f3361..7bc81d0 100644
--- a/lib/libvmod_debug/vmod_debug.c
+++ b/lib/libvmod_debug/vmod_debug.c
@@ -269,3 +269,13 @@ event_function(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
 	priv->free = priv_vcl_free;
 	return (0);
 }
+
+VCL_VOID
+vmod_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip) {
+
+	CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC);
+	AN(acl);
+	AN(ip);
+
+	AN(acl(ctx, ip));
+}
-- 
2.1.0

_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to