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

Reply via email to