Pages

Showing posts with label ldap. Show all posts
Showing posts with label ldap. Show all posts

Multiple Directory Administrative Users

Most of LDAP directory servers configure a single well known directory administrative account (cn=Directory Manager [,dc=example,dc=com]) which has full access to everything. While there is a need to have one special user to bootstrap the server, we are too often seeing that special account being used by all applications that have specific administrative needs : the provisioning application, the email management application, …

OpenDJ has different mechanisms to define multiple administrative accounts, but today, I’m going to focus on the “Root DNs” i.e. defining multiple Directory Managers.
The default administrative account is “cn=Directory Manager”, and is stored in the configuration under the “cn=Root DNs,cn=config” container entry.
Adding another administrative account is as simple as adding another entry under that container, with one specific objectClass : ds-cfg-root-dn-user.

Create a file newAdmin.ldif

dn: cn=Second Admin,cn=Root DNs,cn=config
cn: Second Admin
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
objectclass: ds-cfg-root-dn-user
sn: Second Admin
ds-cfg-alternate-bind-dn: cn=Admin2,dc=example,dc=com
ds-pwp-password-policy-dn: cn=Root Password Policy,cn=Password Policies,cn=config
userPassword: password42

ldapmodify -a -D cn=Directory Manager -j /var/tmp/dmpassfile -f  newAdmin.ldif
Processing ADD request for cn=Second Admin,cn=Root DNs,cn=config
ADD operation successful for DN cn=Second Admin,cn=Root DNs,cn=config
If you prefer, you can choose not to set the password in the LDIF file, but set it in a secure way afterwards :
$ bin/ldappasswordmodify -p 1389 -D “cn=directory manager” -j /var/tmp/dmpassfile -a “”cn=Admin2,dc=example,dc=com” -N /var/tmp/newpw
The LDAP password modify operation was successful
Where /var/tmp/dmpassfile contains the password for “cn=directory manager” and /var/tmp/newpw the new password for Admin2.
Did you notice the “ds-cfg-alternate-bind-dn” attribute in the definition of the new administrative account ? This enables to authenticate to the directory server with the DN value specified in this attribute, while the entry still has a DN and is located under the “cn=config” suffix.

More Here


Courtesy:http://ludopoitou.wordpress.com/2011/01/10/multiple-directory-administrative-users/

