diff --git a/doc/antora/modules/raddb/pages/mods-available/ldap.adoc b/doc/antora/modules/raddb/pages/mods-available/ldap.adoc index 1fc1b45ce69b..95d28b19ce36 100644 --- a/doc/antora/modules/raddb/pages/mods-available/ldap.adoc +++ b/doc/antora/modules/raddb/pages/mods-available/ldap.adoc @@ -744,7 +744,7 @@ binds which there can be on a single thread. The rlm_ldap provides the below xlat's functions. -### %ldap.escape(...} +### %ldap.uri.escape(...} Escape a string for use in an LDAP filter or DN. @@ -755,7 +755,7 @@ Escape a string for use in an LDAP filter or DN. [source,unlang] ---- &my-string := "ldap:///ou=profiles,dc=example,dc=com??sub?(objectClass=radiusprofile)" -&reply.Reply-Message := "The LDAP url is %ldap.escape(%{my-string}}" +&reply.Reply-Message := "The LDAP url is %ldap.uri.escape(%{my-string}}" ---- .Output @@ -764,7 +764,7 @@ Escape a string for use in an LDAP filter or DN. "The LDAP url is ldap:///ou=profiles,dc=example,dc=com??sub?\28objectClass=radiusprofile\29" ``` -### %ldap.unescape(...) +### %ldap.uri.unescape(...) Unescape a string for use in an LDAP filter or DN. @@ -775,7 +775,7 @@ Unescape a string for use in an LDAP filter or DN. [source,unlang] ---- &my-string := "ldap:///ou=profiles,dc=example,dc=com??sub?\28objectClass=radiusprofile\29" -&reply.Reply-Message := "The LDAP url is %ldap.unescape(%{my-string})" +&reply.Reply-Message := "The LDAP url is %ldap.uri.unescape(%{my-string})" ---- .Output diff --git a/raddb/mods-available/ldap b/raddb/mods-available/ldap index ec45c5cfe9ad..76ffbe576031 100644 --- a/raddb/mods-available/ldap +++ b/raddb/mods-available/ldap @@ -884,9 +884,10 @@ ldap { # # The rlm_ldap provides the below xlat's functions. # -# ### %ldap.escape(...} +# ### %ldap.uri.escape(...} # -# Escape a string for use in an LDAP filter or DN. +# Escape a string for use in an LDAP filter or DN. The value will then be marked as safe for use +# in LDAP URIs and DNs, and will not be escaped or modified. # # .Return: _string_ # @@ -895,7 +896,7 @@ ldap { # [source,unlang] # ---- # &my-string := "ldap:///ou=profiles,dc=example,dc=com??sub?(objectClass=radiusprofile)" -# &reply.Reply-Message := "The LDAP url is %ldap.escape(%{my-string}}" +# &reply.Reply-Message := "The LDAP url is %ldap.uri.escape(%{my-string}}" # ---- # # .Output @@ -904,7 +905,22 @@ ldap { # "The LDAP url is ldap:///ou=profiles,dc=example,dc=com??sub?\28objectClass=radiusprofile\29" # ``` # -# ### %ldap.unescape(...) +# ### %ldap.uri.safe(...} +# +# Mark a string as safe for use in an LDAP filter or DN. Values marked as safe for use in LDAP +# URIs will not be escaped or modified, and will be allowed in places where dynamic values are +# usually prohibited. +# +# .Return: _string_ +# +# .Example +# +# [source,unlang] +# ---- +# &my-int := "%ldap.profile(ldap://%ldap.uri.safe(%{LDAP-Host}):%ldap.uri.safe(%{LDAP-Port})/ou=profiles,dc=example,dc=com??sub?(objectClass=radiusprofile)" +# ---- +# +# ### %ldap.uri.unescape(...) # # Unescape a string for use in an LDAP filter or DN. # @@ -915,7 +931,7 @@ ldap { # [source,unlang] # ---- # &my-string := "ldap:///ou=profiles,dc=example,dc=com??sub?\28objectClass=radiusprofile\29" -# &reply.Reply-Message := "The LDAP url is %ldap.unescape(%{my-string})" +# &reply.Reply-Message := "The LDAP url is %ldap.uri.unescape(%{my-string})" # ---- # # .Output diff --git a/src/lib/curl/base.c b/src/lib/curl/base.c index fc23f0066f6d..7428ff6b3783 100644 --- a/src/lib/curl/base.c +++ b/src/lib/curl/base.c @@ -265,6 +265,7 @@ static int fr_curl_init(void) ret = curl_global_init(CURL_GLOBAL_ALL); if (ret != CURLE_OK) { ERROR("CURL init returned error: %i - %s", ret, curl_easy_strerror(ret)); + error: fr_dict_autofree(curl_dict); return -1; } @@ -277,6 +278,47 @@ static int fr_curl_init(void) INFO("libcurl version: %s", curl_version()); + { + xlat_t *xlat; + + /* + * Generic escape function for all CURL based modules + * Use CURL_URI_SAFE_FOR within the module. + */ + xlat = xlat_func_register(NULL, "uri.escape", fr_curl_xlat_uri_escape, FR_TYPE_STRING); + if (unlikely(!xlat)) { + ERROR("Failed registering \"uri.escape\" xlat"); + goto error; + } + xlat_func_args_set(xlat, fr_curl_xlat_uri_args); + xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE); + xlat_func_safe_for_set(xlat, CURL_URI_SAFE_FOR); + + /* + * Generic safe function for all CURL based modules + * Use CURL_URI_SAFE_FOR within the module. + */ + xlat = xlat_func_register(NULL, "uri.safe", xlat_transparent, FR_TYPE_STRING); + if (unlikely(!xlat)) { + ERROR("Failed registering \"uri.safe\" xlat"); + goto error; + } + xlat_func_args_set(xlat, fr_curl_xlat_safe_args); + xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE); + xlat_func_safe_for_set(xlat, CURL_URI_SAFE_FOR); + + /* + * Generic unescape function for all CURL based modules + */ + xlat = xlat_func_register(NULL, "uri.unescape", fr_curl_xlat_uri_unescape, FR_TYPE_STRING); + if (unlikely(!xlat)) { + ERROR("Failed registering \"uri.unescape\" xlat"); + goto error; + } + xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE); + xlat_func_args_set(xlat, fr_curl_xlat_uri_args); + } + return 0; } @@ -288,6 +330,10 @@ static void fr_curl_free(void) fr_openssl_free(); #endif curl_global_cleanup(); + + xlat_func_unregister("uri.escape"); + xlat_func_unregister("uri.safe"); + xlat_func_unregister("uri.unescape"); } /* diff --git a/src/lib/curl/xlat.c b/src/lib/curl/xlat.c index b31ce06f3561..99fcba1fbc2d 100644 --- a/src/lib/curl/xlat.c +++ b/src/lib/curl/xlat.c @@ -36,6 +36,11 @@ xlat_arg_parser_t const fr_curl_xlat_uri_args[] = { XLAT_ARG_PARSER_TERMINATOR }; +xlat_arg_parser_t const fr_curl_xlat_safe_args[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; + /** xlat function to escape URI encoded strings * */ diff --git a/src/lib/curl/xlat.h b/src/lib/curl/xlat.h index b08a2abbc8b8..75e6ea3cce20 100644 --- a/src/lib/curl/xlat.h +++ b/src/lib/curl/xlat.h @@ -30,7 +30,13 @@ extern "C" { #include #include +/** safe for value suitable for all users of the curl library + * + */ +#define CURL_URI_SAFE_FOR ((fr_value_box_safe_for_t)fr_curl_xlat_uri_escape) + extern xlat_arg_parser_t const fr_curl_xlat_uri_args[]; +extern xlat_arg_parser_t const fr_curl_xlat_safe_args[]; xlat_action_t fr_curl_xlat_uri_escape(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, UNUSED request_t *request, diff --git a/src/lib/ldap/base.h b/src/lib/ldap/base.h index 8e346e14432f..5b31227464be 100644 --- a/src/lib/ldap/base.h +++ b/src/lib/ldap/base.h @@ -754,10 +754,10 @@ unlang_action_t fr_ldap_trunk_extended(TALLOC_CTX *ctx, void fr_ldap_timeout_debug(request_t *request, fr_ldap_connection_t const *conn, fr_time_delta_t timeout, char const *prefix); -size_t fr_ldap_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) +size_t fr_ldap_uri_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) CC_HINT(nonnull(2,4)); -size_t fr_ldap_unescape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) +size_t fr_ldap_uri_unescape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) CC_HINT(nonnull(2,4)); ssize_t fr_ldap_xlat_filter(request_t *request, char const **sub, size_t sublen, char *out, size_t outlen); diff --git a/src/lib/ldap/util.c b/src/lib/ldap/util.c index 17e43704ef85..963b0b6cf428 100644 --- a/src/lib/ldap/util.c +++ b/src/lib/ldap/util.c @@ -67,7 +67,7 @@ static const bool escapes[UINT8_MAX + 1] = { * @param in Raw unescaped string. * @param arg Any additional arguments (unused). */ -size_t fr_ldap_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) +size_t fr_ldap_uri_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) { size_t left = outlen; @@ -122,7 +122,7 @@ size_t fr_ldap_escape_func(UNUSED request_t *request, char *out, size_t outlen, * @param in Escaped string string. * @param arg Any additional arguments (unused). */ -size_t fr_ldap_unescape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) +size_t fr_ldap_uri_unescape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg) { char const *p; char *c1, *c2, c3; @@ -532,7 +532,7 @@ ssize_t fr_ldap_xlat_filter(request_t *request, char const **sub, size_t sublen, in = buffer; } - len = xlat_eval(out, outlen, request, in, fr_ldap_escape_func, NULL); + len = xlat_eval(out, outlen, request, in, fr_ldap_uri_escape_func, NULL); if (len < 0) { REDEBUG("Failed creating filter"); diff --git a/src/lib/unlang/xlat.h b/src/lib/unlang/xlat.h index a59317cacb92..729592a2773f 100644 --- a/src/lib/unlang/xlat.h +++ b/src/lib/unlang/xlat.h @@ -427,6 +427,10 @@ int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules); void xlat_debug_attr_list(request_t *request, fr_pair_list_t const *list); void xlat_debug_attr_vp(request_t *request, fr_pair_t *vp, tmpl_t const *vpt); + +xlat_action_t xlat_transparent(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, + UNUSED xlat_ctx_t const *xctx, + request_t *request, fr_value_box_list_t *args); /* * xlat_tokenize.c */ diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index 677570e0bf52..206830590df4 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -255,6 +255,24 @@ void xlat_debug_attr_list(request_t *request, fr_pair_list_t const *list) } } +/** Common function to move boxes form input list to output list + * + * This can be used to implement safe_for functions, as the xlat framework + * can be used for concatenation, casting, and marking up output boxes as + * safe_for. + */ +xlat_action_t xlat_transparent(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, + UNUSED xlat_ctx_t const *xctx, + UNUSED request_t *request, fr_value_box_list_t *args) +{ + fr_value_box_list_foreach_safe(args, vb) { + fr_value_box_list_remove(args, vb); + fr_dcursor_append(out, vb); + }} + + return XLAT_ACTION_DONE; +} + /** Print out attribute info * * Prints out all instances of a current attribute, or all attributes in a list. diff --git a/src/modules/rlm_ldap/groups.c b/src/modules/rlm_ldap/groups.c index e83235132bd8..2f342e1a86b4 100644 --- a/src/modules/rlm_ldap/groups.c +++ b/src/modules/rlm_ldap/groups.c @@ -137,7 +137,7 @@ static unlang_action_t ldap_group_name2dn_start(rlm_rcode_t *p_result, UNUSED in inst->groupobj_filter ? inst->groupobj_filter : "", group_ctx->group_name[0] && group_ctx->group_name[1] ? "(|" : ""); while (*name) { - fr_ldap_escape_func(request, buffer, sizeof(buffer), *name++, NULL); + fr_ldap_uri_escape_func(request, buffer, sizeof(buffer), *name++, NULL); filter = talloc_asprintf_append_buffer(filter, "(%s=%s)", inst->groupobj_name_attr, buffer); group_ctx->name_cnt++; diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c index bdf3881d6978..812861978013 100644 --- a/src/modules/rlm_ldap/rlm_ldap.c +++ b/src/modules/rlm_ldap/rlm_ldap.c @@ -363,20 +363,25 @@ static size_t ldap_uri_scheme_table_len = NUM_ELEMENTS(ldap_uri_scheme_table); /** This is the common function that actually ends up doing all the URI escaping */ -#define LDAP_URI_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_escape_func +#define LDAP_URI_SAFE_FOR (fr_value_box_safe_for_t)fr_ldap_uri_escape_func -static xlat_arg_parser_t const ldap_escape_xlat_arg[] = { +static xlat_arg_parser_t const ldap_uri_escape_xlat_arg[] = { { .required = true, .concat = true, .type = FR_TYPE_STRING, .safe_for = LDAP_URI_SAFE_FOR }, XLAT_ARG_PARSER_TERMINATOR }; +static xlat_arg_parser_t const ldap_safe_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; + /** Escape LDAP string * * @ingroup xlat_functions */ -static xlat_action_t ldap_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, - UNUSED xlat_ctx_t const *xctx, - request_t *request, fr_value_box_list_t *in) +static xlat_action_t ldap_uri_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, + UNUSED xlat_ctx_t const *xctx, + request_t *request, fr_value_box_list_t *in) { fr_value_box_t *vb, *in_vb = fr_value_box_list_head(in); fr_sbuff_t sbuff; @@ -388,7 +393,7 @@ static xlat_action_t ldap_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, /* * If it's already safe, just copy it over. */ - if (fr_value_box_is_safe_for(in_vb, ldap_escape_xlat)) { + if (fr_value_box_is_safe_for(in_vb, LDAP_URI_SAFE_FOR)) { fr_value_box_copy(vb, vb, in_vb); fr_dcursor_append(out, vb); @@ -408,7 +413,7 @@ static xlat_action_t ldap_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, /* * Call the escape function, including the space for the trailing NULL */ - len = fr_ldap_escape_func(request, fr_sbuff_buff(&sbuff), in_vb->vb_length * 3 + 1, in_vb->vb_strvalue, NULL); + len = fr_ldap_uri_escape_func(request, fr_sbuff_buff(&sbuff), in_vb->vb_length * 3 + 1, in_vb->vb_strvalue, NULL); /* * Trim buffer to fit used space and assign to box @@ -420,13 +425,18 @@ static xlat_action_t ldap_escape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_DONE; } +static xlat_arg_parser_t const ldap_uri_unescape_xlat_arg[] = { + { .required = true, .concat = true, .type = FR_TYPE_STRING }, + XLAT_ARG_PARSER_TERMINATOR +}; + /** Unescape LDAP string * * @ingroup xlat_functions */ -static xlat_action_t ldap_unescape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, - UNUSED xlat_ctx_t const *xctx, - request_t *request, fr_value_box_list_t *in) +static xlat_action_t ldap_uri_unescape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, + UNUSED xlat_ctx_t const *xctx, + request_t *request, fr_value_box_list_t *in) { fr_value_box_t *vb, *in_vb = fr_value_box_list_head(in); fr_sbuff_t sbuff; @@ -446,7 +456,7 @@ static xlat_action_t ldap_unescape_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, /* * Call the unescape function, including the space for the trailing NULL */ - len = fr_ldap_unescape_func(request, fr_sbuff_buff(&sbuff), in_vb->vb_length + 1, in_vb->vb_strvalue, NULL); + len = fr_ldap_uri_unescape_func(request, fr_sbuff_buff(&sbuff), in_vb->vb_length + 1, in_vb->vb_strvalue, NULL); /* * Trim buffer to fit used space and assign to box @@ -479,7 +489,7 @@ static int ldap_uri_part_escape(fr_value_box_t *vb, UNUSED void *uctx) /* * Call the escape function, including the space for the trailing NULL */ - len = fr_ldap_escape_func(NULL, fr_sbuff_buff(&sbuff), vb->vb_length * 3 + 1, vb->vb_strvalue, NULL); + len = fr_ldap_uri_escape_func(NULL, fr_sbuff_buff(&sbuff), vb->vb_length * 3 + 1, vb->vb_strvalue, NULL); fr_sbuff_trim_talloc(&sbuff, len); fr_value_box_clear_value(vb); @@ -2593,13 +2603,18 @@ static int mod_load(void) { xlat_t *xlat; - if (unlikely(!(xlat = xlat_func_register(NULL, "ldap.escape", ldap_escape_xlat, FR_TYPE_STRING)))) return -1; - xlat_func_mono_set(xlat, ldap_escape_xlat_arg); + if (unlikely(!(xlat = xlat_func_register(NULL, "ldap.uri.escape", ldap_uri_escape_xlat, FR_TYPE_STRING)))) return -1; + xlat_func_mono_set(xlat, ldap_uri_escape_xlat_arg); xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE); xlat_func_safe_for_set(xlat, LDAP_URI_SAFE_FOR); /* Used for all LDAP escaping */ - if (unlikely(!(xlat = xlat_func_register(NULL, "ldap.unescape", ldap_unescape_xlat, FR_TYPE_STRING)))) return -1; - xlat_func_mono_set(xlat, ldap_escape_xlat_arg); + if (unlikely(!(xlat = xlat_func_register(NULL, "ldap.uri.safe", xlat_transparent, FR_TYPE_STRING)))) return -1; + xlat_func_args_set(xlat, ldap_safe_xlat_arg); + xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE); + xlat_func_safe_for_set(xlat, LDAP_URI_SAFE_FOR); + + if (unlikely(!(xlat = xlat_func_register(NULL, "ldap.uri.unescape", ldap_uri_unescape_xlat, FR_TYPE_STRING)))) return -1; + xlat_func_mono_set(xlat, ldap_uri_unescape_xlat_arg); xlat_func_flags_set(xlat, XLAT_FUNC_FLAG_PURE); return 0; @@ -2607,8 +2622,9 @@ static int mod_load(void) static void mod_unload(void) { - xlat_func_unregister("ldap.escape"); - xlat_func_unregister("ldap.unescape"); + xlat_func_unregister("ldap.uri.escape"); + xlat_func_unregister("ldap.uri.safe"); + xlat_func_unregister("ldap.uri.unescape"); } /* globally exported name */ diff --git a/src/modules/rlm_rest/rlm_rest.c b/src/modules/rlm_rest/rlm_rest.c index 1dc539bb3b7a..1bdf65233f37 100644 --- a/src/modules/rlm_rest/rlm_rest.c +++ b/src/modules/rlm_rest/rlm_rest.c @@ -52,14 +52,12 @@ RCSID("$Id$") static int rest_uri_part_escape(fr_value_box_t *vb, void *uctx); static void *rest_uri_part_escape_uctx_alloc(UNUSED request_t *request, void const *uctx); -#define REST_URI_SAFE_FOR (fr_value_box_safe_for_t)fr_curl_xlat_uri_escape - static fr_uri_part_t const rest_uri_parts[] = { - { .name = "scheme", .safe_for = REST_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L(":")), .part_adv = { [':'] = 1 }, .extra_skip = 2 }, - { .name = "host", .safe_for = REST_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L(":"), L("/")), .part_adv = { [':'] = 1, ['/'] = 2 }, .func = rest_uri_part_escape }, - { .name = "port", .safe_for = REST_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L("/")), .part_adv = { ['/'] = 1 } }, - { .name = "method", .safe_for = REST_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L("?")), .part_adv = { ['?'] = 1 }, .func = rest_uri_part_escape }, - { .name = "param", .safe_for = REST_URI_SAFE_FOR, .func = rest_uri_part_escape }, + { .name = "scheme", .safe_for = CURL_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L(":")), .part_adv = { [':'] = 1 }, .extra_skip = 2 }, + { .name = "host", .safe_for = CURL_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L(":"), L("/")), .part_adv = { [':'] = 1, ['/'] = 2 }, .func = rest_uri_part_escape }, + { .name = "port", .safe_for = CURL_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L("/")), .part_adv = { ['/'] = 1 } }, + { .name = "method", .safe_for = CURL_URI_SAFE_FOR, .terminals = &FR_SBUFF_TERMS(L("?")), .part_adv = { ['?'] = 1 }, .func = rest_uri_part_escape }, + { .name = "param", .safe_for = CURL_URI_SAFE_FOR, .func = rest_uri_part_escape }, XLAT_URI_PART_TERMINATOR }; @@ -215,9 +213,9 @@ static const call_env_method_t _var = { \ } , \ .type = TMPL_ESCAPE_UCTX_ALLOC_FUNC\ }, \ - .safe_for = REST_URI_SAFE_FOR \ + .safe_for = CURL_URI_SAFE_FOR \ }, \ - .pair.literals_safe_for = REST_URI_SAFE_FOR}, /* Do not concat */ \ + .pair.literals_safe_for = CURL_URI_SAFE_FOR}, /* Do not concat */ \ REST_CALL_ENV_REQUEST_COMMON(_dflt_username, _dflt_password) \ CALL_ENV_TERMINATOR \ })) }, \ @@ -497,7 +495,7 @@ static xlat_action_t rest_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, } static xlat_arg_parser_t const rest_xlat_args[] = { - { .required = true, .safe_for = REST_URI_SAFE_FOR, .type = FR_TYPE_STRING }, + { .required = true, .safe_for = CURL_URI_SAFE_FOR, .type = FR_TYPE_STRING }, { .variadic = XLAT_ARG_VARIADIC_EMPTY_KEEP, .type = FR_TYPE_STRING }, XLAT_ARG_PARSER_TERMINATOR }; @@ -1378,33 +1376,9 @@ static int mod_load(void) fr_json_version_print(); #endif - { - xlat_t *xlat; - - xlat = xlat_func_register(NULL, "rest.escape", fr_curl_xlat_uri_escape, FR_TYPE_STRING); - if (unlikely(!xlat)) { - ERROR("Failed registering \"rest.escape\" xlat"); - return -1; - } - xlat_func_args_set(xlat, fr_curl_xlat_uri_args); - xlat_func_safe_for_set(xlat, REST_URI_SAFE_FOR); /* Each instance of the uri_escape xlat has its own safe_for value */ - xlat = xlat_func_register(NULL, "rest.unescape", fr_curl_xlat_uri_unescape, FR_TYPE_STRING); - if (unlikely(!xlat)) { - ERROR("Failed registering \"rest.unescape\" xlat"); - return -1; - } - xlat_func_args_set(xlat, fr_curl_xlat_uri_args); - } - return 0; } -static void mod_unload(void) -{ - xlat_func_unregister("rest.escape"); - xlat_func_unregister("rest.unescape"); -} - /* * The module name should be the only globally exported symbol. * That is, everything else should be 'static'. @@ -1424,7 +1398,6 @@ module_rlm_t rlm_rest = { .thread_inst_size = sizeof(rlm_rest_thread_t), .config = module_config, .onload = mod_load, - .unload = mod_unload, .bootstrap = mod_bootstrap, .instantiate = instantiate, .thread_instantiate = mod_thread_instantiate, diff --git a/src/tests/modules/ldap/xlat.unlang b/src/tests/modules/ldap/xlat.unlang index 409f842ba402..753d225906bf 100644 --- a/src/tests/modules/ldap/xlat.unlang +++ b/src/tests/modules/ldap/xlat.unlang @@ -8,13 +8,13 @@ string result_string &test_string := "safe string" # String with no escaping -&result_string := %ldap.escape(%{test_string}) +&result_string := %ldap.uri.escape(%{test_string}) if (!(&result_string == "safe string")) { test_fail } -&result_string := %ldap.unescape(%{result_string}) +&result_string := %ldap.uri.unescape(%{result_string}) if (!(&result_string == 'safe string')) { test_fail @@ -22,13 +22,13 @@ if (!(&result_string == 'safe string')) { # String with some characters to escape &test_string := 'non safe,+"\<>;*=() string' -&result_string := %ldap.escape(%{test_string}) +&result_string := %ldap.uri.escape(%{test_string}) if (!(&result_string == 'non safe\2c\2b\22\5c\3c\3e\3b\2a\3d\28\29 string')) { test_fail } -&result_string := %ldap.unescape(%{result_string}) +&result_string := %ldap.uri.unescape(%{result_string}) if (!(&result_string == 'non safe,+"\<>;*=() string')) { test_fail @@ -36,13 +36,13 @@ if (!(&result_string == 'non safe,+"\<>;*=() string')) { # String where all characters require escaping &test_string := ',+"\<>;*=()' -&result_string := %ldap.escape(%{test_string}) +&result_string := %ldap.uri.escape(%{test_string}) if (!(&result_string == '\2c\2b\22\5c\3c\3e\3b\2a\3d\28\29')) { test_fail } -&result_string := %ldap.unescape(%{result_string}) +&result_string := %ldap.uri.unescape(%{result_string}) if (!(&result_string == ',+"\<>;*=()')) { test_fail @@ -90,7 +90,7 @@ if (!(&result_string == "Fred Jones")) { } # Reference an alternative LDAP server in the xlat -&result_string := %ldap("ldap://$ENV{LDAP_TEST_SERVER}:%ldap.escape(%{$ENV{LDAP_TEST_SERVER_PORT} + 1})/dc=subdept,dc=example,dc=com?displayName?sub?(uid=fred)") +&result_string := %ldap("ldap://$ENV{LDAP_TEST_SERVER}:%ldap.uri.escape(%{$ENV{LDAP_TEST_SERVER_PORT} + 1})/dc=subdept,dc=example,dc=com?displayName?sub?(uid=fred)") if (!(&result_string == "Fred Jones")) { test_fail diff --git a/src/tests/modules/rest/rest_xlat.unlang b/src/tests/modules/rest/rest_xlat.unlang index 465e22eee7a6..2b70e7295c67 100644 --- a/src/tests/modules/rest/rest_xlat.unlang +++ b/src/tests/modules/rest/rest_xlat.unlang @@ -13,7 +13,7 @@ string result_string &test_string := 'notfound' # Retrieve a plain text file -&result_string := %rest('GET', "http://%{server_host}:%rest.escape(%{server_port})/test.txt") +&result_string := %rest('GET', "http://%{server_host}:%uri.safe(%{server_port})/test.txt") if (!(&REST-HTTP-Status-Code == 200)) { test_fail @@ -24,13 +24,13 @@ if (!(&result_string == "Sample text response\n")) { } # Take host from incoming packet -&result_string := %rest("http://%{Login-IP-Host}:%rest.escape(%{server_port})/test.txt") +&result_string := %rest("http://%{Login-IP-Host}:%uri.safe(%{server_port})/test.txt") if (!(&REST-HTTP-Status-Code == 200) || !(&result_string == "Sample text response\n")) { test_fail } -# Port is not allowed from incoming packet +# Port is not allowed from incoming packets &result_string := %rest("http://%{server_host}:%{NAS-Port}/test.txt") if (!(&Module-Failure-Message == "Failed escaping URI: Unsafe input \"8080\" not allowed in URI part port") || &result_string) { @@ -38,14 +38,14 @@ if (!(&Module-Failure-Message == "Failed escaping URI: Unsafe input \"8080\" not } # Check a "not found" gives a 404 status code -&result_string := %rest('GET', "http://%{server_host}:%rest.escape(%{server_port})/%{test_string}") +&result_string := %rest('GET', "http://%{server_host}:%uri.safe(%{server_port})/%{test_string}") if (!(&REST-HTTP-Status-Code == 404)) { test_fail } # GET with URL parameters -&test_string := %rest('GET', "http://%{server_host}:%rest.escape(%{server_port})/user/%{User-Name}/mac/%{Called-Station-Id}") +&test_string := %rest('GET', "http://%{server_host}:%uri.safe(%{server_port})/user/%{User-Name}/mac/%{Called-Station-Id}") if (!(&REST-HTTP-Status-Code == 200)) { test_fail @@ -67,7 +67,7 @@ if (!(&control.User-Name == "Bob")) { &control.User-Name := 'dummy' # Directly use json map and prepend the returned value -map json %rest('GET', "http://%{server_host}:%rest.escape(%{server_port})/user/%{User-Name}/mac/%{Called-Station-Id}") { +map json %rest('GET', "http://%{server_host}:%uri.safe(%{server_port})/user/%{User-Name}/mac/%{Called-Station-Id}") { &control.User-Name ^= '$.control\.User-Name.value' } @@ -78,7 +78,7 @@ if (!(&control.User-Name[0] == 'Bob') || !(&control.User-Name[1] == 'dummy')) { &test_string := %json.encode('&request.NAS-IP-Address') # POST to https with JSON body data -&result_string := %rest('POST', "https://%{server_host}:%rest.escape(%{server_ssl_port})/user/%{User-Name}/mac/%{Called-Station-Id}?section=accounting", %{test_string}) +&result_string := %rest('POST', "https://%{server_host}:%uri.safe(%{server_ssl_port})/user/%{User-Name}/mac/%{Called-Station-Id}?section=accounting", %{test_string}) if (!(&REST-HTTP-Status-Code == 200)) { test_fail @@ -105,7 +105,7 @@ if (!(&control.NAS-IP-Address == "192.168.1.1")) { &result_string := "NAS=%{NAS-IP-Address}&user=%{User-Name}" # POST to https with POST body data -&result_string := %rest('POST', "https://%{server_host}:%rest.escape(%{server_ssl_port})/post/test?section=dummy", %{result_string}) +&result_string := %rest('POST', "https://%{server_host}:%uri.safe(%{server_ssl_port})/post/test?section=dummy", %{result_string}) if (!(&REST-HTTP-Status-Code == 200)) { test_fail @@ -122,7 +122,7 @@ group { string arguments string body - map json %rest('POST', "http://%{server_host}:%rest.escape(%{server_port})/user/%{User-Name}/reflect/?station=%{Calling-Station-Id}", "{\"test\":\"foo\"}") { + map json %rest('POST', "http://%{server_host}:%uri.safe(%{server_port})/user/%{User-Name}/reflect/?station=%{Calling-Station-Id}", "{\"test\":\"foo\"}") { &headers := '$.reply\.Reply-Message.value[0]' &arguments := '$.reply\.Reply-Message.value[1]' &body := '$.reply\.Reply-Message.value[2]' @@ -160,7 +160,7 @@ group { &test_string := "" - map json %rest(http://%{server_host}:%rest.escape(%{server_port})/user/%{User-Name}/reflect/%{test_string}?station=%{User-Name}) { + map json %rest(http://%{server_host}:%uri.safe(%{server_port})/user/%{User-Name}/reflect/%{test_string}?station=%{User-Name}) { &headers := '$.reply\.Reply-Message.value[0]' &arguments := '$.reply\.Reply-Message.value[1]' } @@ -190,7 +190,7 @@ group { group { string arguments - map json %rest("http://%{server_host}:%rest.escape(%{server_port})/user/%{User-Name}/reflect/%{NAS-Identifier}?station=%{Called-Station-Id}") { + map json %rest("http://%{server_host}:%uri.safe(%{server_port})/user/%{User-Name}/reflect/%{NAS-Identifier}?station=%{Called-Station-Id}") { &arguments := '$.reply\.Reply-Message.value[1]' } @@ -202,7 +202,7 @@ group { } # Test against endpoint which will time out -&result_string := %restshorttimeout("http://%{server_host}:%rest.escape(%{server_port})/delay") +&result_string := %restshorttimeout("http://%{server_host}:%uri.safe(%{server_port})/delay") if (&REST-HTTP-Status-Code) { test_fail