Is it possible displaying ldap folder structure with Perl? - perl

I will retrieve user informations from a LDAP server. Customer sent me following 3 data:
LDAP Server IP
Username to authenticate
Password to authenticate
This is the 1st time I am working with LDAP so I studied on it. I see that I must use some parameters like cn, dc, ou. Should not customer give this info either? Or customer's info is enough and can I find these parameters by a code displaying folder structure?

The structure you want to see is called the directory tree and is made of LDAP "entries" (not folders).
You should be able to collect entries from your directory provided that the credentials you've been given are sufficient. For that you need a client library, you can use Perl LDAP.
Using that library you would do something like :
use Net::LDAP;
# Init connection and bind to the directory.
$ldap = Net::LDAP->new('ldaphost.example.com') or die "$#";
$mesg = $ldap->bind ($binddn, password => $password);
# Perform a search on the whole tree below (and including) the base object.
$mesg = $ldap->search(base => $basedn);
# Handle error
$mesg->code && die $mesg->error;
# Display results
foreach $entry ($mesg->entries) { $entry->dump; }
$mesg = $ldap->unbind;
The code above just print entries to stdout ($entry->dump).
$binddn is the dn to authenticate with. If you've been given a simple username that is not a dn, like 'username' instead of something like uid=username,dc=example,dc=com, it would probably mean that you are dealing with Active Directory. In this case you can try to bind with a binddn that corresponds to the following pattern : 'username#example.com'.
basedn is the dn of the base object entry, the search is performed on the whole tree below (and including) the base object. You will have to specify a valid base dn.
You can try to guess which base dn to use. Domain components (dc) usually match the FQDN but it is not guaranteed it results in a valid base dn (e.g. 'ldaphost.example.com' would give 'dc=example,dc=com'). However you can query the server for rootDSE information and retrieve the namingContexts (or defaultNamingContext if any) and use one of them as the base dn :
$ldap->search(base => '', attrs => 'namingContexts');
That said, if you really want to display the directory tree, you have better to go with an LDAP explorer like Apache Directory Studio.
Note that LDAP is not limited to storing information in strict "tree" structures, it just have to respects a Directory Information Tree (DIT) nomenclature.

Related

LDAP binding in Perl when OU is unknown

Is there a way to successfully bind while leaving out one of the files in the bind search base string? I don't always know what $site is for a user and if I leave it out the binding fails. Can I have something like OU=*,
$ldapSearchBase = "OU=$site,OU=xxxx,OU=xxxx,DC=$globalLocation,DC=companyName,DC=com";
If I leave the site out I get. it works if I put in my correct site
The wrong password was supplied or the SASL credentials could not be processed
LDAP binds require you to have a single unique distinguished name plus the appropriate credentials (user/pass, SSL, etc.). Your bind will always fail if your DN is not unique.
You might want to try splitting your base DN and varying whatever $site is:
my $ldapSearchBase = "OU=user,OU=accounts,DC=$globalLocation,DC=companyName,DC=com";
my $ldapSite = "OU=$site";
my $bindString = $ldapSearch . "," . $ldapSearchBase;
Use the first container as search base:
$ldapSearchBase = "DC=$globalLocation,DC=companyName,DC=com";

Perl Net::LDAP - Fetch DN without Search?

I have the DN of the LDAP entry. I know I could search for it: Doing something like this:
my $search = $ldap->search(
base => $dn,
scope => "base",
filter => "(objectclass=*)",
);
But, I don't need to do a search. I have the DN. I simply want to pull up the DN entry and do my operations directly on that. Something like this:
my $dn_entry = $ldap->get( $dn );
Is there a method to get the DN entry from the DN string itself, or do you have to search for the entry even if you know the DN itself?
Using LDAP, clients must always search or use an extended operation to get data. If you're interested in all the attributes associated with an entry, and the DN is known, use the following parameters in a search request:
baseObject: the DN that is known
search scope: base
filter: either (&) or (objectClass=*)
the list of attributes to be returned. Some APIs use * for all user attributes and + for all operational attributes.
What it sounds like you are saying is that you have stored the "Distinguished Name" (a string) rather than the DN entry (a Net::LDAP::Entry object). If this is the case, I believe you have to create a new Net::LDAP::Entry object from the DN. The documentation indicates that you can apply operations directly to such an object without synchronizing with the server, but this won't supply all the data for the given DN. If you need the server's data, you need to get it via $ldap->search(...).
Have you considered using the Net::LDAP::LDIF mechanism for storing DN data locally?

How to do a search-by-DN using Net::LDAP

I want to check if a given DN exists in the LDAP directory, using Perl and Net::LDAP. So, I figured I'd do something like this:
my $dn = 'uid=foo,ou=bar,ou=baz';
$ldap->search(base => $dn, scope => 'base', attrs => ['dn']);
However, that results in a Bad filter error. I can get it to work by adding filter => '(objectClass=*)', but that seems a little klugey.
Is this how I'm supposed to do this, or have I missed something? I'm new to Net::LDAP.
An LDAP client must supply a valid search filter to a search request. Try using (&) for the filter. Note that some broken directory servers do not accept the legal filter (&). If your server is broken in this way, use the present filter (objectClass=*) instead.

