From 17692058ba332c83dc9a2a6e0bc6636ba5bef000 Mon Sep 17 00:00:00 2001
From: Nigel Kukard <nkukard@lbsd.net>
Date: Sun, 8 Mar 2009 13:23:13 +0000
Subject: [PATCH] * Move attribute code into the new attributes.pm module

---
 smradiusd | 385 +++---------------------------------------------------
 1 file changed, 18 insertions(+), 367 deletions(-)

diff --git a/smradiusd b/smradiusd
index 30a61da2..0756a4c1 100755
--- a/smradiusd
+++ b/smradiusd
@@ -44,6 +44,7 @@ use smradius::config;
 use smradius::dbilayer;
 use smradius::cache;
 use smradius::util;
+use smradius::attributes;
 
 use Radius::Packet;
 
@@ -706,325 +707,20 @@ sub process_request {
 		# AUTHORIZE USER
 		#
 
-		foreach my $attr (@{$user->{'Attributes'}}) {
-
-			# Operator: ==
-			#
-			# Use: Attribute == Value
-			# As a check item, it matches if the named attribute is present in the request,
-			# AND has the given value.
-			#
-
-			if ($attr->{'Operator'} eq '==' ) {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' == '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				# Check for correct value
-				if ($attrVal eq $attr->{'Value'}) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' matched");
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' does not match");
-					$authorized = 0;
-					last;
-				}
-
-			# Operator: >
-			#
-			# Use: Attribute > Value
-			# As a check item, it matches if the request contains an attribute
-			# with a value greater than the one given.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '>') {
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' > '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				if ($attrVal =~ /^[0-9]+$/) {
-					# Check for correct value
-					if ($attrVal > $attr->{'Value'}) {
-						$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' matched");
-					} else {
-						$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' does not match");
-						$authorized = 0;
-						last;
-					}
-				} else {
-					$self->log(LOG_WARN,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' is NOT a number!");
-				}
-
-			# Operator: <
-			#
-			# Use: Attribute < Value
-			# As a check item, it matches if the request contains an attribute
-			# with a value less than the one given.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '<') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing ".$attr->{'Name'}."' < '".$attr->{'Value'}." against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				# Check for correct value
-				if ($attrVal < $attr->{'Value'}) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' less than current value");
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' does not match");
-					$authorized = 0;
-					last;
-				}
-
-			# Operator: <=
-			#
-			# Use: Attribute <= Value
-			# As a check item, it matches if the request contains an attribute
-			# with a value less than, or equal to the one given.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '<=') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' <= '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				# Check for correct value
-				if ($attrVal <= $attr->{'Value'}) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' less than or equals current value");
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' greater than current value");
-					$authorized = 0;
-					last;
-				}
-
-			# Operator: >=
-			#
-			# Use: Attribute >= Value
-			# As a check item, it matches if the request contains an attribute
-			# with a value greater than, or equal to the one given.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '>=') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' >= '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				# Check for correct value
-				if ($attrVal >= $attr->{'Value'}) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' greater than or equals current value");
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value '$attrVal' less than current value");
-					$authorized = 0;
-					last;
-				}
-
-			# Operator: =*
-			#
-			# Use: Attribute =* Value
-			# As a check item, it matches if the request contains the named attribute,
-			# no matter what the value is.
-			#
-			# Not allowed as a reply item.
-
-			# Needs fixing, need to retrieve name, not value?
-
-			} elsif ($attr->{'Operator'} eq '=*') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' =* '".$attr->{'Value'}."' against NAS ".niceUndef($attrVal));
-				# Check for matching value
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not matched");
-					$authorized = 0;
-					next;
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' matches");
-				}
-
-			# Operator !=
-			#
-			# Use: Attribute != Value
-			# As a check item, matches if the given attribute is in the
-			# request, AND does not have the given value.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '!=') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' != '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				# Check for correct value
-				if ($attrVal ne $attr->{'Value'}) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' matches");
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' does not match");
-					$authorized = 0;
-					last;
-				}
-
-			# Operator: !*
-			#
-			# Use: Attribute !* Value
-			# As a check item, matches if the request does not contain the named attribute, no matter
-			# what the value is.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '!*') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' !* '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					$authorized = 0;
-					next;
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' matches");
-				}
-
-			# Operator: =~
-			#
-			# Use: Attribute =~ Value
-			# As a check item, matches if the request contains an attribute which matches the given regular expression.
-			# This operator may only be applied to string attributes.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '=~') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' =~ '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				# Check for correct value
-				my $regex = $attr->{'Value'};
-				if ($attrVal =~ /$regex/) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' matches");
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' does not match");
-					$authorized = 0;
-					last;
-				}
+		# Build a list of our attributes in the packet
+		my $authAttributes;
+		foreach my $attr ($pkt->attributes) {
+			$authAttributes->{$attr} = $pkt->rawattr($attr);
+		}
 
