*/
#include "includes.h"
-#include "libcli/util/asn_1.h"
-#include "lib/util/dlinklist.h"
-#include "lib/events/events.h"
+#include <tevent.h>
#include "lib/socket/socket.h"
+#include "../lib/util/asn1.h"
+#include "../lib/util/dlinklist.h"
#include "libcli/ldap/ldap.h"
+#include "libcli/ldap/ldap_proto.h"
#include "libcli/ldap/ldap_client.h"
#include "libcli/composite/composite.h"
#include "lib/stream/packet.h"
#include "auth/gensec/gensec.h"
#include "system/time.h"
#include "param/param.h"
-
+#include "libcli/resolve/resolve.h"
/**
create a new ldap_connection stucture. The event context is optional
*/
-struct ldap_connection *ldap4_new_connection(TALLOC_CTX *mem_ctx,
+_PUBLIC_ struct ldap_connection *ldap4_new_connection(TALLOC_CTX *mem_ctx,
struct loadparm_context *lp_ctx,
- struct event_context *ev)
+ struct tevent_context *ev)
{
struct ldap_connection *conn;
- conn = talloc_zero(mem_ctx, struct ldap_connection);
- if (conn == NULL) {
+ if (ev == NULL) {
return NULL;
}
- if (ev == NULL) {
- ev = event_context_init(conn);
- if (ev == NULL) {
- talloc_free(conn);
- return NULL;
- }
+ conn = talloc_zero(mem_ctx, struct ldap_connection);
+ if (conn == NULL) {
+ return NULL;
}
conn->next_messageid = 1;
{
struct ldap_request *req;
+ talloc_free(conn->sock); /* this will also free event.fde */
+ talloc_free(conn->packet);
+ conn->sock = NULL;
+ conn->event.fde = NULL;
+ conn->packet = NULL;
+
/* return an error for any pending request ... */
while (conn->pending) {
req = conn->pending;
req->async.fn(req);
}
}
-
- talloc_free(conn->sock); /* this will also free event.fde */
- talloc_free(conn->packet);
- conn->sock = NULL;
- conn->event.fde = NULL;
- conn->packet = NULL;
}
static void ldap_reconnect(struct ldap_connection *conn);
return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
}
- status = ldap_decode(asn1, msg);
+ status = ldap_decode(asn1, samba_ldap_control_handlers(), msg);
if (!NT_STATUS_IS_OK(status)) {
asn1_free(asn1);
return status;
/*
handle ldap socket events
*/
-static void ldap_io_handler(struct event_context *ev, struct fd_event *fde,
+static void ldap_io_handler(struct tevent_context *ev, struct tevent_fd *fde,
uint16_t flags, void *private_data)
{
struct ldap_connection *conn = talloc_get_type(private_data,
struct ldap_connection);
- if (flags & EVENT_FD_WRITE) {
+ if (flags & TEVENT_FD_WRITE) {
packet_queue_run(conn->packet);
if (!tls_enabled(conn->sock)) return;
}
- if (flags & EVENT_FD_READ) {
+ if (flags & TEVENT_FD_READ) {
ldap_read_io_handler(private_data, flags);
}
}
static void ldap_connect_recv_unix_conn(struct composite_context *ctx);
static void ldap_connect_recv_tcp_conn(struct composite_context *ctx);
-struct composite_context *ldap_connect_send(struct ldap_connection *conn,
+_PUBLIC_ struct composite_context *ldap_connect_send(struct ldap_connection *conn,
const char *url)
{
struct composite_context *result, *ctx;
char protocol[11];
int ret;
- result = talloc_zero(NULL, struct composite_context);
+ result = talloc_zero(conn, struct composite_context);
if (result == NULL) goto failed;
result->state = COMPOSITE_STATE_IN_PROGRESS;
result->async.fn = NULL;
SMB_ASSERT(sizeof(protocol)>10);
SMB_ASSERT(sizeof(path)>1024);
+ /* LDAPI connections are to localhost, so give the
+ * local host name as the target for gensec's
+ * DIGEST-MD5 mechanism */
+ conn->host = talloc_asprintf(conn, "%s.%s", lp_netbios_name(conn->lp_ctx), lp_realm(conn->lp_ctx));
+ if (composite_nomem(conn->host, state->ctx)) {
+ return result;
+ }
+
/* The %c specifier doesn't null terminate :-( */
ZERO_STRUCT(path);
ret = sscanf(url, "%10[^:]://%1025c", protocol, path);
}
ctx = socket_connect_send(conn->sock, NULL, unix_addr,
- 0, lp_name_resolve_order(conn->lp_ctx), conn->event.event_ctx);
+ 0, conn->event.event_ctx);
ctx->async.fn = ldap_connect_recv_unix_conn;
ctx->async.private_data = state;
return result;
}
ctx = socket_connect_multi_send(state, conn->host, 1, &conn->port,
- lp_name_resolve_order(conn->lp_ctx), conn->event.event_ctx);
+ lp_resolve_context(conn->lp_ctx), conn->event.event_ctx);
if (ctx == NULL) goto failed;
ctx->async.fn = ldap_connect_recv_tcp_conn;
struct ldap_connection *conn)
{
/* setup a handler for events on this socket */
- conn->event.fde = event_add_fd(conn->event.event_ctx, conn->sock,
- socket_get_fd(conn->sock),
- EVENT_FD_READ | EVENT_FD_AUTOCLOSE, ldap_io_handler, conn);
+ conn->event.fde = tevent_add_fd(conn->event.event_ctx, conn->sock,
+ socket_get_fd(conn->sock),
+ TEVENT_FD_READ, ldap_io_handler, conn);
if (conn->event.fde == NULL) {
composite_error(ctx, NT_STATUS_INTERNAL_ERROR);
return;
}
+ tevent_fd_set_close_fn(conn->event.fde, socket_tevent_fd_close_fn);
socket_set_flags(conn->sock, SOCKET_FLAG_NOCLOSE);
talloc_steal(conn, conn->sock);
if (conn->ldaps) {
struct socket_context *tls_socket;
- char *cafile = private_path(conn->sock, conn->lp_ctx, lp_tls_cafile(conn->lp_ctx));
+ char *cafile = lp_tls_cafile(conn->sock, conn->lp_ctx);
if (!cafile || !*cafile) {
talloc_free(conn->sock);
talloc_free(conn->sock);
return;
}
- talloc_unlink(conn, conn->sock);
- conn->sock = tls_socket;
- talloc_steal(conn, conn->sock);
+
+ conn->sock = talloc_steal(conn, tls_socket);
}
conn->packet = packet_init(conn);
packet_set_error_handler(conn->packet, ldap_error_handler);
packet_set_event_context(conn->packet, conn->event.event_ctx);
packet_set_fde(conn->packet, conn->event.fde);
- packet_set_serialise(conn->packet);
+/* packet_set_serialise(conn->packet); */
+
+ if (conn->ldaps) {
+ packet_set_unreliable_select(conn->packet);
+ }
composite_done(ctx);
}
return status;
}
-NTSTATUS ldap_connect(struct ldap_connection *conn, const char *url)
+_PUBLIC_ NTSTATUS ldap_connect(struct ldap_connection *conn, const char *url)
{
struct composite_context *ctx = ldap_connect_send(conn, url);
return ldap_connect_recv(ctx);
/* set reconnect parameters */
-void ldap_set_reconn_params(struct ldap_connection *conn, int max_retries)
+_PUBLIC_ void ldap_set_reconn_params(struct ldap_connection *conn, int max_retries)
{
if (conn) {
conn->reconnect.max_retries = max_retries;
/*
called on timeout of a ldap request
*/
-static void ldap_request_timeout(struct event_context *ev, struct timed_event *te,
+static void ldap_request_timeout(struct tevent_context *ev, struct tevent_timer *te,
struct timeval t, void *private_data)
{
struct ldap_request *req = talloc_get_type(private_data, struct ldap_request);
/*
called on completion of a one-way ldap request
*/
-static void ldap_request_complete(struct event_context *ev, struct timed_event *te,
+static void ldap_request_complete(struct tevent_context *ev, struct tevent_timer *te,
struct timeval t, void *private_data)
{
struct ldap_request *req = talloc_get_type(private_data, struct ldap_request);
/*
send a ldap message - async interface
*/
-struct ldap_request *ldap_request_send(struct ldap_connection *conn,
+_PUBLIC_ struct ldap_request *ldap_request_send(struct ldap_connection *conn,
struct ldap_message *msg)
{
struct ldap_request *req;
msg->messageid = req->messageid;
- if (!ldap_encode(msg, &req->data, req)) {
+ if (!ldap_encode(msg, samba_ldap_control_handlers(), &req->data, req)) {
status = NT_STATUS_INTERNAL_ERROR;
goto failed;
}
req->state = LDAP_REQUEST_DONE;
/* we can't call the async callback now, as it isn't setup, so
call it as next event */
- event_add_timed(conn->event.event_ctx, req, timeval_zero(),
- ldap_request_complete, req);
+ tevent_add_timer(conn->event.event_ctx, req, timeval_zero(),
+ ldap_request_complete, req);
return req;
}
DLIST_ADD(conn->pending, req);
/* put a timeout on the request */
- req->time_event = event_add_timed(conn->event.event_ctx, req,
- timeval_current_ofs(conn->timeout, 0),
- ldap_request_timeout, req);
+ req->time_event = tevent_add_timer(conn->event.event_ctx, req,
+ timeval_current_ofs(conn->timeout, 0),
+ ldap_request_timeout, req);
return req;
failed:
req->status = status;
req->state = LDAP_REQUEST_ERROR;
- event_add_timed(conn->event.event_ctx, req, timeval_zero(),
- ldap_request_complete, req);
+ tevent_add_timer(conn->event.event_ctx, req, timeval_zero(),
+ ldap_request_complete, req);
return req;
}
wait for a request to complete
note that this does not destroy the request
*/
-NTSTATUS ldap_request_wait(struct ldap_request *req)
+_PUBLIC_ NTSTATUS ldap_request_wait(struct ldap_request *req)
{
while (req->state < LDAP_REQUEST_DONE) {
- if (event_loop_once(req->conn->event.event_ctx) != 0) {
+ if (tevent_loop_once(req->conn->event.event_ctx) != 0) {
req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
break;
}
/*
used to setup the status code from a ldap response
*/
-NTSTATUS ldap_check_response(struct ldap_connection *conn, struct ldap_Result *r)
+_PUBLIC_ NTSTATUS ldap_check_response(struct ldap_connection *conn, struct ldap_Result *r)
{
int i;
const char *codename = "unknown";
/*
return error string representing the last error
*/
-const char *ldap_errstr(struct ldap_connection *conn,
+_PUBLIC_ const char *ldap_errstr(struct ldap_connection *conn,
TALLOC_CTX *mem_ctx,
NTSTATUS status)
{
/*
return the Nth result message, waiting if necessary
*/
-NTSTATUS ldap_result_n(struct ldap_request *req, int n, struct ldap_message **msg)
+_PUBLIC_ NTSTATUS ldap_result_n(struct ldap_request *req, int n, struct ldap_message **msg)
{
*msg = NULL;
NT_STATUS_HAVE_NO_MEMORY(req);
while (req->state < LDAP_REQUEST_DONE && n >= req->num_replies) {
- if (event_loop_once(req->conn->event.event_ctx) != 0) {
+ if (tevent_loop_once(req->conn->event.event_ctx) != 0) {
return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
}
}
/*
return a single result message, checking if it is of the expected LDAP type
*/
-NTSTATUS ldap_result_one(struct ldap_request *req, struct ldap_message **msg, int type)
+_PUBLIC_ NTSTATUS ldap_result_one(struct ldap_request *req, struct ldap_message **msg, int type)
{
NTSTATUS status;
status = ldap_result_n(req, 0, msg);
a simple ldap transaction, for single result requests that only need a status code
this relies on single valued requests having the response type == request type + 1
*/
-NTSTATUS ldap_transaction(struct ldap_connection *conn, struct ldap_message *msg)
+_PUBLIC_ NTSTATUS ldap_transaction(struct ldap_connection *conn, struct ldap_message *msg)
{
struct ldap_request *req = ldap_request_send(conn, msg);
struct ldap_message *res;