LDAP group membership filter used in RT3

I am trying to setup LDAP authentication to an Active Directory server for an RT3 site.
I think that there is an error in the LDAP authentication module, but I really do not understand what the filter is trying to do. See RT/Authen/ExternalAuth/LDAP.pm line 126:
$ldap_msg = $ldap->search( base => $group,
filter => $filter,
attrs => \#attrs,
scope => 'base');
There is a config file that specifies the group, group_attr and group_attr_value.
Group is passed as $group, and the filter is created from a group_attr=group string. In my case group_attr = present and the memberOf line comes back with CN=ITAdmins,CN=Builtin,DC=SPGLOBAL,DC=local and the filter becomes Filter: (present=CN=ITAdmins,CN=Builtin,DC=SPGLOBAL,DC=local) and Attrs: dn.
This is invalid for a filter, but can any one who knows a bit more about this see what is meant to be happening?
Thanks for posting the link to the code, that makes it much simpler to understand.
So the model is, authentitcate with username and password, then $group, if defined means check that they are a member of a group to let them in.
$group should be a full LDAP DN, so cn=AccessGroup,ou=Groups,dc=myDomain,dc=com or the like.
$group_attr_val should be member, memberOf, or maybe Member, depending on whatever the member attribute is in your target LDAP directory.
So I think your issue is that group-attr=present is probably wrong and should be as simple as member instead.

Checking User Groups in Perl Net::LDAP

I have a Perl Subversion pre-commit hook that allows me to verify whether or not a user has permissions to change or add to a particular point in a Subversion repository. It uses a Control file that looks like this:
[GROUP SERVER]
users = bob, ted, carol, alice
[GROUP CLIENT]
users = tom, dick, harry
[FILE Client Developers don't touch the Server]
file = proj/server
users = #CLIENT
permission = read-only
[FILE Server people don't touch the Client]
file = proj/client
users = #SERVER
permission = read-only
[FILE Let Tom Do everything]
file = .*
users = tom
permission = read-write
As you can see, I can define groups and use groups when setting permissions. I thought it would be a hoot if I could use the LDAP groups to do the same. That way, our Windows administrators can figure out who's in what group which gives me more time to keep my Facebook status up to date.
I have LDAP configured as thus in Subversion:
<Location /mfx>
DAV svn
SVNParentPath /subversion/svn_repos
AuthType basic
AuthName "Source Repository"
AuthBasicProvider ldap
AuthzLDAPAuthoritative off
AuthLDAPURL "ldap://ldapserver:3268/dc=mycompany,dc=com?sAMAccountName" NONE
AuthLDAPBindDN "CN=SubVersion,OU=Users,OU=Accounts,DC=mycompany,DC=com"
AuthLDAPBindPassword "Swordfish"
Require valid-user
</Location>
I've got the connection to our LDAP server working fine, but now, I need to find out what groups that user is in. I have the user's Subversion name in $svnUser, and now I need to find that user in our LDAP database, and verify the various groups they're in (which is the memberOf value in their LDAP record). However, I have no idea how to go about this.
So far, my code looks like this:
#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);
use constant {
LDAP_URL => "ldapserver",
LDAP_PORT => 3268,
LDAP_SCHEME => "ldap",
BIND_DN => "CN=SubVersion,OU=Users,OU=Accounts,DC=mycompany,DC=com",
BIND_PWORD => "Swordfish",
USER_DN => "sAMAccountName",
};
use Net::LDAP;
#
# Create LDAP Connection
#
my $ldap = Net::LDAP->new(LDAP_URL, port=> LDAP_PORT, scheme=> LDAP_SCHEME);
my $message;
$message = $ldap->bind(BIND_DN, password => BIND_PWORD);
if ($message->code != 0) {
die qq(Error in LDAP Binding: ) . $message->error_desc;
}
Now, I need to do $ldap->search, but on what? I'm just befuddled by the syntax.
All right, it took me a while, but I figured it out...
It would have been helpful if there was some sample code, but after reading a few LDAP documents, I found out I could do something like this:
(sAMAccountName=$user)
So I tried this:
my $results = $ldap->search(filter => USER_DN . "=$svnUser",
attrs => "memberOf");
I thought this would return only the attributes of memberOf, but didn't. In fact, it returned an array of a single member although I knew this particular user was a member of three groups.
It took me a while to realize that it was returning a Net::LDAP::Search object which meant I had to look up that module to find the methods. From there, I found that I could use the pop_entry method to retrieve a Net::LDAP::Entry object. Okay, another CPAN page to find.
From there, I can do a get_value method on the sMAAccountName, and get an array of DNs that represent the group that person belongs to. I can now parse those names for the groups that Subversion will use.
This means I can now use Windows Groups in my pre-commit script to set write permissions in my repository. This makes it much, much easier to maintain.