From 9d29a642caecea8b6c83c4794a7037a2d3cb3a4e Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Fri, 2 Jan 2015 00:04:54 -0500 Subject: [PATCH] Add some additional xlats to expose attribute name, number and vendor --- src/main/xlat.c | 89 ++++++++++++++++++++++++++++++++++-- src/tests/keywords/xlat-attr | 62 +++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 src/tests/keywords/xlat-attr diff --git a/src/main/xlat.c b/src/main/xlat.c index 068473c61355..30a7852e2648 100644 --- a/src/main/xlat.c +++ b/src/main/xlat.c @@ -288,6 +288,87 @@ static ssize_t xlat_tag(UNUSED void *instance, REQUEST *request, return snprintf(out, outlen, "%u", vp->tag); } +/** Return the vendor of an attribute reference + * + */ +static ssize_t xlat_vendor(UNUSED void *instance, REQUEST *request, + char const *fmt, char *out, size_t outlen) +{ + VALUE_PAIR *vp; + DICT_VENDOR *vendor; + + while (isspace((int) *fmt)) fmt++; + + if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) { + *out = '\0'; + return 0; + } + + vendor = dict_vendorbyvalue(vp->da->vendor); + if (!vendor) { + *out = '\0'; + return 0; + } + strlcpy(out, vendor->name, outlen); + + return vendor->length; +} + +/** Return the vendor number of an attribute reference + * + */ +static ssize_t xlat_vendor_num(UNUSED void *instance, REQUEST *request, + char const *fmt, char *out, size_t outlen) +{ + VALUE_PAIR *vp; + + while (isspace((int) *fmt)) fmt++; + + if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) { + *out = '\0'; + return 0; + } + + return snprintf(out, outlen, "%i", vp->da->vendor); +} + +/** Return the attribute name of an attribute reference + * + */ +static ssize_t xlat_attr(UNUSED void *instance, REQUEST *request, + char const *fmt, char *out, size_t outlen) +{ + VALUE_PAIR *vp; + + while (isspace((int) *fmt)) fmt++; + + if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) { + *out = '\0'; + return 0; + } + strlcpy(out, vp->da->name, outlen); + + return strlen(vp->da->name); +} + +/** Return the attribute number of an attribute reference + * + */ +static ssize_t xlat_attr_num(UNUSED void *instance, REQUEST *request, + char const *fmt, char *out, size_t outlen) +{ + VALUE_PAIR *vp; + + while (isspace((int) *fmt)) fmt++; + + if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) { + *out = '\0'; + return 0; + } + + return snprintf(out, outlen, "%i", vp->da->attr); +} + /** Print out attribute info * * Prints out all instances of a current attribute, or all attributes in a list. @@ -296,9 +377,6 @@ static ssize_t xlat_tag(UNUSED void *instance, REQUEST *request, * value. This is helpful to determine types for unknown attributes of long * passed vendors, or just crazy/broken NAS. * - * It's also useful for exposing issues in the packet decoding functions, as in - * some cases they get fed random garbage data. - * * This expands to a zero length string. */ static ssize_t xlat_debug_attr(UNUSED void *instance, REQUEST *request, char const *fmt, @@ -383,7 +461,6 @@ static ssize_t xlat_debug_attr(UNUSED void *instance, REQUEST *request, char con case PW_TYPE_COMBO_IP_ADDR: /* Covered by IPv4 address IPv6 address */ case PW_TYPE_COMBO_IP_PREFIX: /* Covered by IPv4 address IPv6 address */ case PW_TYPE_TIMEVAL: /* Not a VALUE_PAIR type */ - goto next_type; default: @@ -669,6 +746,10 @@ int xlat_register(char const *name, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING esc XLAT_REGISTER(length); XLAT_REGISTER(hex); XLAT_REGISTER(tag); + XLAT_REGISTER(vendor); + XLAT_REGISTER(vendor_num); + XLAT_REGISTER(attr); + XLAT_REGISTER(attr_num); XLAT_REGISTER(string); XLAT_REGISTER(xlat); XLAT_REGISTER(module); diff --git a/src/tests/keywords/xlat-attr b/src/tests/keywords/xlat-attr new file mode 100644 index 000000000000..d19495a2f64e --- /dev/null +++ b/src/tests/keywords/xlat-attr @@ -0,0 +1,62 @@ +# +# PRE: update +# +# Check attribute info xlats work correctly +# +update { + control:Cleartext-Password := 'hello' + reply:Filter-Id := 'filter' +} + +update request { + Reply-Message := 'foo' + FreeRADIUS-Proxied-To := 127.0.0.1 +} + +if ("%{attr:&FreeRADIUS-Proxied-To}" != 'FreeRADIUS-Proxied-To') { + update reply { + Filter-Id += 'Fail 0' + } +} + +if ("%{attr_num:&FreeRADIUS-Proxied-To}" != 1) { + update reply { + Filter-Id += 'Fail 2' + } +} + +if ("%{vendor:&FreeRADIUS-Proxied-To}" != 'FreeRADIUS') { + update reply { + Filter-Id += 'Fail 3' + } +} + +if ("%{vendor_num:&FreeRADIUS-Proxied-To}" != 11344) { + update reply { + Filter-Id += 'Fail 4' + } +} + +if ("%{attr:&Reply-Message}" != 'Reply-Message') { + update reply { + Filter-Id += 'Fail 5' + } +} + +if ("%{attr_num:&Reply-Message}" != 18) { + update reply { + Filter-Id += 'Fail 6' + } +} + +if ("%{vendor:&Reply-Message}" != '') { + update reply { + Filter-Id += 'Fail 7' + } +} + +if ("%{vendor_num:&Reply-Message}" != 0) { + update reply { + Filter-Id += 'Fail 8' + } +}