views:

1554

answers:

3

Hi,

The project I am working on will integrate with the customers Active Directory in order to authenticate users. I have been trying to write some code that will retrieve a users password and I understand that Active Directory will only expose the relevant properties over a SSL connection on port 636.

The following code connects programmatically without using SSL but then I can't see the password properties:

static void Main(string[] args)
{
 DirectoryEntry entry = new DirectoryEntry(@"LDAP://<IP>/CN=LDAP Test,CN=Users,DC=customer,DC=com");
 entry.AuthenticationType = AuthenticationTypes.None;
 entry.Username = "CN=LDAP Test,CN=Users,DC=customer,DC=com";
 entry.Password = "<password>";
 if (entry != null)
 {
  foreach (Object propName in entry.Properties.PropertyNames)
  {
   Console.WriteLine((String)propName);
  }
 }
}

When I change the code to use SSL I get an exception stating ;Unknown error (0x80005000)'.

I have enabled SSL on the server hosting Active Directory, installed a Microsoft CA on the same server and obtained a certificate from the CA.

I can connect to the Active Directory over SSL using Apache Directory Studio but that does not show the password properties.

The following code shows what I have been trying to use to connect using SSL:

static void Main(string[] args)
{
 DirectoryEntry entry = new DirectoryEntry(@"LDAPS://<IP>:636/CN=LDAP Test,CN=Users,DC=customer,DC=com");
 entry.AuthenticationType = AuthenticationTypes.SecureSocketsLayer;
 entry.Username = "CN=LDAP Test,CN=Users,DC=customer,DC=com";
 entry.Password = "<password>";
 if (entry != null)
 {
  foreach (Object propName in entry.Properties.PropertyNames)
  {
   Console.WriteLine((String)propName);
  }
 }
}

I'm not sure where to go with this and some assistance would be greatly appreciated.

A: 

Try adding the server's certificate and root certificate to your local store. The easiest way to do this is to use IE to connect to https://your.domain.contoller:636. Then click through all the certificate screens and add them to your store.

Andrew Strong
A: 

I have been trying to write some code that will retrieve a users password...

This is unrelated to your SSL problem, but I don't think retrieving a user's password from Active Directory is possible. It only stores a hash and that's why you aren't receiving any kind of "password" property when querying the user's properties.

Updated Answer

After reading your comment, it appears you're looking for the unicodePwd attribute which contains the security hash. According to the MSDN information, writing to that attribute requires the special SSL connection but you still won't be able to read it because it's a write-only attribute.

Specifically from MSDN:

The unicodePwd attribute is never returned by an LDAP search.

Here's also a forum post that I found that seems to say the same thing:

The users' password is stored in the Active Directory on a user object in the unicodePwd attribute. This attribute can be written under restricted conditions, but it cannot be read due to security reasons. (Source)

Lance McNearney
It's the hash that I'm after. I admit my post could have been clearer about that. The intent is to compare or authorise a hash received from another system with the hash stored in Active Directory.
James Watt
I've updated my answer regarding retrieving the hash.
Lance McNearney
A: 

HI, I am also trying to connect to SSL enabled LDAP server which is returning an error code 81 or 51. I am trying connecting with Microsoft Provided code block. I have installed CA certificate for Current USer, Machine and service all.

int main(int argc, char* argv[])
{
    LDAP* ld = NULL;
    INT iRtn = 0; 
    INT connectSuccess = 0;
    PCHAR pHost = NULL;

    char string2[80];
    //char *pHost;
    pHost = strcpy(string2, "ldap-test.com");

    ULONG version = LDAP_VERSION3;
    SecPkgContext_ConnectionInfo sslInfo;
    LONG lv = 0;

    // Create an LDAP session.
    ld = ldap_sslinit(pHost,LDAP_SSL_PORT,1);
    if (ld == NULL)
    {
        printf( "ldap_sslinit failed with 0x%x.\n",GetLastError());
        return -1;
    }

    // Specify version 3; the default is version 2.
    printf("Setting Protocol version to 3.\n");
    iRtn = ldap_set_option(ld,
                           LDAP_OPT_PROTOCOL_VERSION,
                           (void*)&version);
    if (iRtn != LDAP_SUCCESS)
        goto FatalExit;

    // Verify that SSL is enabled on the connection.
    // (returns LDAP_OPT_ON/_OFF).
    printf("Checking if SSL is enabled\n");
    iRtn = ldap_get_option(ld,LDAP_OPT_SSL,(void*)&lv);
    if (iRtn != LDAP_SUCCESS)
        goto FatalExit;

    // If SSL is not enabled, enable it.
    if ((void*)lv == LDAP_OPT_ON)
        printf("SSL is enabled\n");
    else
    {
        printf("SSL not enabled.\n SSL being enabled...\n");
        iRtn = ldap_set_option(ld,LDAP_OPT_SSL,LDAP_OPT_ON);
        if (iRtn != LDAP_SUCCESS)
            goto FatalExit;
    }

    // Connect to the server.
    connectSuccess = ldap_connect(ld, NULL);

    if(connectSuccess == LDAP_SUCCESS)
        printf("ldap_connect succeeded \n");
    else
    {
        printf("ldap_connect failed with 0x%x.\n",connectSuccess);
        goto FatalExit;
    }

    // Bind with current credentials. 
    printf("Binding ...\n");
    iRtn = ldap_bind_s(ld,NULL,NULL,LDAP_AUTH_NEGOTIATE);
    if (iRtn != LDAP_SUCCESS)
        goto FatalExit;

    // Retrieve the SSL cipher strength.
    printf("Getting SSL info\n");
    iRtn = ldap_get_option(ld,LDAP_OPT_SSL_INFO,&sslInfo);
    if (iRtn != LDAP_SUCCESS)
        goto FatalExit;

    printf("SSL cipher strength = %d bits\n",sslInfo.dwCipherStrength);

    goto NormalExit;

    // Cleanup.
NormalExit:
    if (ld != NULL)
        ldap_unbind_s(ld);
    return 0;

    // Cleanup after an error.
FatalExit:
    if( ld != NULL )
        ldap_unbind_s(ld);
    printf( "\n\nERROR: 0x%x\n", iRtn);
    return iRtn;
}
The question was in C#, not C...
Doug