]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Do a second pass over the conditions. Fixes #421
authorAlan T. DeKok <aland@freeradius.org>
Tue, 3 Sep 2013 12:00:04 +0000 (08:00 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 3 Sep 2013 12:02:52 +0000 (08:02 -0400)
Modules can register new attributes, so we may need to convert
literal comparisons to module comparisons.

The core can register new values for Auth-Type && friends
so we need to do a second pass to see if a failed lookup in pass1
is really a failure, or simply an early binding.

The next step is to add code to mark up late-registered paircompare
functions

src/include/modcall.h
src/include/parser.h
src/main/modcall.c
src/main/modules.c
src/main/parser.c

index bcb658370acbb3c7c5d97662a8dfa45eabaf50e8..205c66ef341f9fc7873f9fac49c37c24eca3d35d 100644 (file)
@@ -33,6 +33,11 @@ modcallable *compile_modgroup(modcallable *parent,
 modcallable *compile_modsingle(modcallable *parent, int component, CONF_ITEM *ci,
                               char const **modname);
 
+/*
+ *     Do the second pass on compiling the modules.
+ */
+bool modcall_pass2(modcallable *mc);
+
 /* Add an entry to the end of a modgroup, creating it first if necessary */
 void add_to_modcallable(modcallable **parent, modcallable *this,
                        int component, char const *name);
index 97599c151292139b37089307f42ce8323dd561d5..e8155481b5aa8adfdec45165f63a569ea5648688 100644 (file)
@@ -83,6 +83,10 @@ struct fr_cond_t {
 };
 
 
+#define PASS2_FIXUP_NONE (0)
+#define PASS2_FIXUP_ATTR (1)
+#define PASS2_FIXUP_TYPE (2)
+
 /*
  *     One pass over the conditions means that all references must
  *     exist at parse time.
index 52e4c26bd6fbd9c3f8fbc9c3a6759ee37e7a168d..a1a132ef19d27f5fecb23d7b7da1832177ab137a 100644 (file)
@@ -74,7 +74,7 @@ typedef struct {
        modcallable *children;
        CONF_SECTION *cs;
        value_pair_map_t *map;  /* update */
-       fr_cond_t const *cond;  /* if/elsif */
+       fr_cond_t *cond;        /* if/elsif */
 } modgroup;
 
 typedef struct {
@@ -2369,3 +2369,119 @@ void modcallable_free(modcallable **pc)
        free(c);
        *pc = NULL;
 }
+
+
+static bool pass2_callback(UNUSED void *ctx, fr_cond_t *c)
+{
+       value_pair_map_t *map;
+
+       if (c->pass2_fixup == PASS2_FIXUP_NONE) return true;
+
+       map = c->data.map;      /* shorter */
+
+       /*
+        *      Auth-Type := foo
+        *
+        *      Where "foo" is dynamically defined.
+        */
+       if (c->pass2_fixup == PASS2_FIXUP_TYPE) {
+               if (!dict_valbyname(map->dst->da->attr,
+                                   map->dst->da->vendor,
+                                   map->src->name)) {
+                       cf_log_err(map->ci, "Invalid reference to non-existent %s %s { ... }",
+                                  map->dst->da->name,
+                                  map->src->name);
+                       return false;
+               }
+
+               c->pass2_fixup = 0;
+               return true;
+       }
+
+       if (c->pass2_fixup == PASS2_FIXUP_ATTR) {
+               value_pair_map_t *old;
+               value_pair_tmpl_t vpt;
+
+               /*
+                *      It's still not an attribute.  Ignore it.
+                */
+               if (radius_parse_attr(map->dst->name, &vpt, REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
+                       c->pass2_fixup = 0;
+                       return true;
+               }
+
+               /*
+                *      Re-parse the LHS as an attribute.
+                */
+               old = c->data.map;
+               map = radius_str2map(c, old->dst->name, T_BARE_WORD, old->op,
+                                    old->src->name, T_BARE_WORD,
+                                    REQUEST_CURRENT, PAIR_LIST_REQUEST,
+                                    REQUEST_CURRENT, PAIR_LIST_REQUEST);
+               if (!map) {
+                       cf_log_err(map->ci, "Failed parsing condition");
+                       return false;
+               }
+               map->ci = old->ci;
+               talloc_free(old);
+               c->data.map = map;
+               return true;
+       }
+
+       cf_log_err(map->ci, "Internal sanity check failed in pass2 fixup");
+
+       return false;
+}
+
+/*
+ *     Do a second-stage pass on compiling the modules.
+ */
+bool modcall_pass2(modcallable *mc)
+{
+       modcallable *this;
+       modgroup *g;
+
+       for (this = mc; this != NULL; this = this->next) {
+               switch (this->type) {
+               default:
+                       rad_assert(0 == 1);
+                       break;
+
+               case MOD_SINGLE:
+#ifdef WITH_UNLANG
+               case MOD_UPDATE: /* @todo: pre-parse xlat's */
+               case MOD_XLAT:   /* @todo: pre-parse xlat's */
+               case MOD_BREAK:
+               case MOD_REFERENCE:
+#endif
+                       break;  /* do nothing */
+
+#ifdef WITH_UNLANG
+               case MOD_IF:
+               case MOD_ELSIF:
+                       g = mod_callabletogroup(this);
+                       if (!fr_condition_walk(g->cond, pass2_callback, NULL)) {
+                               return false;
+                       }
+                       /* FALL-THROUGH */
+#endif
+
+               case MOD_GROUP:
+               case MOD_LOAD_BALANCE:
+               case MOD_REDUNDANT_LOAD_BALANCE:
+
+#ifdef WITH_UNLANG
+               case MOD_ELSE:
+               case MOD_SWITCH:
+               case MOD_CASE:
+               case MOD_FOREACH:
+               case MOD_POLICY:
+#endif
+                       g = mod_callabletogroup(this);
+                       if (!modcall_pass2(g->children)) return false;
+                       break;
+               }
+       }
+
+       return true;
+}
index 1508ad8eb5dc5a7f17a2ac7ae996e6eabd7527e9..145d9845de0761acced38144b34eeb18cf4b6bef 100644 (file)
@@ -1275,6 +1275,7 @@ static int load_byserver(CONF_SECTION *cs)
 int virtual_servers_load(CONF_SECTION *config)
 {
        CONF_SECTION *cs;
+       virtual_server_t *server;
        static int first_time = true;
 
        DEBUG2("%s: #### Loading Virtual Servers ####", mainconfig.name);
@@ -1307,7 +1308,6 @@ int virtual_servers_load(CONF_SECTION *config)
             cs != NULL;
             cs = cf_subsection_find_next(config, cs, "server")) {
                char const *name2;
-               virtual_server_t *server;
 
                name2 = cf_section_name2(cs);
                if (!name2) continue; /* handled above */
@@ -1335,6 +1335,26 @@ int virtual_servers_load(CONF_SECTION *config)
                }
        }
 
+       /*
+        *      Now that we've loaded everything, run pass 2 over the
+        *      conditions and xlats.
+        */
+       for (cs = cf_subsection_find_next(config, NULL, "server");
+            cs != NULL;
+            cs = cf_subsection_find_next(config, cs, "server")) {
+               int i;
+               char const *name2;
+
+               name2 = cf_section_name2(cs);
+
+               server = virtual_server_find(name2);
+               if (!server) continue;
+
+               for (i = RLM_COMPONENT_AUTH; i < RLM_COMPONENT_COUNT; i++) {
+                       if (!modcall_pass2(server->mc[i])) return -1;
+               }
+       }
+
        /*
         *      If we succeed the first time around, remember that.
         */
index b93ef8a88cb331dc5883d7f0736d01c352ae8220..609aad7fdfe30a6fa2b57988f816cc70b18e3040 100644 (file)
@@ -30,10 +30,6 @@ RCSID("$Id$")
 
 #define PW_CAST_BASE (1850)
 
-#define PASS2_FIXUP_NONE (0)
-#define PASS2_FIXUP_ATTR (1)
-#define PASS2_FIXUP_TYPE (2)
-
 /*
  *     This file shouldn't use any functions from the server core.
  */