Esempio n. 1
0
static
DWORD
_VmDirSASLGSSBind(
     LDAP*  pLD
     )
{
    DWORD   dwError = 0;

    dwError = ldap_sasl_interactive_bind_s( pLD,
                                            NULL,
                                            "GSSAPI",
                                            NULL,
                                            NULL,
                                            LDAP_SASL_QUIET,
                                            _VmDirSASLInteraction,
                                            NULL);
    BAIL_ON_VMDIR_ERROR(dwError);

cleanup:

    return dwError;

error:

    VmDirLog(LDAP_DEBUG_ANY, "VmDirSASLGSSBind failed. (%d)(%s)\n", dwError, ldap_err2string(dwError));

    goto cleanup;
}
Esempio n. 2
0
DWORD
LwLdapBindDirectorySasl(
    LDAP *ld,
    PCSTR pszServerName,
    BOOLEAN bSeal
    )
{
    DWORD dwError = LW_ERROR_SUCCESS;

    // Do not attempt to canonicalize the server
    // name which isn't necessary since we used
    // the server's FQDN or address.

    dwError = ldap_set_option(
                  ld,
                  LDAP_OPT_X_SASL_NOCANON,
                  LDAP_OPT_ON);
    BAIL_ON_LDAP_ERROR(dwError);

    // ssf=1 is sign, ssf>1 is seal.  By default
    // it will use the maximum available ssf level
    // so setting minssf isn't strictly necessary.
    // Setting minssf guarantees an error if it
    // cannot provide the minimum level.

    if (bSeal)
    {
        dwError = ldap_set_option(
                      ld,
                      LDAP_OPT_X_SASL_SECPROPS,
                      (void *)"minssf=2");
        BAIL_ON_LDAP_ERROR(dwError);
    }
    else
    {
        dwError = ldap_set_option(
                      ld,
                      LDAP_OPT_X_SASL_SECPROPS,
                      (void *)"minssf=1,maxssf=1");
        BAIL_ON_LDAP_ERROR(dwError);
    }

    dwError = ldap_sasl_interactive_bind_s(
                  ld,
                  NULL,
                  "GSS-SPNEGO",
                  NULL,
                  NULL,
                  LDAP_SASL_QUIET,
                  LwLdapGssSpnegoInteract,
                  (void *)pszServerName);
    if (dwError != 0) {
        LW_RTL_LOG_ERROR("ldap_sasl_interactive_bind_s failed with error code %d", dwError);
        BAIL_ON_LDAP_ERROR(dwError);
    }

error:

    return dwError;
}
Esempio n. 3
0
static krb5_error_code
authenticate(krb5_ldap_context *ctx, krb5_ldap_server_handle *server)
{
    int st;
    struct berval bv;

    if (ctx->sasl_mech != NULL) {
        st = ldap_sasl_interactive_bind_s(server->ldap_handle, NULL,
                                          ctx->sasl_mech, NULL, NULL,
                                          LDAP_SASL_QUIET, interact, ctx);
        if (st != LDAP_SUCCESS) {
            k5_setmsg(ctx->kcontext, KRB5_KDB_ACCESS_ERROR,
                      _("Cannot bind to LDAP server '%s' with SASL mechanism "
                        "'%s': %s"), server->server_info->server_name,
                      ctx->sasl_mech, ldap_err2string(st));
            return KRB5_KDB_ACCESS_ERROR;
        }
    } else {
        /* Do a simple bind with DN and password. */
        bv.bv_val = ctx->bind_pwd;
        bv.bv_len = strlen(ctx->bind_pwd);
        st = ldap_sasl_bind_s(server->ldap_handle, ctx->bind_dn, NULL, &bv,
                              NULL, NULL, NULL);
        if (st != LDAP_SUCCESS) {
            k5_setmsg(ctx->kcontext, KRB5_KDB_ACCESS_ERROR,
                      _("Cannot bind to LDAP server '%s' as '%s': %s"),
                      server->server_info->server_name, ctx->bind_dn,
                      ldap_err2string(st));
            return KRB5_KDB_ACCESS_ERROR;
        }
    }
    return 0;
}
Esempio n. 4
0
DWORD
VmCASASLSRPBind(
     LDAP**     ppLd,
     PCSTR      pszURI,
     PCSTR      pszUPN,
     PCSTR      pszPass
     )
{
    DWORD       dwError = 0;
    PSTR        pszLowerCaseUPN = NULL;
    LDAP*       pLd = NULL;
    const int   ldapVer = LDAP_VERSION3;
    VMCA_SASL_INTERACTIVE_DEFAULT srpDefault = {0};

    if ( ppLd == NULL || pszURI == NULL || pszUPN == NULL || pszPass == NULL )
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_ERROR(dwError);
    }

    dwError = VMCAStringToLower( (PSTR)pszUPN, &pszLowerCaseUPN );
    BAIL_ON_ERROR(dwError);

    srpDefault.pszAuthName = pszLowerCaseUPN;
    srpDefault.pszPass     = pszPass;

    dwError = ldap_initialize( &pLd, pszURI);
    BAIL_ON_ERROR(dwError);

    dwError = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer);
    BAIL_ON_ERROR(dwError);

    dwError = ldap_sasl_interactive_bind_s( pLd,
                                            NULL,
                                            "SRP",
                                            NULL,
                                            NULL,
                                            LDAP_SASL_QUIET,
                                            _VMCASASLSRPInteraction,
                                            &srpDefault);
    BAIL_ON_ERROR(dwError);

    *ppLd = pLd;

cleanup:

    VMCA_SAFE_FREE_STRINGA(pszLowerCaseUPN);

    return dwError;

error:

    if ( pLd )
    {
        ldap_unbind_ext_s( pLd, NULL, NULL);
    }
    goto cleanup;
}
Esempio n. 5
0
DWORD
VmDirSASLGSSAPIBind(
     LDAP**     ppLd,
     PCSTR      pszURI
     )
{
    DWORD       dwError = 0;
    int         retVal = 0;
    LDAP*       pLd = NULL;
    const int   ldapVer = LDAP_VERSION3;

    if ( ppLd == NULL || pszURI == NULL )
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    retVal = ldap_initialize( &pLd, pszURI);
    BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

    retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer);
    BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

    retVal = ldap_sasl_interactive_bind_s( pLd,
                                            NULL,
                                            "GSSAPI",
                                            NULL,
                                            NULL,
                                            LDAP_SASL_QUIET,
                                            _VmDirSASLGSSAPIInteraction,
                                            NULL);
    BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

    *ppLd = pLd;

cleanup:

    return dwError;

ldaperror:

    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLGSSBind failed. (%d)(%s)",
                                           retVal, ldap_err2string(retVal) );
    dwError = VmDirMapLdapError(retVal);

error:
    if (retVal == 0)
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLGSSBind failed. (%u)", dwError);
    }

    if ( pLd )
    {
        ldap_unbind_ext_s( pLd, NULL, NULL);
    }
    goto cleanup;
}
Esempio n. 6
0
int ldap_add_machine_account(const char *ldap_host, 
			     const char *hostname, const char *realm)
{
	LDAP *ld;
	int ldap_port = LDAP_PORT;
	char *bind_path;
	int rc;
	LDAPMessage *res;
	void *sasl_defaults;
	int version = LDAP_VERSION3;

	bind_path = build_dn(realm);

	printf("Creating host account for %s@%s\n", hostname, realm);

	ld = ldap_open(ldap_host, ldap_port);
	ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);

	rc = ldap_sasl_interactive_bind_s(ld, NULL, NULL, NULL, NULL, 0,
					  sasl_interact, NULL);

	if (rc != LDAP_SUCCESS) {
		ldap_perror(ld, "ldap_bind");
		goto failed;
	}

	rc = find_host(ld, &res, bind_path, hostname);
	if (rc == LDAP_SUCCESS && ldap_count_entries(ld, res) == 1) {
		printf("Host account for %s already exists\n", hostname);
		goto finished;
	}

	rc = add_host(ld, bind_path, hostname, realm);
	if (rc != LDAP_SUCCESS) {
		ldap_perror(ld, "add_host");
		goto failed;
	}

	rc = find_host(ld, &res, bind_path, hostname);
	if (rc != LDAP_SUCCESS || ldap_count_entries(ld, res) != 1) {
		ldap_perror(ld, "find_host test");
		goto failed;
	}

	printf("Successfully added machine account for %s\n", hostname);

finished:	
	free(bind_path);
	return 0;

failed:
	printf("ldap_add_machine_account failed\n");
	free(bind_path);
	ldap_unbind(ld);
	return 1;
}
Esempio n. 7
0
/** @brief Bind to the server with SASL
  * @param ld Reference to LDAP connection.
  * @param mech SASL mechanisim.
  * @param realm SASL realm.
  * @param authcid SASL auth id.
  * @param passwd Password for authid.
  * @param authzid Proxy authid.
  * @returns -1 on error.*/
