The substar regex patch has been discussed previously.
It adds the -* and ~- operators, and changes -= operator to behave
correctly.
The work I did on rlm_policy to suit my needs I split into 2 patches.
The rlm_policy-fix patch is the minimum I found to be required to make
the module perform for me.
rlm-policy-subops patch is the other half of what I use the rlm_policy
for. It depends on the -~ operator patch.
Included for giggles is my working!! policy.txt file.
Thanks to Alan and company for the rlm_policy module! I have high hopes
for it.
Thanks for any consideration, any and all feedback welcome.
Joe
#! /bin/sh /usr/share/dpatch/dpatch-run
## 030-substar_regex.patch.dpatch by <joe(a)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.
*/
#! /bin/sh /usr/share/dpatch/dpatch-run
## 130-rlm-policy-fix.dpatch by <joe(a)nameserver3.ttec.com>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.
@DPATCH@
diff -urNad --exclude=CVS --exclude=.svn ./raddb/policy.txt /tmp/dpep-work.9zGKeC/freeradius-1.1.0/raddb/policy.txt
--- ./raddb/policy.txt 2005-10-13 20:41:46.000000000 -0400
+++ /tmp/dpep-work.9zGKeC/freeradius-1.1.0/raddb/policy.txt 2005-10-13 20:49:41.000000000 -0400
@@ -67,5 +67,5 @@
#
# Execute "3pm", as if it was in-line here.
#
-# call 3pm
+ 3pm()
}
diff -urNad --exclude=CVS --exclude=.svn ./src/modules/rlm_policy/evaluate.c /tmp/dpep-work.9zGKeC/freeradius-1.1.0/src/modules/rlm_policy/evaluate.c
--- ./src/modules/rlm_policy/evaluate.c 2005-10-13 20:41:47.000000000 -0400
+++ /tmp/dpep-work.9zGKeC/freeradius-1.1.0/src/modules/rlm_policy/evaluate.c 2005-10-13 20:49:41.000000000 -0400
@@ -344,13 +344,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 +492,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 +500,7 @@
#endif
char buffer[256];
char lhs_buffer[2048];
+ int next_vp = 0;
this = (const policy_condition_t *) item;
@@ -533,7 +536,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 +546,8 @@
} else {
rcode = (data != NULL);
}
+ if (this->compare == POLICY_LEX_CMP_FALSE)
+ rcode = !rcode;
break;
default: /* process other comparisons */
@@ -561,9 +568,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 +651,12 @@
int i;
regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
+ /* attribute is not in request */
+ if (compare == -1) {
+ rcode = FALSE;
+ break;
+ }
+
/*
* Include substring matches.
*/
@@ -720,6 +739,11 @@
} /* switch over comparison operators */
break; /* default from first switch over compare */
}
+ if (rcode == FALSE && vp && (vp = vp->next))
+ {
+ next_vp = 1;
+ goto retry_next_vp;
+ }
/*
* No trailing &&, ||
diff -urNad --exclude=CVS --exclude=.svn ./src/modules/rlm_policy/parse.c /tmp/dpep-work.9zGKeC/freeradius-1.1.0/src/modules/rlm_policy/parse.c
--- ./src/modules/rlm_policy/parse.c 2005-10-13 20:41:47.000000000 -0400
+++ /tmp/dpep-work.9zGKeC/freeradius-1.1.0/src/modules/rlm_policy/parse.c 2005-10-13 20:49:41.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 },
@@ -699,8 +701,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 +729,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:
#! /bin/sh /usr/share/dpatch/dpatch-run
## 140-rlm-policy-subops.dpatch by <joe(a)nameserver3.ttec.com>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: No description.
@DPATCH@
diff -urNad --exclude=CVS --exclude=.svn ./src/modules/rlm_policy/evaluate.c /tmp/dpep-work.HBL4sz/freeradius-1.1.0/src/modules/rlm_policy/evaluate.c
--- ./src/modules/rlm_policy/evaluate.c 2005-10-13 20:41:47.000000000 -0400
+++ /tmp/dpep-work.HBL4sz/freeradius-1.1.0/src/modules/rlm_policy/evaluate.c 2005-10-13 20:52:12.000000000 -0400
@@ -814,6 +814,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 +911,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 -urNad --exclude=CVS --exclude=.svn ./src/modules/rlm_policy/parse.c /tmp/dpep-work.HBL4sz/freeradius-1.1.0/src/modules/rlm_policy/parse.c
--- ./src/modules/rlm_policy/parse.c 2005-10-13 20:41:47.000000000 -0400
+++ /tmp/dpep-work.HBL4sz/freeradius-1.1.0/src/modules/rlm_policy/parse.c 2005-10-13 20:52:15.000000000 -0400
@@ -106,6 +106,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 +193,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;
@@ -1231,6 +1244,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 -urNad --exclude=CVS --exclude=.svn ./src/modules/rlm_policy/rlm_policy.h /tmp/dpep-work.HBL4sz/freeradius-1.1.0/src/modules/rlm_policy/rlm_policy.h
--- ./src/modules/rlm_policy/rlm_policy.h 2005-10-13 20:41:47.000000000 -0400
+++ /tmp/dpep-work.HBL4sz/freeradius-1.1.0/src/modules/rlm_policy/rlm_policy.h 2005-10-13 20:52:02.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... */
#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()
}