[RADIATOR] Radiator / LDAP / matching on multi-valued field

Heikki Vatiainen hvn at open.com.au
Mon Feb 14 13:55:22 UTC 2022


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


More information about the radiator mailing list