extern int ldap_saslbind(struct ldap_conn *ld, const char *mech, const char *realm, const char *authcid, const char *passwd, const char *authzid ) {
	struct sasl_defaults *sasl;
	int res, sasl_flags = LDAP_SASL_AUTOMATIC | LDAP_SASL_QUIET;

	if (!objref(ld)) {
		return LDAP_UNAVAILABLE;
	}

	if (!(sasl = objalloc(sizeof(*sasl), free_sasl))) {
		return LDAP_NO_MEMORY;
	}

	ALLOC_CONST(sasl->passwd, passwd);

	if (mech) {
		ALLOC_CONST(sasl->mech, mech);
	} else {
		ldap_get_option(ld->ldap, LDAP_OPT_X_SASL_MECH, &sasl->mech);
	}

	if (realm) {
		ALLOC_CONST(sasl->realm, realm);
	} else {
		ldap_get_option(ld->ldap, LDAP_OPT_X_SASL_REALM, &sasl->realm );
	}

	if (authcid) {
		ALLOC_CONST(sasl->authcid, authcid);
	} else {
		ldap_get_option(ld->ldap, LDAP_OPT_X_SASL_AUTHCID, &sasl->authcid );
	}

	if (authzid) {
		ALLOC_CONST(sasl->authzid, authzid);
	} else {
		ldap_get_option(ld->ldap, LDAP_OPT_X_SASL_AUTHZID, &sasl->authzid );
	}

	objlock(ld);
	if (ld->sasl) {
		objunref(ld->sasl);
	}
	ld->sasl = sasl;
	res = ldap_sasl_interactive_bind_s(ld->ldap, NULL, sasl->mech, ld->sctrlsp , NULL, sasl_flags, dts_sasl_interact, sasl);
	objunlock(ld);
	objunref(ld);
	return res;
}
Esempio n. 8
0
/*
  connect to the LDAP server
*/
int ads_connect(ADS_STRUCT *ads)
{
	int version = LDAP_VERSION3;
	int rc;

	ads->ld = ldap_open(ads->ldap_server, ads->ldap_port);
	if (!ads->ld) {
		return errno;
	}
	ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);

	rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL, 0,
					  sasl_interact, NULL);

	return rc;
}
Esempio n. 9
0
static void* ldap_bind_thread_func( void*arg)
{
	LinphoneLDAPContactProvider* obj = linphone_ldap_contact_provider_ref(arg);
	const char* auth_mechanism = obj->auth_method;
	int ret;

	if( (strcmp(auth_mechanism, "ANONYMOUS") == 0) || (strcmp(auth_mechanism, "SIMPLE") == 0) )
	{
		struct berval passwd = { strlen(obj->password), ms_strdup(obj->password)};
		auth_mechanism = LDAP_SASL_SIMPLE;
		ret = ldap_sasl_bind_s(obj->ld,
							   obj->bind_dn,
							   auth_mechanism,
							   &passwd,
							   NULL,
							   NULL,
							   NULL);

		ms_free(passwd.bv_val);
	}
	else
	{

		ms_message("LDAP interactive bind");
		ret = ldap_sasl_interactive_bind_s(obj->ld,
										   obj->bind_dn,
										   auth_mechanism,
										   NULL,NULL,
										   LDAP_SASL_QUIET,
										   linphone_ldap_contact_provider_bind_interact,
										   obj);
	}

	if( ret == LDAP_SUCCESS ) {
		ms_message("LDAP bind OK");
		obj->connected = 1;
	} else {
		int err;
		ldap_get_option(obj->ld, LDAP_OPT_RESULT_CODE, &err);
		ms_error("ldap_sasl_bind error returned %x, err %x (%s), auth_method: %s",
				 ret, err, ldap_err2string(err), auth_mechanism );
	}

	obj->bind_thread = 0;
	linphone_ldap_contact_provider_unref(obj);
	return (void*)0;
}
Esempio n. 10
0
static
idmap_stat
idmap_open_ad_conn(idmap_nm_handle_t *adh)
{
	int zero = 0;
	int timeoutms = 30 * 1000;
	int ldversion, ldap_rc;
	idmap_stat rc = IDMAP_SUCCESS;

	/* Open and bind an LDAP connection */
	adh->ad = ldap_init(adh->ad_host, adh->ad_port);
	if (adh->ad == NULL) {
		namemap_log(
		    gettext("ldap_init() to server %s port %d failed. (%s)"),
		    CHECK_NULL(adh->ad_host),
		    adh->ad_port, strerror(errno));
		rc = IDMAP_ERR_INTERNAL;
		goto out;
	}
	ldversion = LDAP_VERSION3;
	(void) ldap_set_option(adh->ad, LDAP_OPT_PROTOCOL_VERSION, &ldversion);
	(void) ldap_set_option(adh->ad, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
	(void) ldap_set_option(adh->ad, LDAP_OPT_TIMELIMIT, &zero);
	(void) ldap_set_option(adh->ad, LDAP_OPT_SIZELIMIT, &zero);
	(void) ldap_set_option(adh->ad, LDAP_X_OPT_CONNECT_TIMEOUT, &timeoutms);
	(void) ldap_set_option(adh->ad, LDAP_OPT_RESTART, LDAP_OPT_ON);
	ldap_rc = ldap_sasl_interactive_bind_s(adh->ad, "" /* binddn */,
	    adh->saslmech, NULL, NULL, adh->saslflags, &idmap_saslcallback,
	    NULL);

	if (ldap_rc != LDAP_SUCCESS) {
		(void) ldap_unbind(adh->ad);
		adh->ad = NULL;
		namemap_log(
		    gettext("ldap_sasl_interactive_bind_s() to server "
		    "%s port %d failed. (%s)"), CHECK_NULL(adh->ad_host),
		    adh->ad_port, ldap_err2string(ldap_rc));
		rc = IDMAP_ERR_INTERNAL;
	}

out:
	return (rc);
}
Esempio n. 11
0
static VALUE rldap_sasl_bind(int argc, VALUE *argv, VALUE obj)
{
	RLDAP_WRAP *wrapper;
	char *bind_dn = NULL, *passwd = NULL, *sasl_mech = NULL,
		*sasl_realm = NULL, *sasl_authz_id = NULL, *sasl_authc_id = NULL;
	VALUE rbind_dn, rpasswd, rsasl_mech, rsasl_realm,
		rsasl_authz_id, rsasl_authc_id, rprops;
	int retval;
	RLDAP_BICTX *ctx;
	
	wrapper = get_wrapper(obj);
	rb_scan_args(argc, argv, "07", &rbind_dn, &rpasswd, &rsasl_mech, &rsasl_realm, &rsasl_authz_id, &rsasl_authc_id, &rprops);
	
	if (!NIL_P(rprops))
		ldap_set_option(wrapper->ld, LDAP_OPT_X_SASL_SECPROPS, StringValuePtr(rprops));
	
	if (!NIL_P(rbind_dn))
		bind_dn = StringValuePtr(rbind_dn);
	if (!NIL_P(rpasswd))
		passwd = StringValuePtr(rpasswd);
	if (!NIL_P(rsasl_mech))
		sasl_mech = StringValuePtr(rsasl_mech);
	if (!NIL_P(rsasl_realm))
		sasl_realm = StringValuePtr(rsasl_realm);
	if (!NIL_P(rsasl_authz_id))
		sasl_authz_id = StringValuePtr(rsasl_authz_id);
	if (!NIL_P(rsasl_authc_id))
		sasl_authc_id = StringValuePtr(rsasl_authc_id);
	
	ctx = _rldap_sasl_setdefs(wrapper->ld, sasl_mech, sasl_realm, sasl_authc_id, passwd, sasl_authz_id);
	
	retval = ldap_sasl_interactive_bind_s(wrapper->ld, bind_dn, ctx->mech, NULL, NULL, LDAP_SASL_AUTOMATIC, _rldap_sasl_interact, ctx);
	
	_rldap_sasl_freedefs(ctx);
	
	if (retval != LDAP_SUCCESS)
		rldap_raise(retval);
	else
		return Qtrue;
}
Esempio n. 12
0
static int ldap_rebind_proc(LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params) {
	struct ldap_conn *ldap = params;
	int res = LDAP_UNAVAILABLE;

	if (!objref(ldap)) {
		return LDAP_UNAVAILABLE;
	}

	if (ldap->sasl) {
		int sasl_flags = LDAP_SASL_AUTOMATIC | LDAP_SASL_QUIET;
		struct sasl_defaults *sasl = ldap->sasl;

		res = ldap_sasl_interactive_bind_s(ld, NULL, sasl->mech, ldap->sctrlsp , NULL, sasl_flags, dts_sasl_interact, sasl);
	} else
		if (ldap->simple) {
			struct ldap_simple *simple = ldap->simple;

			res = ldap_sasl_bind_s(ld, simple->dn, LDAP_SASL_SIMPLE, simple->cred, ldap->sctrlsp, NULL, NULL);
		}

	objunref(ldap);
	return res;
}
Esempio n. 13
0
int _LDAP_bind_s(LDAP *ld, char *mech, char* binddn, char *pswstr, char *authcid, char *realm, char *authzid) {
	int rc;
	LDAPControl	**sctrlsp = NULL;
	struct berval passwd;
	struct berval *servdata;
	void *defaults;

	/* Mechanism is set, use SASL interactive bind. */
	if (mech != NULL) {
		if (pswstr == NULL) pswstr = "";
		defaults = create_sasl_defaults(ld, mech, realm, authcid, pswstr, authzid);
		if (defaults == NULL) return -1;
		rc = ldap_sasl_interactive_bind_s(ld, binddn, mech, sctrlsp, NULL, LDAP_SASL_QUIET, sasl_interact, defaults);
	} else {
		if (pswstr == NULL) {
			passwd.bv_len = 0;
		} else {
			passwd.bv_len = strlen(pswstr);
		}
		passwd.bv_val = pswstr;
		rc = ldap_sasl_bind_s(ld, binddn, LDAP_SASL_SIMPLE, &passwd, sctrlsp, NULL, &servdata);
	}
	return rc;
}
Esempio n. 14
0
int ld_con_connect(db_con_t* con)
{
	struct ld_con* lcon;
	struct ld_uri* luri;
	int ret, version = 3;
	char* err_str = NULL;

	lcon = DB_GET_PAYLOAD(con);
	luri = DB_GET_PAYLOAD(con->uri);

	/* Do not reconnect already connected connections */
	if (lcon->flags & LD_CONNECTED) return 0;

	DBG("ldap: Connecting to %s\n", luri->uri);

	if (lcon->con) {
		ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
		if (ret != LDAP_SUCCESS) {
			ERR("ldap: Error while unbinding from %s: %s\n",
				luri->uri, ldap_err2string(ret));
		}
	}

	/* we pass the TLS_REQCERT and TLS_REQCERT attributes over environment
	   variables to ldap library */
	if (luri->tls) {
		if (setenv("LDAPTLS_CACERT", luri->ca_list, 1)) {
			ERR("ldap: Can't set environment variable 'LDAPTLS_CACERT'\n");
			goto error;
		}
		if (setenv("LDAPTLS_REQCERT", luri->req_cert, 1)) {
			ERR("ldap: Can't set environment variable 'LDAPTLS_REQCERT'\n");
			goto error;
		}
	}

	ret = ldap_initialize(&lcon->con, luri->uri);
	if (lcon->con == NULL) {
		ERR("ldap: Error while initializing new LDAP connection to %s\n",
			luri->uri);
		goto error;
	}

	ret = ldap_set_option(lcon->con, LDAP_OPT_PROTOCOL_VERSION, &version);
	if (ret != LDAP_OPT_SUCCESS) {
		ERR("ldap: Error while setting protocol version 3: %s\n",
			ldap_err2string(ret));
		goto error;
	}

	if (luri->tls) {
		ret = ldap_start_tls_s(lcon->con, NULL, NULL);
		if (ret != LDAP_SUCCESS) {
			/* get addition info of this error */
#ifdef OPENLDAP23
			ldap_get_option(lcon->con, LDAP_OPT_ERROR_STRING, &err_str);
#elif OPENLDAP24
			ldap_get_option(lcon->con, LDAP_OPT_DIAGNOSTIC_MESSAGE, &err_str);
#endif
			ERR("ldap: Error while starting TLS: %s\n", ldap_err2string(ret));
			if (err_str) {
				ERR("ldap: %s\n", err_str);
				ldap_memfree(err_str);
			}
			goto error;
		}
	}

	switch (luri->authmech) {
		case LDAP_AUTHMECH_NONE:
			ret = ldap_simple_bind_s(lcon->con, NULL, NULL);
			break;
		case LDAP_AUTHMECH_SIMPLE:
			ret = ldap_simple_bind_s(lcon->con, luri->username, luri->password);
			break;
		case LDAP_AUTHMECH_DIGESTMD5:
			ret = ldap_sasl_interactive_bind_s( lcon->con, NULL,
					LDAP_MECHANISM_STR_DIGESTMD5, NULL, NULL,
					0, lutil_sasl_interact, luri );
			break;
		case LDAP_AUTHMECH_EXTERNAL:
		default:
			ret = !LDAP_SUCCESS;
			break;
	}

	if (ret != LDAP_SUCCESS) {
		ERR("ldap: Bind to %s failed: %s\n",
			luri->uri, ldap_err2string(ret));
		goto error;
	}

	DBG("ldap: Successfully bound to %s\n", luri->uri);
	lcon->flags |= LD_CONNECTED;
	return 0;

 error:
	if (lcon->con) {
		ret = ldap_unbind_ext_s(lcon->con, NULL, NULL);
		if (ret) {
			ERR("ldap: Error while unbinding from %s: %s\n",
				luri->uri, ldap_err2string(ret));
		}
	}
	lcon->con = NULL;
	return -1;
}
Esempio n. 15
0
DWORD
VmDirSASLSRPBindExt1(
     LDAP**     ppLd,
     PCSTR      pszURI,
     PCSTR      pszUPN,
     PCSTR      pszPass,
     int        iTimeout
     )
{
    DWORD       dwError = 0;
    int         retVal = 0;
    PSTR        pszLowerCaseUPN = NULL;
    LDAP*       pLd = NULL;
    const int   ldapVer = LDAP_VERSION3;
    const int   iSaslNoCanon = 1;
    VMDIR_SASL_INTERACTIVE_DEFAULT srpDefault = {0};
    int         iCnt = 0;
    struct timeval  optTimeout={0};

    optTimeout.tv_usec = 0;
    optTimeout.tv_sec = iTimeout;

    if ( ppLd == NULL || pszURI == NULL || pszUPN == NULL || pszPass == NULL )
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirAllocASCIIUpperToLower( pszUPN, &pszLowerCaseUPN );
    BAIL_ON_VMDIR_ERROR(dwError);

    srpDefault.pszAuthName = pszLowerCaseUPN;
    srpDefault.pszPass     = pszPass;

    for (iCnt=0; iCnt<2; iCnt++)
    {
        retVal = ldap_initialize( &pLd, pszURI);
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

        retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer);
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

        // turn off SASL hostname canonicalization for SRP mech
        retVal = ldap_set_option(pLd, LDAP_OPT_X_SASL_NOCANON, &iSaslNoCanon);
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

        if (iTimeout > 0)
        {
            // timeout connect
            retVal = ldap_set_option(pLd, LDAP_OPT_NETWORK_TIMEOUT, (void *)&optTimeout);
            BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
        }

        retVal = ldap_sasl_interactive_bind_s( pLd,
                                                NULL,
                                                "SRP",
                                                NULL,
                                                NULL,
                                                LDAP_SASL_QUIET,
                                                _VmDirSASLSRPInteraction,
                                                &srpDefault);
        if (retVal == LDAP_SERVER_DOWN || retVal == LDAP_TIMEOUT)
        {
            VmDirSleep(50); // pause 50 ms
            if ( pLd )
            {
                ldap_unbind_ext_s(pLd, NULL, NULL);
                pLd = NULL;
            }
            continue;   // if transient network error, retry once.
        }
        else
        {
            break;
        }
    }
    BAIL_ON_SIMPLE_LDAP_ERROR(retVal);  // bail ldap_sasl_interactive_bind_s failure.

    *ppLd = pLd;

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLowerCaseUPN);

    return dwError;

