From: Alan T. DeKok Date: Fri, 4 Sep 2015 15:25:28 +0000 (-0400) Subject: Allow virtual modules to have method over-rides, too X-Git-Tag: release_3_0_10~165 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b69bc8892b50bfc305b1e3d979ce5c43c565e1c1;p=thirdparty%2Ffreeradius-server.git Allow virtual modules to have method over-rides, too --- diff --git a/src/main/modcall.c b/src/main/modcall.c index e503d85f6e5..e2ae38e53ca 100644 --- a/src/main/modcall.c +++ b/src/main/modcall.c @@ -2147,6 +2147,86 @@ static int all_children_are_modules(CONF_SECTION *cs, char const *name) } +/* + * Load a named module from "instantiate" or "policy". + * + * If it's "foo.method", look for "foo", and return "method" as the method + * we wish to use, instead of the input component. + */ +static CONF_SECTION *virtual_module_find_cs(char const *virtual_name, char const *method_name, + rlm_components_t *pcomponent) +{ + CONF_SECTION *cs, *subcs; + rlm_components_t method = *pcomponent; + char buffer[256]; + + /* + * Turn the method name into a method enum. + */ + if (method_name) { + rlm_components_t i; + + for (i = MOD_AUTHENTICATE; i < MOD_COUNT; i++) { + if (strcmp(comp2str[i], method_name)) break; + } + + if (i == MOD_COUNT) return NULL; + } + + /* + * Look for "foo" in the "instantiate" section. If we + * find it, AND there's no method name, we've found the + * right thing. + * + * Return it to the caller, with the updated method. + */ + cs = cf_section_find("instantiate"); + if (cs) { + /* + * Found "foo". Load it as "foo", or "foo.method". + */ + subcs = cf_section_sub_find_name2(cs, NULL, virtual_name); + if (subcs) { + *pcomponent = method; + return subcs; + } + } + + /* + * Look for it in "policy". + * + * If there's no policy section, we can't do anything else. + */ + cs = cf_section_find("policy"); + if (!cs) return NULL; + + /* + * "foo.authorize" means "load policy "foo" as method "authorize". + * + * And bail out if there's no policy "foo". + */ + if (method_name) { + subcs = cf_section_sub_find_name2(cs, NULL, virtual_name); + if (subcs) *pcomponent = method; + + return subcs; + } + + /* + * "foo" means "look for foo.component" first, to allow + * method overrides. If that's not found, just look for + * a policy "foo". + * + */ + snprintf(buffer, sizeof(buffer), "%s.%s", + virtual_name, comp2str[method]); + subcs = cf_section_sub_find_name2(cs, NULL, buffer); + if (subcs) return subcs; + + return cf_section_sub_find_name2(cs, NULL, virtual_name); +} + + /* * Compile one entry of a module call. */ @@ -2422,31 +2502,21 @@ static modcallable *do_compile_modsingle(modcallable *parent, * policy { ... name { .. } .. } * policy { ... name.method { .. } .. } * - * The "instantiate" virtual modules are identical to the - * policies at this point. We should probably get rid of - * the "instantiate" ones, as they're duplicate and - * confusing. + * The only difference between things in "instantiate" + * and "policy" is that "instantiate" will cause modules + * to be instantiated in a particular order. */ subcs = NULL; - cs = cf_section_find("instantiate"); - if (cs) subcs = cf_section_sub_find_name2(cs, NULL, - modrefname); - if (!subcs && - (cs = cf_section_find("policy")) != NULL) { + p = strrchr(modrefname, '.'); + if (!p) { + subcs = virtual_module_find_cs(modrefname, NULL, &method); + } else { char buffer[256]; - snprintf(buffer, sizeof(buffer), "%s.%s", - modrefname, comp2str[component]); + strlcpy(buffer, modrefname, sizeof(buffer)); + buffer[p - modrefname] = '\0'; - /* - * Prefer name.section, then name. - */ - subcs = cf_section_sub_find_name2(cs, NULL, - buffer); - if (!subcs) { - subcs = cf_section_sub_find_name2(cs, NULL, - modrefname); - } + subcs = virtual_module_find_cs(buffer, buffer + (p - modrefname) + 1, &method); } /* @@ -2484,7 +2554,7 @@ static modcallable *do_compile_modsingle(modcallable *parent, */ if (cf_section_name2(subcs)) { csingle = do_compile_modsingle(parent, - component, + method, cf_section_to_item(subcs), grouptype, modname); @@ -2499,7 +2569,7 @@ static modcallable *do_compile_modsingle(modcallable *parent, * group foo { ... */ csingle = do_compile_modgroup(parent, - component, + method, subcs, GROUPTYPE_SIMPLE, grouptype, MOD_GROUP); diff --git a/src/tests/keywords/radiusd.conf b/src/tests/keywords/radiusd.conf index c5e0878977e..a57d7097c54 100644 --- a/src/tests/keywords/radiusd.conf +++ b/src/tests/keywords/radiusd.conf @@ -81,6 +81,23 @@ policy { debug_request debug_reply } + + # + # Just check that this can be referred to as "virtual_policy.post-auth" + # + virtual_policy { + ok + } +} + +instantiate { + # + # Just check that this can be referred to as "virtual_instantiate.post-auth" + # + load-balance virtual_instantiate { + ok + ok + } } server default { diff --git a/src/tests/keywords/virtual-load-balance b/src/tests/keywords/virtual-load-balance new file mode 100644 index 00000000000..256c2ff66db --- /dev/null +++ b/src/tests/keywords/virtual-load-balance @@ -0,0 +1,14 @@ +# PRE: update if foreach +# +# Virtual Load-Balance blocks. +# + +# +# Both of these should parse. +# +virtual_instantiate +virtual_instantiate.post-auth + +update reply { + Filter-Id := 'filter' +} diff --git a/src/tests/keywords/virtual_policy b/src/tests/keywords/virtual_policy new file mode 100644 index 00000000000..4ab00e274ae --- /dev/null +++ b/src/tests/keywords/virtual_policy @@ -0,0 +1,15 @@ +# PRE: update if foreach +# +# Virtual policies +# + + +# +# Both of these should parse. +# +virtual_policy +virtual_policy.post-auth + +update reply { + Filter-Id := 'filter' +}