#! /bin/sh /usr/share/dpatch/dpatch-run ## 030-substar_regex.patch.dpatch by ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: No description. @DPATCH@ diff -urNad freeradius-1.1.0pre0/man/man5/users.5 /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/man/man5/users.5 --- freeradius-1.1.0pre0/man/man5/users.5 2005-03-17 00:16:58.790666042 -0500 +++ /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/man/man5/users.5 2005-03-17 00:38:40.295848027 -0500 @@ -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.0pre0/src/include/token.h /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/include/token.h --- freeradius-1.1.0pre0/src/include/token.h 2005-03-17 00:16:58.837659657 -0500 +++ /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/include/token.h 2005-03-17 00:38:40.296847890 -0500 @@ -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.0pre0/src/lib/print.c /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/lib/print.c --- freeradius-1.1.0pre0/src/lib/print.c 2005-03-17 00:16:58.842658978 -0500 +++ /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/lib/print.c 2005-03-17 00:38:40.297847754 -0500 @@ -223,6 +223,8 @@ ";", "+=", "-=", + "-*", + "-~", ":=", "=", "!=", diff -urNad freeradius-1.1.0pre0/src/lib/token.c /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/lib/token.c --- freeradius-1.1.0pre0/src/lib/token.c 2005-03-17 00:16:58.843658842 -0500 +++ /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/lib/token.c 2005-03-17 00:38:40.299847482 -0500 @@ -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.0pre0/src/main/valuepair.c /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/main/valuepair.c --- freeradius-1.1.0pre0/src/main/valuepair.c 2005-03-17 00:16:58.861656397 -0500 +++ /tmp/dpep.fHbaO6/freeradius-1.1.0pre0/src/main/valuepair.c 2005-03-17 00:38:40.303846938 -0500 @@ -467,7 +467,128 @@ return paircompare( 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 = paircompare(req,first,second,NULL,NULL); + 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. */ @@ -485,6 +606,7 @@ * Point "tailto" to the end of the "to" list. */ tailto = to; + for(i = *to; i; i = i->next) { tailto = &i->next; } @@ -525,30 +647,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. */