void *escape_ctx);
typedef size_t (*RAD_XLAT_FUNC)(void *instance, REQUEST *, const char *, char *, size_t);
-int xlat_register(const char *module, RAD_XLAT_FUNC func,
+int xlat_register(const char *module, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING escape,
void *instance);
void xlat_unregister(const char *module, RAD_XLAT_FUNC func,
void *instance);
*/
if (!*head) return -1;
- xlat_register("listen", xlat_listen, NULL);
+ xlat_register("listen", xlat_listen, NULL, NULL);
return 0;
}
/*
* Register the %{config:section.subsection} xlat function.
*/
- xlat_register("config", xlat_config, NULL);
- xlat_register("client", xlat_client, NULL);
+ xlat_register("config", xlat_config, NULL, NULL);
+ xlat_register("client", xlat_client, NULL, NULL);
/*
* Starting the server, WITHOUT "-x" on the
#ifdef WITH_PROXY
- xlat_register("home_server", xlat_home_server, NULL);
- xlat_register("home_server_pool", xlat_server_pool, NULL);
+ xlat_register("home_server", xlat_home_server, NULL, NULL);
+ xlat_register("home_server_pool", xlat_server_pool, NULL, NULL);
#endif
/*
char module[MAX_STRING_LEN];
int length;
void *instance;
- RAD_XLAT_FUNC do_xlat;
+ RAD_XLAT_FUNC func;
+ RADIUS_ESCAPE_STRING escape;
int internal; /* not allowed to re-define these */
} xlat_t;
* @param instance argument to xlat function
* @return 0 on success, -1 on failure
*/
-int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance)
+int xlat_register(const char *module, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING escape, void *instance)
{
xlat_t *c;
xlat_t my_xlat;
#ifdef WITH_UNLANG
for (i = 0; xlat_foreach_names[i] != NULL; i++) {
xlat_register(xlat_foreach_names[i],
- xlat_foreach, &xlat_inst[i]);
+ xlat_foreach, NULL, &xlat_inst[i]);
c = xlat_find(xlat_foreach_names[i]);
rad_assert(c != NULL);
c->internal = TRUE;
}
#endif
-#define XLAT_REGISTER(_x) xlat_register(Stringify(_x), xlat_ ## _x, NULL); \
+#define XLAT_REGISTER(_x) xlat_register(Stringify(_x), xlat_ ## _x, NULL, NULL); \
c = xlat_find(Stringify(_x)); \
rad_assert(c != NULL); \
c->internal = TRUE
XLAT_REGISTER(xlat);
XLAT_REGISTER(module);
- xlat_register("debug", xlat_debug, &xlat_inst[0]);
+ xlat_register("debug", xlat_debug, NULL, &xlat_inst[0]);
c = xlat_find("debug");
rad_assert(c != NULL);
c->internal = TRUE;
return -1;
}
- c->do_xlat = func;
+ c->func = func;
+ c->escape = escape;
c->instance = instance;
return 0;
}
c = rad_malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
- c->do_xlat = func;
+ c->func = func;
+ c->escape = escape;
strlcpy(c->module, module, sizeof(c->module));
c->length = strlen(c->module);
c->instance = instance;
rbtree_free(xlat_root);
}
+#if 0
+#define XLAT_DEBUG DEBUG3
+#else
+#define XLAT_DEBUG(...)
+#endif
+
static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
const char **error);
static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
int brace, const char **error);
+static size_t xlat_process(char **out, REQUEST *request, const xlat_exp_t * const head,
+ RADIUS_ESCAPE_STRING escape, void *escape_ctx);
static ssize_t xlat_tokenize_alternation(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
const char **error)
rad_assert(fmt[2] == '%');
rad_assert(fmt[3] == '{');
+ XLAT_DEBUG("ALTERNATE: %s", fmt);
+
node = talloc_zero(ctx, xlat_exp_t);
node->type = XLAT_ALTERNATE;
return xlat_tokenize_alternation(ctx, fmt, head, error);
}
+ XLAT_DEBUG("EXPANSION: %s", fmt);
node = talloc_zero(ctx, xlat_exp_t);
attrname = node->fmt = fmt + 2;
node->len = 0;
return -2;
}
+ XLAT_DEBUG("REGEX: %s", fmt);
fmt[3] = '\0';
node->num = fmt[2] - '0'; /* ASCII */
}
#endif /* HAVE_REGEX_H */
-
p = strchr(node->fmt, ':');
if (p) {
*(p++) = '\0';
if (node->xlat) {
node->type = XLAT_MODULE;
+ XLAT_DEBUG("MOD: %s --> %s", node->fmt, p);
slen = xlat_tokenize_literal(node, p, &node->child, TRUE, error);
if (slen < 0) {
talloc_free(node);
if (!*fmt) return 0;
+ XLAT_DEBUG("LITERAL: %s", fmt);
+
node = talloc_zero(ctx, xlat_exp_t);
node->fmt = fmt;
node->len = 0;
if ((p[0] == '%') && (p[1] == '{')) {
ssize_t slen;
+ XLAT_DEBUG("LITERAL: %s --> %s", node->fmt, p);
slen = xlat_tokenize_expansion(node, p, &node->next, error);
if (slen < 0) {
talloc_free(node);
return slen - (p - fmt);
}
+ *p = '\0'; /* end the literal */
p += slen;
rad_assert(node->next != NULL);
while (node) {
switch (node->type) {
case XLAT_LITERAL:
- DEBUG("%.*sliteral: %s", lvl, xlat_tabs, node->fmt);
+ DEBUG("%.*sliteral: '%s'", lvl, xlat_tabs, node->fmt);
break;
case XLAT_PERCENT:
- DEBUG("%.*sliteral (with %%): %s", lvl, xlat_tabs, node->fmt);
+ DEBUG("%.*sliteral (with %%): '%s'", lvl, xlat_tabs, node->fmt);
break;
case XLAT_ATTRIBUTE:
return vp_asprintf(ctx, vp);
}
-static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, const xlat_exp_t * const node)
+static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, const xlat_exp_t * const node,
+ RADIUS_ESCAPE_STRING escape, void *escape_ctx, int lvl)
{
size_t rcode;
char *str, *child;
REQUEST *ref;
+ XLAT_DEBUG("%.*sxlat aprint %d", lvl, xlat_spaces, node->type);
+
switch (node->type) {
+ /*
+ * Don't escape this
+ */
case XLAT_LITERAL:
- str = talloc_strdup(ctx, node->fmt);
- break;
+ return talloc_strdup(ctx, node->fmt);
case XLAT_PERCENT: {
const char *p;
* Some attributes are virtual <sigh>
*/
str = xlat_getvp(ctx, ref, node->list, node->da, node->tag);
+ XLAT_DEBUG("expand attr %s --> '%s'", node->da->name, str);
break;
case XLAT_MODULE:
rad_assert(node->child != NULL);
- child = xlat_aprint(ctx, request, node->child);
- if (!child) return NULL;
+ if (xlat_process(&child, request, node->child, node->xlat->escape, node->xlat->instance) == 0) {
+ rad_assert(child == NULL);
+ return NULL;
+ }
+
+ XLAT_DEBUG("%.*sexpand mod %s --> '%s'", lvl, xlat_spaces, node->fmt, child);
str = talloc_array(ctx, char, 1024); /* FIXME: have the module call talloc_asprintf */
rad_assert(node->child != NULL);
- rcode = node->xlat->do_xlat(node->xlat->instance, request, child, str, 1024);
+ rcode = node->xlat->func(node->xlat->instance, request, child, str, 1024);
talloc_free(child);
if (rcode == 0) {
talloc_free(str);
rad_assert(node->child != NULL);
rad_assert(node->alternate != NULL);
- str = xlat_aprint(ctx, request, node->child);
+ str = xlat_aprint(ctx, request, node->child, node->xlat->escape, node->xlat->instance, lvl);
if (str) break;
- str = xlat_aprint(ctx, request, node->alternate);
+ str = xlat_aprint(ctx, request, node->alternate, node->xlat->escape, node->xlat->instance, lvl);
break;
}
+ /*
+ * Escape the non-literals we found above.
+ */
+ if (escape) {
+ size_t esclen;
+ char *escaped;
+
+ escaped = talloc_array(ctx, char, 1024); /* FIXME: do something intelligent */
+ esclen = escape(request, escaped, 1024, str, escape_ctx);
+ talloc_free(str);
+ if (esclen == 0) {
+ talloc_free(escaped);
+ return NULL;
+ }
+
+ str = escaped;
+ }
+
rad_assert(str != NULL);
return str;
}
-static size_t xlat_process(char **out, REQUEST *request, const xlat_exp_t * const head)
-
+static size_t xlat_process(char **out, REQUEST *request, const xlat_exp_t * const head,
+ RADIUS_ESCAPE_STRING escape, void *escape_ctx)
{
int i, list;
size_t total;
* array.
*/
if (!head->next) {
- answer = xlat_aprint(request, request, head);
+ /*
+ * Pass the MAIN escape function. Recursive
+ * calls will call node-specific escape
+ * functions.
+ */
+ answer = xlat_aprint(request, request, head, escape, escape_ctx, 0);
if (!answer) return 0;
*out = answer;
return strlen(answer);
if (!array) return -1;
for (node = head, i = 0; node != NULL; node = node->next, i++) {
- array[i] = xlat_aprint(array, request, node); /* may be NULL */
+ array[i] = xlat_aprint(array, request, node, escape, escape_ctx, 0); /* may be NULL */
}
total = 0;
* @return length of string written @bug should really have -1 for failure
*/
static ssize_t xlat_expand(char **out, size_t outlen, REQUEST *request, const char *fmt,
- UNUSED RADIUS_ESCAPE_STRING escape, UNUSED void *escape_ctx)
+ RADIUS_ESCAPE_STRING escape, void *escape_ctx)
{
char *buff;
ssize_t len;
return -1;
}
- len = xlat_process(&buff, request, node);
+ len = xlat_process(&buff, request, node, escape, escape_ctx);
talloc_free(node);
if (len <= 0) {
{
rlm_dhcp_t *inst = instance;
- xlat_register("dhcp_options", dhcp_options_xlat, inst);
+ xlat_register("dhcp_options", dhcp_options_xlat, NULL, inst);
return 0;
}
pair_lists_t list;
const DICT_ATTR *target;
const char *p = fmt;
- char buffer[1024];
int ret = 0;
- if (radius_xlat(buffer, sizeof(buffer), request, inst->key, NULL, NULL) < 0) {
- return 0;
- }
-
list = radius_list_name(&p, PAIR_LIST_REQUEST);
target = dict_attrbyname(p);
}
PTHREAD_MUTEX_LOCK(&inst->cache_mutex);
- c = cache_find(inst, request, buffer);
+ c = cache_find(inst, request, fmt);
if (!c) {
- RDEBUG("No cache entry for key \"%s\"", buffer);
+ RDEBUG("No cache entry for key \"%s\"", fmt);
goto done;
}
/*
* Register the cache xlat function
*/
- xlat_register(inst->xlat_name, cache_xlat, inst);
+ xlat_register(inst->xlat_name, cache_xlat, NULL, inst);
rad_assert(inst->key && *inst->key);
}
+static const char special[] = "\\'\"`<>|; \t\r\n()[]?#$^&*=";
+
+/*
+ * Escape special characters
+ */
+static size_t shell_escape(UNUSED REQUEST *request, char *out, size_t outlen, const char *in, UNUSED void *inst)
+{
+ char *q, *end;
+ const char *p;
+
+ q = out;
+ end = out + outlen;
+ p = in;
+
+ while (*p) {
+ if ((q + 3) >= end) break;
+
+ if (strchr(special, *p) != NULL) {
+ *(q++) = '\\';
+ }
+ *(q++) = *(p++);
+ }
+
+ *q = '\0';
+ return q - out;
+}
+
+
/*
* Do any per-module initialization that is separate to each
* configured instance of the module. e.g. set up connections
inst->bare = 1;
}
- xlat_register(inst->xlat_name, exec_xlat, inst);
+ xlat_register(inst->xlat_name, exec_xlat, shell_escape, inst);
/*
* No input pairs defined. Why are we executing a program?
int rcode;
int64_t result;
const char *p;
- char buffer[256];
-
- /*
- * Do an xlat on the provided string (nice recursive operation).
- */
- if (radius_xlat(buffer, sizeof(buffer), request, fmt, NULL, NULL) < 0) {
- *out = '\0';
- return 0;
- }
- p = buffer;
+ p = fmt;
rcode = get_number(request, &p, &result);
if (rcode < 0) {
return 0;
inst->xlat_name = cf_section_name1(conf);
}
- xlat_register(inst->xlat_name, expr_xlat, inst);
+ xlat_register(inst->xlat_name, expr_xlat, NULL, inst);
/*
* FIXME: unregister these, too
*/
- xlat_register("rand", rand_xlat, inst);
- xlat_register("randstr", randstr_xlat, inst);
- xlat_register("urlquote", urlquote_xlat, inst);
- xlat_register("escape", escape_xlat, inst);
- xlat_register("tolower", lc_xlat, inst);
- xlat_register("toupper", uc_xlat, inst);
- xlat_register("md5", md5_xlat, inst);
- xlat_register("tobase64", base64_xlat, inst);
- xlat_register("base64tohex", base64_to_hex_xlat, inst);
+ xlat_register("rand", rand_xlat, NULL, inst);
+ xlat_register("randstr", randstr_xlat, NULL, inst);
+ xlat_register("urlquote", urlquote_xlat, NULL, inst);
+ xlat_register("escape", escape_xlat, NULL, inst);
+ xlat_register("tolower", lc_xlat, NULL, inst);
+ xlat_register("toupper", uc_xlat, NULL, inst);
+ xlat_register("md5", md5_xlat, NULL, inst);
+ xlat_register("tobase64", base64_xlat, NULL, inst);
+ xlat_register("base64tohex", base64_to_hex_xlat, NULL, inst);
/*
* Initialize various paircompare functions
int ldap_errno;
const char *url;
const char **attrs;
- char buffer[LDAP_MAX_DN_STR_LEN + LDAP_MAX_FILTER_STR_LEN];
- if (strchr(fmt, '%') != NULL) {
- if (!radius_xlat(buffer, sizeof(buffer), request, fmt, rlm_ldap_escape_func, NULL)) {
- RDEBUGE("Unable to create LDAP URL");
- return 0;
- }
- url = buffer;
- } else {
- url = fmt;
- }
+ url = fmt;
if (!ldap_is_ldap_url(url)) {
RDEBUGE("String passed does not look like an LDAP URL");
paircompare_register(inst->group_da->attr, PW_USER_NAME, rlm_ldap_groupcmp, inst);
}
- xlat_register(inst->xlat_name, ldap_xlat, inst);
+ xlat_register(inst->xlat_name, ldap_xlat, rlm_ldap_escape_func, inst);
/*
* Initialize the socket pool.
name = cf_section_name2(conf);
if (!name) name = cf_section_name1(conf);
inst->xlat_name = name;
- xlat_register(inst->xlat_name, mschap_xlat, inst);
+ xlat_register(inst->xlat_name, mschap_xlat, NULL, inst);
/*
* For backwards compatibility
size_t ret = 0;
STRLEN n_a;
- /*
- * Do an xlat on the provided string (nice recursive operation).
- */
- if (radius_axlat(&expanded, request, fmt, NULL, NULL) < 0) {
- return 0;
- }
+ expanded = fmt; /* FIXME */
#ifndef WITH_ITHREADS
perl = inst->perl;
if (!xlat_name)
xlat_name = cf_section_name1(conf);
if (xlat_name) {
- xlat_register(xlat_name, perl_xlat, inst);
+ xlat_register(xlat_name, perl_xlat, NULL, inst);
}
return 0;
if (!inst->xlat_name)
inst->xlat_name = cf_section_name1(conf);
- xlat_register(inst->xlat_name, redis_xlat, inst);
+ xlat_register(inst->xlat_name, redis_xlat, NULL, inst); /* FIXME! */
inst->pool = fr_connection_pool_init(conf, inst,
conn_create, NULL,
if (!name) name = cf_section_name1(conf);
inst->xlat_name = name;
if (!inst->xlat_name) return -1;
- xlat_register(inst->xlat_name, soh_xlat, inst);
+ xlat_register(inst->xlat_name, soh_xlat, NULL, inst);
return 0;
}
rlm_sql_row_t row;
rlm_sql_t *inst = instance;
size_t ret = 0;
-
- char *expanded = NULL;
+ char *query = fmt; /* FIXME: */
/*
* Add SQL-User-Name attribute just in case it is needed
*/
sql_set_user(inst, request, NULL);
- /*
- * Do an xlat on the provided string (nice recursive operation).
- */
- if (radius_axlat(&expanded, request, fmt, sql_escape_func, inst) < 0) {
- return 0;
- }
-
handle = sql_get_socket(inst);
if (!handle) {
return 0;
}
- rlm_sql_query_log(inst, request, NULL, expanded);
+ rlm_sql_query_log(inst, request, NULL, query);
/*
* If the query starts with any of the following prefixes,
* then return the number of rows affected
*/
- if ((strncasecmp(expanded, "insert", 6) == 0) ||
- (strncasecmp(expanded, "update", 6) == 0) ||
- (strncasecmp(expanded, "delete", 6) == 0)) {
+ if ((strncasecmp(query, "insert", 6) == 0) ||
+ (strncasecmp(query, "update", 6) == 0) ||
+ (strncasecmp(query, "delete", 6) == 0)) {
int numaffected;
char buffer[21]; /* 64bit max is 20 decimal chars + null byte */
- if (rlm_sql_query(&handle, inst, expanded)) {
+ if (rlm_sql_query(&handle, inst, query)) {
goto finish;
}
goto finish;
} /* else it's a SELECT statement */
- if (rlm_sql_select_query(&handle, inst, expanded)){
+ if (rlm_sql_select_query(&handle, inst, query)){
goto finish;
}
(inst->module->sql_finish_select_query)(handle, inst->config);
finish:
- talloc_free(expanded);
sql_release_socket(inst, handle);
return ret;
* Register the SQL xlat function
*/
inst->config->xlat_name = talloc_strdup(inst->config, xlat_name);
- xlat_register(xlat_name, sql_xlat, inst);
+ xlat_register(xlat_name, sql_xlat, sql_escape_func, inst);
/*
* Sanity check for crazy people.
{
ssize_t len;
- char *expanded = NULL;
- len = radius_axlat(&expanded, request, fmt, NULL, NULL);
- if (len < 0) {
- return len;
+ if (outlen < strlen(fmt)) {
+ *out = '\0';
+ return 0;
}
-
+
/*
* mod2hex allows conversions in place
*/
- len = modhex2hex(expanded, (uint8_t *) expanded, strlen(expanded));
+ len = modhex2hex(fmt, (uint8_t *) out, strlen(fmt));
if (len <= 0) {
- talloc_free(expanded);
*out = '\0';
-
RDEBUGE("Modhex string invalid");
- return len;
+ return 0;
}
- strlcpy(out, expanded, outlen);
-
return len;
}