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() }