}
-static size_t config_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
+static int xlat_config_escape(UNUSED request_t *request, fr_value_box_t *vb, UNUSED void *uctx)
{
- size_t len = 0;
- static char const disallowed[] = "%{}\\'\"`";
-
- while (in[0]) {
+ static char const disallowed[] = "%{}\\'\"`";
+ size_t outmax = vb->vb_length * 3;
+ size_t outlen = 0;
+ char escaped[outmax];
+ char const *in, *end;
+ char *out = escaped;
+
+ fr_assert(vb->type == FR_TYPE_STRING);
+ in = vb->vb_strvalue;
+ end = in + vb->vb_length;
+
+ do {
/*
* Non-printable characters get replaced with their
* mime-encoded equivalents.
*/
if ((in[0] < 32)) {
- if (outlen <= 3) break;
+ if (outlen >= (outmax - 3)) return -1;
snprintf(out, outlen, "=%02X", (unsigned char) in[0]);
- in++;
out += 3;
- outlen -= 3;
- len += 3;
+ outlen += 3;
continue;
} else if (strchr(disallowed, *in) != NULL) {
- if (outlen <= 2) break;
+ if (outlen >= (outmax - 2)) return -1;
out[0] = '\\';
out[1] = *in;
- in++;
out += 2;
- outlen -= 2;
- len += 2;
+ outlen += 2;
continue;
}
/*
* Only one byte left.
*/
- if (outlen <= 1) {
- break;
- }
+ if (outlen >= (outmax - 1)) return -1;
/*
* Allowed character.
*/
*out = *in;
out++;
- in++;
- outlen--;
- len++;
- }
+ outlen++;
+ } while (++in < end);
*out = '\0';
- return len;
+
+ /*
+ * If the output length is greater than the input length
+ * something has been escaped - replace the original string
+ */
+ if (outlen > vb->vb_length) {
+ char *outbuff;
+ fr_value_box_bstr_realloc(vb, &outbuff, vb, outlen);
+ memcpy(outbuff, escaped, outlen);
+ }
+
+ return 0;
+
}
+static xlat_arg_parser_t const xlat_config_args[] = {
+ { .required = true, .concat = true, .type = FR_TYPE_STRING, .always_escape = true, .func = xlat_config_escape },
+ XLAT_ARG_PARSER_TERMINATOR
+};
+
/** xlat to get config values
*
@verbatim
-%{config:section.subsection.attribute}
+%(config:section.subsection.attribute)
@endverbatim
*
* @ingroup xlat_functions
*/
-static ssize_t xlat_config(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
- UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
- request_t *request, char const *fmt)
+static xlat_action_t xlat_config(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
+ UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
+ fr_value_box_list_t *in)
{
- char const *value;
- CONF_PAIR *cp;
- CONF_ITEM *ci;
- char buffer[1024];
-
- /*
- * Expand it safely.
- */
- if (xlat_eval(buffer, sizeof(buffer), request, fmt, config_escape_func, NULL) < 0) return 0;
+ char const *value;
+ CONF_PAIR *cp;
+ CONF_ITEM *ci;
+ fr_value_box_t *in_head = fr_dlist_head(in);
+ fr_value_box_t *vb;
- ci = cf_reference_item(main_config->root_cs, main_config->root_cs, buffer);
+ ci = cf_reference_item(main_config->root_cs, main_config->root_cs, in_head->vb_strvalue);
if (!ci || !cf_item_is_pair(ci)) {
- REDEBUG("Config item \"%s\" does not exist", fmt);
- return -1;
+ REDEBUG("Config item \"%pV\" does not exist", in_head);
+ return XLAT_ACTION_FAIL;
}
cp = cf_item_to_pair(ci);
- /*
- * Ensure that we only copy what's necessary.
- *
- * If 'outlen' is too small, then the output is chopped to fit.
- */
value = cf_pair_value(cp);
- if (!value) return 0;
-
- if (outlen > strlen(value)) outlen = strlen(value) + 1;
+ if (!value) return XLAT_ACTION_DONE;
- strlcpy(*out, value, outlen);
+ MEM(vb = fr_value_box_alloc_null(ctx));
+ fr_value_box_bstrndup(ctx, vb, NULL, value, strlen(value), false);
+ fr_dcursor_append(out, vb);
- return strlen(*out);
+ return XLAT_ACTION_DONE;
}
#ifdef HAVE_SETUID
*/
int main_config_init(main_config_t *config)
{
- char const *p = NULL;
- CONF_SECTION *cs = NULL, *subcs;
- struct stat statbuf;
- bool can_colourise = false;
- char buffer[1024];
+ char const *p = NULL;
+ CONF_SECTION *cs = NULL, *subcs;
+ struct stat statbuf;
+ bool can_colourise = false;
+ char buffer[1024];
+ xlat_t *xlat;
if (stat(config->raddb_dir, &statbuf) < 0) {
ERROR("Error checking raddb_dir \"%s\": %s", config->raddb_dir, fr_syserror(errno));
if (!client_list_parse_section(cs, 0, false)) goto failure;
/*
- * Register the %{config:section.subsection} xlat function.
+ * Register the %(config:section.subsection) xlat function.
*/
- xlat_register_legacy(NULL, "config", xlat_config, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN);
+ xlat = xlat_register(NULL, "config", xlat_config, false);
+ xlat_func_args(xlat, xlat_config_args);
/*
* Ensure cwd is inside the chroot.