Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I query LDAP from C# to resolve Oracle TNS hostname while using managed ODP.NET?

Further to my previous Question, which I managed to answer myself with help from the Oracle forums, I now have another issue which follows on from the earlier one (provided for background).

I wish to query LDAP directly from my C# code to perform an LDAP lookup of an Oracle TNS hostname in order to get the connection string. This is normally stored in tnsnames.ora, and my organisation uses LDAP (via ldap.ora) to resolve hostnames from an LDAP server using Active Directory.

However, I am using ODP.NET, Managed Driver Beta (Oracle.ManagedDataAccess.dll) in my C# application which doesn't support LDAP as mentioned in the release notes pointed to by the Oracle forum reply I mentioned earlier. This is why I wish to query LDAP directly from C#.

I found a way to do this here using DirectoryEntry and DirectorySearcher, but I have no idea what to put as the parameters to DirectorySearcher. I have access to ldap.ora which is in the following format:

# LDAP.ORA Configuration
# Generated by Oracle configuration tools.
DEFAULT_ADMIN_CONTEXT = "dc=xx,dc=mycompany,dc=com"
DIRECTORY_SERVERS = (ldap_server1.mycompany.com:389:636,ldap_server2.mycompany.com:389:636, ...) DIRECTORY_SERVER_TYPE = OID

But, how do I map this to setting up the LDAP query in my C# code?

like image 226
Neo Avatar asked Jan 28 '13 16:01

Neo


People also ask

How do I access LDAP from Windows?

Sign in to a computer that has the AD DS Admin Tools installed. Select Start > Run, type ldp.exe, and then select OK. Select Connection > Connect. In Server and in Port, type the server name and the non-SSL/TLS port of your directory server, and then select OK.

How do I connect to LDAP database?

Enter the LDAP Connection URL for the LDAP server in the format: ldap://hostname:port . Enter the Username (for example: cn=admin,cn=users,dc=us,dc=company,dc=com). Password — Enter the password if required. Enter the JNDI Context Factor Class (for example: com.


1 Answers

Further to my second comment in the accepted Answer, this is the code for performing an LDAP lookup which improves the original version I found here. And it also handles server lists in the ldap.ora file that includes multiple delimited port numbers.

private static string ResolveServiceNameLdap(string serviceName)
{
    string tnsAdminPath = Path.Combine(@"C:\Apps\oracle\network\admin", "ldap.ora");
    string connectionString = string.Empty;

    // ldap.ora can contain many LDAP servers
    IEnumerable<string> directoryServers = null;

    if (File.Exists(tnsAdminPath))
    {
        string defaultAdminContext = string.Empty;

        using (var sr = File.OpenText(tnsAdminPath))
        {
            string line;

            while ((line = sr.ReadLine()) != null)
            {
                // Ignore commetns
                if (line.StartsWith("#"))
                {
                    continue;
                }

                // Ignore empty lines
                if (line == string.Empty)
                {
                    continue;
                }

                // If line starts with DEFAULT_ADMIN_CONTEXT then get its value
                if (line.StartsWith("DEFAULT_ADMIN_CONTEXT"))
                {
                    defaultAdminContext = line.Substring(line.IndexOf('=') + 1).Trim(new[] {'\"', ' '});
                }

                // If line starts with DIRECTORY_SERVERS then get its value
                if (line.StartsWith("DIRECTORY_SERVERS"))
                {
                    string[] serversPorts = line.Substring(line.IndexOf('=') + 1).Trim(new[] {'(', ')', ' '}).Split(',');
                    directoryServers = serversPorts.SelectMany(x =>
                    {
                        // If the server includes multiple port numbers, this needs to be handled
                        string[] serverPorts = x.Split(':');
                        if (serverPorts.Count() > 1)
                        {
                            return serverPorts.Skip(1).Select(y => string.Format("{0}:{1}", serverPorts.First(), y));
                        }

                        return new[] {x};
                    });
                }
            }
        }

        // Iterate through each LDAP server, and try to connect
        foreach (string directoryServer in directoryServers)
        {
            // Try to connect to LDAP server with using default admin contact
            try
            {
                var directoryEntry = new DirectoryEntry("LDAP://" + directoryServer + "/" + defaultAdminContext, null, null, AuthenticationTypes.Anonymous);
                var directorySearcher = new DirectorySearcher(directoryEntry, "(&(objectclass=orclNetService)(cn=" + serviceName + "))", new[] { "orclnetdescstring" }, SearchScope.Subtree);

                SearchResult searchResult = directorySearcher.FindOne();

                var value = searchResult.Properties["orclnetdescstring"][0] as byte[];

                if (value != null)
                {
                    connectionString = Encoding.Default.GetString(value);
                }

                // If the connection was successful, then not necessary to try other LDAP servers
                break;
            }
            catch
            {
                // If the connection to LDAP server not successful, try to connect to the next LDAP server
                continue;
            }
        }

        // If casting was not successful, or not found any TNS value, then result is an error message
        if (string.IsNullOrEmpty(connectionString))
        {
            connectionString = "TNS value not found in LDAP";
        }
    }
    else
    {
        // If ldap.ora doesn't exist, then return error message
        connectionString = "ldap.ora not found";
    }

    return connectionString;
}
like image 92
Neo Avatar answered Sep 29 '22 16:09

Neo