(RADIATOR) Re: (RADMIN) Skipping "User-Password" check-item

Mike McCauley mikem at open.com.au
Fri Nov 15 15:42:00 CST 2002


Hello Nicolai,


Yes, thats a good idea. Added for the next release, and also available as a 
patch to AuthRADMIN.pm in the Radiator 3.3.1 patches area.

Thanks for your suggestion.

Cheers.

On Fri, 15 Nov 2002 22:28, Nicolai van der Smagt wrote:
> Hi Mike,
>
> Thanks for the patch. I have another problem with AuthRADMIN. I couldn't
> find a way to disable the feature that a user account get's disabled
> when MaxBadLogins get's exceeded.
>
> I have DSL customers, if they get installed with the wrong password
> they'll try reconnecting at a rate of once every couple of seconds.
> MaxBadLogins isn't really useful here as the max will be reached within
> seconds. This happens so often with our not so bright installers that it
> causes a lot of extra work for the customer care people, who have to
> reset the bad login count ( and can't do that from the GUI, so in
> practise it means I have to go into the database and manually reset bad
> login count).
>
> I patched it like so:
> [root at radius1 Radius]# diff -u AuthRADMIN.pm.orig AuthRADMIN.pm
> --- AuthRADMIN.pm.orig  Fri Nov 15 12:05:12 2002
> +++ AuthRADMIN.pm       Fri Nov 15 12:16:18 2002
> @@ -119,7 +119,7 @@
>         $user->get_check->add_attr('ValidTo', $validto)
>             if defined $validto;
>
> -       if ($badlogins >= $self->{MaxBadLogins})
> +       if ($badlogins >= $self->{MaxBadLogins} && $self->{MaxBadLogins}
> != 0)
>         {
>             $self->log($main::LOG_INFO,
>                        "User $name Bad Login count exceeded");
>
> And then by setting MaxBadLogins 0 in the AuthBy Radmin clause in the
> config.
>
> I think it would be a nice feature to add.
>
> Regards,
>
> Nicolai
>
> On Thu, 2002-11-14 at 23:48, Mike McCauley wrote:
> > Hello Nicolai,
> >
> > I think I concur with Davids suggestion to use AuthBy SQL. More below
> > about your second question.
> >
> > On Fri, 15 Nov 2002 01:33, david.kramar at aliatel.cz wrote:
> > > Hi Nicolai
> > >
> > > Try use this schema. Use radmin database schema, but use AuthBy SQL
> > > ....
> > > <Realm DEFAULT>
> > >         <AuthBy SQL>
> > >                 DBSource        dbi:mysql:radmin:localhost
> > >                 DBUsername      raduser
> > >                 DBAuth          radpw
> > >
> > >             AuthSelect select USERNAME,FRAMED_PROTOCOL from RADUSERS
> > > where USERNAME='%n' AuthColumnDef 0,User-Name, check
> > > 		AuthColumnDef 1,Framed-Protocol, check
> > >
> > >             NoDefault
> > >             LogQuery
> > >             AccountingStopsOnly
> > >
> > >                 AccountingTable RADUSAGE
> > >                 AcctColumnDef   USERNAME,User-Name
> > >                 AcctColumnDef   TIME_STAMP,Timestamp,integer
> > >                 AcctColumnDef   ACCTSTATUSTYPE,Acct-Status-Type,integer
> > > 		#.....continue acct..
> > >
> > >                 AddToReply Service-Type = Framed-User,\
> > >                         Framed-Protocol = PPP,\
> > >         			Tunnel-Type = L2TP,\
> > >         			Tunnel-Medium-Type = IP,\
> > >         			Tunnel-Server-Endpoint = "xxx.xxx.xxx.xxx",\
> > >         			Tunnel-Client-Auth-ID = "xxxx01",\
> > >         			Tunnel-Password = "xxxxxxxx"
> > >         </AuthBy>
> > > </Realm>
> > >
> > > David
> > >
> > > -----Původní zpráva-----
> > > Od: Nicolai van der Smagt [mailto:nicolai.vandersmagt at BBNED.NL]
> > > Odesláno: 14. listopadu 2002 13:16
> > > Komu: radmin at open.com.au
> > > Předmět: (RADMIN) Skipping "User-Password" check-item
> > >
> > >
> > > Hi,
> > >
> > > I'm converting my current configuration from flat text users database
> > > to Radmin. I've encountered this:
> > >
> > > Old realm:
> > > #<Handler Realm=bbeyond.test.net>
> > > #       RewriteUsername
> > > s/^([^@]+)\@bbeyond\.test\.net/bbeyond\.test\.net/
> > > #       <AuthBy FILE>
> > > #       </AuthBy>
> > > #</Handler>
> > >
> > > This is used to return parameters for L2TP tunnels to a NAS. Username
> > > gets rewritten to a generic user, no password check is attempted, and
> > > tunnel attributes like Tunnel-Type etc. get returned to the NAS.
> > >
> > > This is the generic user from the users file:
> > >
> > > bbeyond.flatisdn.net  Service-Type = Framed-User
> > >         Tunnel-Type = L2TP,
> > >         Tunnel-Medium-Type = IP,
> > >         Tunnel-Server-Endpoint = "xxx.xxx.xxx.xxx",
> > >         Tunnel-Client-Auth-ID = "xxxx01",
> > >         Tunnel-Password = "xxxxxxxx"
> > >
> > > The problem is that I've not been able to make Radmin skip the
> > > User-Password check-item, it tries this anyway, and fails, as the
> > > credentials passed to radiator from the client includes the password
> > > that is used in another handler to authenticate the user. Is there a
> > > way to make Radmin skip checking the "User-Password" check-item? We can
> > > work around this ofcourse, but skipping User-Password is the method we
> > > prefer.
> > >
> > >
> > > Also, I sent this in so time ago, but did not get a reply yet:
> > >
> > > editRadconfig.pl from the latest Radmin 1.6 patches (2002/06/12)
> > > doesn't do what I want it to. You can change attributes belonging to
> > > serviceprofiles and to users with this script.
> > >
> > > I want my helpdesk users to be able to update attributes for single
> > > users, but not for serviceprofiles, as that could affect thousands of
> > > users.
> > >
> > > The scripts is called from both editService.pl and editUser.pl, so I
> > > would have expected checks for both USER_E and SERVICE_E, depending on
> > > which database table you're trying to configure, but it just always
> > > checks for USER_E.
> > >
> > > I think that's not the way it's supposed to be, at least not the way we
> > > want it to.
> >
> > Quite right.
> >
> > We have now fixed this. I have attached a new editRadconfig.pl that now
> > check either USER or SERVICE, depending on which table is being edited.
> > Please let me know if it works for you. Its also available in the patches
> > area.
> > We apologise for the delay in dealing with this.
> >
> > Cheers.
> >
> > > Thanks in advance,
> >
> > --
> > 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.
> > ----
> >
> >
> > #!/usr/bin/perl
> > # -*- mode: Perl -*-
> > # editRadconfig.pl
> > #
> > # CGI script to create and edit Radius attributes for users
> > # and services in Radmin
> > #
> > # Author: Mike McCauley (mikem at open.com.au)
> > # Copyright (C) 1997 Open System Consultants
> > # $Id: editRadconfig.pl,v 1.5 2002/11/14 22:46:29 mikem Exp mikem $
> > BEGIN
> > {
> >     # Not all web servers start us off in the  directory where
> >     # this executable is. Lets be consistent.
> >     chdir('Radmin/private') if $^O eq 'MSWin32';
> > }
> >
> > use CGI;
> > use Radmin::DBSQL;
> > use Radmin::Util;
> > use Radmin::CGIUtil;
> > use Radmin::Site;
> >
> > # Load the schema description into %Radmin::schema
> > &Radmin::Util::init();
> >
> > my $tname = 'RADCONFIG'; # The name of the table to look in;
> > $tname = $Radmin::CGIUtil::q->param('_tname')
> >     if defined $Radmin::CGIUtil::q->param('_tname');
> > my $editService;
> > my $name;  # The identifier for the configs we are looking for
> > my $title; # Page title;
> > my $id = $Radmin::CGIUtil::q->param('_id');
> > $db->connect();
> >
> > my $qid = $db->quote($id);
> > my $eid = CGI::escape($id); # escaped HTML
> > my $hid = CGI::escapeHTML($id); # escaped HTML
> >
> > # Figure out if we are looking at per-user or per-service config
> > if ($tname eq 'RADCONFIG')
> > {
> >     # Per-user config
> >     $title = "RADIUS attributes for User $hid";
> > }
> > else
> > {
> >     # Per-service-type config
> >     $title = "RADIUS attributes for Service $hid";
> >     $tname = 'RADSTCONFIG'; # Normalise
> >     $editService++;
> > }
> >
> > if ($Radmin::CGIUtil::q->param('_action') eq 'Add New Check Item')
> > {
> >     &Radmin::CGIUtil::checkPermission($editService ? 'SERVICE_E' :
> > 'USER_E');
> >
> >     # Tag _next_check_item is the item_type of the next check item
> >     # to add
> >     # Tag _new_item_type is id:vendorid of the new type to add
> >     my $item_type = $Radmin::CGIUtil::q->param('_next_check_item');
> >     my ($attr_id, $vendor_id) =  split(/:/,
> > $Radmin::CGIUtil::q->param('_new_item_type')); $db->do("insert into
> > $tname (NAME, ATTR_ID, VENDOR_ID, ITEM_TYPE) values ($qid, $attr_id,
> > $vendor_id, $item_type)");
> > }
> > elsif ($Radmin::CGIUtil::q->param('_action') eq 'Add New Reply Item')
> > {
> >     &Radmin::CGIUtil::checkPermission($editService ? 'SERVICE_E' :
> > 'USER_E');
> >
> >     # Tag _next_reply_item is the item_type of the next reply item
> >     # to add
> >     # Tag _new_item_type is id:vendorid of the new type to add
> >     my $item_type = $Radmin::CGIUtil::q->param('_next_reply_item');
> >     my ($attr_id, $vendor_id) =  split(/:/,
> > $Radmin::CGIUtil::q->param('_new_item_type')); $db->do("insert into
> > $tname (NAME, ATTR_ID, VENDOR_ID, ITEM_TYPE) values ($qid, $attr_id,
> > $vendor_id, $item_type)");
> > }
> > elsif ($Radmin::CGIUtil::q->param('_action') eq 'Update')
> > {
> >     &Radmin::CGIUtil::checkPermission($editService ? 'SERVICE_E' :
> > 'USER_E');
> >
> >     # In order to update this users attribtues, we delete all the
> > existing # ones and then recreate them from the data in the form.
> >     $db->do("delete from $tname where NAME=$qid");
> >     # First do the check items
> >     my $count = $Radmin::CGIUtil::q->param('_check_items');
> >     my ($i, $value, $attr_id, $vendor_id, $item_type);
> >     for ($i = 0; $i < $count; $i++)
> >     {
> > 	($attr_id, $vendor_id) = split(/:/,
> > $Radmin::CGIUtil::q->param("_check_${i}_type")); $value =
> > $Radmin::CGIUtil::q->param("_check_${i}_ivalue");
> > 	if (defined $value)
> > 	{
> > 	    # Its an integer type value
> > 	    $db->do("insert into $tname (NAME, ATTR_ID, VENDOR_ID, IVALUE,
> > ITEM_TYPE) values ($qid, $attr_id, $vendor_id, $value, $i)"); }
> > 	else
> > 	{
> > 	    # its a stringy thing
> > 	    $value = $Radmin::CGIUtil::q->param("_check_${i}_svalue");
> > 	    $value = $db->quote($value);
> > 	    $db->do("insert into $tname (NAME, ATTR_ID, VENDOR_ID, SVALUE,
> > ITEM_TYPE) values ($qid, $attr_id, $vendor_id, $value, $i)"); }
> >     }
> >
> >     # then do the reply items
> >     $count = $Radmin::CGIUtil::q->param('_reply_items');
> >     for ($i = 0; $i < $count; $i++)
> >     {
> > 	($attr_id, $vendor_id) = split(/:/,
> > $Radmin::CGIUtil::q->param("_reply_${i}_type")); $value =
> > $Radmin::CGIUtil::q->param("_reply_${i}_ivalue");
> > 	$item_type = $i + 10000;
> > 	if (defined $value)
> > 	{
> > 	    # Its an integer type value
> > 	    $db->do("insert into $tname (NAME, ATTR_ID, VENDOR_ID, IVALUE,
> > ITEM_TYPE) values ($qid, $attr_id, $vendor_id, $value, $item_type)"); }
> > 	else
> > 	{
> > 	    # its a stringy thing
> > 	    $value = $Radmin::CGIUtil::q->param("_reply_${i}_svalue");
> > 	    $value = $db->quote($value);
> > 	    $db->do("insert into $tname (NAME, ATTR_ID, VENDOR_ID, SVALUE,
> > ITEM_TYPE) values ($qid, $attr_id, $vendor_id, $value, $item_type)"); }
> >     }
> >
> > }
> > elsif ($Radmin::CGIUtil::q->param('_action') eq 'Delete')
> > {
> >     &Radmin::CGIUtil::checkPermission($editService ? 'SERVICE_E' :
> > 'USER_E');
> >
> >     # tag _item is the item_type of the item to delete
> >     my $item_type = $Radmin::CGIUtil::q->param('_item_type');
> >     $db->do("delete from $tname where NAME=$qid and
> > ITEM_TYPE=$item_type"); }
> >
> > &Radmin::CGIUtil::checkPermission($editService ? 'SERVICE_V' : 'USER_V');
> >
> > # (re)display the current attributes
> > my $q = "select T.IVALUE, T.SVALUE, T.ITEM_TYPE, T.ATTR_ID, T.VENDOR_ID,
> > A.NAME, A.TYPE from $tname T, RADATTRS A where T.NAME=$qid and
> > A.ATTR_ID=T.ATTR_ID and A.VENDOR_ID=T.VENDOR_ID order by T.ITEM_TYPE"; my
> > $sth = $db->prepareAndExecute($q);
> > return undef unless $sth;
> >
> > # Have to collect all the attributes into an array, becuase we might
> > # need to do another query for some rows, and some databses (Sybase)
> > # dont permit nested queries
> > my (@attrs, @attrlist);
> > while (@attrs = $sth->fetchrow())
> > {
> >     push(@attrlist, [@attrs]);
> > }
> >
> > # We build 2 tables, one for check items and one for reply items
> > $ctable = "<tr><th colspan=2>Current Check Items</td></tr><tr
> > bgcolor=#0000C0><th><font color=white>Attribute</font></th><th><font
> > color=white>Value</font></th><th></th></tr>\n"; $rtable = "<tr><th
> > colspan=2>Current Reply Items</td></tr><tr bgcolor=#0000C0><th><font
> > color=white>Attribute</font></th><th><font
> > color=white>Value</font></th><th></th></tr>\n";
> >
> > # row numbers for the next check and reply items
> > my ($check_items, $reply_items, $next_check_item, $next_reply_item)
> >     = (0, 0, 0, 10000);
> >
> > # Now get all the matching entries and format them, one per row
> > my ($ivalue, $svalue, $item_type, $attr_id, $vendor_id, $aname, $atype);
> > foreach (@attrlist)
> > {
> >     ($ivalue, $svalue, $item_type, $attr_id, $vendor_id, $aname, $atype)
> > 	= @$_;
> >
> >     # Each row in the form has a unique number (item_type) that specifies
> >     # the order. Item_type >= 10000 means its a reply item
> >     if ($item_type < 10000)
> >     {
> > 	# Add it to the check items table
> > 	&addRow(\$ctable, "_check_$check_items", $ivalue, $svalue, $item_type,
> > $attr_id, $vendor_id, $aname, $atype); $check_items++;
> > 	$next_check_item = $item_type + 1;
> >     }
> >     else
> >     {
> > 	# Add it to the reply items table
> > 	&addRow(\$rtable, "_reply_$reply_items", $ivalue, $svalue, $item_type,
> > $attr_id, $vendor_id, $aname, $atype); $reply_items++;
> > 	$next_reply_item = $item_type + 1;
> >     }
> > }
> > # Now add an option menu, which allows them to add a new attribute
> > # First an option munu of all attribute names
> > $q = "select ATTR_ID, VENDOR_ID, NAME from RADATTRS order by VENDOR_ID,
> > ATTR_ID"; $sth = $db->prepareAndExecute($q);
> > my (@anames, %labels, $key);
> > while (($attr_id, $vendor_id, $aname) = $sth->fetchrow())
> > {
> >     $key = "$attr_id:$vendor_id";
> >     if (!exists $labels{$key})
> >     {
> > 	$labels{$key} = $aname;
> > 	push(@anames, $key);
> >     }
> > }
> > $menu = CGI::popup_menu
> >     (-name => '_new_item_type',
> >      -values => \@anames,
> >      -labels => \%labels);
> > my $newmenu = "<tr bgcolor=#e6e6fa><td>$menu</td><td><input type=submit
> > name=_action value=\"Add New Check Item\"><br><input type=submit
> > name=_action value=\"Add New Reply Item\"></td></tr>\n";
> >
> > # Now show the current setup
> > my $toolBar = &Radmin::CGIUtil::toolBar();
> > my $header = &Radmin::CGIUtil::header();
> > my $footer = &Radmin::CGIUtil::footer();
> >
> >     # Print the final edit page to stdout
> > print &CGI::PrintHeader;
> > print <<_END_OF_CONTENT_;
> > <html>
> > <head>
> > <title>$title</title>
> > </head>
> > $header
> > $toolBar
> > <h1>$title</h1>
> > This page allows you to set specific $title. If any Check Item does not
> > match, the user will not be able to log in. If they are permitted to log
> > in, all the Reply Items will be used to configure their dialup session.
> > See your NAS vendor documentation for more details.
> > <hr>
> > $message
> > <form method=post>
> > <input type=hidden name=database value=\"$Radmin::CGIUtil::db\">
> > <input type=hidden name=_tname value=$tname>
> > <input type=hidden name=_id value=\"$hid\">
> > <input type=hidden name=_check_items value=$check_items>
> > <input type=hidden name=_reply_items value=$reply_items>
> > <input type=hidden name=_next_check_item value=$next_check_item>
> > <input type=hidden name=_next_reply_item value=$next_reply_item>
> > <table cellspacing=0 cellpadding=0>
> > $newmenu
> > <tr><td>&nbsp</td></tr>
> > $ctable
> > <tr><td>&nbsp</td></tr>
> > $rtable
> > </table>
> > <input type=submit name=_action value=Update>
> > </form>
> > $footer
> > </body>
> > </html>
> >
> > _END_OF_CONTENT_
> >
> >
> > #####################################################################
> > # Add an attribute row to a table
> > # Each check and reply item in the table has a unique row name
> > # There is an item type in the form id:vendorid for each row
> > sub addRow
> > {
> >     my ($table, $rowname, $ivalue, $svalue, $item_type, $attr_id,
> > $vendor_id, $aname, $atype) = @_;
> >
> >     my $deleteButton = "<a
> > href=\"editRadconfig.pl?database=$Radmin::CGIUtil::db&_action=Delete&_tna
> >me=$tname&_item_type=$item_type&_id=$eid\">Delete</a>"; my $e;
> >     $$table .= "<input type=hidden name=${rowname}_type
> > value=\"$attr_id:$vendor_id\">\n"; if ($atype == 2) # See the
> > typeStringToInt table in convertDict.pl {
> > 	#Its an integer, maybe make a menu of allowable selections
> > 	my $sth = $db->prepareAndExecute("select NAME, IVALUE from RADVALUES
> > where ATTR_ID=$attr_id and VENDOR_ID=$vendor_id"); return unless $sth;
> > 	my ($n, $v, @values, %labels);
> > 	while (($n, $v) = $sth->fetchrow())
> > 	{
> > 	    push(@values, $v);
> > 	    $labels{$v} = $n;
> > 	}
> > 	if (@values)
> > 	{
> > 	    # There are symbolic dict names for this integer
> > 	    # so make a menu
> > 	    $e = CGI::popup_menu(-name => "${rowname}_ivalue",
> > 				 -values => \@values,
> > 				 -labels => \%labels,
> > 				 -default => $ivalue);
> > 	}
> > 	else
> > 	{
> > 	    # No symblic name, make an editable test field
> > 	    $e = "<input type=text name=${rowname}_ivalue size=8 maxlength=150
> > value=\"$ivalue\">"; }
> > 	$$table .= "<tr><td
> > align=right>$aname</td><td>$e</td><td>$deleteButton</td></tr>\n"; }
> >     else
> >     {
> > 	# Its a stringy sort of thing, make an editable text field
> > 	$e = "<input type=text name=${rowname}_svalue size=30 maxlength=150
> > value=\"$svalue\">"; $$table .= "<tr><td
> > align=right>$aname</td><td>$e</td><td>$deleteButton</td></tr>\n"; }
> > }

-- 
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.


More information about the radiator mailing list