ldaperror:

    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%d)(%s)",
                                           retVal, ldap_err2string(retVal) );
    dwError = VmDirMapLdapError(retVal);

error:
    if (retVal == 0)
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%u)", dwError);
    }

    if ( pLd )
    {
        ldap_unbind_ext_s( pLd, NULL, NULL);
    }
    goto cleanup;
}
Esempio n. 16
0
DWORD
VmDirSASLSRPBind(
     LDAP**     ppLd,
     PCSTR      pszURI,
     PCSTR      pszUPN,
     PCSTR      pszPass
     )
{
    DWORD       dwError = 0;
    int         retVal = 0;
    PSTR        pszLowerCaseUPN = NULL;
    LDAP*       pLd = NULL;
    const int   ldapVer = LDAP_VERSION3;
    VMDIR_SASL_INTERACTIVE_DEFAULT srpDefault = {0};
    int         iCnt = 0;

    if ( ppLd == NULL || pszURI == NULL || pszUPN == NULL || pszPass == NULL )
    {
        dwError = VMDIR_ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    dwError = VmDirAllocASCIIUpperToLower( pszUPN, &pszLowerCaseUPN );
    BAIL_ON_VMDIR_ERROR(dwError);

    srpDefault.pszAuthName = pszLowerCaseUPN;
    srpDefault.pszPass     = pszPass;

    for (iCnt=0; iCnt<2; iCnt++)
    {
        retVal = ldap_initialize( &pLd, pszURI);
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

        retVal = ldap_set_option(pLd, LDAP_OPT_PROTOCOL_VERSION, &ldapVer);
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);

        retVal = ldap_sasl_interactive_bind_s( pLd,
                                                NULL,
                                                "SRP",
                                                NULL,
                                                NULL,
                                                LDAP_SASL_QUIET,
                                                _VmDirSASLSRPInteraction,
                                                &srpDefault);
        if (retVal == LDAP_SERVER_DOWN)
        {
            VmDirSleep(50); // pause 50 ms
            if ( pLd )
            {
                ldap_unbind_ext_s(pLd, NULL, NULL);
                pLd = NULL;
            }
            continue;   // if transient network error, retry once.
        }
        else
        {
            break;
        }
    }
    BAIL_ON_SIMPLE_LDAP_ERROR(retVal);  // bail ldap_sasl_interactive_bind_s failure.

    *ppLd = pLd;

cleanup:

    VMDIR_SAFE_FREE_MEMORY(pszLowerCaseUPN);

    return dwError;

ldaperror:

    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%d)(%s)",
                                           retVal, ldap_err2string(retVal) );
    dwError = VmDirMapLdapError(retVal);

