From cfd3baa761aca3fa3475928495155aebc6205280 Mon Sep 17 00:00:00 2001 From: Robert Anderson <randerson@lbsd.net> Date: Tue, 3 Mar 2009 12:26:43 +0000 Subject: [PATCH] Added some support for operators --- smradiusd | 311 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 305 insertions(+), 6 deletions(-) diff --git a/smradiusd b/smradiusd index 94af0707..49bf454d 100755 --- a/smradiusd +++ b/smradiusd @@ -43,6 +43,7 @@ use smradius::logging; use smradius::config; use smradius::dbilayer; use smradius::cache; +use smradius::util; use Radius::Packet; @@ -638,7 +639,7 @@ sub process_request { # Check result if (!defined($res)) { - $self->log(LOG_DEBUG,"[SMRADIUS] AUTH: Error with plugin '".$module->{'Name'}."'"); + $self->log(LOG_DEBUG,"[SMRADIUS] AUTH: Error with plugin '".$module->{'Name'}."'"); # Check if we skipping this plugin } elsif ($res == MOD_RES_SKIP) { @@ -665,22 +666,320 @@ sub process_request { # AUTHORIZE USER # - # FIXME: Merge attributes + 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 '==' ) { + 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"); + my $authorized = 1; + } 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. + + if ($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. + + if ($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; + } + # 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. + + if ($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; + } + # 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. + + if ($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; + } + # 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? + + if ($attr->{'Operator'} eq '=*') { + my $attrVal = $pkt->attr($attr->{'Name'}); + $self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' =* '".$attr->{'Value'}."' against NAS ".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'}."' matched"); + } + } + + # 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. + + if ($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; + } + # Check for correct value + if ($attrVal ne $attr->{'Value'}) { + $self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' does not match"); + } else { + $self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' matches"); + $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. + + if ($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"); + $authorized = 0; + next; + } + } + + # 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. + + #if ($attr->{'Operator'} eq '=~') { + # my $attrVal = $pkt->attr($attr->{'Name'}); + # $self->log(LOG_DEBUG,"[SMRADIUS] Processing ".$attr->{'Name'}." '=~' ".$attr->{'Value'}." against NAS $attrVal"); + # # Skip if value not defined + # if (!defined($attrVal)) { + # $self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}." not defined"); + # next; + # } + # # Check for correct value + # if ($attrVal =~ /$attr->{'Value'}/) { + # $self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal does not match"); + # } else { + # $self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal matches"); + # $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. + + #if ($attr->{'Operator'} eq '!~') { + # my $attrVal = $pkt->attr($attr->{'Name'}); + # $self->log(LOG_DEBUG,"[SMRADIUS] Processing ".$attr->{'Name'}." '!~' ".$attr->{'Value'}." against NAS $attrVal"); + # Skip if value not defined + # if (!defined($attrVal)) { + # $self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}." not defined"); + # next; + # } + # Check for correct value + # if (!($attrVal =~ /$attr->{'Value'}/)) { + # $self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal does not match"); + # } else { + # $self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}.": $attrVal matches"); + # $authorized = 0; + # last; + # } + #} + + # FIXME - Nigel + # 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 '+=') { + # my $attrVal = $pkt->attr($attr->{'Name'}); + # $self->log(LOG_DEBUG,"[SMRADIUS] Processing ".$attr->{'Name'}." '+=' ".$attr->{'Value'}." against NAS $attrVal"); + # # Skip if value not defined + # if (!defined($attrVal)) { + # $self->log(LOG_DEBUG,"[SMRADIUS] ".$attr->{'Name'}." not defined"); + # next; + # } + # # Check for correct value + # if ($attrVal == $attr->{'Value'}) { + # #FIXME 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 - if ($authenticated) { + if ($authenticated && $authorized) { my $resp = Radius::Packet->new($self->{'radius'}->{'dictionary'}); - $resp->set_code('Access-Accept'); + $resp->set_code('Access-Accept'); $resp->set_identifier($pkt->identifier); $resp->set_authenticator($pkt->authenticator); # Loop with user attributes and add to radius response foreach my $attr (@{$user->{'Attributes'}}) { - $resp->set_attr($attr->{'Name'},$attr->{'Value'}); + + #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 '=') { + $resp->set_attr($attr->{'Name'},$attr->{'Value'}); + } } $self->log(LOG_DEBUG,"[SMRADIUS] User attributes:".Dumper($user)); - + $udp_packet = auth_resp($resp->pack, "test"); $server->{'client'}->send($udp_packet); + } CHECK_RESULT: -- GitLab