}
-static const CONF_ITEM *cf_reference_item(const CONF_SECTION *parentcs,
- const CONF_SECTION *outercs,
- const char *ptr)
+CONF_ITEM *cf_reference_item(const CONF_SECTION *parentcs,
+ const CONF_SECTION *outercs,
+ const char *ptr)
{
CONF_PAIR *cp;
const CONF_SECTION *cs = outercs, *next;
}
while (*p) {
- char *q = strchr(p, '.');
+ char *q, *r;
- if (!q) break;
+ r = strchr(p, '[');
+ q = strchr(p, '.');
+ if (!r && !q) break;
- *q = '\0';
- next = cf_section_sub_find(cs, p);
- *q = '.';
+ if (r && q > r) q = NULL;
+ if (q && q < r) r = NULL;
+
+ /*
+ * Split off name2.
+ */
+ if (r) {
+ q = strchr(r + 1, ']');
+ if (!q) return NULL; /* parse error */
+
+ /*
+ * Points to foo[bar]xx: parse error,
+ * it should be foo[bar] or foo[bar].baz
+ */
+ if (q[1] && q[1] != '.') goto no_such_item;
+
+ *r = '\0';
+ *q = '\0';
+ next = cf_section_sub_find_name2(cs, p, r + 1);
+ *r = '[';
+ *q = ']';
+
+ /*
+ * Points to a named instance of a section.
+ */
+ if (!q[1]) {
+ if (!next) goto no_such_item;
+ return cf_sectiontoitem(next);
+ }
+
+ q++; /* ensure we skip the ']' and '.' */
+
+ } else {
+ *q = '\0';
+ next = cf_section_sub_find(cs, p);
+ *q = '.';
+ }
if (!next) break; /* it MAY be a pair in this section! */
p = q + 1;
}
- if (!*p) return NULL;
+ if (!*p) goto no_such_item;
retry:
/*
goto retry;
}
+no_such_item:
+ DEBUG2("WARNING: No such configuration item %s", ptr);
return NULL;
}
*/
CONF_SECTION *cf_file_read(const char *filename)
{
+ char *p;
+ CONF_PAIR *cp;
CONF_SECTION *cs;
cs = cf_section_alloc("main", NULL, NULL);
if (!cs) return NULL;
+ cp = cf_pair_alloc("confdir", filename, T_OP_SET, T_BARE_WORD, cs);
+ if (!cp) return NULL;
+
+ p = strrchr(cp->value, '/');
+ if (p) *p = '\0';
+
+ cp->item.filename = "internal";
+ cp->item.lineno = 0;
+ cf_item_add(cs, cf_pairtoitem(cp));
+
if (cf_file_include(filename, cs) < 0) {
cf_section_free(&cs);
return NULL;
size_t outlen,
RADIUS_ESCAPE_STRING func)
{
- CONF_SECTION *cs;
- CONF_PAIR *cp;
- int i, argc, left;
- const char *from, *value;
- char *to;
- char myfmt[1024];
- char argv_buf[1024];
- char *argv[MAX_ARGV];
+ const char *value;
+ const CONF_PAIR *cp;
+ const CONF_ITEM *ci;
request = request; /* -Wunused */
instance = instance; /* -Wunused */
- cp = NULL;
- cs = NULL;
-
/*
- * Split the string into argv's BEFORE doing radius_xlat...
- * Copied from exec.c
+ * FIXME: radius_xlat, with a function that escapes
+ * "%{[].\\\'"\`".
*/
- from = fmt;
- to = myfmt;
- argc = 0;
- while (*from) {
- int flag, length;
-
- flag = 0;
- argv[argc] = to;
- argc++;
-
- if (argc >= (MAX_ARGV - 1)) break;
-
- /*
- * Copy the argv over to our buffer.
- */
- while (*from) {
- if (to >= myfmt + sizeof(myfmt) - 1) {
- return 0; /* no error msg */
- }
-
- switch (*from) {
- case '%':
- if (from[1] == '{') {
- *(to++) = *(from++);
-
- length = rad_copy_variable(to, from);
- if (length < 0) {
- return -1;
- }
- from += length;
- to += length;
- } else { /* FIXME: catch %%{ ? */
- *(to++) = *(from++);
- }
- break;
-
- case '[':
- if (flag != 0) {
- radlog(L_ERR, "config: Unexpected nested '[' in \"%s\"", fmt);
- return 0;
- }
- flag++;
- *(to++) = *(from++);
- break;
-
- case ']':
- if (flag == 0) {
- radlog(L_ERR, "config: Unbalanced ']' in \"%s\"", fmt);
- return 0;
- }
- if (from[1] != '.') {
- radlog(L_ERR, "config: Unexpected text after ']' in \"%s\"", fmt);
- return 0;
- }
-
- flag--;
- *(to++) = *(from++);
- break;
-
- case '.':
- if (flag == 0) break;
- /* FALL-THROUGH */
-
- default:
- *(to++) = *(from++);
- break;
- }
-
- if ((*from == '.') && (flag == 0)) {
- from++;
- break;
- }
- } /* end of string, or found a period */
- if (flag != 0) {
- radlog(L_ERR, "config: Unbalanced '[' in \"%s\"", fmt);
- return 0;
- }
-
- *(to++) = '\0'; /* terminate the string. */
- }
-
- /*
- * Expand each string, as appropriate
- */
- to = argv_buf;
- left = sizeof(argv_buf);
- for (i = 0; i < argc; i++) {
- int sublen;
-
- /*
- * Don't touch argv's which won't be translated.
- */
- if (strchr(argv[i], '%') == NULL) continue;
-
- sublen = radius_xlat(to, left - 1, argv[i], request, NULL);
- if (sublen <= 0) {
- /*
- * Fail to be backwards compatible.
- *
- * It's yucky, but it won't break anything,
- * and it won't cause security problems.
- */
- sublen = 0;
- }
-
- argv[i] = to;
- to += sublen;
- *(to++) = '\0';
- left -= sublen;
- left--;
-
- if (left <= 0) {
- return 0;
- }
- }
- argv[argc] = NULL;
-
- cs = request->root->config;
-
- /*
- * Root through section & subsection references.
- * The last entry of argv MUST be the CONF_PAIR.
- */
- for (i = 0; i < argc - 1; i++) {
- char *name2 = NULL;
- CONF_SECTION *subcs;
-
- /*
- * FIXME: What about RADIUS attributes containing '['?
- */
- name2 = strchr(argv[i], '[');
- if (name2) {
- char *p = strchr(name2, ']');
- rad_assert(p != NULL);
- rad_assert(p[1] =='\0');
- *p = '\0';
- *name2 = '\0';
- name2++;
- }
-
- if (name2) {
- subcs = cf_section_sub_find_name2(cs, argv[i],
- name2);
- if (!subcs) {
- radlog(L_ERR, "config: section \"%s %s {}\" not found while dereferencing \"%s\"", argv[i], name2, fmt);
- return 0;
- }
- } else {
- subcs = cf_section_sub_find(cs, argv[i]);
- if (!subcs) {
- radlog(L_ERR, "config: section \"%s {}\" not found while dereferencing \"%s\"", argv[i], fmt);
- return 0;
- }
- }
- cs = subcs;
- } /* until argc - 1 */
-
- /*
- * This can now have embedded periods in it.
- */
- cp = cf_pair_find(cs, argv[argc - 1]);
- if (!cp) {
- radlog(L_ERR, "config: item \"%s\" not found while dereferencing \"%s\"", argv[argc], fmt);
+ ci = cf_reference_item(request->root->config,
+ request->root->config, fmt);
+ if (!ci || !cf_item_is_pair(ci)) {
+ *out = '\0';
return 0;
}
+ cp = cf_itemtopair(ci);
+
/*
* Ensure that we only copy what's necessary.
*