rlm_exec does not change already existing attributes
In the rlm_exec module for change of attributes according to result of script it is used if (output_pairs) pairmove(output_pairs, &answer); in function static int exec_dispatch(void *instance, REQUEST *request) But function pairmove in valuepair.c does only the following /* * Move attributes from one list to the other * if not already present. */ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from) I.e. if such attribute does not exist that it will be added, and if already exists, will take place nothing. As result using an external script we can only add new attributes, but we can not change existing attributes! How to change User-Name in Radius request? Is it possible to change existing attributes in the simple way without change of the module rlm_exec code? Dmitry
Dmitry Lyubimkov wrote:
In the rlm_exec module for change of attributes according to result of script it is used
if (output_pairs) pairmove(output_pairs, &answer);
in function
static int exec_dispatch(void *instance, REQUEST *request)
But function pairmove in valuepair.c does only the following
/* * Move attributes from one list to the other * if not already present. */ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
I.e. if such attribute does not exist that it will be added, and if already exists, will take place nothing. As result using an external script we can only add new attributes, but we can not change existing attributes! How to change User-Name in Radius request? Is it possible to change existing attributes in the simple way without change of the module rlm_exec code?
Dmitry
if you keep reading in that function you will find that certain operators produce different behavior. Furthermore, if you look at the server's version of valuepair.c (not lib/valuepair.c but main/valuepair.c ) you might decide to patch your version of rlm_exec to use pairxlatmove() instead. My local radiusd runs with this patches which further extends/corrects pairxlatmove() #! /bin/sh /usr/share/dpatch/dpatch-run ## 030-substar_regex.patch.dpatch by <joe@nameserver3.ttec.com> ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: No description. @DPATCH@ diff -urNad freeradius-1.1.0~/man/man5/users.5 freeradius-1.1.0/man/man5/users.5 --- freeradius-1.1.0~/man/man5/users.5 2005-10-21 16:07:29.000000000 -0400 +++ freeradius-1.1.0/man/man5/users.5 2005-10-21 16:07:30.000000000 -0400 @@ -95,6 +95,25 @@ As a reply item, it has an identical meaning, but the attribute is added to the reply items. + +.TP 0.5i +.B "Attribute -= Value" +As a reply item it means remove matching items from the reply list. +.br +Not allowed as a check item. + +.TP 0.5i +.B "Attribute -* Value" +As a reply item it means remove all "Attribute" attributes items from the reply list. +.br +Not allowed as a check item. + +.TP 0.5i +.B "Attribute -~ Value" +As a reply item it means remove regex matching items from the reply list. +.br +Not allowed as a check item. + .TP 0.5i .B "Attribute != Value" As a check item, matches if the given attribute is in the request, AND diff -urNad freeradius-1.1.0~/src/include/token.h freeradius-1.1.0/src/include/token.h --- freeradius-1.1.0~/src/include/token.h 2005-10-21 16:07:29.000000000 -0400 +++ freeradius-1.1.0/src/include/token.h 2005-10-21 16:07:30.000000000 -0400 @@ -35,6 +35,8 @@ T_OP_ADD, /* += */ T_OP_SUB, /* -= */ + T_OP_SUB_ALL, /* -* */ + T_OP_SUB_REG, /* -~ */ T_OP_SET, /* := */ T_OP_EQ, /* = */ T_OP_NE, /* != */ diff -urNad freeradius-1.1.0~/src/lib/print.c freeradius-1.1.0/src/lib/print.c --- freeradius-1.1.0~/src/lib/print.c 2005-10-21 16:07:29.000000000 -0400 +++ freeradius-1.1.0/src/lib/print.c 2005-10-21 16:07:30.000000000 -0400 @@ -243,6 +243,8 @@ ";", "+=", "-=", + "-*", + "-~", ":=", "=", "!=", diff -urNad freeradius-1.1.0~/src/lib/token.c freeradius-1.1.0/src/lib/token.c --- freeradius-1.1.0~/src/lib/token.c 2005-10-21 16:07:29.000000000 -0400 +++ freeradius-1.1.0/src/lib/token.c 2005-10-21 16:07:30.000000000 -0400 @@ -39,6 +39,8 @@ { ",", T_COMMA, }, { "+=", T_OP_ADD, }, { "-=", T_OP_SUB, }, + { "-*", T_OP_SUB_ALL, }, + { "-~", T_OP_SUB_REG, }, { ":=", T_OP_SET, }, { "=*", T_OP_CMP_TRUE, }, { "!*", T_OP_CMP_FALSE, }, diff -urNad freeradius-1.1.0~/src/main/valuepair.c freeradius-1.1.0/src/main/valuepair.c --- freeradius-1.1.0~/src/main/valuepair.c 2005-10-21 16:07:29.000000000 -0400 +++ freeradius-1.1.0/src/main/valuepair.c 2005-10-21 16:10:00.000000000 -0400 @@ -487,7 +487,128 @@ return compare_pair( req, first, second, NULL, NULL ); } +/* + * Compare ONE attribute from a (potential) list. + * Return the first matching one. + */ + +static VALUE_PAIR * paircmpmatchone(REQUEST *req, VALUE_PAIR *first, VALUE_PAIR *second) +{ + VALUE_PAIR *fnext = NULL; + VALUE_PAIR *snext = NULL; + int result = 0; + + for(; second; second = second->next){ + for(; first; first = first->next){ + if(first->attribute == second->attribute){ + /* No matter what, compare only THESE items in chain */ + fnext = first->next; + first->next = NULL; + snext = second->next; + second->next = NULL; + result = simplepaircmp(req, first, second); + first->next = fnext; + second->next = snext; + + if(!result) + return first; + } + } + } + return NULL; +} +#ifdef HAVE_REGEX_H +/* + * Regex Compare ONE attribute from a (potential) list. + * Return the first matching one. + */ + +static VALUE_PAIR * pairregmatchone(REQUEST *req, VALUE_PAIR *first, VALUE_PAIR *second) +{ + int result = 0; + regex_t reg; + + for(; second; second = second->next){ + for(; first; first = first->next){ + if(first->attribute == second->attribute) { + if (second->operator == T_OP_REG_EQ || + second->operator == T_OP_REG_NE || + second->operator == T_OP_SUB_REG) + { + regcomp(®, (char *)second->vp_strvalue, + REG_EXTENDED); + result = regexec(®, (char *)first->vp_strvalue, + 0, NULL, 0); + regfree(®); + + if(!result) + return first; + } + if (first->operator == T_OP_REG_EQ || + first->operator == T_OP_REG_NE || + first->operator == T_OP_SUB_REG) + { + + regcomp(®, (char *)first->vp_strvalue, + REG_EXTENDED); + result = regexec(®, (char *)second->vp_strvalue, + 0, NULL, 0); + regfree(®); + + if(!result) + return second; + } + } + } + } + return NULL; +} +#endif + +/* + * Deletes matching attributes. + */ +static void pairdeletematch(REQUEST *req,VALUE_PAIR **first,VALUE_PAIR *second) +{ + VALUE_PAIR *vp, *i; + + while((vp = paircmpmatchone(req,*first,second))){ + if(*first == vp) /* new head of chain */ + *first = vp->next; + else + for(i = *first; i; i = i->next){ + if(i->next == vp){ /* dis-own */ + i->next = vp->next; + break; + } + } + pairbasicfree(vp); + } +} + +#ifdef HAVE_REGEX_H +/* + * deletes matching regex pairs +*/ +static void pairdeleteregmatch(REQUEST *req,VALUE_PAIR **first,VALUE_PAIR *second) +{ + VALUE_PAIR *vp, *i; + + while((vp = pairregmatchone(req,*first,second))){ + if(*first == vp) /* new head of chain */ + *first = vp->next; + else + for(i = *first; i; i = i->next){ + if(i->next == vp){ /* dis-own */ + i->next = vp->next; + break; + } + } + pairbasicfree(vp); + } +} +#endif /* * Move pairs, replacing/over-writing them, and doing xlat. */ @@ -505,6 +626,7 @@ * Point "tailto" to the end of the "to" list. */ tailto = to; + for(i = *to; i; i = i->next) { tailto = &i->next; } @@ -545,30 +667,57 @@ switch (i->operator) { /* - * If a similar attribute is found, - * delete it. + * If a similar attribute are found, + * delete them. */ case T_OP_SUB: /* -= */ if (found) { - if (!i->vp_strvalue[0] || - (strcmp((char *)found->vp_strvalue, - (char *)i->vp_strvalue) == 0)){ - pairdelete(to, found->attribute); - - /* - * 'tailto' may have been - * deleted... - */ + if (!i->vp_strvalue[0]) + goto delete_all; + + pairdeletematch(req,to,i); + /* + * 'tailto' may have been + * deleted... + */ + tailto = to; + for(j = *to; j; j = j->next) { + tailto = &j->next; + } + + } + tailfrom = i; + continue; + break; + case T_OP_SUB_ALL: /* -* */ + if (found) { +delete_all: + pairdelete(to, found->attribute); tailto = to; for(j = *to; j; j = j->next) { tailto = &j->next; } - } } tailfrom = i; continue; break; +#ifdef HAVE_REGEX_H + case T_OP_SUB_REG: /* -~ */ + if (found) { + + pairdeleteregmatch(req,to,i); + + tailto = to; + for(j = *to; j; j = j->next) { + tailto = &j->next; + } + + tailfrom = i; + continue; + break; + } +#endif /* * Add it, if it's not already there. */
participants (2)
-
Dmitry Lyubimkov -
Joe Maimon