LDAP Connecting with IP address and Port Number

Refresh

December 2018

Views

2.4k time

1

The company I work for has a product that uses Active Directory to enable our product's security features using a library that includes DirectoryEntry and DirectorySearcher components.

If someone is a member of group FOO, they have standard access. If they are a member of FOO-ADMIN, they have Admin rights.

We have a potential client who does not use Active Directory. They have an Apache server running their LDAP, and they have provided this screenshot.

Customer Properties

Above, it looks like I would need to connect to a domain of xxx.xxx.5.101:389 (i.e. DirectoryEntry("LDAP://xxx.xxx.5.101:389")), but how does that "DN or user" field fit with the password?

Are Active Directory components able to do LDAP authentication on an Apache system, or would the code need completely different controls?

Here is some crude code that I have put together:

/// <summary>
/// Untested Method
/// </summary>
/// <param name="hostIp">String (EX: xxx.xxx.5.101)</param>
/// <param name="port">Int (EX: 389)</param>
/// <param name="user">String (EX: cn=danibla,ou=sysdata,ou=townhall,o=toh)</param>
/// <param name="password">String - provided password</param>
/// <param name="groupsLike">String (EX: find all groups like FOO)</param>
/// <returns>String[] array of matching membership groups</returns>
public static String[] GetMemberships(String hostIp, int port, String user, String password, String groupsLike)
{
    var results = new List<String>();
    var path = String.Format("LDAP://{0}:{1}", hostIp, port);
    using (var entry = new DirectoryEntry(path, user, password))
    {
        using (var search = new DirectorySearcher(entry, String.Format("(CN={0}*)", groupsLike)))
        {
            var expression = new Regex("CN=([^,]*),", RegexOptions.Compiled & RegexOptions.IgnoreCase);
            foreach (SearchResult item in search.FindAll())
            {
                var match = expression.Match(item.Path);
                var name = match.Groups[1].Value;
                if (name.StartsWith(groupsLike, StringComparison.OrdinalIgnoreCase))
                {
                    if (!results.Contains(name))
                    {
                        results.Add(name);
                    }
                }
            }
        }
    }
    return results.ToArray();
}

I am bothered by the "path like" parameters they pass in for the "DN or user" field, particularly when it shows them providing a password with it.

We do not have an Apache environment to test this on. Our company does not want me going to this client with a lot of unnecessary questions.

UPDATE:
Still need a way to do this. Starting a bounty. Maybe bringing some attention to this will get me a solution.

currentState

In the screenshot above, the value for username in the code was both cn-mikead,ou=sysdata,ou=townhall,o=toh and separately mikead, both with the same COM Exception at the call to FindAll().

Here is the code I have now.

public static String[] Groups(String domain, int port, String username, int authenticationValue, String startsWith)
{
    String name;
    var results = new List<String>();
    var ldapPath =
        String.IsNullOrEmpty(domain) ? null :
        (0 < port) ?
        String.Format("LDAP://DC={0}:{1}", domain, port) :
        String.Format("LDAP://DC={0}", domain);
    using (var entry = new DirectoryEntry(String.Format("WinNT://{0}/{1}", Environment.UserDomainName, username)))
    {
        name = String.Format("{0}", entry.Properties["fullName"].Value);
    }
    var filter = String.Format("(CN={0}", name);
    var expression = new Regex("CN=([^,]*),", RegexOptions.Compiled & RegexOptions.IgnoreCase);
    using (var entry = new DirectoryEntry(ldapPath))
    {
        entry.AuthenticationType = (AuthenticationTypes)authenticationValue;
        using (var search = new DirectorySearcher(entry) { Filter = filter })
        {
            search.PropertiesToLoad.Add("memberOf");
            try
            {
                foreach (SearchResult item in search.FindAll())
                {
                    foreach (var property in item.Properties["memberOf"])
                    {
                        var name = expression.Match(String.Format("{0}", property)).Groups[1].Value;
                        if (name.StartsWith(startsWith, StringComparison.OrdinalIgnoreCase))
                        {
                            if (!results.Contains(name))
                            {
                                results.Add(name);
                            }
                        }
                    }
                }
            }
            catch (Exception err)
            {
                LogError("Groups", err);
            }
        }
    }
    return results.ToArray();
}

2 answers

1

I wish I had more time to give you a more complete answer. But let me see if this helps at all. Group membership works differently in eDirectory and there is no memberOf attribute. You also may find that you have to go lower level than the DirectoryEntry, DirectorySearcher, etc... (as these are tailored for AD). The System.DirectoryServices.Protocols will give you lower level access.

Alternately, Novell also has c# libraries that you could consider using: https://www.novell.com/developer/ndk/ldap_libraries_for_c_sharp.html

  1. I suggest you first bind to the database as a user with the rights you need to search or anonymously (if anonymous can search) , and search for the (&(cn=USERNAME)(objectclass=Person)) to find the dn you need to bind as.
  2. Now bind as the user dn you found with the supplied credentials and get the groupMembership attribute.
  3. Examine the groupMembership attribute to determine your privileges.

If you can't get the groupMembership attribute to work, alternately, you can search the directory for the group: ((cn=GROUPNAME)(objectclass=groupOfNames)) Then you can look through the groupOfNames:member attributes to find your username.

I'd start by trying to get just binding/authenticating up and then add the group stuff. There's an example of binding here: https://www.codeproject.com/Articles/5969/Authentication-against-Active-Directory-and-Edirec

Or an alternate method here if you have certificate issues: https://www.codeproject.com/Articles/19097/eDirectory-Authentication-using-LdapConnection-and

Here are some useful references:

https://www.mediawiki.org/wiki/Extension:LDAP_Authentication/Examples#Configuration_for_non-AD_domains

https://docs.oracle.com/cd/E36500_01/E36503/html/ldap-filters-attrs-users.html#ldap-filters-attrs-users-openldap

https://www.ibm.com/support/knowledgecenter/en/SSEQTP_8.5.5/com.ibm.websphere.wlp.doc/ae/rwlp_config_edirectoryLdapFilterProperties.html

Connecting to LDAP from C# using DirectoryServices

https://forums.novell.com/showthread.php/491292-Is-user-member-of-group-in-C

https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bovtz77.html

http://mikemstech.blogspot.com/2013/03/searching-non-microsoft-ldap.html

https://www.sqlservercentral.com/Forums/Topic811694-391-1.aspx

2

Apache can run LDAP, my advice would be to make sure your client has LDAP configured properly on their server. This could be done in the httpd.conf on their server