Joe Maimon wrote:
Alan DeKok wrote:
Joe Maimon <jmaimon@ttec.com> wrote:
If I have the Framed-IP-Address attribute, I need to remove any attribute of
Cisco-AVPair -~ "ip:addr-pool.*"
Ok got it to work with a bunch of hacks Included is -policy.txt file used(fresh from today) -substar&sunregex operator patch(old stuff works well) -policy patch (fresh from today) #! /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.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. */ diff -ur radiusd/src/modules/rlm_policy/evaluate.c freeradius-1.1.0/src/modules/rlm_policy/evaluate.c --- radiusd/src/modules/rlm_policy/evaluate.c 2005-09-27 19:59:11.000000000 -0400 +++ freeradius-1.1.0/src/modules/rlm_policy/evaluate.c 2005-10-12 13:09:21.000000000 -0400 @@ -344,13 +342,15 @@ rad_assert(pitem != NULL); rad_assert(state->depth >= 0); - redo: +redo: if (state->depth == 0) { *pitem = NULL; return 0; } *pitem = state->stack[state->depth - 1]; + if(state->depth > 1) + state->depth--; /* * Named policies are on the stack for catching recursion. @@ -490,7 +490,7 @@ { int rcode; const policy_condition_t *this; - VALUE_PAIR *vp; + VALUE_PAIR *vp = NULL; const char *data = NULL; int compare; #ifdef HAVE_REGEX_H @@ -498,6 +498,7 @@ #endif char buffer[256]; char lhs_buffer[2048]; + int next_vp = 0; this = (const policy_condition_t *) item; @@ -533,7 +534,9 @@ rcode = evaluate_condition(state, this->child); rcode = (rcode == FALSE); /* reverse sense of test */ break; - + + case POLICY_LEX_CMP_FALSE: /* no existence */ + /*fall through*/ case POLICY_LEX_CMP_TRUE: /* existence */ if (this->lhs_type == POLICY_LEX_BARE_WORD) { vp = find_vp(state->request, this->lhs); @@ -541,6 +544,8 @@ } else { rcode = (data != NULL); } + if (this->compare == POLICY_LEX_CMP_FALSE) + rcode = !rcode; break; default: /* process other comparisons */ @@ -561,9 +566,15 @@ if (this->lhs_type == POLICY_LEX_BARE_WORD) { VALUE_PAIR *myvp; + vp = find_vp(state->request, this->lhs); +retry_next_vp: + if(vp && next_vp) + { + const DICT_ATTR *dattr = dict_attrbyname(vp->name); + vp = pairfind(vp, dattr->attr); + } - vp = find_vp(state->request, this->lhs); /* * FIXME: Move sanity checks to * post-parse code, so we don't do @@ -638,6 +649,12 @@ int i; regmatch_t rxmatch[REQUEST_MAX_REGEX + 1]; + /* attribute is not in request */ + if (compare == -1) { + rcode = FALSE; + break; + } + /* * Include substring matches. */ @@ -646,6 +663,7 @@ return FALSE; } rad_assert(data != NULL); + rcode = regexec(®, data, REQUEST_MAX_REGEX + 1, rxmatch, 0); @@ -720,6 +738,11 @@ } /* switch over comparison operators */ break; /* default from first switch over compare */ } + if (rcode == FALSE && (vp = vp->next)) + { + next_vp = 1; + goto retry_next_vp; + } /* * No trailing &&, || @@ -814,6 +837,19 @@ case POLICY_LEX_PLUS_EQUALS: operator = T_OP_ADD; break; + + case POLICY_LEX_MINUS_EQUALS: + operator = T_OP_SUB; + break; + + case POLICY_LEX_MINUS_TRUE: + operator = T_OP_SUB_ALL; + break; + + case POLICY_LEX_RX_MINUS: + operator = T_OP_SUB_REG; + break; + default: fprintf(stderr, "Expected '=' for operator, not '%s' at line %d\n", @@ -898,12 +934,12 @@ break; case POLICY_LEX_ASSIGN: /* 'union' */ - pairmove(vps, &head); + pairxlatmove(NULL, vps, &head); pairfree(&head); break; case POLICY_LEX_CONCAT_EQUALS: - pairadd(vps, head); + pairxlatmove(NULL, vps, &head); break; default: diff -ur radiusd/src/modules/rlm_policy/parse.c freeradius-1.1.0/src/modules/rlm_policy/parse.c --- radiusd/src/modules/rlm_policy/parse.c 2005-10-10 06:41:37.000000000 -0400 +++ freeradius-1.1.0/src/modules/rlm_policy/parse.c 2005-10-12 06:46:38.000000000 -0400 @@ -97,6 +97,8 @@ { "!", POLICY_LEX_L_NOT }, { "=", POLICY_LEX_ASSIGN }, { "==", POLICY_LEX_CMP_EQUALS }, + { "=*", POLICY_LEX_CMP_TRUE }, + { "!*", POLICY_LEX_CMP_FALSE }, { "!=", POLICY_LEX_CMP_NOT_EQUALS }, { "<", POLICY_LEX_LT }, { ">", POLICY_LEX_GT }, @@ -106,6 +108,9 @@ { "!~", POLICY_LEX_RX_NOT_EQUALS }, { ".=", POLICY_LEX_CONCAT_EQUALS }, { ":=", POLICY_LEX_SET_EQUALS }, + { "-=", POLICY_LEX_MINUS_EQUALS }, + { "-*", POLICY_LEX_MINUS_TRUE }, + { "-~", POLICY_LEX_RX_MINUS }, { "double quoted string", POLICY_LEX_DOUBLE_QUOTED_STRING }, { "single quoted string", POLICY_LEX_SINGLE_QUOTED_STRING }, { "back quoted string", POLICY_LEX_BACK_QUOTED_STRING }, @@ -190,6 +195,16 @@ *token = POLICY_LEX_MINUS_EQUALS; input++; break; + + case '*': + *token = POLICY_LEX_MINUS_TRUE; + input++; + break; + + case '~': + *token = POLICY_LEX_RX_MINUS; + input++; + break; default: *token = POLICY_LEX_MINUS; @@ -699,8 +714,8 @@ lrad_int2str(rlm_policy_tokens, token, "?")); return 0; } - goto check; } /* else it's a comparison? */ + goto check; case POLICY_LEX_DOUBLE_QUOTED_STRING: this->lhs_type = token; @@ -727,6 +742,8 @@ case POLICY_LEX_GT: case POLICY_LEX_LE: case POLICY_LEX_GE: + case POLICY_LEX_CMP_TRUE: + case POLICY_LEX_CMP_FALSE: break; default: @@ -1231,6 +1248,9 @@ case POLICY_LEX_AND_EQUALS: case POLICY_LEX_OR_EQUALS: case POLICY_LEX_PLUS_EQUALS: + case POLICY_LEX_MINUS_EQUALS: + case POLICY_LEX_MINUS_TRUE: + case POLICY_LEX_RX_MINUS: break; default: diff -ur radiusd/src/modules/rlm_policy/rlm_policy.h freeradius-1.1.0/src/modules/rlm_policy/rlm_policy.h --- radiusd/src/modules/rlm_policy/rlm_policy.h 2005-10-10 06:41:39.000000000 -0400 +++ freeradius-1.1.0/src/modules/rlm_policy/rlm_policy.h 2005-10-12 13:10:15.000000000 -0400 @@ -37,6 +37,7 @@ #include "rad_assert.h" + /* * Internal lexer. */ @@ -74,6 +75,8 @@ POLICY_LEX_OR_EQUALS, /* |= */ POLICY_LEX_PLUS_EQUALS, /* += */ POLICY_LEX_MINUS_EQUALS, /* -= */ + POLICY_LEX_MINUS_TRUE, /* -* */ + POLICY_LEX_RX_MINUS, /* -~*/ POLICY_LEX_CONCAT_EQUALS, /* .= */ POLICY_LEX_VARIABLE, /* %{foo} */ POLICY_LEX_FUNCTION, /* Hmmm... */ --- radiusd/raddb/policy.txt 2004-12-16 17:21:41.000000000 -0500 +++ freeradius-1.1.0/raddb/policy.txt 2005-10-10 08:19:48.000000000 -0400 @@ -67,5 +67,5 @@ # # Execute "3pm", as if it was in-line here. # -# call 3pm + 3pm() } debug print_tokens # as we're parsing this file debug print_policy # once the file has been parsed debug evaluate # print limited information during evaluation policy pool_conflict_ipaddr { if ( (proxy-reply:Framed-IP-Address =* "") && (reply:Cisco-Avpair =~ "ip:addr-pool.*")) { reply .= { Cisco-Avpair -~ "ip:addr-pool.*" } } } policy post-proxy { pool_conflict_ipaddr() }