/// <summary> /// Function that will be sent to the Sasl interactive bind procedure which will resolve all Sasl challenges /// that get passed in by using the defaults that we get passed in. /// </summary> /// <param name="ldapHandle">The connection handle to the LDAP server.</param> /// <param name="flags">Flags that control the interaction used to retrieve any necessary Sasl authentication parameters</param> /// <param name="defaultsPtr">Pointer to the defaults structure that was sent to sasl_interactive_bind</param> /// <param name="interactPtr">Pointer to the challenge we need to resolve</param> /// <returns></returns> internal static int SaslInteractionProcedure(IntPtr ldapHandle, uint flags, IntPtr defaultsPtr, IntPtr interactPtr) { if (ldapHandle == IntPtr.Zero) { return(-9); // Parameter Error } // Convert pointers into managed structures. IntPtr currentInteractPtr = interactPtr; SaslInteractiveChallenge interactChallenge = Marshal.PtrToStructure <SaslInteractiveChallenge>(currentInteractPtr); SaslDefaultCredentials defaults = Marshal.PtrToStructure <SaslDefaultCredentials>(defaultsPtr); // loop through all of the challenges that were sent through the interactChallenge. while (interactChallenge.saslChallengeType != (int)SaslChallengeType.SASL_CB_LIST_END) { // use defaults to fix the challenge type switch (interactChallenge.saslChallengeType) { case (int)SaslChallengeType.SASL_CB_GETREALM: interactChallenge.defresult = defaults.realm; break; case (int)SaslChallengeType.SASL_CB_AUTHNAME: interactChallenge.defresult = defaults.authcid; break; case (int)SaslChallengeType.SASL_CB_PASS: interactChallenge.defresult = defaults.passwd; break; case (int)SaslChallengeType.SASL_CB_USER: interactChallenge.defresult = defaults.authzid; break; } if (!string.IsNullOrEmpty(interactChallenge.defresult)) { interactChallenge.result = Marshal.StringToHGlobalAnsi(interactChallenge.defresult); interactChallenge.len = interactChallenge != null ? (uint)interactChallenge.defresult.Length : 0; } // Move to next interact challenge Marshal.StructureToPtr(interactChallenge, currentInteractPtr, false); currentInteractPtr = IntPtr.Add(currentInteractPtr, Marshal.SizeOf <SaslInteractiveChallenge>()); interactChallenge = Marshal.PtrToStructure <SaslInteractiveChallenge>(currentInteractPtr); } return(0); }
private int BindSasl() { SaslDefaultCredentials defaults = GetSaslDefaults(); IntPtr ptrToDefaults = Marshal.AllocHGlobal(Marshal.SizeOf(defaults)); Marshal.StructureToPtr(defaults, ptrToDefaults, false); try { return(Interop.Ldap.ldap_sasl_interactive_bind(_ldapHandle, null, Interop.KerberosDefaultMechanism, IntPtr.Zero, IntPtr.Zero, Interop.LDAP_SASL_QUIET, LdapPal.SaslInteractionProcedure, ptrToDefaults)); } finally { GC.KeepAlive(defaults); //Making sure we keep it in scope as we will still use ptrToDefaults Marshal.FreeHGlobal(ptrToDefaults); } }
private SaslDefaultCredentials GetSaslDefaults() { var defaults = new SaslDefaultCredentials { mech = Interop.KerberosDefaultMechanism }; IntPtr outValue = IntPtr.Zero; int error = Interop.Ldap.ldap_get_option_ptr(_ldapHandle, LdapOption.LDAP_OPT_X_SASL_REALM, ref outValue); if (error == 0 && outValue != IntPtr.Zero) { defaults.realm = Marshal.PtrToStringAnsi(outValue); } error = Interop.Ldap.ldap_get_option_ptr(_ldapHandle, LdapOption.LDAP_OPT_X_SASL_AUTHCID, ref outValue); if (error == 0 && outValue != IntPtr.Zero) { defaults.authcid = Marshal.PtrToStringAnsi(outValue); } error = Interop.Ldap.ldap_get_option_ptr(_ldapHandle, LdapOption.LDAP_OPT_X_SASL_AUTHZID, ref outValue); if (error == 0 && outValue != IntPtr.Zero) { defaults.authzid = Marshal.PtrToStringAnsi(outValue); } return(defaults); }