Heikki,

Thanks again so much for the reply. Per your one suggestion, I'm considering 
embedding that other hook code at the end (see the 3 lines right before 
"return" of the below snippet).

I also stuck a "return;" right after:

   $user->get_check->add_attr('Auth-Type', "Reject:No authorisation group found 
in LDAP for '$dn'");

per your comment: "In this branch you could return directly and let the rest of 
the cases (success cases) exit via insertotp call." In other words, bypass the 
insert when they fail.

Based on the comments:

# Replay atack detection is not specified in RFC 6238. Nevertheless
# AuthSQLTOTP implements replay attack detection by recording the TOTP
# timestep of the last valid authentication. It will not authenticate
# a TOTP with the same or earlier timestep as the last recorded
# timestep.

I'm guessing this inserttotp.sh entry is the one that prevents replay attacks? 
And that we should therefore not execute this when the user fails login? If so, 
then my code changes look good, right?

Then the only question that comes to mind is, your original:

        PostSearchHook sub { my @hash = $_[4]->get('pager'); \
               my @username = $_[4]->get('sAMAccountName'); \
               
system('/opt/radiator/radiator/goodies/inserttotp.sh',@username,@hash); \
               return 1 ;}

that was embedded in the totp.cfg... in that old setup (which I'm not using, 
but humor me, since I'm trying to understand how this works) the insert was 
taking place without checking the outcome of the pass/fail, right?

DK

_____

     if ( ($nas_ip eq 'X.X.X.X' || $nas_ip eq 'Y.Y.Y.Y') &&
         (List::Util::first { $admin_dn eq $_ } @ldapgroups))
     {
         main::log($main::LOG_DEBUG, "PostSearchHook: matched LDAP group 
'$admin_dn'", $p);
         $user->get_reply->add_attr('Reply-Message', 'You are admin');
     }
     elsif ($nas_ip eq 'Y.Y.Y.Y' &&
            (List::Util::first { $regular_dn eq $_ } @ldapgroups))
     {
         main::log($main::LOG_DEBUG, "PostSearchHook: matched LDAP group 
'$regular_dn'", $p);
         $user->get_reply->add_attr('Reply-Message', 'You are regular');
     }
     else
     {
         # Could also use add_attr to assing a default
         # authorization level.
         $user->get_check->add_attr('Auth-Type', "Reject:No authorisation group 
found in LDAP for '$dn'");
         return;
     }

     my @hash = $entry->get('hash');
     my @username = $entry->get('sAMAccountName');
     system('/etc/radiator/inserttotp.sh',@username,@hash);

     return;
}

_____

-----Original Message-----
From: Heikki Vatiainen <h...@open.com.au>
Sent: Thursday, February 17, 2022 11:44 AM
To: Dave Kitabjian <d...@corp.netcarrier.com>; radiator@lists.open.com.au
Subject: Re: [RADIATOR] Radiator / LDAP / matching on multi-valued field

On 15.2.2022 22.40, Dave Kitabjian wrote:

> First question: our AuthBy LDAP2 already has a PostSearchHook specified:
>
>          PostSearchHook sub { my @hash = $_[4]->get('hash'); \
>                  my @username = $_[4]->get('sAMAccountName'); \
>                  
> system('/opt/radiator/radiator/goodies/inserttotp.sh',@username,@hash); \
>                  return 1 ;}
>
> It appears that if I define two, the latter one overrides. What's the right 
> way to configure two hooks in the same context? Is the only way to merge them 
> into a single perl script?

You can merge them. For example, put somewhere after 'return unless
$entry' and change $_[4] to $entry (but $_[4] would work too) for
consistent naming.

> And the follow up question is (and forgive me that all of this plumbing isn't 
> entirely clear to me): should the hook code from ldap-memberof-hook.pl come 
> before inserttotp.sh since we don't want to bother to update the totp table 
> if they're not even granted NAS access? Or the other way around, so we can 
> track the "bad logins"??

I think there's the insertopt functionality can be placed after group
authorisation logic. For example, just before the last 'return;' in
ldap-memberof-hook.pl.

In the example below, it shows how to use 'Auth-Type' to trigger a
reject. In this branch you could return directly and let the rest of the
cases (success cases) exit via insertotp call.

For list archive and future reference, goodies/logformat.cfg has an
example where the hooks are collected to a common module. Instead of
having just one file with everything in a single function, module can
contain multiple functions. In this case it may not be necessary, but if
there is, or will be, more customisation, then this kind of
re-arrangement can be helpful.

Thanks,
Heikki


> Thanks in advance!
>
> Dave
>
> -----Original Message-----
> From: radiator <radiator-boun...@lists.open.com.au> On Behalf Of Heikki 
> Vatiainen
> Sent: Monday, February 14, 2022 8:55 AM
> To: radiator@lists.open.com.au
> Subject: Re: [RADIATOR] Radiator / LDAP / matching on multi-valued field
>
> On 12.2.2022 0.39, Dave Kitabjian wrote:
>
>> So, the second part of my problem is that obviously "DC=com CN=Admin
>> Access" won't match the NAS-IP-Address. What I really need is logic like:
>>
>> IF AD.memberOf(user) matches "DC=com CN=Admin Access" AND NAS-IP-Address
>> = A.B.C.D
>> THEN PASS
>> ELSE IF AD.memberOf(user) matches "DC=com CN=Regular Access" AND
>> NAS-IP-Address = W.X.Y.Z
>> THEN PASS
>> ELSE FAIL
>
> One option is to use code to implement the authorisation logic. First,
> configure AuthBy LDAP2 to fetch 'memberOf' attributes. There's no need
> to store them in request or response, so the configuration is simply this:
>
>       AuthAttrDef memberOf
>       PostSearchHook file:"%D/ldap-memberof-hook.pl"
>
> The hook that processes the LDAP groups is below. Implementing flexbile
> authorisation with configuration options might be possible, for example
> how Martin shows in his email, and a hook can then cover the rest of the
> cases.
>
> Here's ldap-memberof-hook.pl. I'll see that a copy gets added to goodies
> too. The logic is meant for tailoring for local needs.
>
>
> use strict;
> use warnings;
> use List::Util;
>
> sub {
>       my $p = $_[2];     # The request
>       my $user = $_[3];  # The user trying to authenticate
>       my $entry = $_[4]; # Returned LDAP entry
>       my $rp = $_[5];    # The reply
>
>       # Process Access-Request messages only
>       return unless $p->code() eq 'Access-Request';
>
>       # Do nothing if the search did not return any results.
>       return unless $entry;
>
>       # groupMembership or memberOf is typically a multivalued LDAP
> attribute for group memberships
>       my $attr = 'memberOf';
>       my $dn = $entry->dn();
>       main::log($main::LOG_DEBUG, "PostSearchHook: processing '$attr'
> values for '$dn'", $p);
>
>       # Convert all DNs to canonical format and then fully lowercase them
>       my $admin_dn   = lc(Net::LDAP::Util::canonical_dn('CN=Demo Admin
> Access,OU=Groups,DC=dev,DC=radiatorsoftware,DC=com'));
>       my $regular_dn = lc(Net::LDAP::Util::canonical_dn('cn=DEMO Regular
> Access,ou=Groups,dc=dev,dc=radiatorsoftware,dc=com'));
>       my @ldapgroups = map { lc(Net::LDAP::Util::canonical_dn($_)) }
> $entry->get_value($attr);
>
>       my $nas_ip = $p->get_attr('NAS-IP-Address');
>
>       # We can now run authorisation logic based on LDAP groups, request
>       # attributes and other available information.
>       #
>       # Sample: The first NAS allows only admins, the second only
>       # regular users. Otherwise trigger failure.
>       if ($nas_ip eq '10.20.30.44' &&
>           (List::Util::first { $admin_dn eq $_ } @ldapgroups))
>       {
>           main::log($main::LOG_DEBUG, "PostSearchHook: matched LDAP group
> '$admin_dn'", $p);
>           $user->get_reply->add_attr('Reply-Message', 'You are admin');
>       }
>       elsif ($nas_ip eq '10.20.50.66' &&
>              (List::Util::first { $regular_dn eq $_ } @ldapgroups))
>       {
>           main::log($main::LOG_DEBUG, "PostSearchHook: matched LDAP group
> '$regular_dn'", $p);
>           $user->get_reply->add_attr('Reply-Message', 'You are regular');
>       }
>       else
>       {
>           # Could also use add_attr to assing a default
>           # authorization level.
>           $user->get_check->add_attr('Auth-Type', "Reject:No
> authorisation group found in LDAP for '$dn'");
>       }
>
>       return;
> }
>
>
>
>
> --
> Heikki Vatiainen
> OSC, makers of Radiator
> Visit radiatorsoftware.com for Radiator AAA server software
> _______________________________________________
> radiator mailing list
> radiator@lists.open.com.au
> https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.open.com.au%2Fmailman%2Flistinfo%2Fradiator&amp;data=04%7C01%7Cdave%40corp.netcarrier.com%7Ca8e333bf1250488e1c2808d9f234b64d%7C0cb89eef04a7465c893f447a3df63d9b%7C0%7C0%7C637807130644329867%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C2000&amp;sdata=BBdLGpbGkFID7Cglh%2BUI4HpCilaIsjmW0STRfPj%2FVvE%3D&amp;reserved=0
> CONFIDENTIALITY NOTICE***The information contained in this message may be 
> privileged, confidential, and protected from disclosure. If the reader of 
> this message is not the intended recipient, or any employee or agent 
> responsible for delivering this message to the intended recipient, you are 
> hereby notified that any dissemination, distribution, or copying of this 
> communication is strictly prohibited. If you have received this communication 
> in error, please notify us immediately by replying to the message and 
> deleting it from your computer. Thank you.

--
Heikki Vatiainen
OSC, makers of Radiator
Visit radiatorsoftware.com for Radiator AAA server software
CONFIDENTIALITY NOTICE***The information contained in this message may be 
privileged, confidential, and protected from disclosure. If the reader of this 
message is not the intended recipient, or any employee or agent responsible for 
delivering this message to the intended recipient, you are hereby notified that 
any dissemination, distribution, or copying of this communication is strictly 
prohibited. If you have received this communication in error, please notify us 
immediately by replying to the message and deleting it from your computer. 
Thank you.
_______________________________________________
radiator mailing list
radiator@lists.open.com.au
https://lists.open.com.au/mailman/listinfo/radiator

Reply via email to