1

I have been given the simple task to do Windows authentication against the AD from a Windows Compact 7 device in a C# app. Now - 14 days later I'm still struggling, so any help would be greatly appreciated.

Anyway - what I’ve managed to come up with so far is doing Windows authentication on my PC using the wldap32.dll. I’m far from a C++ expert, and with Visual C++ even less so, so bear with me. Here is my C++ code:

EXPORT_METHOD unsigned long Authenticate(char *userName, char *password, char *domain)
{
    unsigned long result = 0;

    unsigned short *uUserName = (unsigned short *)userName;
    unsigned short *uPassword = (unsigned short *)password;
    unsigned short *uDomain = (unsigned short *)domain;

    PWCHAR hostName = NULL;
    LDAP* pLdapConnection = NULL;
    ULONG version = LDAP_VERSION3;

    size_t origsize = strlen("ELLAB.COM") + 1;
    size_t convertedChars = 0;
    wchar_t wcstring[100];
    mbstowcs_s(&convertedChars, wcstring, origsize, "ELLAB.COM", _TRUNCATE);
    wcscat_s(wcstring, L" (wchar_t *)");
    hostName = wcstring;

    //  Initialize a session. LDAP_PORT is the default port, 389.
    pLdapConnection = ldap_init(hostName, LDAP_PORT);

    if (pLdapConnection == NULL)
    {
        #ifdef DEBUG
        AfxMessageBox(_T("Unable to Init"));
        #endif // DEBUG
        result = 0xff;
    }
    else
    {
        //  Set the version to 3.0 (default is 2.0).
        result = ldap_set_option(pLdapConnection, LDAP_OPT_PROTOCOL_VERSION, (void*)&version);
        if (result != LDAP_SUCCESS)
        {
            #ifdef DEBUG
            AfxMessageBox(_T("Unable to Set Optins"));
            #endif // DEBUG
        }
        else
        {
            // Connect to the server.
            result = ldap_connect(pLdapConnection, NULL);
            if (result != LDAP_SUCCESS)
            {
                #ifdef DEBUG
                AfxMessageBox(_T("Unable to Connect"));
                #endif // DEBUG
            }
            else
            {
                //  Be aware that the password itself is never sent over the network, and encryption is not used.
                SEC_WINNT_AUTH_IDENTITY NtAuthIdentity;
                ZeroMemory(&NtAuthIdentity, sizeof(NtAuthIdentity));
                NtAuthIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

                NtAuthIdentity.Domain = uDomain;
                NtAuthIdentity.DomainLength = sizeof(uDomain);
                NtAuthIdentity.User = uUserName;
                NtAuthIdentity.UserLength = sizeof(uUserName);
                NtAuthIdentity.Password = uPassword;
                NtAuthIdentity.PasswordLength = sizeof(uPassword);

                //if (ldap_bind_s(pLdapConnection, NULL, NULL, LDAP_AUTH_NEGOTIATE) == LDAP_SUCCESS)
                result = ldap_bind_s(pLdapConnection, NULL, (PWCHAR)&NtAuthIdentity, LDAP_AUTH_NTLM);
                //if (result != LDAP_SUCCESS)
                {
                    #ifdef DEBUG
                    AfxMessageBox(_T("Unable to Bind using ldap_bind_s"));
                    #endif // DEBUG
                    result = ldap_bind(pLdapConnection, NULL, (PWCHAR)&NtAuthIdentity, LDAP_AUTH_NTLM);
                    if (result != LDAP_SUCCESS)
                    {
                        #ifdef DEBUG
                        AfxMessageBox(_T("Unable to Bind using ldap_bind"));
                        #endif // DEBUG
                    }
                }
            }

        }
        //  Normal cleanup and exit.
        ldap_unbind(pLdapConnection);
    }

    return result;
}

And my C# sample wrapper:

[DllImport(@"C:\Users\ckbn.ELLAB\Documents\Visual Studio 2015\Projects\WCE7_LDAP\Debug\LDAPHandler.dll", CharSet = CharSet.Unicode)]
    public static extern int Authenticate(string userName, string password, string domain);

    private void buttonAuthenticate_Click(object sender, EventArgs e)
    {
        try
        {
            textBoxResult.Text = "";
            LDAPReturns result = (LDAPReturns)Authenticate(textBoxUserName.Text, textBoxPassword.Text, textBoxDomain.Text);
            switch (result)
            {
                case LDAPReturns.LDAP_SUCCESS:
                    textBoxResult.Text = "User '" + textBoxUserName.Text + "' is authenticated";
                    break;
                default:
                    textBoxResult.Text = result.ToString();
                    break;
            }
        }
        catch (Exception ex) { textBoxResult.Text = "Failed: " + ex.ToString(); }
    }

So - using the above code I can authenticate with my own credentials on my PC. Running the same code on the WCE device, I can connect to the AD server, but when I try to ldap_bind_s, it returns LDAP_AUTH_METHOD_NOT_SUPPORTED. So I’m thinking the the ARM version of the wldap32.dll is different from the x86 version.

Then I tried to use the ldap_bind (without ‘_s’) method. This is not working nighter on my PC nor on the WCE device and always returns 0xFFFF_FFFF.

So basically my questions are:

What does LDAP_AUTH_METHOD_NOT_SUPPORTED means, and what other methods do I have on a WCE7 device? and

What does it means when ldap_bind returns 0xFFFF_FFFF?

But any input or suggestion would be highly appreciated. Thanks in advance!

Viking
  • 293
  • 4
  • 12
  • Did you check [MSDN](https://msdn.microsoft.com/en-us/library/aa367014(v=vs.85).aspx) for the error code? – Simon Kraemer Mar 30 '17 at 09:20
  • @Simon Kraemer thanks for your quick reply. Yeah I did (The authentication method is not supported. To determine the authentication methods supported by an Active Directory server, retrieve the SupportedSASLMechanisms property of rootDSE. For more information, see Serverless Binding and RootDSE.) but I haven't been able to come up with a method to 'retrieve the SupportedSASLMechanisms property'. And still, its working on my PC??? – Viking Mar 30 '17 at 09:26
  • 1
    Viking - apologies for posting a completely wrong answer, duly deleted! The question then becomes, did the vendor of your WEC7 device include the LDAP feature in the OS build? Or, if the vendor is you, did you specify SYSGEN_LDAP in your Platform Builder project? Try checking the ceconfig.h file in the \Windows directory of your device if you have access to that – Carsten Hansen Apr 06 '17 at 09:46
  • @CarstenHansen No problem, and thanks a lot for your suggestion. I do have access, and I'll check immediately. – Viking Apr 06 '17 at 10:30
  • @CarstenHansen I don't have a #define SYSGEN_LDAP in my ceconfig.h file, so I'll try cooking a new OS as you suggested. Thanks a lot in advance. – Viking Apr 06 '17 at 10:37
  • @CarstenHansen If you post your comment as an answer, I'll mark it as such. – Viking Apr 26 '18 at 14:05
  • Done - thanks a lot :) – Carsten Hansen Apr 30 '18 at 02:27

1 Answers1

1

Did the vendor of your WEC7 device include the LDAP feature in the OS build?

Or, if the vendor is you, did you specify SYSGEN_LDAP in your Platform Builder project?

Try checking the ceconfig.h file in the \Windows directory of your device if you have access to that.

Carsten Hansen
  • 1,508
  • 2
  • 21
  • 27