The attached is our postauthhook file which we use to see if the user
has exceeded their quota of usage, this is calculated on a rolling 30
days. The problem we have is that when a user has used 150% or more we
are trying to send a reject, and due to safety in the script we return 1
second session timeout. The user receives an "Access-Accept" with the
reply message and attributes clearly showing that this user should not
have connected. Where are we going wrong with the changing of the return
code ?
--
Steve Wilson <[EMAIL PROTECTED]>
#!/usr/bin/perl
#host isdn0.radius.legend.net.uk:3306
#user auth / 4uTH
#select from usergroup where UserName = '' and GroupName like 'service_%';
# start of main function
sub {
my $p = ${$_[0]}; # proxy reply packet
my $rp = ${$_[1]}; # reply packet to NAS
my $op = ${$_[2]}; # original request packet
# my $sp = ${$_[3]}; # packet sent to proxy
use DBI;
my %dat;
$dat{username} = $p->getUserName;
if ( not defined ( $dat{contention} ) ) {
$dat{contention} = "service_8to2";
};
# variable names;
my $dbh;
my $sql_query;
my $sth;
my $rv;
my $tmp;
# Config data
# define accounting database config
$dat{dbhost} = 'localhost';
$dat{db} = 'isdn';
$dat{dbuser} = 'user';
$dat{dbpass} = 'pass';
# contention database config
$dat{dbchost} = 'other.radius.server';
$dat{dbc} = 'radius';
$dat{dbcuser} = 'user';
$dat{dbcpass} = 'pass';
# define constants
$dat{time} = time; # current time
$dat{tday} = ( 60*60*24 ); # seconds in 1 day
$dat{tmon} = (30*$dat{tday}); # seconds in 30 days
$dat{tlivem} = $dat{time} - $dat{tmon}; # time 30 days ago
$dat{tlived} = $dat{time} - $dat{tday}; # time 1 days ago
$dat{idlet} = 600; # 10 minutes
if ($p->code eq 'Access-Request')
{
# connect to the contention database
$dbh = DBI->connect("DBI:mysql:$dat{dbc}:$dat{dbchost}",$dat{dbcuser},$dat{dbcpass}) || die "Cannot connect to contention DB" ;
$sql_query = "SELECT `GroupName` FROM `usergroup` WHERE `UserName` = '$dat{username}' AND `GroupName` LIKE 'service_%';";
&main::log($main::LOG_DEBUG, "ASQL[$sql_query]\n");
$sth = $dbh->prepare($sql_query);
$rv = $sth->execute;
$tmp = $sth->fetchrow_hashref;
print "[[[$tmp->{GroupName}]]]\n";
$dat{contention} = $tmp->{GroupName};
$sth->finish;
$dbh->disconnect();
$dat{contention} =~ m/^service_(\d+)to(\d+)$/;
$dat{denominator} = $1;
$dat{numerator} = $2;
$dat{ulimit} = ( $dat{tmon} / $dat{denominator} ) * $dat{numerator};
$dat{ulimitd} = ( $dat{tday} / $dat{denominator} ) * $dat{numerator};
# connect to the accounting database
$dbh = DBI->connect("DBI:mysql:$dat{db}:$dat{dbhost}",$dat{dbuser},$dat{dbpass}) ;
# find the amount of time the user has used this month
$sql_query = "SELECT `ACCTSESSIONTIME`,`TIME_STAMP` FROM `ACCOUNTING` WHERE `USERNAME`='$dat{username}' AND `TIME_STAMP`>$dat{tlivem};";
$dat{usedm} = 0;
$dat{usedd} = 0;
$sth = $dbh->prepare($sql_query);
$rv = $sth->execute;
while ( $tmp = $sth->fetchrow_hashref ) {
if ( defined ( $tmp->{ACCTSESSIONTIME} ) ) {
$dat{usedm} += $tmp->{ACCTSESSIONTIME};
if ( $tmp->{TIME_STAMP} > $dat{tlived} ) {
$dat{usedd} += $tmp->{ACCTSESSIONTIME};
};
};
};
$sth->finish;
$dbh->disconnect();
# found it's in the $dat{usedm} variable and $dat{usedd} variables
print " $dat{ulimit} ";
$dat{percentm} = ( $dat{usedm} / $dat{ulimit} ) * 100;
$dat{percentd} = ( $dat{usedd} / $dat{ulimitd} ) * 100;
&main::log($main::LOG_DEBUG, "$dat{time} $dat{tlivem} Username: $dat{username} - at $dat{contention} has $dat{ulimit} seconds per month and has used $dat{usedm} so has used $dat{percentm}\% this month. and $dat{percentd}\% today - $dat{usedd} / $dat{ulimitd} - $dat{tlived}\n");
#
# users daily limit = their contention in a 24 hour period
#
# idle timeout = 10 mins
#
# so now we decide what to do about it.
#
#$dat{percentm} = 199;
my %ret;
if ( $dat{percentm} >= 150 ) {
$ret{RETURNCODE} = 'Access-Reject';
$ret{IDLETIMEOUT} = 1;
$ret{KICKTIMEOUT} = 1;
} elsif ( $dat{percentm} < 105 ) {
$ret{RETURNCODE} = 'Access-Accept';
$ret{IDLETIMEOUT} = $dat{idlet};
$ret{KICKTIMEOUT} = $dat{ulimitd};
} else {
$ret{RETURNCODE} = 'Access-Accept';
$ret{IDLETIMEOUT} = $dat{idlet} * ( ( 200 - $dat{percentm} ) / 200 );
$ret{KICKTIMEOUT} = $dat{ulimitd} * ( ( 200 - $dat{percentm} ) / 200 );
}
$ret{IDLETIMEOUT} =~ s/\.\d*$//;
$ret{KICKTIMEOUT} =~ s/\.\d*$//;
&main::log($main::LOG_DEBUG, "RC[$ret{RETURNCODE}] IT[$ret{IDLETIMEOUT}] KT[$ret{KICKTIMEOUT}] PM[$dat{percentm}] UM[$dat{usedm}]\n");
my ($it,$st,$it2,$st2);
$it=$rp->get_attr('Idle-Timeout');
$st=$rp->get_attr('Session-Timeout');
$rp->change_attr('Idle-Timeout', $ret{IDLETIMEOUT} );
$rp->change_attr('Session-Timeout', $ret{KICKTIMEOUT} );
$it2=$rp->get_attr('Idle-Timeout');
$st2=$rp->get_attr('Session-Timeout');
&main::log($main::LOG_DEBUG, "-- << {{ [[ IT[$it] ST[$st] IT2[$it2] ST2[$st2] ]] }} >> --\n");
if ($ret{RETURNCODE} eq 'Access-Reject')
{
my $reason = "Abusive Usage";
$rp->set_code('Access-Reject');
$rp->change_attr('Reply-Message',$reason);
$p->{Client}->replyTo($rp,$p);
}
return $ret{RETURNCODE};
}
}