error:
    if (retVal == 0)
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "_VmDirSASLSRPBind failed. (%u)", dwError);
    }

    if ( pLd )
    {
        ldap_unbind_ext_s( pLd, NULL, NULL);
    }
    goto cleanup;
}
Esempio n. 17
0
static int ipa_ldap_bind(const char *server_name, krb5_principal bind_princ,
			 const char *bind_dn, const char *bind_pw, LDAP **_ld)
{
    char *msg = NULL;
    struct berval bv;
    int version;
    LDAP *ld;
    int ssl;
    int ret;

    /* TODO: support referrals ? */
    if (bind_dn) {
        ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ca_cert_file);
        if (ret != LDAP_OPT_SUCCESS) {
            fprintf(stderr, _("Unable to set LDAP_OPT_X_TLS_CERTIFICATE\n"));
            return ret;
        }

        ret = ipa_ldap_init(&ld, "ldaps", server_name, 636);
        if (ret != LDAP_SUCCESS) {
            fprintf(stderr, _("Unable to init for ldaps(636) connection\n"));
            return ret;
        }

        ssl = LDAP_OPT_X_TLS_HARD;;
        ret = ldap_set_option(ld, LDAP_OPT_X_TLS, &ssl);
        if (ret != LDAP_OPT_SUCCESS) {
            fprintf(stderr, _("Unable to set LDAP_OPT_X_TLS\n"));
            goto done;
        }
    } else {
        ret = ipa_ldap_init(&ld, "ldap", server_name, 389);
        if (ret != LDAP_SUCCESS) {
            fprintf(stderr, _("Unable to init for ldap(389) connection\n"));
            return ret;
        }
    }

    if (ld == NULL) {
        fprintf(stderr, _("Unable to initialize ldap library!\n"));
        return LDAP_OPERATIONS_ERROR;
    }

#ifdef LDAP_OPT_X_SASL_NOCANON
    /* Don't do DNS canonicalization */
    ret = ldap_set_option(ld, LDAP_OPT_X_SASL_NOCANON, LDAP_OPT_ON);
    if (ret != LDAP_SUCCESS) {
	fprintf(stderr, _("Unable to set LDAP_OPT_X_SASL_NOCANON\n"));
        goto done;
    }
#endif

    version = LDAP_VERSION3;
    ret = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
    if (ret != LDAP_SUCCESS) {
	fprintf(stderr, _("Unable to set LDAP_OPT_PROTOCOL_VERSION\n"));
	goto done;
    }

    if (bind_dn) {
        bv.bv_val = discard_const(bind_pw);
        bv.bv_len = strlen(bind_pw);

        ret = ldap_sasl_bind_s(ld, bind_dn, LDAP_SASL_SIMPLE,
                               &bv, NULL, NULL, NULL);
        if (ret != LDAP_SUCCESS) {
            fprintf(stderr, _("Simple bind failed\n"));
            goto done;
        }
    } else {
        ret = ldap_sasl_interactive_bind_s(ld, NULL, "GSSAPI",
                                           NULL, NULL, LDAP_SASL_QUIET,
                                           ldap_sasl_interact, bind_princ);
        if (ret != LDAP_SUCCESS) {
#ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
            ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg);
#endif
            fprintf(stderr, "SASL Bind failed %s (%d) %s!\n",
                            ldap_err2string(ret), ret, msg ? msg : "");
            goto done;
        }
    }

    ret = LDAP_SUCCESS;