Lightweight Directory Access Protocol PHP

  • Introduction

  • Installing/Configuring

  • Predefined Constants

  • Using the PHP LDAP calls

  • Examples

  • LDAP Functions



  • More Here


    Courtesy:http://php.net/manual/en/book.ldap.php

    LDAP Authentication & Authorization Dissected and Digested

    The steps below are general enough to be used by anyone and will hopefully shed some light into the steps performed in LDAP authentication.  The process below also includes some steps for authorization.

    Authentication

    1.  Get a connection to the LDAP server.
    With the host and port for the LDAP server, create a connection to it.  This can be  a simple direct connection or a pooled connection.  If more than a basic test, it is best to use a pooled connection.  Log and fail if a connection cannot be created.
    2.  Bind as the application user.
    Bind the connection to the application user.  This user should have enough permissions to search the area of LDAP where users are located.  This user may also have permissions to search for things outside of the users area (groups, authorization).  Log and fail if the application user cannot bind.
    3.  Search for the DN (distinguished name) of the user to be authenticated.
    This is where we verify the username is valid.  This does not authenticate the user but simply makes sure the requested username exists in the system.  Log and fail if the user’s DN is not found.


    4.  Bind as user to be authenticated using DN from step 3.
    Now for the moment of truth.  Bind to the connection using the DN found in step 3 and the password supplied by the user.  Log and fail if unable to bind using the user’s DN and password.

    Authorization

    5.  Re-bind as application user.
    To check the authorization of a user, we need to read attributes from the user’s account. To do this, we need to re-bind as the application user.
    6.  Search for user and require attributes.
    A filter is used to search for the user like was done in step 3 but we’ll add an extra check to the query to look for the attributes that show we’re authorized.

    Example Code


    Courtesy:http://thecarlhall.wordpress.com/2011/01/04/ldap-authentication-authorization-dissected-and-digested/

    LDAP Authentication & Authorization Dissected and Digested

    LDAP is one of those things that I’ve integrated with a few times but never put enough energy into to really get the details or understand it much.  There’s always been someone I can bounce questions off of and thankfully those people were available again as I started working out the details of performing LDAP authentication.
    The steps below are general enough to be used by anyone and will hopefully shed some light into the steps performed in LDAP authentication.  The process below also includes some steps for authorization.

    Authentication

    1.  Get a connection to the LDAP server.
    With the host and port for the LDAP server, create a connection to it.  This can be  a simple direct connection or a pooled connection.  If more than a basic test, it is best to use a pooled connection.  Log and fail if a connection cannot be created.

    2.  Bind as the application user.
    Bind the connection to the application user.  This user should have enough permissions to search the area of LDAP where users are located.  This user may also have permissions to search for things outside of the users area (groups, authorization).  Log and fail if the application user cannot bind.
    3.  Search for the DN (distinguished name) of the user to be authenticated.
    This is where we verify the username is valid.  This does not authenticate the user but simply makes sure the requested username exists in the system.  Log and fail if the user’s DN is not found.
    4.  Bind as user to be authenticated using DN from step 3.
    Now for the moment of truth.  Bind to the connection using the DN found in step 3 and the password supplied by the user.  Log and fail if unable to bind using the user’s DN and password.

    Authorization

    5.  Re-bind as application user.
    To check the authorization of a user, we need to read attributes from the user’s account. To do this, we need to re-bind as the application user.
    6.  Search for user and require attributes.
    A filter is used to search for the user like was done in step 3 but we’ll add an extra check to the query to look for the attributes that show we’re authorized.

    Example Code

    The code shown here is using the JLDAP library from Novell.  Interesting includes are noted at the top. The utility class used for escaping the search filter can be found in the Sakai Project’s Nakamura codebase.
    001import com.novell.ldap.LDAPAttribute;
    002import com.novell.ldap.LDAPConnection;
    003import com.novell.ldap.LDAPEntry;
    004import com.novell.ldap.LDAPException;
    005import com.novell.ldap.LDAPSearchResults;
    006// ...
    007String baseDn = "ou=People,o=MyOrg";
    008String userFilter = "uid = {}";
    009String authzFilter = "authzAttr=special:Entitlement:value";
    010// ...
    011public boolean authenticate(Credentials credentials) throws RepositoryException {
    012    boolean auth = false;
    013    if (credentials instanceof SimpleCredentials) {
    014      // get application user credentials
    015      String appUser = connMgr.getConfig().getLdapUser();
    016      String appPass = connMgr.getConfig().getLdapPassword();
    017 
    018      // get user credentials
    019      SimpleCredentials sc = (SimpleCredentials) credentials;
    020 
    021      long timeStart = System.currentTimeMillis();
    022 
    023      String userDn = LdapUtil.escapeLDAPSearchFilter(userFilter.replace("{}",
    024          sc.getUserID()));
    025      String userPass = new String(sc.getPassword());
    026 
    027      LDAPConnection conn = null;
    028      try {
    029        // 1) Get a connection to the server
    030        try {
    031          conn = connMgr.getConnection();
    032          log.debug("Connected to LDAP server");
    033        } catch (LDAPException e) {
    034          throw new IllegalStateException("Unable to connect to LDAP server ["
    035              + connMgr.getConfig().getLdapHost() + "]");
    036        }
    037 
    038        // 2) Bind as app user
    039        try {
    040          conn.bind(LDAPConnection.LDAP_V3, appUser, appPass.getBytes(UTF8));
    041          log.debug("Bound as application user");
    042        } catch (LDAPException e) {
    043          throw new IllegalArgumentException("Can't bind application user [" + appUser
    044              + "]", e);
    045        }
    046 
    047        // 3) Search for username (not authz).
    048        // If search fails, log/report invalid username or password.
    049        LDAPSearchResults results = conn.search(baseDn, LDAPConnection.SCOPE_SUB, userDn,
    050            null, true);
    051        if (results.hasMore()) {
    052          log.debug("Found user via search");
    053        } else {
    054          throw new IllegalArgumentException("Can't find user [" + userDn + "]");
    055        }
    056 
    057        // 4) Bind as user.
    058        // If bind fails, log/report invalid username or password.
    059 
    060        // value is set below. define here for use in authz check.
    061        String userEntryDn = null;
    062        try {
    063          LDAPEntry userEntry = results.next();
    064          LDAPAttribute objectClass = userEntry.getAttribute("objectClass");
    065 
    066          if ("aliasObject".equals(objectClass.getStringValue())) {
    067            LDAPAttribute aliasDN = userEntry.getAttribute("aliasedObjectName");
    068            userEntryDn = aliasDN.getStringValue();
    069          } else {
    070            userEntryDn = userEntry.getDN();
    071          }
    072 
    073          conn.bind(LDAPConnection.LDAP_V3, userEntryDn, userPass.getBytes(UTF8));
    074          log.debug("Bound as user");
    075        } catch (LDAPException e) {
    076          log.warn("Can't bind user [{}]", userDn);
    077          throw e;
    078        }
    079 
    080        if (authzFilter.length() > 0) {
    081          // 5) Return to app user
    082          try {
    083            conn.bind(LDAPConnection.LDAP_V3, appUser, appPass.getBytes(UTF8));
    084            log.debug("Rebound as application user");
    085          } catch (LDAPException e) {
    086            throw new IllegalArgumentException("Can't bind application user [" + appUser
    087                + "]");
    088          }
    089 
    090          // 6) Search user DN with authz filter
    091          // If search fails, log/report that user is not authorized
    092          String userAuthzFilter = "(&(" + userEntryDn + ")(" + authzFilter + "))";
    093          results = conn.search(baseDn, LDAPConnection.SCOPE_SUB, userAuthzFilter, null,
    094              true);
    095          if (results.hasMore()) {
    096            log.debug("Found user + authz filter via search");
    097          } else {
    098            throw new IllegalArgumentException("User not authorized [" + userDn + "]");
    099          }
    100        }
    101 
    102        // FINALLY!
    103        auth = true;
    104        log.info("User [{}] authenticated with LDAP in {}ms", userDn,
    105            System.currentTimeMillis() - timeStart);
    106      } catch (Exception e) {
    107        log.warn(e.getMessage(), e);
    108      } finally {
    109        connMgr.returnConnection(conn);
    110      }
    111    }
    112    return auth;
    113  }

    More Here


    Courtesy:http://thecarlhall.wordpress.com/2011/01/04/ldap-authentication-authorization-dissected-and-digested/

    Samba Insanity – LDAP, groups and valid users

    Have you ever run into one of those “tiny” issues just before going live with a month long project and have it turn into a 3 day nightmare? Well, recently I had the privilege of experiencing a rather frustrating problem.


    Working on quite an interesting project lately dealing with Samba and LDAP. I need to upgrade a Samba PDC, add a secondary Samba member server, migrate +/- 200 domain accounts from a smbpasswd backend to LDAP and of course this all needs to be completely transparent to the users. So I’m about to swap over to the new member server first and decide to do one last check in terms of making sure user access to specific shares is working correctly when I ran into a serious problem.


    For some odd reason I was being denied access to shares where I should definitely have access to. This was all working perfectly a few days ago and I still cannot explain exactly what went wrong but when I find out I’ll update this post. This is what one of my typical Samba share configs looked like:

    [testshare]
    comment = Test Share
    path = /data/testshare
    admin users = @testadmins
    valid users = +testusers
    write list = +testusers
    force group = +testusers
    browseable = yes
    writable = yes


    I made 100% sure that testuser was definitely in the testusers group:


    beer:~# getent group | grep testusers
    testusers:*:1006:testuser


    beer:~# smbldap-groupshow testusers
    dn: cn=testusers,ou=group,dc=example,dc=com
    objectClass: top,posixGroup
    cn: testusers
    gidNumber: 1006
    memberUid: testuser


    Next, check that testuser can access the testshare:


    beer:~# smbclient -U testuser \\\\SERVER\\testshare
    Enter testuser's password:
    Domain=[DOMAIN] OS=[Unix] Server=[Samba 3.4.9-SerNet-Debian]
    tree connect failed: NT_STATUS_ACCESS_DENIED


    What? Ok, set log level = 10 in smb.conf and noticed the following:


    string_to_sid: Sid +testusers does not start with 'S-'.
    push_sec_ctx(0, 0) : sec_ctx_stack_ndx = 1
    push_conn_ctx(0) : conn_ctx_stack_ndx = 0
    setting sec ctx (0, 0) - sec_ctx_stack_ndx = 1
    pop_sec_ctx (0, 0) - sec_ctx_stack_ndx = 0
    user 'testuser' (from session setup) not permitted to access this share (testshare)
    create_connection_server_info failed: NT_STATUS_ACCESS_DENIED
    error packet at smbd/reply.c(776) cmd=117 (SMBtconX) NT_STATUS_ACCESS_DENIED


    Oh yes, before I continue I must mention that user authentication via LDAP was working 100%. The user is authenticated but then as soon as Samba seems to check the valid users option it bombs out with the message string_to_sid: Sid +testusers does not start with ‘S-’.


    I spent a good few hours googling for the error and all I seemed to find was dead ends. People have run into this problem before but not many have updated their posts with solutions or any real reason as to why this error pops up. I managed to find a post which talked about the string_to_sid function in reply.c, which apparently converts a SID char string to binary (see http://lists.samba.org/archive/samba/2008-November/144990.html). Obviously this function is failing and Samba can’t run a proper check against the group and allow the user access to the share.


    Some posts I came across mention the format of the valid users line in smb.conf. I tried every possible combination, no luck at all:


    valid users = +testusers
    valid users = @testusers
    valid users = @'DOMAIN\testusers'
    valid users = @DOMAIN\testusers


    …etc


    No difference at all. I eventually stumbled across a few more posts which passed this error off as a bug, and that users should just upgrade Samba. Initially I tried to avoid that route as I really wanted to know what the problem was here but eventually gave in and upgraded Samba.


    I was running Sernet’s Samba-3.4.9 packages for Debian Lenny (see http://enterprisesamba.org/index.php?id=148) and upgraded to Samba-3.5.4 (see http://us.generation-nt.com/answer/samba-samba-3-5-2-packages-debian-lenny-help-197929381.html).


    In a nutshell, upgrading Samba was the solution for me:


    Add following to your sources.list:


    deb http://www.backports.org/debian lenny-backports main contrib non-free
    deb http://pkg-samba.alioth.debian.org/packages lenny-backports-latest/


    Then


    apt-get update
    apt-get remove
    apt-get install -t lenny-backports-latest samba smbclient


    Now the final test:


    beer:~# smbclient -U testuser \\\\SERVER\\testshare
    Enter testuser's password:
    Domain=[DOMAIN] OS=[Unix] Server=[Samba 3.5.4]
    smb: \>


    Nice. Here’s a log extract showing what went down:


    smbldap_search_ext: base => [dc=example,dc=com], filter => [(&(objectClass=sambaGroupMapping)(|(displayName=testusers)(cn=testusers)))], scope => [2]
    ldapsam_getgroup: Did not find group, filter was (&(objectClass=sambaGroupMapping)(|(displayName=testusers)(cn=testusers)))
    pop_sec_ctx (0, 0) - sec_ctx_stack_ndx = 0
    lookup_name: Unix Group\testusers => Unix Group (domain), testusers (name)
    lookup_name: flags = 0x077
    user_ok_token: share testshare is ok for unix user testuser


    Don’t worry about the error Did not find group error, it’s looking for some attributes that have not yet been added to the group in LDAP – running smbldap-groupmod -a testusers fixed this.


    I ran another test by removing testuser from the testusers group and was denied access as required, here’s another log extract:


    user 'testuser' (from session setup) not permitted to access this share (testshare)
    create_connection_server_info failed: NT_STATUS_ACCESS_DENIED
    error packet at smbd/reply.c(776) cmd=117 (SMBtconX) NT_STATUS_ACCESS_DENIED


    Obviously I need to do quite a bit more research around this problem and as soon as I have some more answers I’ll update this post.


    Anyways, I hope this post helps someone out there who runs into a similar problem. I was seriously pulling my hair out with this one, and in the end I just needed to upgrade haha. For further reading, here are a few posts I found along the way which might help if you run into this problem:


    More Here



    Courtesy:http://writequit.co.za/2010/12/19/samba-ldap-groups-insanity/

    LDAP Authentication with Apache2 & .htaccess Files

    Protecting web accessible directories with .htaccess and htpasswd files is a relatively simple process, it works great but when you’re maintaining 300 different htpasswd files all over the place it can become a slight ballache. If you have a LDAP server configured and in place, a nice alternative is to point all your .htaccess files to your LDAP server to handle the authentication.

    Before you continue reading, this article assumes you already have the following in place:

    * Apache2 server installed and configured
    * OpenLDAP server installed and configured

    First we need LDAP support for Apache2, so enable it & restart apache:

    beer:~# a2enmod authnz_ldap
    Considering dependency ldap for authnz_ldap:
    Enabling module ldap.
    Enabling module authnz_ldap.
    Run '/etc/init.d/apache2 restart' to activate new configuration!
    beer:~# /etc/init.d/apache2 restart
    Restarting web server: apache2 ... waiting .
    beer:~#

    Next configure your Apache2 virtual host file with the following:


    ServerAdmin bartender@example.com
    ServerName beer.example.com
    DocumentRoot /var/www/

    Options FollowSymLinks
    AllowOverride None


    Options -Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order deny,allow
    Deny from all
    Allow from 10.100.0.1

    ErrorLog /var/log/apache2/error.log
    LogLevel warn
    CustomLog /var/log/apache2/access.log combined


    Your vhost configuration does not have to look exactly like the above, but just make sure that you have the AllowOverride All option set as this tells Apache to enable .htaccess files. I’ve also restricted access to 10.100.0.1 and disabled index listings, call me paranoid but I see nothing wrong with adding as many security layers as possible.

    Next, assuming you are trying to protect the /var/www directory, dump a .htaccess file into that directory with the following contents:

    Order deny,allow
    Deny from All
    AuthName "Restricted - Barmen Only"
    AuthType Basic
    AuthBasicProvider ldap
    AuthzLDAPAuthoritative on
    AuthLDAPUrl ldap://127.0.0.1/ou=people,dc=example,dc=com?uid
    AuthLDAPGroupAttribute memberUid
    AuthLDAPGroupAttributeIsDN off
    Require ldap-user dave
    Satisfy any

    The above config allows the user dave to authenticate, all other users are denied access. You can append additional user names to the Require ldap-user line or you could just allow all users in a specific LDAP group like so:

    Order deny,allow
    Deny from All
    AuthName "Restricted - Barmen Only"
    AuthType Basic
    AuthBasicProvider ldap
    AuthzLDAPAuthoritative on
    AuthLDAPUrl ldap://127.0.0.1/ou=people,dc=example,dc=com?uid
    AuthLDAPGroupAttribute memberUid
    AuthLDAPGroupAttributeIsDN off
    Require ldap-group cn=barmen,ou=group,dc=example,dc=com
    Require ldap-attribute gidNumber=1234
    Satisfy any

    Now all users in the barmen LDAP group will be able to authenticate and access this web directory. Remember to update the GID above with the GID of the barmen group.

    You can also combine these 2 methods, for example to allow all users in the barmen group and also user fred (who is not in the barmen group) just use the following:

    Require ldap-group cn=barmen,ou=group,dc=example,dc=com
    Require ldap-attribute gidNumber=1234

    More Here


    Courtesy:http://writequit.co.za/2011/01/05/ldap-apache-htaccess/