Menu

YfiTechLDAP

Anonymous

LDAP Introduction

  • LDAP is typically used in corporate environments where there is a directory of some sort involved.
  • Novell's e-Directory as well as Microsoft's Active Directory both has a LDAP component to it.
  • OpenLDAP can also be used.
  • LDAP can be used for authentication requests as well as searches.
  • The easiest way to add LDAP functionality to YFi Hotspot Manager is by adding extra Perl code.
  • We will use LDAP only for authentication. The management of accounts remains part of the application serving the LDAP to us.
  • LDAP will be used with the SQL data managed by YFi Hotspot Manager - we will thus have two user stores which can be consulted for authentication requests.

Best practices

  • When your system (YFi Hotspot Manager's FreeRADIUS code) connects with a LDAP sestem it has to bind to it.
  • It can bind anonymous of with a specified user.
  • Good practice is to bind with a specified user and password.
  • This makes it easy to troubleshoot.
  • When one does LDAP queries you can specify which node in the LDAP tree should be used as the base. This makes searches more specific which in turn will make them faster. - we all want fast applications.
  • In corporate environments you do not want passwords to go in cleartext 'on the wire' - LDAP supports ssl encryption

With the above in mind we will create a Perl component which can be used by FreeRADIUS to

  • Verify if the user is defined in the LDAP tree.
  • Their credentials are valid.

The Code

  • Ensure the following packages are installed:

    sudo apt-get install libnet-ldap-perl libnet-ssleay-perl libnet-ssleay-perl libcrypt-ssleay-perl libio-socket-ssl-perl
    
  • Create a file called Yfi_ldap.pm in the /usr/local/etc/raddb/rlm_perl_modules/ directory.

  • Add the following to it - make adjustments to suit your LDAP environment where necessary.

    package Yfi_ldap;
    
    use strict;
    use warnings;
    use Data::Dumper;
    use Net::LDAP;
    
    #===============================================================
    #===== CONFIGURATION DATA ======================================
    #===============================================================
    my $ldap_server = 'ldaps://ldap_server.yfi.co.za:636';
    my $ldap_user   = 'cn=yfi_system,ou=users,o=yfi';
    my $ldap_pw     = 'secret';
    my $ldap_base   = 'o=yfi';
    #===============================================================
    #===== END of Configuration Data ===============================
    #===============================================================
    
    #Initialise this
    sub new {
    
        print "   Yfi_ldap::new called\n";
        my $type = shift;           # The package/type name
        my $self = {};              # Reference to empty hash
        return bless $self, $type;
    }
    
    sub authenticate {
    #---------------------------------------------------------------
    #-- Check if the user is a LDAP user check the password if is---
    #---------------------------------------------------------------
        my($self,$username,$password) = @_;
    
        my $ldap = Net::LDAP->new("$ldap_server", verify => 'none' ) or print "$@";
        my $mesg = $ldap->bind(
                    "$ldap_user",
                    password => "$ldap_pw",
                );
    
        $self->{'connection'}   = $ldap;
        $self->{'ldap_base'}    = $ldap_base;
    
        my $mesg = $self->{'connection'}->search(
                            base    => $self->{'ldap_base'},
                            filter  => "(&(objectclass=posixAccount)(homeDirectory=/home/*)(cn=$username))",
                            attrs   => ['dn'],
                );
    
        if($mesg->count() > 0){
            my $entry   = $mesg->entry(0);
            my $dn      = $entry->dn();
    
            $mesg = $self->{'connection'}->bind(
                            "$dn",
                            password=>"$password",
                    );
            if($mesg->code){
                print "Yfi_ldap::Failed to Authenticate\n"; 
                return 0; #Fail to Authenticate
            }else{
                print "Yfi_ldap::Authenticated OK\n";
                return 1; #Authenticate OK
            }
            $self->{'connection'}->unbind();
        }
    
        $self->{'connection'}->unbind();
        #If we could not find the user we return 0;
        return 0;
    }
    
    1;
    

Implementing the Code

  • Add the following bits to /usr/local/etc/raddb/rlm_perl/rlm_perl.pm.

    use SQLCounter;
    
    use Yfi_ldap;
    
    our $sql_connector;
    our $sql_counter;
    our $ldap;
    
    sub CLONE {
        $sql_connector  = SQLConnector->new();
        $sql_connector->prepare_statements();
    
        #Create a $sql_counter object which will read the counters defined once (its good to avoid unnecesary file reads)
        $sql_counter    = SQLCounter->new($sql_connector);
        $sql_counter->create_sql_counter_hash();
    
        #Create a new LDAP object
        $ldap           = Yfi_ldap->new();
    }
    
  • Then we assume all other users will be user@<realm> and users without a realm will be LDAP users - you may want to change that part to suit your environment.

    sub authenticate_worker {
    
        my ($username, $password) = @_;
    
        #______ LDAP _________________________________________________
        #-- LDAP users will not have the @<suffix> in their username--
        #-------------------------------------------------------------
        if($username !~ m/\@.+/){
            print "==LDAP -> Assume LDAP user - Do LDAP verify ==\n";
    
            if($ldap->authenticate($username, $password) == 1){ #It passes
                return 1;
            }
            $RAD_REPLY{'Reply-Message'} = "LDAP Authentication failure";
            return 0;
        }
        #____________________________________________________________
    
        #---- Comment out for Prime time / Normal time function ---
    
  • Restart FreeRADIUS in debug mode to see if everything works OK when you authenticate using an LDAP user.


Related

Wiki: Home