*** /home/alister/Playpen/Source/Easynet-SVN/svn/UK/Infrastructure_Projects/Customer_Radius/FreeRadius/Vendor/src/main/valuepair.c	2005-10-06 10:42:43.000000000 +0100
--- valuepair_fix.c	2005-11-03 15:34:10.000000000 +0000
***************
*** 213,226 ****
   */
  int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **reply)
  {
! 	VALUE_PAIR *check_item;
! 	VALUE_PAIR *auth_item;
  	int result = 0;
! 	int compare;
! 	int other;
! #ifdef HAVE_REGEX_H
! 	regex_t reg;
! #endif
  
  	for (check_item = check; check_item != NULL; check_item = check_item->next) {
  		/*
--- 213,226 ----
   */
  int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **reply)
  {
! 	VALUE_PAIR *check_item =NULL;
! 	VALUE_PAIR *auth_item = NULL;
! 	
  	int result = 0;
! 	int negative_test = 0;
! 	int seen = 0;
! 	int compare = 0;
! 	int other = 0;
  
  	for (check_item = check; check_item != NULL; check_item = check_item->next) {
  		/*
***************
*** 228,233 ****
--- 228,235 ----
  		 *	then don't bother comparing it to any attributes
  		 *	sent to us by the user.  It ALWAYS matches.
  		 */
+ 		negative_test = 0;
+ 		seen = 0;
  		if ((check_item->operator == T_OP_SET) ||
  		    (check_item->operator == T_OP_ADD)) {
  			continue;
***************
*** 283,306 ****
  			 *	Didn't find it.  If we were *trying*
  			 *	to not find it, then we succeeded.
  			 */
! 			if (check_item->operator == T_OP_CMP_FALSE)
  				return 0;
! 			else
! 				return -1;
  		}
  
  		/*
  		 *	Else we found it, but we were trying to not
  		 *	find it, so we failed.
  		 */
! 		if (check_item->operator == T_OP_CMP_FALSE)
  			return -1;
  
  
  		/*
  		 *	We've got to xlat the string before doing
  		 *	the comparison.
  		 */
  		if (check_item->flags.do_xlat) {
  			int rcode;
  			char buffer[sizeof(check_item->strvalue)];
--- 285,316 ----
  			 *	Didn't find it.  If we were *trying*
  			 *	to not find it, then we succeeded.
  			 */
! 			if (check_item->operator == T_OP_CMP_FALSE) {
! 				continue;
! 			} 
! 	                if (seen=1 && negative_test == 1) {
! 				continue;
! 	                } 
! 			if (seen=0) {
  				return 0;
! 			}
! 			return -1;
  		}
  
  		/*
  		 *	Else we found it, but we were trying to not
  		 *	find it, so we failed.
  		 */
! 		if (check_item->operator == T_OP_CMP_FALSE) {
  			return -1;
+ 		}
  
  
  		/*
  		 *	We've got to xlat the string before doing
  		 *	the comparison.
  		 */
+ 
  		if (check_item->flags.do_xlat) {
  			int rcode;
  			char buffer[sizeof(check_item->strvalue)];
***************
*** 320,326 ****
--- 330,342 ----
  		 *	OK it is present now compare them.
  		 */
  		compare = paircompare(req, auth_item, check_item, check, reply);
+ 		seen = 1;
  
+ 		/* When handling negative results.... 
+ 		 * seen=0 and no match is FALSE
+ 		 * seen=1 and no match is TRUE
+ 		 * this caused much pain before I noticed it.
+ 		 */
  		switch (check_item->operator) {
  			case T_OP_EQ:
  			default:
***************
*** 328,340 ****
  						"reverting to '=='", check_item->name);
  				/*FALLTHRU*/
  		        case T_OP_CMP_TRUE:    /* compare always == 0 */
- 		        case T_OP_CMP_FALSE:   /* compare always == 1 */
- 			case T_OP_CMP_EQ:
  				if (compare != 0) result = -1;
! 				break;
  
  			case T_OP_NE:
! 				if (compare == 0) result = -1;
  				break;
  
  			case T_OP_LT:
--- 344,360 ----
  						"reverting to '=='", check_item->name);
  				/*FALLTHRU*/
  		        case T_OP_CMP_TRUE:    /* compare always == 0 */
  				if (compare != 0) result = -1;
!                                 break;
  
+ 		        case T_OP_CMP_FALSE:   /* compare always == 1 */
+ 				if (compare != 0) result = -1;
+                                 break;
+ 	
  			case T_OP_NE:
! 				negative_test = 1;
! 			case T_OP_CMP_EQ:
! 				if (compare != 0) result = -1;
  				break;
  
  			case T_OP_LT:
***************
*** 354,363 ****
--- 374,386 ----
  				break;
  
  #ifdef HAVE_REGEX_H
+ 			case T_OP_REG_NE:
+ 				negative_test = 1;
  			case T_OP_REG_EQ:
  			{
  				int i;
  				regmatch_t rxmatch[9];
+ 				regex_t reg;
  
  				/*
  				 *	Include substring matches.
***************
*** 420,435 ****
  							 p, free);
  				}
  			}				
! 				if (compare != 0) result = -1;
! 				break;
  
- 			case T_OP_REG_NE:
- 				regcomp(&reg, (char *)check_item->strvalue, REG_EXTENDED|REG_NOSUB);
- 				compare = regexec(&reg, (char *)auth_item->strvalue,
- 						0, NULL, 0);
- 				regfree(&reg);
- 				if (compare == 0) result = -1;
- 				break;
  #endif
  
  		} /* switch over the operator of the check item */
--- 443,451 ----
  							 p, free);
  				}
  			}				
! 			if (compare != 0) result = -1;
! 			break;
  
  #endif
  
  		} /* switch over the operator of the check item */
***************
*** 437,451 ****
  		/*
  		 *	This attribute didn't match, but maybe there's
  		 *	another of the same attribute, which DOES match.
  		 */
  		if (result != 0) {
  			auth_item = auth_item->next;
  			result = 0;
  			goto try_again;
  		}
  
  	} /* for every entry in the check item list */
- 
  	return 0;		/* it matched */
  }
  
--- 453,472 ----
  		/*
  		 *	This attribute didn't match, but maybe there's
  		 *	another of the same attribute, which DOES match.
+ 		 *	Slightly harder maybe we are looking to find that 
+ 		 *	all values of an attribute does not match a given 
+ 		 *	regex / value.
  		 */
  		if (result != 0) {
  			auth_item = auth_item->next;
  			result = 0;
  			goto try_again;
  		}
+ 		if ((negative_test && result == 0) || result != 0) {
+ 			return -1;
+ 		}
  
  	} /* for every entry in the check item list */
  	return 0;		/* it matched */
  }
  
