(RADIATOR) PostAuthHook nightmares.

Hugh Irvine hugh at open.com.au
Mon Nov 25 21:02:44 CST 2002


Hello Steve -

There are some example hooks including a ReplyHook that does pretty 
much what you require in the file "goodies/hooks.txt".

If you have any further questions, please let me know.

regards

Hugh


>
> Hey all, I have the following script (included below) that I use to 
> assign
> an IP address based upon a user "Class"
>
> NAS --- Radius Proxy --- Radius Auth
>
>                 --- Auth File
>
> Say a user logs in with "user at dingbat.com" they will get authed out of 
> a
> file, the PostAuthHook looks at the "Class" attribute that is set in 
> the
> Auth File and preforms a database lookup against that IP class pool,
> allocates the user an IP, then updates the database tagging that IP 
> against
> this user.
>
> This all seemed to work quite happily until I tried to do the same 
> thing by
> proxying across to a remote radius server (customer run so no control 
> over
> the attributes that are returned)
>
> I added the ' AddToReplyIfNotExist Class = "fred.com" ' directive in 
> the
> AuthBy RADIUS clause, which appears to work quite happily, however, the
> hook documentation seems to be rather lacking when it comes to 
> discussing
> radius proxy requests
>
> Under the AuthBy FILE directive, the hook variables as set as such 
> (for an
> Access-Accept)
>
> ${$_[0]} is the current request
> ${$_[1]} is the reply packet -> nas
> ${$_[2]} is the auth result
>
> The issue appears to be that the Auth Result for a file auth, and the 
> Auth
> Result for a radius proxy auth are not the same, in the file auth, we 
> get a
> $main::ACCEPT (${$_[2]} == 0) when the auth succeeds, with the radius
> proxy, wether it is an Accept or a Reject we end up with a 
> $main::IGNORE.
>
> This obviously is an issue because it becomes difficult to allocate 
> IP's
> based upon an access accept, and not allocate when getting an 
> access-reject.
>
> Question is - what should I be testing against if it is not supposed 
> to be
> the Auth Result ? I need this to be able to work against both radius
> authing and file authing, and what other gotcha's am I going to see 
> later
> on ? is there any fuller documentation than the goodies/hooks.txt list 
> ?
>
> Hope this makes some sense :-)
>
> -- Script follows, I've since gone through and added much logging for 
> debug
> purposes --
> -- The script is still in development obviously so please ignore any
> discrepancies --
>
> sub {
>
>          use Mysql;
>
>          my $dbuser      = 'someuser';
>          my $dbpass      =
> 'thisisatopsecretdatabasepasswordthatwillneverappearonamailinglist';
>          my $dbhost      = 'bigarse.database.server';
>
>          my $dbh_ipalloc = undef;
>
>          my $p           = ${$_[0]};     # Current Request
>          my $rp          = ${$_[1]};     # reply packet to NAS
>          my $ar          = ${$_[2]};     # Result of Auth
>          my $rr          = ${$_[3]};     # Reject Reason
>
>          # get the reply code from the proxy radius
>          my $code = $p->code;
>
>          # and a few other attributes
>          my $class    = $rp->get_attr('Class');
>          my $type     = $p->get_attr('Acct-Status-Type');
>          my $actclass = $p->get_attr('Class');
>          my $username = $p->get_attr('User-Name');
>
>          &main::log($main::DEBUG, "ar        = $ar");
>          &main::log($main::DEBUG, "ACCEPT    = $main::ACCEPT");
>          &main::log($main::DEBUG, "REJECT    = $main::REJECT");
>          &main::log($main::DEBUG, "IGNORE    = $main::IGNORE");
>          &main::log($main::DEBUG, "code      = $code");
>          &main::log($main::DEBUG, "Username  = $username");
>          &main::log($main::DEBUG, "Type      = $type");
>          &main::log($main::DEBUG, "Class     = $class");
>          &main::log($main::DEBUG, "AcctClass = $actclass");
>          if (($ar == $main::ACCEPT) || ($ar == $main::IGNORE))
>          {
>
>                  # delete any framed-ip or netmask
>                  $rp->delete_attr('Framed-IP-Address');
>                  $rp->delete_attr('Framed-IP-Netmask');
>
>                  my ($user, $realm) = split /@/, $username, 2;
>
>                  if (!$realm) { $realm = $class; }
>                  if (!$class) { $class = $realm; }
>
>                  $username = $user . '@' . $realm;
>
>                  my $table =  $class;
>                     $table =~ s/\./_/g;
>                     $table = 'tb_ipAlloc_' . $table;
>
>                  &main::log($main::DEBUG, "Table used : $table");
>                  &main::log($main::DEBUG, "UserName   : $username");
>
>                  # open a databse connection
>                  if ($dbh_ipalloc = Mysql->connect($dbhost, undef, 
> $dbuser,
> $dbpass)) {
>                          $dbh_ipalloc->selectdb('data');
>                  } else {
>                          &HandleError ("connect failed");
>                  }
>
>                  # construct the SQL query to get the IP address
>
>                  my $SQL = "SELECT ip FROM $table WHERE name = 
> '$username'";
>                  &main::log($main::DEBUG, "SQL        : $SQL");
>
>                  my $sth = $dbh_ipalloc->query($SQL);
>                  my $totalRows = $sth->numrows;
>
>                  &main::log($main::DEBUG, "Rows       : $totalRows");
>
>                  if (!$totalRows) {
>                          # There were no rows returned, this means that
>                          # there were no instances of this user 
> logging in
> already
>                          # Lets try and get the next available IP 
> address
> from the table
>
>                          $SQL = "SELECT ip FROM $table WHERE name IS 
> NULL
> LIMIT 1";
>                          &main::log($main::DEBUG, "SQL        : $SQL");
>                          my $sth = $dbh_ipalloc->query($SQL);
>
>                          my $returnedIP = $sth->numrows;
>                          &main::log($main::DEBUG, "Rows       :
>  $returnedIP");
>
>                          if (!$returnedIP) {
>                                  # there were no IP's returned, we 
> have run
> out !
>                                  # set the access code to 
> $main::REJECT and
>                                  # set the reject reason to return to 
> the NAS
>                                  my $rejectReason = 'No more ports 
> left to
> allocate';
>                                  &main::log($main::DEBUG, "Reject     :
> $rejectReason");
>                                  # $ar = $main::REJECT;
>                                  # $rp->change_attr('Reply-Message' ,
> $rejectReason);
>                                  ${$_[2]} = $main::REJECT;
>                                  ${$_[1]}->change_attr('Reply-Message' 
> ,
> $rejectReason);
>                          } else {
>                                  # user not already in table, ip 
> addresses
> free to allocate
>                                  # lets allocate one and update the 
> table
> to reflect this
>                                  my $ip = $sth->fetchrow;
>                                  &main::log($main::DEBUG, "Allocated  :
>  $ip"); $rp->add_attr('Framed-IP-Address', $ip);
>
>                                  $SQL = "UPDATE $table SET name =
> '$username' WHERE ip = '$ip'";
>                                  &main::log($main::DEBUG, "SQL        :
>  $SQL"); my $sth = $dbh_ipalloc->query($SQL); }
>                  } else {
>                          # we had a row returned, this means that the 
> user
> exists and an
>                          # IP has been allocated, so we need to grab 
> this
> IP and re-allocate
>                          # it to this user (we do this to account for
> missed stop records
>                          # and IPNet going nuts and using up our 
> entire IP
> pool !
>
>                          # careful here, we should only ever get one 
> result
> back so it
>                          # should be ok.
>                          my $ip = $sth->fetchrow;
>                          &main::log($main::DEBUG, "Allocated  : $ip");
>                          $rp->add_attr('Framed-IP-Address', $ip);
>
>
>                  }
>
>
>          }
>          if ($type eq 'Stop')
>          {
>                  # we have a Stop record, so we will need to update 
> the DB
>                  # and remove any allocated IP's so the port is freed 
> up
>                  #
>                  # As the Class variable is set on the original 
> packet, not
>                  # the reply packet (accounting request) we have a new
>  variable # that stores the "Class" attribute.
>
>                  my $ip     = $p->get_attr('Framed-IP-Address');
>                  my ($user, $realm) = split /@/, $username, 2;
>
>                  if (!$realm) { $realm = $actclass; }
>                  $username = $user . '@' . $realm;
>
>                  my $table =  $actclass;
>                     $table =~ s/\./_/g;
>                     $table = 'tb_ipAlloc_' . $table;
>
>                  &main::log($main::DEBUG, "Table used : $table");
>                  &main::log($main::DEBUG, "Type       : $type");
>                  &main::log($main::DEBUG, "UserName   : $username");
>                  &main::log($main::DEBUG, "IP         : $ip");
>
>                  # open a databse connection
>                  if ($dbh_ipalloc = Mysql->connect($dbhost, undef, 
> $dbuser,
> $dbpass)) {
>                          $dbh_ipalloc->selectdb('data');
>                  } else {
>                          &HandleError ("connect failed");
>                  }
>
>                  # construct the SQL query to get the IP address
>
>                  my $SQL = "UPDATE $table SET name = NULL WHERE ip = 
> '$ip'";
>                  &main::log($main::DEBUG, "SQL        : $SQL");
>
>                  my $sth = $dbh_ipalloc->query($SQL);
>
>          }
> }
>
>
> --
> Steve
> Systems Admin, ICONZ
>
> -------------------------------------------------------
>
> -- 
> Mike McCauley                               mikem at open.com.au
> Open System Consultants Pty. Ltd            Unix, Perl, Motif, C++, WWW
> 24 Bateman St Hampton, VIC 3188 Australia   http://www.open.com.au
> Phone +61 3 9598-0985                       Fax   +61 3 9598-0955
>
> Radiator: the most portable, flexible and configurable RADIUS server
> anywhere. SQL, proxy, DBM, files, LDAP, NIS+, password, NT, Emerald,
> Platypus, Freeside, TACACS+, PAM, external, Active Directory, EAP, TLS,
> TTLS etc on Unix, Windows, MacOS etc.
>
> ===
> Archive at http://www.open.com.au/archives/radiator/
> Announcements on radiator-announce at open.com.au
> To unsubscribe, email 'majordomo at open.com.au' with
> 'unsubscribe radiator' in the body of the message.
>
>

-- 
Radiator: the most portable, flexible and configurable RADIUS server
anywhere. Available on *NIX, *BSD, Windows 95/98/2000, NT, MacOS X.
-
Nets: internetwork inventory and management - graphical, extensible,
flexible with hardware, software, platform and database independence.

===
Archive at http://www.open.com.au/archives/radiator/
Announcements on radiator-announce at open.com.au
To unsubscribe, email 'majordomo at open.com.au' with
'unsubscribe radiator' in the body of the message.


More information about the radiator mailing list