done:
    if (ret != LDAP_SUCCESS) {
        if (ld) ldap_unbind_ext(ld, NULL, NULL);
    } else {
        *_ld = ld;
    }
    return ret;
}
Esempio n. 18
0
void
OPENLDAP::Book::refresh_start ()
{
  int msgid = -1;
  int result = LDAP_SUCCESS;
  int ldap_version = LDAP_VERSION3;

  status = std::string (_("Refreshing"));
  updated (this->shared_from_this ());

  result = ldap_initialize (&ldap_context, bookinfo.uri_host.c_str());
  if (result != LDAP_SUCCESS) {

    status = std::string (_("Could not initialize server"));
    updated (this->shared_from_this ());
    return;
  }

  /* the openldap code shows I don't have to check the result of this
   * (see for example tests/prog/slapd-search.c)
   */
  (void)ldap_set_option (ldap_context,
			 LDAP_OPT_PROTOCOL_VERSION, &ldap_version);

  if (bookinfo.starttls) {
    result = ldap_start_tls_s (ldap_context, NULL, NULL);
    if (result != LDAP_SUCCESS) {
      status = std::string (_("LDAP Error: ")) +
        std::string (ldap_err2string (result));
      updated (this->shared_from_this ());
      ldap_unbind_ext (ldap_context, NULL, NULL);
      ldap_context = NULL;
      return;
    }
  }

  if (bookinfo.sasl) {
    interctx ctx;

    ctx.book = this;
    ctx.authcID = bookinfo.authcID;
    ctx.password = bookinfo.password;
    result = ldap_sasl_interactive_bind_s (ldap_context, NULL,
					   bookinfo.saslMech.c_str(), NULL, NULL, LDAP_SASL_QUIET,
					   book_saslinter, &ctx);

  } else {
    /* Simple Bind */
    if (bookinfo.password.empty ()) {
      struct berval bv={0,NULL};

      result = ldap_sasl_bind (ldap_context, NULL,
			       LDAP_SASL_SIMPLE, &bv,
			       NULL, NULL,
			       &msgid);
    } else {

      struct berval passwd = { 0, NULL };
      passwd.bv_val = g_strdup (bookinfo.password.c_str ());
      passwd.bv_len = bookinfo.password.length();

      result = ldap_sasl_bind (ldap_context, bookinfo.authcID.c_str(),
			       LDAP_SASL_SIMPLE, &passwd,
			       NULL, NULL,
			       &msgid);

      g_free (passwd.bv_val);
    }
  }

  if (result != LDAP_SUCCESS) {

    status = std::string (_("LDAP Error: ")) +
      std::string (ldap_err2string (result));
    updated (this->shared_from_this ());

    ldap_unbind_ext (ldap_context, NULL, NULL);
    ldap_context = NULL;
    return;
  }

  status = std::string (_("Contacted server"));
  updated (this->shared_from_this ());

  patience = 3;
  refresh_bound ();
}
Esempio n. 19
0
LDAP *ads_init(Env E)
{
    LDAP  *ld = NULL;
    LDAPMessage    *result, *e;
    int        i;
    int h, nh;
    int rc;
    char uri[1024];
   
    syslog(LOG_DEBUG, ".. auth_initialize, host=%s\n", E->ads_host);

    /* Get a handle to the server */

       if (E->ads_ca) {  /* tls version */

#ifdef LDAP_DEBUG
          set_ldap_debug();
#endif

          if (!set_int_option(NULL, LDAP_OPT_PROTOCOL_VERSION, LDAP_VERSION3)) rc=1;
          if (!set_int_option(NULL, LDAP_OPT_X_TLS, LDAP_OPT_X_TLS_DEMAND)) rc=1;
          if (!set_char_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, E->ads_ca)) rc=1;

          sprintf(uri,"ldap://%s:%s/", E->ads_host, E->ads_port);
          if ( (rc = ldap_initialize(&ld,  uri )) != LDAP_SUCCESS ) {
             report_error(rc, "ldap_initialize");
             rc=1;
          }

          syslog(LOG_DEBUG, ".. ldap tls initialize ok\n");

       } else { /* not tls */

          if ( (ld = ldap_init( E->ads_host, atoi(E->ads_port) )) == NULL ) {
             syslog(LOG_ERR,  "non tls ldap_init failed" );
             rc=1;
          }

       } 

       /* Bind */

       if (E->ads_ca && E->ads_crt) {
        
          /* cert */
          syslog(LOG_DEBUG, "using cert from %s\n", E->ads_crt);
          if (!set_char_option(NULL, LDAP_OPT_X_TLS_CERTFILE, E->ads_crt)) exit (1);
          if (!set_char_option(NULL, LDAP_OPT_X_TLS_KEYFILE, E->ads_key)) exit (1);

          if ((rc=ldap_start_tls_s(ld, NULL, NULL)) != LDAP_SUCCESS) {
             report_error(rc, "ldap_start_tls_s");
             rc=1;
          }

          if ((rc=ldap_sasl_interactive_bind_s(ld, NULL, "EXTERNAL", 0, 0,
                LDAP_SASL_AUTOMATIC|LDAP_SASL_QUIET, tsasl_interact, 0)) != LDAP_SUCCESS) {
             report_error(rc, "ldap_sasl_interactive_bind_s");
             rc=1;
          }


       } else {

          syslog(LOG_ERR, "invalid ldap config\n");
          rc=1;
       }
       syslog(LOG_DEBUG, ".. ldap bind ok\n");

       set_int_option( ld, LDAP_OPT_PROTOCOL_VERSION, LDAP_VERSION3);
     

    if (ld) syslog(LOG_DEBUG, ".. ldap connect OK.\n");
    else syslog(LOG_DEBUG, ".. ldap connect failed.\n");
    E->ldap = ld;
    // show_cfg(cfg);
    return (ld);
}
Esempio n. 20
0
int is_admin(struct rekey_session *sess)
{
  static int ldap_initialized=0;
  char *username=NULL;
  LDAP *l=NULL;
  int v, ssl_hard=LDAP_OPT_X_TLS_HARD, rc, ret=0;
  struct timeval tv;
  LDAPMessage *response=NULL;
  char *reason, *filter;
  char *ldap_url, *ldap_base, *ldap_filter, *ldap_binddn;
  char *ldap_pwfile, *ldap_cacertdir;
  char ldap_pwbuf[257];
#ifdef HAVE_KRB5_REALM
  krb5_realm *realm;
#else
  krb5_data rdata;
  krb5_data *realm = &rdata;
#endif
#if !defined(LDAP_OPT_X_TLS_PROTOCOL_MIN)
  SSL_CTX *sslctx;
#endif

  if (!princ_ncomp_eq(sess->kctx, sess->princ, 2) ||
      !compare_princ_comp(sess->kctx, sess->princ, 1, "admin")) {
    goto freeall;
  }

  if (!(username=dup_comp_string(sess->kctx, sess->princ, 0))) {
    prtmsg("Failed to extract username for admin check");
    goto freeall;
  }

#ifdef HAVE_KRB5_REALM
  realm=sess->realm;
#else
  rdata.data=sess->realm;
  rdata.length=strlen(sess->realm);
#endif
  krb5_appdefault_string(sess->kctx, "rekey", realm, "ldap_uri", LDAP_URI, &ldap_url);
  krb5_appdefault_string(sess->kctx, "rekey", realm, "ldap_base", LDAP_BASEDN, &ldap_base);
  krb5_appdefault_string(sess->kctx, "rekey", realm, "ldap_filter", USER_INGROUP_FILTER, &ldap_filter);
  krb5_appdefault_string(sess->kctx, "rekey", realm, "ldap_binddn", LDAP_BINDDN, &ldap_binddn);
  krb5_appdefault_string(sess->kctx, "rekey", realm, "ldap_pwfile", LDAP_PWFILE, &ldap_pwfile);
  krb5_appdefault_string(sess->kctx, "rekey", realm, "ldap_cacertdir", "/etc/andy/ldapcerts", &ldap_cacertdir);

  if (strlen(ldap_pwfile) > 0) {
    int fd=open(ldap_pwfile, O_RDONLY);
    ssize_t rsize;
    if (fd < 0) {
      prtmsg("Failed to open LDAP password file %s: %s", ldap_pwfile, strerror(errno));
      goto freeall;
    }
    rsize=read(fd, ldap_pwbuf, 256);
    if (rsize < 0) {
      prtmsg("Failed to read from LDAP password file %s: %s", ldap_pwfile, strerror(errno));
      goto freeall;
    }
    if (rsize > 255) {
      prtmsg("LDAP password file %s is too large. limit to 255 characters", ldap_pwfile);
      goto freeall;
    }
    while(rsize > 0 && isspace(ldap_pwbuf[rsize-1]))
      rsize--;
    ldap_pwbuf[rsize]=0;
  }
  if (!ldap_initialized) {
    LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ssl_hard);
    LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CACERTDIR, ldap_cacertdir);
    LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, "HIGH:!ADH:!eNULL:-SSLv2");
#if defined(LDAP_OPT_X_TLS_PROTOCOL_MIN)
    v=LDAP_OPT_X_TLS_PROTOCOL_TLS1_0;
    LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_PROTOCOL_MIN, &v);
#else
    extern int ldap_pvt_tls_init();
    extern int ldap_pvt_tls_init_def_ctx( int is_server );
    ldap_pvt_tls_init();
    ldap_pvt_tls_init_def_ctx(0);
    LDAP_GET_OPTION(NULL, LDAP_OPT_X_TLS_CTX, &sslctx);
    if (sslctx) {
      SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);
      SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3);
    }
#endif
    ldap_initialized=1;
  }
  errno=0;
  rc = ldap_initialize(&l, ldap_url);

  
  if (rc!=LDAP_SUCCESS)
  {
    prtmsg("Failed to initialize ldap for %s: %s%s%s", ldap_url,
	   ldap_err2string(rc),(errno==0)?"":": ",
	   (errno==0)?"":strerror(errno));
    goto freeall;
  }
  v=LDAP_VERSION3;
  LDAP_SET_OPTION(l, LDAP_OPT_PROTOCOL_VERSION, &v);
  LDAP_SET_OPTION(l, LDAP_OPT_X_TLS, &ssl_hard);

  errno=0;
#if 0
  rc = ldap_sasl_interactive_bind_s(l, NULL, "GSSAPI", NULL, NULL,
				    LDAP_SASL_QUIET, do_sasl_interact, NULL);
#else
  rc = ldap_bind_s(l, ldap_binddn, ldap_pwbuf, LDAP_AUTH_SIMPLE);
#endif
  if (rc!=LDAP_SUCCESS)
  {
    prtmsg("Failed to connect or authenticate to ldap for %s: %s%s%s", LDAP_URI,
	   ldap_err2string(rc),(errno==0)?"":": ",
	   (errno==0)?"":strerror(errno));
    goto freeall;
  }

  tv.tv_sec=30;
  tv.tv_usec=0;
  rc = ldap_search_ext_s(l, rekey_admin_group, LDAP_SCOPE_BASE, NO_FILTER,
			 no_attrs, 0, NULL, NULL, &tv, LDAP_NO_LIMIT, &response);
  if (rc != LDAP_SUCCESS) {
      prtmsg("Failed to verify group %s existence (searching): %s%s%s", rekey_admin_group,
	   ldap_err2string(rc),(errno==0)?"":": ",
	   (errno==0)?"":strerror(errno));
      goto freeall;
  }

  reason=aasprintf("verify group %s existence", rekey_admin_group);
  if (!verify_op_success(l, reason, response))
    goto freeall;
  ldap_msgfree(response);
  response=NULL;

  filter=aasprintf(ldap_filter, username, rekey_admin_group);
  rc = ldap_search_ext_s(l, ldap_base, LDAP_SCOPE_SUB, filter,
			 no_attrs, 0, NULL, NULL, &tv, LDAP_NO_LIMIT, &response);
  if (rc != LDAP_SUCCESS) {
      prtmsg("Failed to check user %s admin permission (searching): %s%s%s", username,
	   ldap_err2string(rc),(errno==0)?"":": ",
	   (errno==0)?"":strerror(errno));
      goto freeall;
  }

  reason=aasprintf("check user %s admin permission", username);
  if (!verify_single_result(l, 0, reason, response))
    goto freeall;

  ret=1;
 freeall:
  ldap_msgfree(response);
  if (l)
    ldap_unbind_ext_s(l, NULL, NULL);
  free(username);
  return ret;
}
Esempio n. 21
0
DWORD
IDMLdapSaslBind(
    LDAP*        pLd                       /* IN     */
    )
{
    DWORD dwError = 0;
    DWORD dwCleanupError = 0;
    BOOLEAN bLocked = FALSE;
    PSTR  pszCachePath = NULL;

    if (!pLd)
    {
        dwError = ERROR_INVALID_PARAMETER;
        BAIL_ON_ERROR(dwError);
    }

    switch (IDMKrbGetState(pgIdmKrbContext))
    {
        case IDM_KRB_CONTEXT_STATE_INITIAL:

            dwError = IDMKrbDetermineJoinState(pgIdmKrbContext);
            BAIL_ON_ERROR(dwError);

        case IDM_KRB_CONTEXT_STATE_JOINED:

            dwError = IDMKrbRenewCredentials(pgIdmKrbContext);
            if (dwError)
            {
               // Refreshing credentials might fail if the system left
               // the domain or there were issues reaching the domain
               // controller.
               IDMKrbSetState(pgIdmKrbContext, IDM_KRB_CONTEXT_STATE_INITIAL);
            }
            BAIL_ON_ERROR(dwError);

            IDM_RWMUTEX_LOCK_SHARED(
                &pgIdmKrbContext->mutex_rw,
                bLocked,
                dwError);
            BAIL_ON_ERROR(dwError);

            dwError = LwKrb5SetThreadDefaultCachePath(
                            pgIdmKrbContext->pszCachePath,
                            &pszCachePath);
            BAIL_ON_ERROR(dwError);

            dwError = LwMapLdapErrorToLwError(
                        ldap_sasl_interactive_bind_s(
                            pLd,
                            NULL,
                            "GSSAPI",
                            NULL,
                            NULL,
                            LDAP_SASL_QUIET,
                            &IDMSASLInteraction,
                            NULL));
            BAIL_ON_ERROR(dwError);

            break;

        default:

            dwError = ERROR_INVALID_STATE;
            BAIL_ON_ERROR(dwError);

            break;
    }

cleanup:

    if (pszCachePath)
    {
        LwKrb5SetThreadDefaultCachePath(pszCachePath, NULL);

        LwFreeMemory(pszCachePath);
    }

    IDM_RWMUTEX_UNLOCK(&pgIdmKrbContext->mutex_rw, bLocked, dwCleanupError);
    if(!dwError)
    {
        dwError = dwCleanupError;
    }
    return dwError;

error:

    goto cleanup;
}
Esempio n. 22
0
/*
 * call-seq:
 * conn.sasl_bind(dn=nil, mech=nil, cred=nil, sctrls=nil, cctrls=nil, sasl_options=nil)  => self
 * conn.sasl_bind(dn=nil, mech=nil, cred=nil, sctrls=nil, cctrls=nil, sasl_options=nil)
 *   { |conn| }  => nil
 *
 * Bind an LDAP connection, using the DN, +dn+, the mechanism, +mech+, and the
 * credential, +cred+.
 *
 * +sctrls+ is an array of server controls, whilst +cctrls+ is an array of
 * client controls.
 *
 * sasl_options is a hash which should have the following keys:
 *
 * - +:authcid+ and +:authzid+ for alternate SASL authentication
 * - +realm+ to specify the SASL realm
 *
 * If a block is given, +self+ is yielded to the block.
 */
VALUE
rb_ldap_conn_sasl_bind (int argc, VALUE argv[], VALUE self)
{
  RB_LDAP_DATA *ldapdata;

  VALUE arg1, arg2, arg3, arg4, arg5, sasl_options = Qnil;
  int version;
  char *dn = NULL;
  char *mechanism = NULL;
  struct berval *cred = ALLOCA_N (struct berval, 1);
  LDAPControl **serverctrls = NULL;
  LDAPControl **clientctrls = NULL;

  /*
  struct berval *servercred = NULL;
  char *sasl_realm = NULL;
  char *sasl_authc_id = NULL;
  char *sasl_authz_id = NULL;
  char *sasl_secprops = NULL;
  struct berval passwd = { 0, NULL };
  */

  unsigned sasl_flags = LDAP_SASL_AUTOMATIC;

  Data_Get_Struct (self, RB_LDAP_DATA, ldapdata);
  if (!ldapdata->ldap)
    {
      if (rb_iv_get (self, "@args") != Qnil)
	{
	  rb_ldap_conn_rebind (self);
	  GET_LDAP_DATA (self, ldapdata);
	}
      else
	{
	  rb_raise (rb_eLDAP_InvalidDataError,
		    "The LDAP handler has already unbound.");
	}
    }

  if (ldapdata->bind)
    {
      rb_raise (rb_eLDAP_Error, "already bound.");
    };

  switch (rb_scan_args (argc, argv, "24", &arg1, &arg2, &arg3, &arg4, &arg5, &sasl_options))
    {
    case 6:
      /* nothing. this requires credentials to be parsed first. we'll get defaults after arg-scanning */
    case 5:
      if(!NIL_P(arg5))
        clientctrls = rb_ldap_get_controls (arg5);
      /* down seems more likely */
    case 4:
      if(!NIL_P(arg4))
        serverctrls = rb_ldap_get_controls (arg4);
      /* down seems more likely */
    case 3:
      if(!NIL_P(arg3))
        {
          cred->bv_val = StringValueCStr (arg3);
          cred->bv_len = RSTRING_LEN (arg3);
        }
      /* down seems more likely */
    case 2:			/* don't need the cred for GSSAPI */
      dn = StringValuePtr (arg1);
      mechanism = StringValuePtr (arg2);
      if (rb_iv_get (self, "@sasl_quiet") == Qtrue)
        sasl_flags = LDAP_SASL_QUIET;
      break;
    default:
      rb_bug ("rb_ldap_conn_bind_s");
    }

  ldap_get_option (ldapdata->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
  if (version < LDAP_VERSION3)
    {
      version = LDAP_VERSION3;
      ldapdata->err =
	ldap_set_option (ldapdata->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
      Check_LDAP_Result (ldapdata->err);
    }

  /* the following works for GSSAPI, at least */
  ldapdata->err =
    ldap_sasl_interactive_bind_s (ldapdata->ldap, dn, mechanism,
				  serverctrls, clientctrls, sasl_flags,
				  rb_ldap_sasl_interaction, (void*)sasl_options);

  if (ldapdata->err == LDAP_SASL_BIND_IN_PROGRESS)
    {
      rb_raise (rb_eNotImpError,
		"SASL authentication is not fully supported.");
      /* How can I implement this with portability? */
      /* 
         VALUE scred;
	 scred = rb_tainted_str_new(servercred->bv_val,
         servercred->bv_len);
      */
    }
  else
    {
      Check_LDAP_Result (ldapdata->err);
      ldapdata->bind = 1;
    }

  if (rb_block_given_p ())
    {
      rb_ensure (rb_yield, self, rb_ldap_conn_unbind, self);
      return Qnil;
    }
  else
    {
      return self;
    };
}
Esempio n. 23
0
void
tester_init_ld( LDAP **ldp, struct tester_conn_args *config, int flags )
{
	LDAP *ld;
	int rc, do_retry = config->retries;
	int version = LDAP_VERSION3;

retry:;
	ldap_initialize( &ld, config->uri );
	if ( ld == NULL ) {
		tester_perror( "ldap_initialize", NULL );
		exit( EXIT_FAILURE );
	}

	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
		config->chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );

	if ( !( flags & TESTER_INIT_ONLY ) ) {
		if ( config->authmethod == LDAP_AUTH_SASL ) {
#ifdef HAVE_CYRUS_SASL
			if ( config->secprops != NULL ) {
				rc = ldap_set_option( ld,
						LDAP_OPT_X_SASL_SECPROPS, config->secprops );

				if ( rc != LDAP_OPT_SUCCESS ) {
					tester_ldap_error( ld, "ldap_set_option(SECPROPS)", NULL );
					ldap_unbind_ext( ld, NULL, NULL );
					exit( EXIT_FAILURE );
				}
			}

			rc = ldap_sasl_interactive_bind_s( ld,
					config->binddn,
					config->mech,
					NULL, NULL,
					LDAP_SASL_QUIET,
					lutil_sasl_interact,
					config->defaults );
#else /* HAVE_CYRUS_SASL */
			/* caller shouldn't have allowed this */
			assert(0);
#endif
		} else if ( config->authmethod == LDAP_AUTH_SIMPLE ) {
			rc = ldap_sasl_bind_s( ld,
					config->binddn, LDAP_SASL_SIMPLE,
					&config->pass, NULL, NULL, NULL );
		}

		if ( rc != LDAP_SUCCESS ) {
			tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
			switch ( rc ) {
				case LDAP_BUSY:
				case LDAP_UNAVAILABLE:
					if ( do_retry > 0 ) {
						do_retry--;
						if ( config->delay > 0 ) {
							sleep( config->delay );
						}
						goto retry;
					}
			}
			ldap_unbind_ext( ld, NULL, NULL );
			exit( EXIT_FAILURE );
		}
	}

	*ldp = ld;
}
Esempio n. 24
0
static switch_xml_t xml_ldap_search(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params,
									void *user_data)
{
	xml_binding_t *binding = (xml_binding_t *) user_data;
	switch_event_header_t *hi;

	switch_xml_t xml = NULL, sub = NULL;

	struct ldap_c ldap_connection;
	struct ldap_c *ldap = &ldap_connection;

	int auth_method = LDAP_AUTH_SIMPLE;
	int desired_version = LDAP_VERSION3;
	xml_ldap_query_type_t query_type;
	char *dir_exten = NULL, *dir_domain = NULL;

	char *search_filter = NULL, *search_base = NULL;
	int off = 0, ret = 1;

	//char *buf;
	//buf = malloc(4096);


	if (!binding) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No bindings...sorry bud returning now\n");
		return NULL;
	}

	if (!strcmp(section, "configuration")) {
		query_type = XML_LDAP_CONFIG;
	} else if (!strcmp(section, "directory")) {
		query_type = XML_LDAP_DIRECTORY;
	} else if (!strcmp(section, "dialplan")) {
		query_type = XML_LDAP_DIALPLAN;
	} else if (!strcmp(section, "phrases")) {
		query_type = XML_LDAP_PHRASE;
	} else if (!strcmp(section, "languages")) {
		query_type = XML_LDAP_LANGUAGE;
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid section\n");
		return NULL;
	}

	if (params) {
		if ((hi = params->headers)) {
			for (; hi; hi = hi->next) {
				switch (query_type) {
				case XML_LDAP_CONFIG:
					break;

				case XML_LDAP_DIRECTORY:
					if (!strcmp(hi->name, "user")) {
						dir_exten = strdup(hi->value);
					} else if (!strcmp(hi->name, "domain")) {
						dir_domain = strdup(hi->value);
					}
					break;

				case XML_LDAP_DIALPLAN:
				case XML_LDAP_PHRASE:
				case XML_LDAP_LANGUAGE:
					break;
				}
			}
			switch (query_type) {
			case XML_LDAP_CONFIG:
				break;

			case XML_LDAP_DIRECTORY:
				if (dir_exten && dir_domain) {
					if ((xml = switch_xml_new("directory"))) {
						switch_xml_set_attr_d(xml, "type", "freeswitch/xml");

						if ((sub = switch_xml_add_child_d(xml, "section", off++))) {
							switch_xml_set_attr_d(sub, "name", "directory");
						}

						if ((sub = switch_xml_add_child_d(sub, "domain", off++))) {
							switch_xml_set_attr_d(sub, "name", dir_domain);
						}

						if ((sub = switch_xml_add_child_d(sub, "user", off++))) {
							switch_xml_set_attr_d(sub, "id", dir_exten);
						}

					}

					search_filter = switch_mprintf(binding->filter, dir_exten);
					search_base = switch_mprintf(binding->basedn, dir_domain);

					free(dir_exten);
					dir_exten = NULL;

					free(dir_domain);
					dir_domain = NULL;

				} else {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
									  "Something bad happened during the query construction phase likely exten(%s) or domain(%s) is null\n", dir_exten,
									  dir_domain);
					goto cleanup;
				}
				break;

			case XML_LDAP_DIALPLAN:
				if ((xml = switch_xml_new("document"))) {
					switch_xml_set_attr_d(xml, "type", "freeswitch/xml");

					if ((sub = switch_xml_add_child_d(xml, "section", off++))) {
						switch_xml_set_attr_d(sub, "name", "dialplan");
					}

					sub = switch_xml_add_child_d(xml, "context", off++);
				}

				break;

			case XML_LDAP_PHRASE:
			case XML_LDAP_LANGUAGE:
				break;
			}
		} else {
			goto cleanup;
		}
	}



	if ((ldap->ld = (LDAP *) ldap_init(binding->host, LDAP_PORT)) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to connect to ldap server.%s\n", binding->host);
		goto cleanup;
	}

	if (ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version) != LDAP_OPT_SUCCESS) {
		goto cleanup;
	}

	ldap_set_option(ldap->ld, LDAP_OPT_X_SASL_SECPROPS, &ldap->sp);



	if (binding->binddn) {
		if (ldap_bind_s(ldap->ld, binding->binddn, binding->bindpass, auth_method) != LDAP_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to bind to ldap server %s as %s\n", binding->host, binding->binddn);
			goto cleanup;
		}
	} else {
		if (ldap_sasl_interactive_bind_s
			(ldap->ld, NULL, binding->defaults->mech, NULL, NULL, (unsigned) (intptr_t) LDAP_SASL_SIMPLE, lutil_sasl_interact,
			 binding->defaults) != LDAP_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to sasl_bind to ldap server %s as %s\n", binding->host,
							  binding->defaults->authcid);
			goto cleanup;
		}
	}

	if (ldap_search_s(ldap->ld, search_base, LDAP_SCOPE_SUBTREE, search_filter, NULL, 0, &ldap->msg) != LDAP_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Query failed: -b \"%s\" \"%s\"\n", search_base, search_filter);
		goto cleanup;
	}

	if (ldap_count_entries(ldap->ld, ldap->msg) <= 0) {
		goto cleanup;
	}

	if (sub && xml_ldap_result(&ldap_connection, binding, &sub, &off, query_type) != SWITCH_STATUS_SUCCESS) {
		goto cleanup;
	}

	ret = 0;

  cleanup:
	if (ldap->msg) {
		ldap_msgfree(ldap->msg);
	}

	if (ldap->ld) {
		ldap_unbind_s(ldap->ld);
	}

	switch_safe_free(search_filter);
	switch_safe_free(search_base);

	//switch_xml_toxml_buf(xml,buf,0,0,1);
	//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Providing:\n%s\n", buf);

	if (ret) {
		switch_xml_free(xml);
		return NULL;
	}

	return xml;
}
Esempio n. 25
0
/*
 * meta_back_proxy_authz_cred()
 *
 * prepares credentials & method for meta_back_proxy_authz_bind();
 * or, if method is SASL, performs the SASL bind directly.
 */
int
meta_back_proxy_authz_cred(
	metaconn_t		*mc,
	int			candidate,
	Operation		*op,
	SlapReply		*rs,
	ldap_back_send_t	sendok,
	struct berval		*binddn,
	struct berval		*bindcred,
	int			*method )
{
	metainfo_t		*mi = (metainfo_t *)op->o_bd->be_private;
	metatarget_t		*mt = mi->mi_targets[ candidate ];
	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
	struct berval		ndn;
	int			dobind = 0;

	/* don't proxyAuthz if protocol is not LDAPv3 */
	switch ( mt->mt_version ) {
	case LDAP_VERSION3:
		break;

	case 0:
		if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
			break;
		}
		/* fall thru */

	default:
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		if ( sendok & LDAP_BACK_SENDERR ) {
			send_ldap_result( op, rs );
		}
		LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
		goto done;
	}

	if ( op->o_tag == LDAP_REQ_BIND ) {
		ndn = op->o_req_ndn;

	} else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
		ndn = op->o_conn->c_ndn;

	} else {
		ndn = op->o_ndn;
	}
	rs->sr_err = LDAP_SUCCESS;

	/*
	 * FIXME: we need to let clients use proxyAuthz
	 * otherwise we cannot do symmetric pools of servers;
	 * we have to live with the fact that a user can
	 * authorize itself as any ID that is allowed
	 * by the authzTo directive of the "proxyauthzdn".
	 */
	/*
	 * NOTE: current Proxy Authorization specification
	 * and implementation do not allow proxy authorization
	 * control to be provided with Bind requests
	 */
	/*
	 * if no bind took place yet, but the connection is bound
	 * and the "proxyauthzdn" is set, then bind as
	 * "proxyauthzdn" and explicitly add the proxyAuthz
	 * control to every operation with the dn bound
	 * to the connection as control value.
	 */

	/* bind as proxyauthzdn only if no idassert mode
	 * is requested, or if the client's identity
	 * is authorized */
	switch ( mt->mt_idassert_mode ) {
	case LDAP_BACK_IDASSERT_LEGACY:
		if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) {
			if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) && !BER_BVISEMPTY( &mt->mt_idassert_authcDN ) )
			{
				*binddn = mt->mt_idassert_authcDN;
				*bindcred = mt->mt_idassert_passwd;
				dobind = 1;
			}
		}
		break;

	default:
		/* NOTE: rootdn can always idassert */
		if ( BER_BVISNULL( &ndn )
			&& mt->mt_idassert_authz == NULL
			&& !( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) )
		{
			if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
				rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
				if ( sendok & LDAP_BACK_SENDERR ) {
					send_ldap_result( op, rs );
				}
				LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
				goto done;

			}

			rs->sr_err = LDAP_SUCCESS;
			*binddn = slap_empty_bv;
			*bindcred = slap_empty_bv;
			break;

		} else if ( mt->mt_idassert_authz && !be_isroot( op ) ) {
			struct berval authcDN;

			if ( BER_BVISNULL( &ndn ) ) {
				authcDN = slap_empty_bv;

			} else {
				authcDN = ndn;
			}
			rs->sr_err = slap_sasl_matches( op, mt->mt_idassert_authz,
					&authcDN, &authcDN );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
					if ( sendok & LDAP_BACK_SENDERR ) {
						send_ldap_result( op, rs );
					}
					LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
					goto done;
				}

				rs->sr_err = LDAP_SUCCESS;
				*binddn = slap_empty_bv;
				*bindcred = slap_empty_bv;
				break;
			}
		}

		*binddn = mt->mt_idassert_authcDN;
		*bindcred = mt->mt_idassert_passwd;
		dobind = 1;
		break;
	}

	if ( dobind && mt->mt_idassert_authmethod == LDAP_AUTH_SASL ) {
#ifdef HAVE_CYRUS_SASL
		void		*defaults = NULL;
		struct berval	authzID = BER_BVNULL;
		int		freeauthz = 0;

		/* if SASL supports native authz, prepare for it */
		if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) &&
				( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
		{
			switch ( mt->mt_idassert_mode ) {
			case LDAP_BACK_IDASSERT_OTHERID:
			case LDAP_BACK_IDASSERT_OTHERDN:
				authzID = mt->mt_idassert_authzID;
				break;

			case LDAP_BACK_IDASSERT_ANONYMOUS:
				BER_BVSTR( &authzID, "dn:" );
				break;

			case LDAP_BACK_IDASSERT_SELF:
				if ( BER_BVISNULL( &ndn ) ) {
					/* connection is not authc'd, so don't idassert */
					BER_BVSTR( &authzID, "dn:" );
					break;
				}
				authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
				authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx );
				memcpy( authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
				memcpy( authzID.bv_val + STRLENOF( "dn:" ),
						ndn.bv_val, ndn.bv_len + 1 );
				freeauthz = 1;
				break;

			default:
				break;
			}
		}

		if ( mt->mt_idassert_secprops != NULL ) {
			rs->sr_err = ldap_set_option( msc->msc_ld,
				LDAP_OPT_X_SASL_SECPROPS,
				(void *)mt->mt_idassert_secprops );

			if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
				rs->sr_err = LDAP_OTHER;
				if ( sendok & LDAP_BACK_SENDERR ) {
					send_ldap_result( op, rs );
				}
				LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
				goto done;
			}
		}

		defaults = lutil_sasl_defaults( msc->msc_ld,
				mt->mt_idassert_sasl_mech.bv_val,
				mt->mt_idassert_sasl_realm.bv_val,
				mt->mt_idassert_authcID.bv_val,
				mt->mt_idassert_passwd.bv_val,
				authzID.bv_val );
		if ( defaults == NULL ) {
			rs->sr_err = LDAP_OTHER;
			LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
			if ( sendok & LDAP_BACK_SENDERR ) {
				send_ldap_result( op, rs );
			}
			goto done;
		}

		rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val,
				mt->mt_idassert_sasl_mech.bv_val, NULL, NULL,
				LDAP_SASL_QUIET, lutil_sasl_interact,
				defaults );

		rs->sr_err = slap_map_api2result( rs );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
			if ( sendok & LDAP_BACK_SENDERR ) {
				send_ldap_result( op, rs );
			}

		} else {
			LDAP_BACK_CONN_ISBOUND_SET( msc );
		}

		lutil_sasl_freedefs( defaults );
		if ( freeauthz ) {
			slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
		}

		goto done;