-			# Operator: !~
-			#
-			# Use: Attribute !~ Value
-			# As a check item, matches if the request does not contain the named attribute, no matter
-			# what the value is.
-			#
-			# Not allowed as a reply item.
-
-			} elsif ($attr->{'Operator'} eq '!~') {
-				# Check packet for value
-				my $attrVal = $pkt->attr($attr->{'Name'});
-				$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' !~ '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-				# Skip if value not defined
-				if (!defined($attrVal)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-					next;
-				}
-				# Check for correct value
-				my $regex = $attr->{'Value'};
-				if (!($attrVal =~ /$regex/)) {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value $attrVal does not match");
-				} else {
-					$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' with value $attrVal matches");
-					$authorized = 0;
-					last;
-				}
+		# Loop with attributes we got from the user
+		foreach my $attr (@{$user->{'Attributes'}}) {
+			# Check attribute against authorization attributes
+			my $res = checkAttributeAuth($server,$authAttributes,$attr);
+			if ($res != 0) {
+				$authorized = 0;
+				last;
 			}
-
-			# FIXME
-			# Operator: +=
-			#
-			# Use: Attribute += Value
-			# Always matches as a check item, and adds the current
-			# attribute with value to the list of configuration items.
-			#
-			# As a reply item, it has an itendtical meaning, but the
-			# attribute is added to the reply items.
-
-			#if ($attr->{'Operator'} eq '+=') {
-			#	# Check packet for value
-			#	my $attrVal = $pkt->attr($attr->{'Name'});
-			#	$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' !~ '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-			#	# Skip if value not defined
-			#	if (!defined($attrVal)) {
-			#		$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-			#		next;
-			#	}
-			#	# Check for correct value
-			#	if ($attrVal == $attr->{'Value'}) {
-			#	# FIXME - Add to config items
-			#		#add to config item list
-			#		$self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal exists and is equal to ".$attr->{'Name'});
-			#	} else {
-			#		$self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal exists and is not equal to ".$attr->{'Name'});
-			#		$authorized = 0;
-			#		last;
-			#	}
-			#}
-
-			# FIXME
-			# Operator: :=
-			#
-			# Use: Attribute := Value
-			# Always matches as a check item, and replaces in the configuration items any attribute of the same name. 
-			# If no attribute of that name appears in the request, then this attribute is added.
-			#
-			# As a reply item, it has an itendtical meaning, but for the reply items, instead of the request items.
-
-			#if ($attr->{'Operator'} eq ':=') {
-			#	# Check packet for value
-			#	my $attrVal = $pkt->attr($attr->{'Name'});
-			#	$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' !~ '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
-			#	# Skip if value not defined
-			#	if (!defined($attrVal)) {
-			#		$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
-			#		next;
-			#	}
-			#	# Check for correct value
-			#	if ($attrVal == $attr->{'Value'}) {
-			#	# FIXME - Add or replace config items
-			#		#add to config item list
-			#		$self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal exists and is equal to ".$attr->{'Name'});
-			#		} else {
-			#		$self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal exists and is not equal to ".$attr->{'Name'});
-			#		$authorized = 0;
-			#		last;
-			#	}
-			#}
 		}
 
 		# Check if we authenticated or not
@@ -1035,58 +731,13 @@ sub process_request {
 		 	$resp->set_code('Access-Accept');
 			$resp->set_identifier($pkt->identifier);
 			$resp->set_authenticator($pkt->authenticator);
+
 			# Loop with user attributes and add to radius response
+			my %replyAttributes;
 			foreach my $attr (@{$user->{'Attributes'}}) {
-
-				# Operator: =
-				#
-				# Use: Attribute = Value
-				# Not allowed as a check item for RADIUS protocol attributes. It is allowed for server
-				# configuration attributes (Auth-Type, etc), and sets the value of on attribute,
-				# only if there is no other item of the same attribute.
-				#
-				# As a reply item, it means "add the item to the reply list, but only if there is
-				# no other item of the same attribute.
-
-				if ($attr->{'Operator'} eq '=') {
-					my $attrVal = $resp->attr($attr->{'Name'});
-					if (!defined($attrVal)) {
-						$resp->set_attr($attr->{'Name'},$attr->{'Value'});
-					}
-
-				# Operator: :=
-				#
-				# Use: Attribute := Value
-				# Always matches as a check item, and replaces in the configuration items any attribute of the same name. 
-				# If no attribute of that name appears in the request, then this attribute is added.
-				#
-				# As a reply item, it has an itendtical meaning, but for the reply items, instead of the request items.
-
-				} elsif ($attr->{'Operator'} eq ':=') {
-					my $attrVal = $resp->attr($attr->{'Name'});
-					$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' !~ '".$attr->{'Value'}."' against REPLY value ".niceUndef($attrVal));
-					
-					# Add attribute if attribute appears
-					if (!defined($attrVal)) {
-						$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined, adding attribute");
-						$resp->set_attr($attr->{'Name'},$attr->{'Value'});
-
-					}
-
-				# Operator: +=
-				#
-				# Use: Attribute += Value
-				# Always matches as a check item, and adds the current
-				# attribute with value to the list of configuration items.
-				#
-				# As a reply item, it has an itendtical meaning, but the
-				# attribute is added to the reply items.
-
-				} elsif ($attr->{'Operator'} eq '+=') {
-					my $attrVal = $resp->attr($attr->{'Name'});
-					$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' += '".$attr->{'Value'}."' and adding to reply item");
-					
-					# Add attribute
+				# Add this to the reply attribute?
+				my $res = getReplyAttribute($server,\%replyAttributes,$attr);
+				if ($res) {
 					$resp->set_attr($attr->{'Name'},$attr->{'Value'});
 				}
 			}
-- 
GitLab