I’m trying to use the ldap_sasl_bind_s method from the Microsoft LDAP C SDK, with GSSAPI as the authentication mechanism. ldap_sasl_bind_s expects the credentials as a BERVAL structure, which is opaque.
Given a username (or a DN) and a password, how do I get to the BERVAL structure that I’m supposed to pass to ldap_sasl_bind_s?
The examples I’ve found so far
- are from other LDAP C SDKs – not the one from Microsoft
- use
ldap_sasl_bind_swhen SIMPLE authentication is desired – but I need to use GSSAPI - use
ldap_sasl_interactive_bind_swhen other SASL authentication mechanisms are desired. However, there is noldap_sasl_interactive_bind_sin the Microsoft SDK.
As a side note, the goal is to be able to bind over SASL to a variety of LDAP servers; for now: ActiveDirectory and OpenLDAP.
Any pointers will be greatly appreciated.
I managed to perform an LDAP SASL bind over GSSAPI, using
ldap_sasl_bind_s. For those interested, here are some pointers.For an abstract description of the actions a client and server need to perform during a GSSAPI SASL authentication, "The Kerberos V5 ("GSSAPI") Simple Authentication and Security Layer (SASL) Mechanism" RFC should be read; specifically, the ‘Client Side of Authentication Protocol Exchange’ section is of interest, because it gives an indication of the sequence of actions we need to perform to successfully bind to an LDAP server over Kerberos.
The credentials
ldap_sasl_bind_sexpects – their form and their meaning – depend on the actual authentication mechanism being used, which in our case is Kerberos.In the Microsoft SDK, Kerberos is available through SSPI – which is roughly the Microsoft implementation of GSSAPI; the methods that are relevant for our particular case are:
AcquireCredentialsHandle,InitializeSecurityContext,DecryptMessage,EncryptMessageAn LDAP SASL bind over Kerberos has 3 phases.
Phase 1
Call
AcquireCredentialsHandleandInitializeSecurityContext.Important notes here:
AcquireCredentialsHandlea pointer to aSEC_WINNT_AUTH_IDENTITYstructure containing the actual credentials (realm, username, password), orNULLif the credentials of the current thread are to be usedInitializeSecurityContext, mutual authentication must be requested.If all important arguments are correct – valid credentials, valid SPN,
NULLinput token – theInitializeSecurityContextcall should returnSEC_I_CONTINUE_NEEDEDand properly fill the output token. The contents of this output token should go in theBERVALstructureldap_sasl_bind_sexpects as client credentials.Call
ldap_sasl_bind_swith the output token fromInitializeSecurityContextas client credentials. If all arguments are correct – empty DN, GSSAPI as the mechanism name – the actual call should returnLDAP_SUCCESSand the most recent LDAP error for the LDAP session should beLDAP_SASL_BIND_IN_PROGRESS.As a side note, the most recent LDAP error for an LDAP session can be discovered by calling
ldap_get_optionon the session, withLDAP_OPT_ERROR_NUMBERas the option.Phase 2
After the successful call to
ldap_sasl_bind_s, its last argument points to aBERVALstructure containing the server credentials. The content of thisBERVALstructure should now be used as the input token for the second call toInitializeSecurityContext.This second call to
InitializeSecurityContextshould returnSEC_OKand an empty output token.This empty output token should be used as the client credentials for another call to
ldap_sasl_bind_s. This second call toldap_sasl_bind_sshould returnLDAP_SUCCESS, with the most recent LDAP error for the LDAP session beingLDAP_SASL_BIND_IN_PROGRESS.Phase 3
After the second successful call to
ldap_sasl_bind_s, its last argument points to aBERVALstructure containing server data. This server data should be given as input toDecryptMessage. As specified in the previously mentioned RFC, the decrypted data must be 4 bytes long.The client should build its reply according to the information in the same RFC.
Note: In my case, I omitted the authorization id mentioned in the RFC. To my understanding, an empty authorization id leads to the authentication id being used for authorization as well.
The reply the client built should then be passed as input to
EncryptMessage. The output of theEncryptMessagecall should then be passed as the client credentials for the third and final call toldap_sasl_bind_s.Note: The MSDN documentation for using
EncryptMessageunder Kerberos seems to be incomplete. Google’s Code Search should assist with a working example. Also, for a working example of the flow described above, Samba’s source code can be consulted.