diff --git a/raddb/radiusd.conf.in b/raddb/radiusd.conf.in index 090308833c38..376892e15185 100644 --- a/raddb/radiusd.conf.in +++ b/raddb/radiusd.conf.in @@ -290,6 +290,27 @@ hostname_lookups = no # #proxy_dedup_window = 1 +# +# Unlang behavior options +# +unlang { + # + # By default, the "return" keyword will cause the current process + # section to complete. These two options allow "return" to be + # used to just exit "group" sections or "policy" sections + # + # Setting this to yes, will cause "return" within a group to + # exit the group but continue processing after that. + # +# group_stop_return = no + + # + # Setting this to yes, will cause "return" within a policy to + # exit the policy but continue processing after that. + # +# policy_stop_return = no +} + # # Logging section. The various "log_*" configuration items # will eventually be moved here. diff --git a/src/include/radiusd.h b/src/include/radiusd.h index ec69b8d4e096..5e65b32927dc 100644 --- a/src/include/radiusd.h +++ b/src/include/radiusd.h @@ -183,6 +183,9 @@ typedef struct main_config { #ifdef ENABLE_OPENSSL_VERSION_CHECK char const *allow_vulnerable_openssl; //!< The CVE number of the last security issue acknowledged. #endif + + bool group_stop_return; //!< "return" stops at end of group + bool policy_stop_return; //!< "return" stops at end of policy } main_config_t; #if defined(WITH_VERIFY_PTR) diff --git a/src/main/mainconfig.c b/src/main/mainconfig.c index 6cb8a25c4e79..debfb296f030 100644 --- a/src/main/mainconfig.c +++ b/src/main/mainconfig.c @@ -230,6 +230,15 @@ static const CONF_PARSER resources[] = { CONF_PARSER_TERMINATOR }; +static const CONF_PARSER unlang_config[] = { + /* + * Unlang behaviour options + */ + { "group_stop_return", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &main_config.group_stop_return), "no" }, + { "policy_stop_return", FR_CONF_POINTER(PW_TYPE_BOOLEAN, &main_config.policy_stop_return), "no" }, + CONF_PARSER_TERMINATOR +}; + static const CONF_PARSER server_config[] = { /* * FIXME: 'prefix' is the ONLY one which should be @@ -282,6 +291,8 @@ static const CONF_PARSER server_config[] = { { "log_stripped_names", FR_CONF_POINTER(PW_TYPE_BOOLEAN | PW_TYPE_DEPRECATED, &log_stripped_names), NULL }, { "security", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) security_config }, + + { "unlang", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) unlang_config }, CONF_PARSER_TERMINATOR }; diff --git a/src/main/modcall.c b/src/main/modcall.c index 5a3116cc58cd..29fc2be1b991 100644 --- a/src/main/modcall.c +++ b/src/main/modcall.c @@ -1096,6 +1096,12 @@ static bool modcall_recurse(REQUEST *request, rlm_components_t component, int de } if (entry->unwind == MOD_RETURN) { + if ((entry->c->type == MOD_GROUP && main_config.group_stop_return) || + (entry->c->type == MOD_POLICY && main_config.policy_stop_return)) { + entry->unwind = 0; + goto next_sibling; + } + goto finish; } diff --git a/src/tests/map/map_unit.c b/src/tests/map/map_unit.c index af6d016a5ab8..24f1a291b1bc 100644 --- a/src/tests/map/map_unit.c +++ b/src/tests/map/map_unit.c @@ -54,6 +54,9 @@ pid_t rad_waitpid(pid_t pid, int *status) } #endif +/* Dummy config to allow linking to modcall */ +main_config_t main_config; + rlm_rcode_t indexed_modcall(UNUSED rlm_components_t comp, UNUSED int idx, UNUSED REQUEST *request) { return RLM_MODULE_OK;