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};
}

}

Reply via email to