(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