#endif /* HAVE_CYRUS_SASL */
	}

	*method = mt->mt_idassert_authmethod;
	switch ( mt->mt_idassert_authmethod ) {
	case LDAP_AUTH_NONE:
		BER_BVSTR( binddn, "" );
		BER_BVSTR( bindcred, "" );
		/* fallthru */

	case LDAP_AUTH_SIMPLE:
		break;

	default:
		/* unsupported! */
		LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
		rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
		if ( sendok & LDAP_BACK_SENDERR ) {
			send_ldap_result( op, rs );
		}
		break;
	}

done:;

	if ( !BER_BVISEMPTY( binddn ) ) {
		LDAP_BACK_CONN_ISIDASSERT_SET( msc );
	}

	return rs->sr_err;
}
Esempio n. 26
0
static int ipa_ldap_bind(const char *ldap_uri, krb5_principal bind_princ,
                         const char *bind_dn, const char *bind_pw,
                         const char *mech, const char *ca_cert_file,
                         LDAP **_ld)
{
    char *msg = NULL;
    struct berval bv;
    LDAP *ld;
    int ret;

    /* TODO: support referrals ? */
    ret = ipa_ldap_init(&ld, ldap_uri);
    if (ret != LDAP_SUCCESS) {
        return ret;
    }

    if (ld == NULL) {
        fprintf(stderr, _("Unable to initialize ldap library!\n"));
        return LDAP_OPERATIONS_ERROR;
    }

    ret = ipa_tls_ssl_init(ld, ldap_uri, ca_cert_file);
    if (ret != LDAP_OPT_SUCCESS) {
        goto done;
    }

    if (bind_dn) {
        bv.bv_val = discard_const(bind_pw);
        bv.bv_len = strlen(bind_pw);

        ret = ldap_sasl_bind_s(ld, bind_dn, LDAP_SASL_SIMPLE,
                               &bv, NULL, NULL, NULL);
        if (ret != LDAP_SUCCESS) {
            fprintf(stderr, _("Simple bind failed\n"));
            goto done;
        }
    } else {
        if (strcmp(mech, LDAP_SASL_EXTERNAL) == 0) {
            ret = ldap_sasl_bind_s(ld, NULL, LDAP_SASL_EXTERNAL,
                                   NULL, NULL, NULL, NULL);
        } else {
            ret = ldap_sasl_interactive_bind_s(ld, NULL, LDAP_SASL_GSSAPI,
                                               NULL, NULL, LDAP_SASL_QUIET,
                                               ldap_sasl_interact, bind_princ);
        }

        if (ret != LDAP_SUCCESS) {
#ifdef LDAP_OPT_DIAGNOSTIC_MESSAGE
            ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg);
#endif
            fprintf(stderr, "SASL Bind failed %s (%d) %s!\n",
                            ldap_err2string(ret), ret, msg ? msg : "");
            goto done;
        }
    }

    ret = LDAP_SUCCESS;

done:
    if (ret != LDAP_SUCCESS) {
        if (ld) ldap_unbind_ext(ld, NULL, NULL);
    } else {
        *_ld = ld;
    }
    return ret;
}
Esempio n. 27
0
static int
libbalsa_address_book_ldap_open_connection(LibBalsaAddressBookLdap * ab)
{
    int result;
    static const int version = LDAP_VERSION3;
    gboolean v3_enabled;
    LibBalsaAddressBook *lbab = LIBBALSA_ADDRESS_BOOK(ab);

    g_return_val_if_fail(ab->host != NULL, FALSE);

    ldap_initialize(&ab->directory, ab->host);
    if (ab->directory == NULL) { /* very unlikely... */
        libbalsa_address_book_set_status(lbab, g_strdup("Host not found"));
	return LDAP_SERVER_DOWN;
    }
    /* ignore error if the V3 LDAP cannot be set */
    v3_enabled = 
        ldap_set_option(ab->directory, LDAP_OPT_PROTOCOL_VERSION, &version)
       == LDAP_OPT_SUCCESS;
    if(!v3_enabled) printf("Too old LDAP server - interaction may fail.\n");
    if(v3_enabled && ab->enable_tls) {
#ifdef HAVE_LDAP_TLS
        /* turn TLS on  but what if we have SSL already on? */
        result = ldap_start_tls_s(ab->directory, NULL, NULL);
        if(result != LDAP_SUCCESS) {
            ldap_unbind_ext(ab->directory, NULL, NULL);
            ab->directory = NULL;
            libbalsa_address_book_set_status
                (lbab, g_strdup(ldap_err2string(result)));
            return result;
        }
#else /* HAVE_LDAP_TLS */
     libbalsa_address_book_set_status(lbab,
                                      _("TLS requested but not compiled in"));
     return LDAP_INAPPRIOPRIATE_AUTH;
#endif /* HAVE_LDAP_TLS */
    }

#ifdef HAVE_CYRUS_SASL
    result = ldap_sasl_interactive_bind_s(ab->directory, ab->bind_dn, NULL,
                                          NULL, NULL,
                                          LDAP_SASL_QUIET, abl_interact, ab);
#else /* HAVE_CYRUS_SASL */
    {
     struct berval   cred;   
     cred.bv_val = ab->passwd;
     cred.bv_len = ab->passwd ? strlen(ab->passwd) : 0;
     result = ldap_sasl_bind_s(ab->directory, ab->bind_dn, NULL, &cred,
                              NULL, NULL, NULL);
    }
#endif /* HAVE_CYRUS_SASL */

    /* do not follow referrals (OpenLDAP binds anonymously here, which will usually
     * fail */
    if (result == LDAP_SUCCESS)
	result = ldap_set_option(ab->directory, LDAP_OPT_REFERRALS, (void *)LDAP_OPT_OFF);

    if (result != LDAP_SUCCESS) {
        libbalsa_address_book_set_status(lbab,
                                         g_strdup(ldap_err2string(result)));
	ldap_unbind_ext(ab->directory, NULL, NULL);
	ab->directory = NULL;
    }
    return result;
}