--- ../../cvs/cvs-20051029/radiusd/src/main/valuepair.c 2005-10-18 19:52:49.000000000 -0400 +++ src/main/valuepair.c 2005-11-05 19:32:46.000000000 -0500 @@ -298,8 +298,13 @@ * Didn't find it. If we were *trying* * to not find it, then we succeeded. */ - if (check_item->operator == T_OP_CMP_FALSE) - return 0; + if (check_item->operator == T_OP_CMP_FALSE || +#ifdef HAVE_REGEX_H + check_item->operator == T_OP_REG_NE || +#endif + check_item->operator == T_OP_NE + ) + continue; else return -1; } @@ -310,7 +315,10 @@ */ if (check_item->operator == T_OP_CMP_FALSE) return -1; - + + /* no comparison needed if it exists */ + if (check_item->operator == T_OP_CMP_TRUE) + continue; /* * We've got to xlat the string before doing @@ -342,14 +350,14 @@ radlog(L_INFO, "Invalid operator for item %s: " "reverting to '=='", check_item->name); /*FALLTHRU*/ - case T_OP_CMP_TRUE: /* compare always == 0 */ - case T_OP_CMP_FALSE: /* compare always == 1 */ case T_OP_CMP_EQ: if (compare != 0) result = -1; break; case T_OP_NE: - if (compare == 0) result = -1; + /* != only succeeds if NO reply values match*/ + if (compare == 0) return -1; + result = -1; /*check the rest for no match */ break; case T_OP_LT: @@ -457,7 +465,9 @@ compare = regexec(®, (char *)auth_item->vp_strvalue, 0, NULL, 0); regfree(®); - if (compare == 0) result = -1; + /* !~ only succeeds if NO matches are found in reply pair */ + if (compare == 0) return -1; + result = -1; /*check the rest for no match */ break; #endif @@ -487,7 +497,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 +636,7 @@ * Point "tailto" to the end of the "to" list. */ tailto = to; + for(i = *to; i; i = i->next) { tailto = &i->next; } @@ -545,30 +677,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. */