#include "lib/tls/tls.h"
#include "auth/auth.h"
+struct ldap_simple_creds {
+ const char *dn;
+ const char *pw;
+};
+
+NTSTATUS ldap_rebind(struct ldap_connection *conn)
+{
+ NTSTATUS status;
+ struct ldap_simple_creds *creds;
+
+ switch (conn->bind.type) {
+ case LDAP_BIND_SASL:
+ status = ldap_bind_sasl(conn, (struct cli_credentials *)conn->bind.creds);
+ break;
+
+ case LDAP_BIND_SIMPLE:
+ creds = (struct ldap_simple_creds *)conn->bind.creds;
+
+ if (creds == NULL) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ status = ldap_bind_simple(conn, creds->dn, creds->pw);
+ break;
+
+ default:
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return status;
+}
+
+
static struct ldap_message *new_ldap_simple_bind_msg(struct ldap_connection *conn,
const char *dn, const char *pw)
{
talloc_free(req);
+ if (NT_STATUS_IS_OK(status)) {
+ struct ldap_simple_creds *creds = talloc(conn, struct ldap_simple_creds);
+ if (creds == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ creds->dn = talloc_strdup(creds, dn);
+ creds->pw = talloc_strdup(creds, pw);
+ if (creds->dn == NULL || creds->pw == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ conn->bind.type = LDAP_BIND_SIMPLE;
+ conn->bind.creds = creds;
+ }
+
return status;
}
}
talloc_free(tmp_ctx);
+
+ if (NT_STATUS_IS_OK(status)) {
+ conn->bind.type = LDAP_BIND_SASL;
+ conn->bind.creds = creds;
+ }
+
return status;
failed:
#include "libcli/composite/composite.h"
#include "lib/stream/packet.h"
#include "auth/gensec/gensec.h"
+#include "system/time.h"
/*
/* set a reasonable request timeout */
conn->timeout = 60;
+ /* explicitly avoid reconnections by default */
+ conn->reconnect.max_retries = 0;
+
return conn;
}
-
/*
the connection is dead
*/
{
struct ldap_request *req;
+ /* return an error for any pending request ... */
while (conn->pending) {
req = conn->pending;
DLIST_REMOVE(req->conn->pending, req);
}
talloc_free(conn->tls);
+ talloc_free(conn->sock); /* this will also free event.fde */
+ talloc_free(conn->packet);
conn->tls = NULL;
+ conn->sock = NULL;
+ conn->event.fde = NULL;
+ conn->packet = NULL;
}
+static void ldap_reconnect(struct ldap_connection *conn);
+
/*
handle packet errors
*/
struct ldap_connection *conn = talloc_get_type(private_data,
struct ldap_connection);
ldap_connection_dead(conn);
+
+ /* but try to reconnect so that the ldb client can go on */
+ ldap_reconnect(conn);
}
struct composite_context *result, *ctx;
struct ldap_connect_state *state;
+ if (conn->reconnect.url == NULL) {
+ conn->reconnect.url = talloc_strdup(conn, url);
+ if (conn->reconnect.url == NULL) goto failed;
+ }
+
result = talloc_zero(NULL, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
return ldap_connect_recv(ctx);
}
+/* Actually this function is NOT ASYNC safe, FIXME? */
+static void ldap_reconnect(struct ldap_connection *conn)
+{
+ NTSTATUS status;
+ time_t now = time(NULL);
+
+ /* do we have set up reconnect ? */
+ if (conn->reconnect.max_retries == 0) return;
+
+ /* is the retry time expired ? */
+ if (now > conn->reconnect.previous + 30) {
+ conn->reconnect.retries = 0;
+ conn->reconnect.previous = now;
+ }
+
+ /* are we reconnectind too often and too fast? */
+ if (conn->reconnect.retries > conn->reconnect.max_retries) return;
+
+ /* keep track of the number of reconnections */
+ conn->reconnect.retries++;
+
+ /* reconnect */
+ status = ldap_connect(conn, conn->reconnect.url);
+ if ( ! NT_STATUS_IS_OK(status)) {
+ return;
+ }
+
+ /* rebind */
+ status = ldap_rebind(conn);
+ if ( ! NT_STATUS_IS_OK(status)) {
+ ldap_connection_dead(conn);
+ }
+}
+
/* destroy an open ldap request */
static int ldap_request_destructor(void *ptr)
{
struct ldap_message *msg)
{
struct ldap_request *req;
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+
+ req = talloc_zero(conn, struct ldap_request);
+ if (req == NULL) return NULL;
if (conn->tls == NULL) {
- return NULL;
+ status = NT_STATUS_INVALID_CONNECTION;
+ goto failed;
}
- req = talloc_zero(conn, struct ldap_request);
- if (req == NULL) goto failed;
-
req->state = LDAP_REQUEST_SEND;
req->conn = conn;
req->messageid = conn->next_messageid++;
return req;
failed:
- talloc_free(req);
- return NULL;
+ req->status = status;
+ req->state = LDAP_REQUEST_ERROR;
+ event_add_timed(conn->event.event_ctx, req, timeval_zero(),
+ ldap_request_complete, req);
+
+ return req;
}
*/
NTSTATUS ldap_request_wait(struct ldap_request *req)
{
- while (req->state != LDAP_REQUEST_DONE) {
+ while (req->state <= LDAP_REQUEST_DONE) {
if (event_loop_once(req->conn->event.event_ctx) != 0) {
req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
break;
NT_STATUS_HAVE_NO_MEMORY(req);
- while (req->state != LDAP_REQUEST_DONE && n >= req->num_replies) {
+ while (req->state <= LDAP_REQUEST_DONE && n >= req->num_replies) {
if (event_loop_once(req->conn->event.event_ctx) != 0) {
return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
}