#! /bin/sh /usr/share/dpatch/dpatch-run
## 130-rlm-policy-fix.dpatch by  <joe@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:
