---------- Forwarded Message ----------
Subject: BOUNCE [EMAIL PROTECTED]: Non-member submission from [Steve Phillips <[EMAIL PROTECTED]>] Date: Mon, 25 Nov 2002 14:26:01 -0600 From: [EMAIL PROTECTED] To: [EMAIL PROTECTED] >From [EMAIL PROTECTED] Mon Nov 25 14:26:01 2002 Received: from mail.nz.asiaonline.net (etrn.iconz.co.nz [210.48.22.36]) by server1.open.com.au (8.11.0/8.11.0) with ESMTP id gAPKPxC21266 for <[EMAIL PROTECTED]>; Mon, 25 Nov 2002 14:26:00 -0600 Received: from doodlebug.iconz.net (liv.nz.asiaonline.net [202.14.100.208]) by mail.nz.asiaonline.net (8.9.3/8.9.3) with ESMTP id OAA076061038273417 for <[EMAIL PROTECTED]>; Tue, 26 Nov 2002 14:16:57 +1300 (NZDT) Message-Id: <[EMAIL PROTECTED]> X-Sender: [EMAIL PROTECTED] X-Mailer: QUALCOMM Windows Eudora Version 5.1.1 Date: Tue, 26 Nov 2002 14:20:13 +1300 To: [EMAIL PROTECTED] From: Steve Phillips <[EMAIL PROTECTED]> Subject: PostAuthHook nightmares. Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; format=flowed 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 "[EMAIL PROTECTED]" 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] To unsubscribe, email '[EMAIL PROTECTED]' with 'unsubscribe radiator' in the body of the message.