Newer
Older
#!/usr/bin/perl
# Radius daemon
# Copyright (C) 2008, AllWorldIT
# Copyright (C) 2007, Nigel Kukard <nkukard@lbsd.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use strict;
use warnings;
# Set library directory
use lib qw(
../ ./
smradius/modules/authentication
);
package radiusd;
use base qw(Net::Server::PreFork);
use Config::IniFiles;
use Getopt::Long;
use Sys::Syslog;
use smradius::version;
use smradius::constants;
use smradius::logging;
use smradius::config;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
use Radius::Packet;
use Data::Dumper;
# Override configuration
sub configure {
my ($self,$defaults) = @_;
my $server = $self->{'server'};
# If we hit a hash, add the config vars to the server
if (defined($defaults)) {
foreach my $item (keys %{$defaults}) {
$server->{$item} = $defaults->{$item};
}
return;
}
# Set defaults
my $cfg;
$cfg->{'config_file'} = "/etc/smradiusd.conf";
$server->{'timeout'} = 120;
$server->{'background'} = "yes";
$server->{'pid_file'} = "/var/run/smradiusd.pid";
$server->{'log_level'} = 2;
$server->{'log_file'} = "/var/log/smradiusd.log";
$server->{'host'} = "*";
$server->{'port'} = [ 1812, 1813 ];
$server->{'proto'} = 'udp';
$server->{'min_servers'} = 4;
$server->{'min_spare_servers'} = 4;
$server->{'max_spare_servers'} = 12;
$server->{'max_servers'} = 25;
$server->{'max_requests'} = 1000;
# Parse command line params
my $cmdline;
%{$cmdline} = ();
GetOptions(
\%{$cmdline},
"help",
"config:s",
"debug",
"fg",
) or die "Error parsing commandline arguments";
# Check for some args
if ($cmdline->{'help'}) {
$self->displayHelp();
exit 0;
}
if (defined($cmdline->{'config'}) && $cmdline->{'config'} ne "") {
$cfg->{'config_file'} = $cmdline->{'config'};
}
# Check config file exists
if (! -f $cfg->{'config_file'}) {
die("No configuration file '".$cfg->{'config_file'}."' found!\n");
}
# Use config file, ignore case
tie my %inifile, 'Config::IniFiles', (
-file => $cfg->{'config_file'},
-nocase => 1
) or die "Failed to open config file '".$cfg->{'config_file'}."': $!";
# Copy config
my %config = %inifile;
untie(%inifile);
# Pull in params for the server
my @server_params = (
'log_level','log_file',
# 'port', - We don't want to override this do we?
'host',
'cidr_allow', 'cidr_deny',
'pid_file',
'user', 'group',
'timeout',
'background',
'min_servers',
'min_spare_servers',
'max_spare_servers',
'max_servers',
'max_requests',
);
foreach my $param (@server_params) {
$server->{$param} = $config{'server'}{$param} if (defined($config{'server'}{$param}));
}
# Fix up these ...
if (defined($server->{'cidr_allow'})) {
my @lst = split(/,\s;/,$server->{'cidr_allow'});
$server->{'cidr_allow'} = \@lst;
}
if (defined($server->{'cidr_deny'})) {
my @lst = split(/,\s;/,$server->{'cidr_deny'});
$server->{'cidr_deny'} = \@lst;
}
# Override
if ($cmdline->{'debug'}) {
$server->{'log_level'} = 4;
$cfg->{'debug'} = 1;
}
# If we set on commandline for foreground, keep in foreground
if ($cmdline->{'fg'} || (defined($config{'server'}{'background'}) && $config{'server'}{'background'} eq "no" )) {
$server->{'background'} = undef;
$server->{'log_file'} = undef;
} else {
$server->{'setsid'} = 1;
}
# Loop with logging detail
if (defined($config{'server'}{'log_detail'})) {
# Lets see what we have to enable
foreach my $detail (split(/[,\s;]/,$config{'server'}{'log_detail'})) {
$cfg->{'logging'}{$detail} = 1;
}
}
#
# Authentication plugins
#
my @auth_params = (
);
my $auth;
foreach my $param (@auth_params) {
$auth->{$param} = $config{'authentication'}{$param} if (defined($config{'authentication'}{$param}));
}
if (!defined($auth->{'mechanisms'})) {
$self->log(LOG_ERR,"[SMRADIUS] Authentication configuration error: Mechanism plugins not found");
if (!defined($auth->{'users'})) {
$self->log(LOG_ERR,"[SMRADIUS] Authentication configuration error: Userdb plugins not found");
exit 1;
}
foreach my $plugin (@{$auth->{'mechanisms'}},@{$auth->{'users'}}) {
#
# Accounting plugins
#
my @acct_params = (
'plugins',
);
my $acct;
foreach my $param (@acct_params) {
$acct->{$param} = $config{'accounting'}{$param} if (defined($config{'accounting'}{$param}));
}
if (!defined($acct->{'plugins'})) {
$self->log(LOG_ERR,"[SMRADIUS] Accounting configuration error: Plugins not found");
exit 1;
}
# Split off plugins
foreach my $plugin (@{$auth->{'plugins'}}) {
$plugin =~ s/\s+//g;
}
#
# Dictionary configuration
#
my @dictionary_params = (
'load',
);
my $dictionary;
foreach my $param (@dictionary_params) {
$dictionary->{$param} = $config{'dictionary'}{$param} if (defined($config{'dictionary'}{$param}));
}
if (!defined($dictionary->{'load'})) {
$self->log(LOG_ERR,"[SMRADIUS] Dictionary configuration error: 'load' not found");
exit 1;
}
# Split off dictionaries to load
foreach my $fn (@{$dictionary->{'load'}}) {
$fn =~ s/\s+//g;
}
$cfg->{'authentication'} = $auth;
$cfg->{'dictionary'} = $dictionary;
$cfg->{'plugins'} = [
@{$auth->{'mechanisms'}},
@{$auth->{'users'}},
@{$acct->{'plugins'}}
# Save our config and stuff
$self->{'config'} = $cfg;
$self->{'cmdline'} = $cmdline;
$self->{'inifile'} = \%config;
}
# Run straight after ->run
sub post_configure_hook {
my $self = shift;
my $config = $self->{'config'};
# Init config
$self->log(LOG_NOTICE,"[SMRADIUS] Initializing configuration...");
smradius::config::Init($self);
$self->log(LOG_NOTICE,"[SMRADIUS] Configuration initialized.");
# Load dictionaries
$self->log(LOG_NOTICE,"[SMRADIUS] Initializing dictionaries...");
my $dict = new Radius::Dictionary;
foreach my $fn (@{$config->{'dictionary'}->{'load'}}) {
# Load dictionary
if (!$dict->readfile($fn)) {
$self->log(LOG_WARN,"[SMRADIUS] Failed to load dictionary '$fn': $!");
}
$self->log(LOG_DEBUG,"[SMRADIUS] Loaded plugin '$fn'.");
}
$self->log(LOG_NOTICE,"[SMRADIUS] Dictionaries initialized.");
# Store the dictionary
$self->{'radius'}->{'dictionary'} = $dict;
$self->log(LOG_NOTICE,"[SMRADIUS] Initializing modules...");
# Load plugins
foreach my $plugin (@{$config->{'plugins'}}) {
# Load plugin
my $res = eval("
use $plugin;
plugin_register(\$self,\"$plugin\",\$${plugin}::pluginInfo);
");
if ($@ || (defined($res) && $res != 0)) {
$self->log(LOG_WARN,"[SMRADIUS] Error loading plugin $plugin ($@)");
$self->log(LOG_DEBUG,"[SMRADIUS] Plugin '$plugin' loaded.");
$self->log(LOG_NOTICE,"[SMRADIUS] Plugins initialized.");
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
$self->log(LOG_NOTICE,"[SMRADIUS] Initializing system modules.");
# Init caching engine
# smradius::cache::Init($self);
$self->log(LOG_NOTICE,"[SMRADIUS] System modules initialized.");
}
# Register plugin info
sub plugin_register {
my ($self,$plugin,$info) = @_;
# If no info, return
if (!defined($info)) {
print(STDERR "WARNING: Plugin info not found for plugin => $plugin\n");
return -1;
}
# Set real module name & save
$info->{'Module'} = $plugin;
push(@{$self->{'plugins'}},$info);
# If we should, init the module
if (defined($info->{'Init'})) {
$info->{'Init'}($self);
}
return 0;
}
# Initialize child
sub child_init_hook
{
my $self = shift;
my $config = $self->{'config'};
$self->log(LOG_DEBUG,"[SMRADIUS] Starting up caching engine");
smradius::cache::connect($self);
# Do we need database support?
if ($self->{'smradius'}->{'database'}->{'enabled'}) {
# This is the database connection timestamp, if we connect, it resets to 0
# if not its used to check if we must kill the child and try a reconnect
$self->{'client'}->{'dbh_status'} = time();
# Init core database support
$self->{'client'}->{'dbh'} = smradius::dbilayer::Init($self);
if (defined($self->{'client'}->{'dbh'})) {
# Check if we succeeded
if (!($self->{'client'}->{'dbh'}->connect())) {
$self->{'client'}->{'dbh_status'} = 0;
} else {
$self->log(LOG_WARN,"[SMRADIUS] Failed to connect to database: ".$self->{'client'}->{'dbh'}->Error()." ($$)");
}
$self->log(LOG_WARN,"[SMRADIUS] Failed to Initialize: ".smradius::dbilayer::internalErr()." ($$)");
}
# Destroy the child
sub child_finish_hook {
my $self = shift;
my $server = $self->{'server'};
$self->SUPER::child_finish_hook();
$self->log(LOG_DEBUG,"[SMRADIUS] Shutting down caching engine ($$)");
smradius::cache::disconnect($self);
}
# Process requests we get
sub process_request {
my $self = shift;
my $server = $self->{'server'};
my $client = $self->{'client'};
my $log = defined($server->{'config'}{'logging'}{'modules'});
# Grab packet
my $udp_packet = $server->{'udp_data'};
# Check min size
if (length($udp_packet) < 18)
{
$self->log(LOG_WARN, "[SMRADIUS] Packet too short - Ignoring");
return;
}
# Parse packet
my $pkt = new Radius::Packet($self->{'radius'}->{'dictionary'},$udp_packet);
# VERIFY SOURCE SERVER
$self->log(LOG_DEBUG,"[SMRADIUS] Packet From = > ".$server->{'peeraddr'});
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
# Check if we got connected, if not ... bypass
if ($self->{'client'}->{'dbh_status'} > 0) {
my $action;
$self->log(LOG_WARN,"[SMRADIUS] Client in BYPASS mode due to DB connection failure!");
# Check bypass mode
if (!defined($self->{'inifile'}{'database'}{'bypass_mode'})) {
$self->log(LOG_ERR,"[SMRADIUS] No bypass_mode specified for failed database connections, defaulting to tempfail");
$action = "tempfail";
# Check for "tempfail"
} elsif (lc($self->{'inifile'}{'database'}{'bypass_mode'}) eq "tempfail") {
# And for "bypass"
} elsif (lc($self->{'inifile'}{'database'}{'bypass_mode'}) eq "pass") {
}
# Check if we need to reconnect or not
my $timeout = $self->{'inifile'}{'database'}{'bypass_timeout'};
if (!defined($timeout)) {
$self->log(LOG_ERR,"[SMRADIUS] No bypass_timeout specified for failed database connections, defaulting to 120s");
$timeout = 120;
}
# Get time left
my $timepassed = time() - $self->{'client'}->{'dbh_status'};
# Then check...
if ($timepassed >= $timeout) {
$self->log(LOG_NOTICE,"[SMRADIUS] Client BYPASS timeout exceeded, reconnecting...");
exit 0;
} else {
$self->log(LOG_NOTICE,"[SMRADIUS] Client still in BYPASS mode, ".( $timeout - $timepassed )."s left till next reconnect");
return;
}
}
# Setup database handle
smradius::dblayer::setHandle($self->{'client'}->{'dbh'});
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
#LOGIN
#Service-Type: Login-User
#User-Name: joe
#User-Password: \x{d3}\x{df}\x{10}\x{8c}\x{a0}r.\x{fd}=\x{ff}\x{96}\x{a}\x{86}\x{91}\x{e}c
#Calling-Station-Id: 10.254.254.242
#NAS-Identifier: lbsd-test
#NAS-IP-Address: 10.254.254.239
#PPPOE:
#Service-Type: Framed-User
#Framed-Protocol: PPP
#NAS-Port: 19
#NAS-Port-Type: Ethernet
#User-Name: nigel
#Calling-Station-Id: 00:E0:4D:2A:72:35
#Called-Station-Id: pppoe-24
#NAS-Port-Id: ether1
#NAS-Identifier: lbsd-test
#NAS-IP-Address: 10.254.254.239
#
# User Authentication
#
# Authentication
#a. SELECT ID, Password FROM Users WHERE Username = %u
# Optional Items:
# 'Disabled' - Indicates the user is disabled
#
# Save the query result, so we can use it as macros.... ${user.<column name>} below...
#
# Authorization: Attribute checks
#
# User attributes
#b. SELECT Attribute, OP, Value FROM UserAttributes WHERE UserID = ${user.id}
# Attribute groups
#c. SELECT Group FROM UsersToGroups WHERE UserID = ${user.id}
# Save the query result, so we can use it as macros... ${group.<column name>} below...
# Group attributes
#d. SELECT Attribute, OP, Value FROM GroupAttributes WHERE GroupID = ${group.id}
# Loop with groups and do the query ...
#
# Authentication procedure
#
# On user AUTH ....
#1. Execute query (a), set query result in 'user' hash
# - Check 'disabled' parameter
#2. Run past plugins - check if we authenticate
# - if not reject
#3. Pull in query (c), loop with groups for query (d)
#4. Merge in query (b)
#5. Check attributes that need checking
# - reject if fail
#6. Return attributes that need to be returned
# find user
# get user
# - User
# - Password
# {mech}data
# - Data
# (additional columns from table)
# - Attributes (array)
# Attribute,OP,Value
# - Group (array)
# - Data
# (additional columns from table)
# - Attributes
# Attribute,OP,Value
# try authenticate
# check attribs
# Main user hash with everything in
my $user;
# UserDB module if we using/need it
my $userdb;
# Common stuff for multiple codes....
if ($pkt->code eq "Accounting-Request" || $pkt->code eq "Access-Request") {
# Set username
$user->{'Username'} = $pkt->attr('User-Name');
#
# FIND USER
#
# Loop with modules to try find user
foreach my $module (@{$self->{'plugins'}}) {
# Try find user
if ($module->{'User_find'}) {
$self->log(LOG_INFO,"[SMRADIUS] FIND: Trying plugin '".$module->{'Name'}."' for username '".$user->{'Username'}."'");
my ($res,$userdb_data) = $module->{'User_find'}($self,$user,$pkt);
# Check result
if (!defined($res)) {
$self->log(LOG_DEBUG,"[SMRADIUS] FIND: Error with plugin '".$module->{'Name'}."'");
# Check if we skipping this plugin
} elsif ($res == MOD_RES_SKIP) {
$self->log(LOG_DEBUG,"[SMRADIUS] FIND: Skipping '".$module->{'Name'}."'");
# Check if we got a positive result back
} elsif ($res == MOD_RES_ACK) {
$self->log(LOG_NOTICE,"[SMRADIUS] FIND: Username found with '".$module->{'Name'}."'");
$userdb = $module;
$user->{'_UserDB_Data'} = $userdb_data;
last;
# Or a negative result
} elsif ($res == MOD_RES_NACK) {
$self->log(LOG_NOTICE,"[SMRADIUS] FIND: Username not found with '".$module->{'Name'}."'");
last;
}
}
}
}
# Is this an accounting request
if ($pkt->code eq "Accounting-Request") {
$self->log(LOG_DEBUG,"[SMRADIUS] Accounting Request Packet");
#
# GET USER
#
# Get user data
if (defined($userdb) && defined($userdb->{'User_get'})) {
my $res = $userdb->{'User_get'}($self,$user,$pkt);
# Check result
if (defined($res) && ref($res) eq "HASH") {
# We're only after the attributes here
$user->{'Attributes'} = $res->{'Attributes'};
}
}
# Loop with modules to try something that handles accounting
foreach my $module (@{$self->{'plugins'}}) {
# Try find user
if ($module->{'Accounting_log'}) {
$self->log(LOG_INFO,"[SMRADIUS] ACCOUNTING: Trying plugin '".$module->{'Name'}."'");
my $res = $module->{'Accounting_log'}($self,$user,$pkt);
# Check result
if (!defined($res)) {
$self->log(LOG_DEBUG,"[SMRADIUS] ACCOUNTING: Error with plugin '".$module->{'Name'}."'");
# Check if we skipping this plugin
} elsif ($res == MOD_RES_SKIP) {
$self->log(LOG_DEBUG,"[SMRADIUS] ACCOUNTING: Skipping '".$module->{'Name'}."'");
# Check if we got a positive result back
} elsif ($res == MOD_RES_ACK) {
$self->log(LOG_NOTICE,"[SMRADIUS] ACCOUNTING: Accounting logged using '".$module->{'Name'}."'");
# Check if we got a negative result back
} elsif ($res == MOD_RES_NACK) {
$self->log(LOG_NOTICE,"[SMRADIUS] ACCOUNTING: Accounting NOT LOGGED using '".$module->{'Name'}."'");
}
}
}
# Tell the NAS we got its packet
my $resp = Radius::Packet->new($self->{'radius'}->{'dictionary'});
$resp->set_code('Accounting-Response');
$resp->set_identifier($pkt->identifier);
$resp->set_authenticator($pkt->authenticator);
$udp_packet = auth_resp($resp->pack, "test");
$server->{'client'}->send($udp_packet);
# Or maybe a access request
} elsif ($pkt->code eq "Access-Request") {
$self->log(LOG_DEBUG,"[SMRADIUS] Access Request Packet");
$self->log(LOG_DEBUG,"[SMRADIUS] Packet: ".$pkt->dump);
# Authentication variables
if (!defined($userdb)) {
$self->log(LOG_INFO,"[SMRADIUS] FIND: No plugin found for username '".$user->{'Username'}."'");
goto CHECK_RESULT;
}
#
# GET USER
#
# Get user data
my $res = $userdb->{'User_get'}($self,$user,$pkt);
# Check result
if (!defined($res) || ref($res) ne "HASH") {
$self->log(LOG_WARN,"[SMRADIUS] GET: No data returned from '".$userdb->{'Name'}."' for username '".$user->{'Username'}."'");
# Setup user dataw
$user->{'ClearPassword'} = $res->{'ClearPassword'};
$user->{'Attributes'} = $res->{'Attributes'};
} else {
$self->log(LOG_INFO,"[SMRADIUS] GET: No 'User_get' function available for module '".$userdb->{'Name'}."'");
# Loop with modules
foreach my $module (@{$self->{'plugins'}}) {
# Try authenticate
if ($module->{'Auth_try'}) {
$self->log(LOG_INFO,"[SMRADIUS] AUTH: Trying plugin '".$module->{'Name'}."' for '".$user->{'Username'}."'");
my $res = $module->{'Auth_try'}($self,$user,$pkt);
$self->log(LOG_DEBUG,"[SMRADIUS] AUTH: Error with plugin '".$module->{'Name'}."'");
# Check if we skipping this plugin
} elsif ($res == MOD_RES_SKIP) {
$self->log(LOG_DEBUG,"[SMRADIUS] AUTH: Skipping '".$module->{'Name'}."'");
# Check if we got a positive result back
} elsif ($res == MOD_RES_ACK) {
$self->log(LOG_NOTICE,"[SMRADIUS] AUTH: Authenticated by '".$module->{'Name'}."'");
$mechanism = $module;
$authenticated = 1;
last;
# Or a negative result
} elsif ($res == MOD_RES_NACK) {
$self->log(LOG_NOTICE,"[SMRADIUS] AUTH: Failed authentication by '".$module->{'Name'}."'");
$mechanism = $module;
last;
}
}
}
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");
} 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 '>') {
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
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 '<') {
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 '<=') {
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 '>=') {
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
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 '=*') {
my $attrVal = $pkt->attr($attr->{'Name'});
$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' =* '".$attr->{'Value'}."' against NAS ".niceUndef($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 '!=') {
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 '!*') {
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 '=~') {
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;
}
# 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 '!~') {
my $attrVal = $pkt->attr($attr->{'Name'});
$self->log(LOG_DEBUG,"[SMRADIUS] Processing '".$attr->{'Name'}."' !~ '".$attr->{'Value'}."' against NAS value ".niceUndef($attrVal));
if (!defined($attrVal)) {
$self->log(LOG_DEBUG,"[SMRADIUS] - Attribute '".$attr->{'Name'}."' not defined");
next;
}
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;
}
}
# 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 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: :=