Hi, guys:
Using ldap_sasl_interactive_bind_ext_s(), I've come up with an implementation
of SASL binding. The main idea is as follows:
=======================================================
#include <sasl/sasl.h>
...
static int sasl_flags = LDAP_SASL_QUIET;
static char *sasl_mech = "GSSAPI";
...
/* warning! - the following requires intimate knowledge of sasl.h */
static char *default_values[] = {
"", /* SASL_CB_USER 0x4001 */
"", /* SASL_CB_AUTHNAME 0x4002 */
"", /* SASL_CB_LANGUAGE 0x4003 */ /* not used */
"", /* SASL_CB_PASS 0x4004 */
"", /* SASL_CB_ECHOPROMPT 0x4005 */
"", /* SASL_CB_NOECHOPROMPT 0x4006 */
"", /* SASL_CB_CNONCE 0x4007 */
"" /* SASL_CB_GETREALM 0x4008 */
};
/* this is so we can use SASL_CB_USER etc. to index into default_values */
#define VALIDVAL(n) ((n >= SASL_CB_USER) && (n <= SASL_CB_GETREALM))
#define VAL(n) default_values[n-0x4001]
...
static int example_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void
*prompts);
...
static int example_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void
*prompts)
{
sasl_interact_t *interact = NULL;
if (prompts == NULL)
{
return (LDAP_PARAM_ERROR);
}
for (interact = prompts; interact->id != SASL_CB_LIST_END; interact++)
{
if (VALIDVAL(interact->id))
{
interact->result = VAL(interact->id);
interact->len = strlen((char *)interact->result);
}
}
return (LDAP_SUCCESS);
}
...
int ldapStatus = LDAP_SUCCESS;
LDAP *ldapHandle = (LDAP *)NULL;
LDAPControl **responseControls = NULL;
...
if ((ldapHandle = prldap_init((ldapServerConfigData.hostnames),
LDAP_PORT, 0)) == NULL)
{
LOGERROR("prldap_init failed");
return(ABA_LDAP_INIT_CALL_FAILED);
}
LOGINFO("prldap_init succeeded");
...
version = LDAP_VERSION3;
if (ldap_set_option(ldapHandle,LDAP_OPT_PROTOCOL_VERSION,&version)
!= LDAP_SUCCESS)
{
LOGERROR("Setting Version Failed");
/*
** unbind ldap handle.
*/
if (ldapHandle != (LDAP *)NULL)
{
LOGINFO("ldap_unbind_s2");
ldap_unbind_s(ldapHandle);
ldapHandle = (LDAP *)NULL;
}
return(ABA_LDAP_SET_UNABLE_TO_SET_PREFS);
}
...
/* no need for dn and password in case of SASL binding */
ldapStatus = ldap_sasl_interactive_bind_ext_s(ldapHandle, "", sasl_mech,
NULL, NULL, sasl_flags,
example_sasl_interact, NULL,
&responseControls);
if (responseControls != NULL)
{
LOGINFO("SASL binding finished, will destroy responseControls");
ldap_controls_free(responseControls);
}
LOGINFO("SASL LDAP BIND with GSSAPI: Value of ldapStatus %d", ldapStatus);
=======================================================
The core part is almost a direct copy from
http://mxr.mozilla.org/mozilla/source/directory/c-sdk/ldap/examples/saslsearch.c
or http://mxr.mozilla.org/mozilla/source/directory/c-sdk/ldap/examples/sasl.c.
It looks straightforward. And after an operation of "kinit..." followed by the
above SASL binding, the log gives me LDAP_SUCCESS.
However, the network trace doesn't shows the SASL packets between the printer
and the ADS. No wonder the failure of the following LDAP search, with the error
message reminding me to bind to the server before doing any query.
Yes, I know binding is prerequisite to a query. But how come the function
ldap_sasl_interactive_bind_ext_s() returns 0 when it actually doesn't contact
the server? I am really bewildered.
Hope someone can shed some light on this,
Xu Qiang
_______________________________________________
dev-tech-ldap mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-ldap