char const *identity; //!< Bind identity for referral connection
char const *password; //!< Bind password for referral connecition
fr_ldap_thread_trunk_t *ttrunk; //!< Trunk this referral should use
+ request_t *request; //!< Request this referral relates to
} fr_ldap_referral_t;
/** Holds arguments for the async bind operation
/*
* referral.c - Handle LDAP referrals
*/
-fr_ldap_referral_t *fr_ldap_referral_alloc(TALLOC_CTX *ctx);
+fr_ldap_referral_t *fr_ldap_referral_alloc(TALLOC_CTX *ctx, request_t *request);
int fr_ldap_referral_follow(fr_ldap_thread_t *thread, request_t *request, fr_ldap_query_t *query);
PERROR("Bind as \"%s\" to \"%s\" not permitted",
*bind_ctx->bind_dn ? bind_ctx->bind_dn : "(anonymous)", c->config->server);
fr_ldap_state_error(c); /* Restart the connection state machine */
- break;
+ return;
default:
PERROR("Bind as \"%s\" to \"%s\" failed",
*bind_ctx->bind_dn ? bind_ctx->bind_dn : "(anonymous)", c->config->server);
fr_ldap_state_error(c); /* Restart the connection state machine */
- break;
+ return;
}
talloc_free(bind_ctx); /* Also removes fd events */
}
* - a new referral structure on success
* - NULL on failure
*/
-fr_ldap_referral_t *fr_ldap_referral_alloc(TALLOC_CTX *ctx)
+fr_ldap_referral_t *fr_ldap_referral_alloc(TALLOC_CTX *ctx, request_t *request)
{
fr_ldap_referral_t *referral;
PERROR("Failed to allocate LDAP referral container");
return NULL;
}
+ referral->request = request;
talloc_set_destructor(referral, _fr_ldap_referral_free);
return referral;
* Enqueue referral query on active trunk connection
*/
query->referral = referral;
- query->treq = fr_trunk_request_alloc(referral->ttrunk->trunk, NULL);
+ query->treq = fr_trunk_request_alloc(referral->ttrunk->trunk, referral->request);
fr_trunk_request_enqueue(&query->treq, referral->ttrunk->trunk, NULL, query, NULL);
DEBUG3("Pending LDAP referral query queued on active trunk");
continue;
}
- referral = fr_ldap_referral_alloc(query);
+ referral = fr_ldap_referral_alloc(query, request);
if (!referral) continue;
referral->query = query;
switch (cb_p->id) {
case SASL_CB_AUTHNAME:
cb_p->result = sasl_ctx->identity;
+ cb_p->len = strlen(sasl_ctx->identity);
break;
case SASL_CB_PASS:
cb_p->result = sasl_ctx->password;
+ cb_p->len = strlen(sasl_ctx->password);
break;
case SASL_CB_USER:
cb_p->result = sasl_ctx->proxy ? sasl_ctx->proxy : sasl_ctx->identity;
+ cb_p->len = sasl_ctx->proxy ? strlen(sasl_ctx->proxy) : strlen(sasl_ctx->identity);
break;
case SASL_CB_GETREALM:
cb_p->result = sasl_ctx->realm;
+ cb_p->len = strlen(sasl_ctx->realm);
break;
default:
fr_ldap_connection_t *c = sasl_ctx->c;
fr_ldap_rcode_t status;
+ /*
+ * Free the old result (if there is one)
+ */
+ if (sasl_ctx->result) {
+ ldap_msgfree(sasl_ctx->result);
+ sasl_ctx->result = NULL;
+ }
+
/*
* If LDAP parse result indicates there was an error
* then we're done.
struct berval *srv_cred;
int ret;
- /*
- * Free the old result (if there is one)
- */
- if (sasl_ctx->result) {
- ldap_msgfree(sasl_ctx->result);
- sasl_ctx->result = NULL;
- }
-
ret = ldap_parse_sasl_bind_result(c->handle, sasl_ctx->result, &srv_cred, 0);
if (ret != LDAP_SUCCESS) {
ERROR("SASL decode failed (bind failed): %s", ldap_err2string(ret));
}
DEBUG3("SASL response : %pV", fr_box_strvalue_len(srv_cred->bv_val, srv_cred->bv_len));
- ldap_memfree(srv_cred);
+ ber_bvfree(srv_cred);
/*
* If we need to continue, wait until the
NUM_ELEMENTS(our_clientctrls),
c, sasl_ctx->serverctrls, sasl_ctx->clientctrls);
- DEBUG2("Starting SASL mech(s): %s", sasl_ctx->mechs);
+ DEBUG2("%s SASL mech(s): %s", (sasl_ctx->result == NULL ? "Starting" : "Continuing"), sasl_ctx->mechs);
- /*
- * Set timeout to be 0.0, which is the magic
- * non-blocking value.
- */
- (void) ldap_set_option(c->handle, LDAP_OPT_NETWORK_TIMEOUT, &fr_time_delta_to_timeval(fr_time_delta_wrap(0)));
ret = ldap_sasl_interactive_bind(c->handle, NULL, sasl_ctx->mechs,
our_serverctrls, our_clientctrls,
LDAP_SASL_AUTOMATIC,
* Want to read more SASL stuff...
*/
case LDAP_SASL_BIND_IN_PROGRESS:
+ if (fd < 0) {
+ ret = ldap_get_option(c->handle, LDAP_OPT_DESC, &fd);
+ if ((ret != LDAP_OPT_SUCCESS) || (fd < 0)) goto error;
+ }
+ c->fd = fd;
ret = fr_event_fd_insert(sasl_ctx, el, fd,
_ldap_sasl_bind_io_read,
NULL,
el = c->conn->el;
- if (ldap_get_option(c->handle, LDAP_OPT_DESC, &fd) == LDAP_SUCCESS) {
+ /*
+ * ldap_get_option can return LDAP_SUCCESS even if the fd is not yet available
+ * - hence the test for fd >= 0
+ */
+ if ((ldap_get_option(c->handle, LDAP_OPT_DESC, &fd) == LDAP_SUCCESS) && (fd >= 0)){
int ret;
ret = fr_event_fd_insert(sasl_ctx, el, fd,
NUM_ELEMENTS(our_clientctrls),
c, tls_ctx->serverctrls, tls_ctx->clientctrls);
- /*
- * Set timeout to be 0.0, which is the magic
- * non-blocking value.
- */
- (void) ldap_set_option(c->handle, LDAP_OPT_NETWORK_TIMEOUT, &fr_time_delta_to_timeval(fr_time_delta_wrap(0)));
ret = ldap_start_tls(c->handle, our_serverctrls, our_clientctrls, &tls_ctx->msgid);
/*
* If the handle was not connected, this operation
break;
case LDAP_SUCCESS:
+ if (fd < 0) {
+ ret = ldap_get_option(c->handle, LDAP_OPT_DESC, &fd);
+ if ((ret != LDAP_OPT_SUCCESS) || (fd < 0)) goto error;
+ }
+ c->fd = fd;
ret = fr_event_fd_insert(tls_ctx, el, fd,
_ldap_start_tls_io_read,
NULL,
el = c->conn->el;
- if (ldap_get_option(c->handle, LDAP_OPT_DESC, &fd) == LDAP_SUCCESS) {
+ /*
+ * ldap_get_option can return LDAP_SUCCESS even if the fd is not yet available
+ * - hence the test for fd >= 0
+ */
+ if ((ldap_get_option(c->handle, LDAP_OPT_DESC, &fd) == LDAP_SUCCESS) && (fd >= 0)) {
int ret;
ret = fr_event_fd_insert(tls_ctx, el, fd,