Removing attributes from a reply

Joe Maimon jmaimon at ttec.com
Wed Oct 12 22:54:19 CEST 2005


in evaluate.c

   if (rcode == FALSE && vp && (vp = vp->next))

instead of

   if (rcode == FALSE && (vp = vp->next))

Joe Maimon wrote:

> 
> 
> Joe Maimon wrote:
> 
>>
>>
>> Alan DeKok wrote:
>>
>>> Joe Maimon <jmaimon at 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 at 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(&reg, (char *)second->vp_strvalue,
> +					REG_EXTENDED);
> +					result = regexec(&reg, (char *)first->vp_strvalue,
> +						0, NULL, 0);
> +					regfree(&reg);
> +				
> +					if(!result)
> +						return first;
> +				}
> +				if (first->operator == T_OP_REG_EQ ||
> +				    first->operator == T_OP_REG_NE ||
> +				    first->operator == T_OP_SUB_REG)
> +				{
> +
> +					regcomp(&reg, (char *)first->vp_strvalue,
> +						REG_EXTENDED);
> +					result = regexec(&reg, (char *)second->vp_strvalue,
> +							0, NULL, 0);
> +					regfree(&reg);
> +
> +					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(&reg, 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()
> }
> 	
> 		
> 
> 
> ------------------------------------------------------------------------
> 
> - 
> List info/subscribe/unsubscribe? See http://www.freeradius.org/list/devel.html



More information about the Freeradius-Devel mailing list