*
*/
ssize_t tmpl_from_attr_substr(value_pair_tmpl_t *vpt, char const *name,
- request_refs_t request_def, pair_lists_t list_def, bool allow_undefined);
+ request_refs_t request_def, pair_lists_t list_def,
+ bool allow_unknown, bool allow_undefined);
ssize_t tmpl_from_attr_str(value_pair_tmpl_t *vpt, char const *name,
request_refs_t request_def,
- pair_lists_t list_def, bool allow_undefined);
+ pair_lists_t list_def,
+ bool allow_unknown, bool allow_undefined);
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, value_pair_tmpl_t **out, char const *name,
request_refs_t request_def,
- pair_lists_t list_def, bool allow_undefined);
+ pair_lists_t list_def,
+ bool allow_unknown, bool allow_undefined);
/*
* Parses any type of string into a template
* - Vendor-%d-Attr-%d
* - VendorName-Attr-%d
*
- * @todo should check attr/vendor against dictionary and return the real da.
- *
* @param[in] da to initialise.
* @param[in] name of attribute.
* @return 0 on success -1 on failure.
* - Vendor-%d-Attr-%d
* - VendorName-Attr-%d
*
- * @todo should check attr/vendor against dictionary and return the real da.
- *
* @param[in] ctx to alloc new attribute in.
* @param[in] name of attribute.
* @return 0 on success -1 on failure.
/*
* LHS must always be an attribute reference.
*/
- slen = tmpl_afrom_attr_str(ctx, &map->lhs, attr, dst_request_def, dst_list_def, true);
+ slen = tmpl_afrom_attr_str(ctx, &map->lhs, attr, dst_request_def, dst_list_def, true, true);
if (slen <= 0) {
char *spaces, *text;
*out = NULL;
- if (tmpl_from_attr_str(&vpt, name, REQUEST_CURRENT, PAIR_LIST_REQUEST, false) <= 0) {
+ if (tmpl_from_attr_str(&vpt, name, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) <= 0) {
return -4;
}
*out = NULL;
- if (tmpl_from_attr_str(&vpt, name, REQUEST_CURRENT, PAIR_LIST_REQUEST, false) <= 0) {
+ if (tmpl_from_attr_str(&vpt, name, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) <= 0) {
return -4;
}
* @param[in] name of attribute including qualifiers.
* @param[in] request_def The default request to insert unqualified attributes into.
* @param[in] list_def The default list to insert unqualified attributes into.
- * @param[in] allow_undefined If true, we don't generate a parse error on attributes
- * that are not in the global dictionary, and are not in unknown attribute format.
+ * @param[in] allow_unknown If true attributes in the format accepted by dict_unknown_from_substr
+ * will be allowed, even if they're not in the main dictionaries.
+ * @param[in] allow_undefined If true, we don't generate a parse error on unknown
+ * attributes, and instead set type to TMPL_TYPE_ATTR_UNDEFINED.
* @return <= 0 on error (offset as negative integer), > 0 on success (number of bytes parsed)
*/
ssize_t tmpl_from_attr_substr(value_pair_tmpl_t *vpt, char const *name,
- request_refs_t request_def, pair_lists_t list_def, bool allow_undefined)
+ request_refs_t request_def, pair_lists_t list_def,
+ bool allow_unknown, bool allow_undefined)
{
char const *p;
long num;
attr.da = dict_attrbyname_substr(&p);
if (!attr.da) {
+ char const *a;
+
+ /*
+ * Record start of attribute in case we need to error out.
+ */
+ a = p;
+
/*
* Attr-1.2.3.4 is OK.
*/
if (dict_unknown_from_substr((DICT_ATTR *)&attr.unknown.da, &p) == 0) {
+ /*
+ * Check what we just parsed really hasn't been defined
+ * in the main dictionaries.
+ */
+ attr.da = dict_attrbyvalue(((DICT_ATTR *)&attr.unknown.da)->attr,
+ ((DICT_ATTR *)&attr.unknown.da)->vendor);
+ if (attr.da) goto do_tag;
+
+
+ fprintf(stderr, "\n%i:%i\n", ((DICT_ATTR *)&attr.unknown.da)->attr,
+ ((DICT_ATTR *)&attr.unknown.da)->vendor);
+
+ if (!allow_unknown) {
+ fr_strerror_printf("Unknown attribute");
+ return -(a - name);
+ }
+
attr.da = (DICT_ATTR *)&attr.unknown.da;
goto skip_tag; /* unknown attributes can't have tags */
}
* let the caller decide.
*/
if (!allow_undefined) {
- fr_strerror_printf("Unknown attribute");
- return -(p - name);
+ fr_strerror_printf("Undefined attribute");
+ return -(a - name);
}
/*
goto skip_tag;
}
+
+do_tag:
type = TMPL_TYPE_ATTR;
/*
* @return <= 0 on error (offset as negative integer), > 0 on success (number of bytes parsed)
*/
ssize_t tmpl_from_attr_str(value_pair_tmpl_t *vpt, char const *name,
- request_refs_t request_def, pair_lists_t list_def, bool allow_undefined)
+ request_refs_t request_def, pair_lists_t list_def,
+ bool allow_unknown, bool allow_undefined)
{
ssize_t slen;
- slen = tmpl_from_attr_substr(vpt, name, request_def, list_def, allow_undefined);
+ slen = tmpl_from_attr_substr(vpt, name, request_def, list_def, allow_unknown, allow_undefined);
if (slen <= 0) return slen;
if (name[slen] != '\0') {
fr_strerror_printf("Unexpected text after attribute name");
* @param[in] request_def The default request to insert unqualified
* attributes into.
* @param[in] list_def The default list to insert unqualified attributes into.
+ * @param[in] allow_unknown If true attributes in the format accepted by dict_unknown_from_substr
+ * will be allowed, even if they're not in the main dictionaries.
* @param[in] allow_undefined If true, we don't generate a parse error on unknown
* attributes, and instead set type to TMPL_TYPE_ATTR_UNDEFINED.
* @return <= 0 on error (offset as negative integer), > 0 on success (number of bytes parsed)
*/
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, value_pair_tmpl_t **out, char const *name,
- request_refs_t request_def, pair_lists_t list_def, bool allow_undefined)
+ request_refs_t request_def, pair_lists_t list_def,
+ bool allow_unknown, bool allow_undefined)
{
ssize_t slen;
value_pair_tmpl_t *vpt;
MEM(vpt = talloc(ctx, value_pair_tmpl_t)); /* tmpl_from_attr_substr zeros it */
- slen = tmpl_from_attr_substr(vpt, name, request_def, list_def, allow_undefined);
+ slen = tmpl_from_attr_substr(vpt, name, request_def, list_def, allow_unknown, allow_undefined);
if (slen <= 0) {
tmpl_free(&vpt);
return slen;
* If we can parse it as an attribute, it's an attribute.
* Otherwise, treat it as a literal.
*/
- slen = tmpl_afrom_attr_str(ctx, &vpt, name, request_def, list_def, (name[0] == '&'));
+ slen = tmpl_afrom_attr_str(ctx, &vpt, name, request_def, list_def, true, (name[0] == '&'));
if ((name[0] == '&') && (slen <= 0)) return slen;
if (slen > 0) break;
/* FALL-THROUGH */
while (isspace((int) *fmt)) fmt++;
- if (tmpl_from_attr_str(&vpt, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false) <= 0) {
+ if (tmpl_from_attr_str(&vpt, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) <= 0) {
RDEBUG("%s", fr_strerror());
return -1;
}
* - '[' - Which is an attribute index, so it must be an attribute.
* - '}' - The end of the expansion, which means it was a bareword.
*/
- slen = tmpl_from_attr_substr(&node->attr, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, true);
+ slen = tmpl_from_attr_substr(&node->attr, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, true, true);
if (slen <= 0) {
/*
* If the parse error occurred before the ':'
p += 1;
- slen = tmpl_from_attr_substr(&vpt, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, false);
+ slen = tmpl_from_attr_substr(&vpt, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false);
if (slen < 0) {
RDEBUG("Failed parsing attribute name '%s': %s", p, fr_strerror());
return false;
VALUE_PAIR *vp;
- if (tmpl_from_attr_str(&vpt, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false) <= 0) {
+ if (tmpl_from_attr_str(&vpt, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) <= 0) {
REDEBUG("%s", fr_strerror());
return -1;
}
*/
RDEBUG2("Parsing attribute \"%s\"", name);
- if (tmpl_from_attr_str(&dst, name, REQUEST_CURRENT, PAIR_LIST_REPLY, false) <= 0) {
+ if (tmpl_from_attr_str(&dst, name, REQUEST_CURRENT, PAIR_LIST_REPLY, false, false) <= 0) {
RWDEBUG("Failed parsing attribute: %s, skipping...", fr_strerror());
continue;
}
Cleartext-Password := 'hello'
}
+update reply {
+ Filter-Id := "filter"
+}
+
+update request {
+ FreeRADIUS-Proxied-To := 127.0.0.2
+}
+
#
# Check that a known but malformed attr is malformed
#
if (&Attr-26.24757.84.9.5.7 != 0xab) {
update reply {
- Filter-Id += "fail-1"
+ Filter-Id += 'Fail 1'
}
}
if (&Attr-26.24757.84.9.5.15 != 0xabcdef) {
update reply {
- Filter-Id += "fail-2"
+ Filter-Id += 'Fail 2'
+ }
+}
+
+#
+# Check that unknown attributes which are defined
+# get automatically resolved to the real attribute.
+#
+if (&Vendor-11344-Attr-1 == 127.0.0.1) {
+ update reply {
+ Filter-Id += 'Fail 3'
+ }
+}
+
+if (&Vendor-11344-Attr-1 != 127.0.0.2) {
+ update reply {
+ Filter-Id += 'Fail 4'
+ }
+}
+
+update request {
+ &Vendor-11344-Attr-1 := 127.0.0.1
+}
+
+if (&FreeRADIUS-Proxied-To == 127.0.0.2) {
+ update reply {
+ Filter-Id += 'Fail 5'
+ }
+}
+
+if (&FreeRADIUS-Proxied-To != 127.0.0.1) {
+ update reply {
+ Filter-Id += 'Fail 6'
+ }
+}
+
+if (&Vendor-11344-Attr-1 == 127.0.0.2) {
+ update reply {
+ Filter-Id += 'Fail 7'
}
}
-if (!reply:Filter-Id) {
+if (&Vendor-11344-Attr-1 != 127.0.0.1) {
update reply {
- Filter-Id := "filter"
+ Filter-Id += 'Fail 8'
}
}
#
condition ('i have scary embedded things\000 inside me' == "i have scary embedded things\000 inside me")
data false
+
+#
+# 'Unknown' attributes which are defined in the main dictionary
+# should be resolved to their real names.
+condition &Attr-1 == 'bar'
+data &User-Name == 'bar'
+
+condition &Vendor-11344-Attr-1 == 127.0.0.1
+data &FreeRADIUS-Proxied-To == 127.0.0.1/32