summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/cldap_server/cldap_server.c96
-rw-r--r--source4/cldap_server/netlogon.c23
-rw-r--r--source4/cldap_server/rootdse.c13
-rw-r--r--source4/libcli/cldap/cldap.c1147
-rw-r--r--source4/libcli/cldap/cldap.h139
-rw-r--r--source4/libcli/config.mk2
-rw-r--r--source4/libnet/libnet_become_dc.c24
-rw-r--r--source4/libnet/libnet_site.c10
-rw-r--r--source4/libnet/libnet_unbecome_dc.c24
-rw-r--r--source4/torture/ldap/cldap.c75
-rw-r--r--source4/torture/ldap/cldapbench.c46
-rw-r--r--source4/torture/rpc/dssync.c9
12 files changed, 1002 insertions, 606 deletions
diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c
index 240f2b1dc23..1a08cd21f90 100644
--- a/source4/cldap_server/cldap_server.c
+++ b/source4/cldap_server/cldap_server.c
@@ -20,8 +20,8 @@
*/
#include "includes.h"
+#include <talloc.h>
#include "libcli/ldap/ldap.h"
-#include "lib/socket/socket.h"
#include "lib/messaging/irpc.h"
#include "smbd/service_task.h"
#include "smbd/service.h"
@@ -34,50 +34,67 @@
#include "ldb_wrap.h"
#include "auth/auth.h"
#include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
/*
handle incoming cldap requests
*/
-static void cldapd_request_handler(struct cldap_socket *cldap,
- struct ldap_message *ldap_msg,
- struct socket_address *src)
+static void cldapd_request_handler(struct cldap_socket *cldap,
+ void *private_data,
+ struct cldap_incoming *in)
{
+ struct cldapd_server *cldapd = talloc_get_type(private_data,
+ struct cldapd_server);
struct ldap_SearchRequest *search;
- if (ldap_msg->type != LDAP_TAG_SearchRequest) {
- DEBUG(0,("Invalid CLDAP request type %d from %s:%d\n",
- ldap_msg->type, src->addr, src->port));
- cldap_error_reply(cldap, ldap_msg->messageid, src,
+
+ if (in->ldap_msg->type != LDAP_TAG_SearchRequest) {
+ DEBUG(0,("Invalid CLDAP request type %d from %s\n",
+ in->ldap_msg->type,
+ tsocket_address_string(in->src, in)));
+ cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
LDAP_OPERATIONS_ERROR, "Invalid CLDAP request");
+ talloc_free(in);
return;
}
- search = &ldap_msg->r.SearchRequest;
+ search = &in->ldap_msg->r.SearchRequest;
if (strcmp("", search->basedn) != 0) {
- DEBUG(0,("Invalid CLDAP basedn '%s' from %s:%d\n",
- search->basedn, src->addr, src->port));
- cldap_error_reply(cldap, ldap_msg->messageid, src,
+ DEBUG(0,("Invalid CLDAP basedn '%s' from %s\n",
+ search->basedn,
+ tsocket_address_string(in->src, in)));
+ cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
LDAP_OPERATIONS_ERROR, "Invalid CLDAP basedn");
+ talloc_free(in);
return;
}
if (search->scope != LDAP_SEARCH_SCOPE_BASE) {
- DEBUG(0,("Invalid CLDAP scope %d from %s:%d\n",
- search->scope, src->addr, src->port));
- cldap_error_reply(cldap, ldap_msg->messageid, src,
+ DEBUG(0,("Invalid CLDAP scope %d from %s\n",
+ search->scope,
+ tsocket_address_string(in->src, in)));
+ cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
LDAP_OPERATIONS_ERROR, "Invalid CLDAP scope");
+ talloc_free(in);
return;
}
if (search->num_attributes == 1 &&
strcasecmp(search->attributes[0], "netlogon") == 0) {
- cldapd_netlogon_request(cldap, ldap_msg->messageid,
- search->tree, src);
+ cldapd_netlogon_request(cldap,
+ cldapd,
+ in,
+ in->ldap_msg->messageid,
+ search->tree,
+ in->src);
+ talloc_free(in);
return;
}
- cldapd_rootdse_request(cldap, ldap_msg->messageid,
- search, src);
+ cldapd_rootdse_request(cldap, cldapd, in,
+ in->ldap_msg->messageid,
+ search, in->src);
+ talloc_free(in);
}
@@ -88,28 +105,36 @@ static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_
const char *address)
{
struct cldap_socket *cldapsock;
- struct socket_address *socket_address;
+ struct tsocket_address *socket_address;
NTSTATUS status;
-
- /* listen for unicasts on the CLDAP port (389) */
- cldapsock = cldap_socket_init(cldapd, cldapd->task->event_ctx, lp_iconv_convenience(cldapd->task->lp_ctx));
- NT_STATUS_HAVE_NO_MEMORY(cldapsock);
-
- socket_address = socket_address_from_strings(cldapsock, cldapsock->sock->backend_name,
- address, lp_cldap_port(lp_ctx));
- if (!socket_address) {
- talloc_free(cldapsock);
- return NT_STATUS_NO_MEMORY;
+ int ret;
+
+ ret = tsocket_address_inet_from_strings(cldapd,
+ "ip",
+ address,
+ lp_cldap_port(lp_ctx),
+ &socket_address);
+ if (ret != 0) {
+ status = map_nt_error_from_unix(errno);
+ DEBUG(0,("invalid address %s:%d - %s:%s\n",
+ address, lp_cldap_port(lp_ctx),
+ gai_strerror(ret), nt_errstr(status)));
+ return status;
}
- status = socket_listen(cldapsock->sock, socket_address, 0, 0);
+ /* listen for unicasts on the CLDAP port (389) */
+ status = cldap_socket_init(cldapd,
+ cldapd->task->event_ctx,
+ socket_address,
+ NULL,
+ &cldapsock);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("Failed to bind to %s:%d - %s\n",
- address, lp_cldap_port(lp_ctx), nt_errstr(status)));
- talloc_free(cldapsock);
+ DEBUG(0,("Failed to bind to %s - %s\n",
+ tsocket_address_string(socket_address, socket_address),
+ nt_errstr(status)));
+ talloc_free(socket_address);
return status;
}
-
talloc_free(socket_address);
cldap_set_incoming_handler(cldapsock, cldapd_request_handler, cldapd);
@@ -117,7 +142,6 @@ static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_
return NT_STATUS_OK;
}
-
/*
setup our listening sockets on the configured network interfaces
*/
diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c
index 0df35be6fdd..33c0adc3b18 100644
--- a/source4/cldap_server/netlogon.c
+++ b/source4/cldap_server/netlogon.c
@@ -24,7 +24,6 @@
#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
#include "lib/events/events.h"
-#include "lib/socket/socket.h"
#include "smbd/service_task.h"
#include "cldap_server/cldap_server.h"
#include "librpc/gen_ndr/ndr_misc.h"
@@ -36,6 +35,8 @@
#include "system/network.h"
#include "lib/socket/netif.h"
#include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
+
/*
fill in the cldap netlogon union for a given version
*/
@@ -402,12 +403,13 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
/*
handle incoming cldap requests
*/
-void cldapd_netlogon_request(struct cldap_socket *cldap,
+void cldapd_netlogon_request(struct cldap_socket *cldap,
+ struct cldapd_server *cldapd,
+ TALLOC_CTX *tmp_ctx,
uint32_t message_id,
struct ldb_parse_tree *tree,
- struct socket_address *src)
+ struct tsocket_address *src)
{
- struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private_data, struct cldapd_server);
int i;
const char *domain = NULL;
const char *host = NULL;
@@ -419,8 +421,6 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
struct netlogon_samlogon_response netlogon;
NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
- TALLOC_CTX *tmp_ctx = talloc_new(cldap);
-
if (tree->operation != LDB_OP_AND) goto failed;
/* extract the query elements */
@@ -478,24 +478,25 @@ void cldapd_netlogon_request(struct cldap_socket *cldap,
domain, host, user, version, domain_guid));
status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, domain, NULL, NULL, domain_guid,
- user, acct_control, src->addr,
+ user, acct_control,
+ tsocket_address_inet_addr_string(src, tmp_ctx),
version, cldapd->task->lp_ctx, &netlogon);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
- status = cldap_netlogon_reply(cldap, message_id, src, version,
+ status = cldap_netlogon_reply(cldap,
+ lp_iconv_convenience(cldapd->task->lp_ctx),
+ message_id, src, version,
&netlogon);
if (!NT_STATUS_IS_OK(status)) {
goto failed;
}
- talloc_free(tmp_ctx);
return;
failed:
DEBUG(2,("cldap netlogon query failed domain=%s host=%s version=%d - %s\n",
domain, host, version, nt_errstr(status)));
- talloc_free(tmp_ctx);
- cldap_empty_reply(cldap, message_id, src);
+ cldap_empty_reply(cldap, message_id, src);
}
diff --git a/source4/cldap_server/rootdse.c b/source4/cldap_server/rootdse.c
index daa5060d07c..7e867deff29 100644
--- a/source4/cldap_server/rootdse.c
+++ b/source4/cldap_server/rootdse.c
@@ -20,19 +20,15 @@
*/
#include "includes.h"
+#include <tevent.h>
#include "libcli/ldap/ldap.h"
#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
-#include "lib/events/events.h"
-#include "lib/socket/socket.h"
#include "smbd/service_task.h"
#include "cldap_server/cldap_server.h"
#include "librpc/gen_ndr/ndr_misc.h"
#include "dsdb/samdb/samdb.h"
-#include "auth/auth.h"
#include "ldb_wrap.h"
-#include "system/network.h"
-#include "lib/socket/netif.h"
static void cldapd_rootdse_fill(struct cldapd_server *cldapd,
TALLOC_CTX *mem_ctx,
@@ -151,15 +147,15 @@ done:
handle incoming cldap requests
*/
void cldapd_rootdse_request(struct cldap_socket *cldap,
+ struct cldapd_server *cldapd,
+ TALLOC_CTX *tmp_ctx,
uint32_t message_id,
struct ldap_SearchRequest *search,
- struct socket_address *src)
+ struct tsocket_address *src)
{
- struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private_data, struct cldapd_server);
NTSTATUS status;
struct cldap_reply reply;
struct ldap_Result result;
- TALLOC_CTX *tmp_ctx = talloc_new(cldap);
ZERO_STRUCT(result);
@@ -176,6 +172,5 @@ void cldapd_rootdse_request(struct cldap_socket *cldap,
ldb_filter_from_tree(tmp_ctx, search->tree), nt_errstr(status)));
}
- talloc_free(tmp_ctx);
return;
}
diff --git a/source4/libcli/cldap/cldap.c b/source4/libcli/cldap/cldap.c
index b18ba12b1fc..0f2175b42dd 100644
--- a/source4/libcli/cldap/cldap.c
+++ b/source4/libcli/cldap/cldap.c
@@ -4,6 +4,7 @@
cldap client library
Copyright (C) Andrew Tridgell 2005
+ Copyright (C) Stefan Metzmacher 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -32,442 +33,708 @@
*/
#include "includes.h"
-#include "lib/events/events.h"
+#include <tevent.h>
#include "../lib/util/dlinklist.h"
#include "libcli/ldap/ldap.h"
#include "libcli/ldap/ldap_ndr.h"
#include "libcli/cldap/cldap.h"
-#include "lib/socket/socket.h"
+#include "../lib/tsocket/tsocket.h"
#include "libcli/security/security.h"
#include "librpc/gen_ndr/ndr_nbt.h"
+#include "../lib/util/asn1.h"
+#include "../lib/util/tevent_ntstatus.h"
/*
- destroy a pending request
+ context structure for operations on cldap packets
*/
-static int cldap_request_destructor(struct cldap_request *req)
+struct cldap_socket {
+ /* the low level socket */
+ struct tsocket_context *sock;
+
+ /*
+ * Are we in connected mode, which means
+ * we get ICMP errors back instead of timing
+ * out requests. And we can only send requests
+ * to the connected peer.
+ */
+ bool connected;
+
+ /*
+ * we allow sync requests only, if the caller
+ * did not pass an event context to cldap_socket_init()
+ */
+ struct {
+ bool allow_poll;
+ struct tevent_context *ctx;
+ } event;
+
+ /* the queue for outgoing dgrams */
+ struct tevent_queue *send_queue;
+
+ /* do we have an async tsocket_recvfrom request pending */
+ struct tevent_req *recv_subreq;
+
+ struct {
+ /* a queue of pending search requests */
+ struct cldap_search_state *list;
+
+ /* mapping from message_id to pending request */
+ struct idr_context *idr;
+ } searches;
+
+ /* what to do with incoming request packets */
+ struct {
+ void (*handler)(struct cldap_socket *,
+ void *private_data,
+ struct cldap_incoming *);
+ void *private_data;
+ } incoming;
+};
+
+struct cldap_search_state {
+ struct cldap_search_state *prev, *next;
+
+ struct {
+ struct cldap_socket *cldap;
+ } caller;
+
+ int message_id;
+
+ struct {
+ uint32_t idx;
+ uint32_t delay;
+ uint32_t count;
+ struct tsocket_address *dest;
+ DATA_BLOB blob;
+ } request;
+
+ struct {
+ struct cldap_incoming *in;
+ struct asn1_data *asn1;
+ } response;
+
+ struct tevent_req *req;
+};
+
+static int cldap_socket_destructor(struct cldap_socket *c)
{
- if (req->state == CLDAP_REQUEST_SEND) {
- DLIST_REMOVE(req->cldap->send_queue, req);
- }
- if (!req->is_reply && req->message_id != 0) {
- idr_remove(req->cldap->idr, req->message_id);
- req->message_id = 0;
+ tsocket_disconnect(c->sock);
+
+ while (c->searches.list) {
+ struct cldap_search_state *s = c->searches.list;
+ DLIST_REMOVE(c->searches.list, s);
+ ZERO_STRUCT(s->caller);
}
+
+ talloc_free(c->recv_subreq);
+ talloc_free(c->send_queue);
+ talloc_free(c->sock);
return 0;
}
-/*
- handle recv events on a cldap socket
-*/
-static void cldap_socket_recv(struct cldap_socket *cldap)
-{
- TALLOC_CTX *tmp_ctx = talloc_new(cldap);
- NTSTATUS status;
- struct socket_address *src;
- DATA_BLOB blob;
- size_t nread, dsize;
- struct asn1_data *asn1 = asn1_init(tmp_ctx);
- struct ldap_message *ldap_msg;
- struct cldap_request *req;
-
- if (!asn1) return;
+static void cldap_recvfrom_done(struct tevent_req *subreq);
- status = socket_pending(cldap->sock, &dsize);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return;
+static bool cldap_recvfrom_setup(struct cldap_socket *c)
+{
+ if (c->recv_subreq) {
+ return true;
}
- blob = data_blob_talloc(tmp_ctx, NULL, dsize);
- if (blob.data == NULL) {
- talloc_free(tmp_ctx);
- return;
+ if (!c->searches.list && !c->incoming.handler) {
+ return true;
}
- status = socket_recvfrom(cldap->sock, blob.data, blob.length, &nread,
- tmp_ctx, &src);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return;
+ c->recv_subreq = tsocket_recvfrom_send(c->sock, c);
+ if (!c->recv_subreq) {
+ return false;
}
- blob.length = nread;
+ tevent_req_set_callback(c->recv_subreq, cldap_recvfrom_done, c);
- DEBUG(2,("Received cldap packet of length %d from %s:%d\n",
- (int)blob.length, src->addr, src->port));
+ return true;
+}
- if (!asn1_load(asn1, blob)) {
- DEBUG(2,("Failed to setup for asn.1 decode\n"));
- talloc_free(tmp_ctx);
+static void cldap_recvfrom_stop(struct cldap_socket *c)
+{
+ if (!c->recv_subreq) {
return;
}
- ldap_msg = talloc(tmp_ctx, struct ldap_message);
- if (ldap_msg == NULL) {
- talloc_free(tmp_ctx);
+ if (c->searches.list || c->incoming.handler) {
return;
}
- /* this initial decode is used to find the message id */
- status = ldap_decode(asn1, NULL, ldap_msg);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(2,("Failed to decode ldap message: %s\n", nt_errstr(status)));
- talloc_free(tmp_ctx);
- return;
- }
-
- /* find the pending request */
- req = idr_find(cldap->idr, ldap_msg->messageid);
- if (req == NULL) {
- if (cldap->incoming.handler) {
- cldap->incoming.handler(cldap, ldap_msg, src);
- } else {
- DEBUG(2,("Mismatched cldap reply %u from %s:%d\n",
- ldap_msg->messageid, src->addr, src->port));
- }
- talloc_free(tmp_ctx);
- return;
- }
+ talloc_free(c->recv_subreq);
+ c->recv_subreq = NULL;
+}
- req->asn1 = talloc_steal(req, asn1);
- req->asn1->ofs = 0;
+static void cldap_socket_recv_dgram(struct cldap_socket *c,
+ struct cldap_incoming *in);
- req->state = CLDAP_REQUEST_DONE;
- talloc_free(req->te);
+static void cldap_recvfrom_done(struct tevent_req *subreq)
+{
+ struct cldap_socket *c = tevent_req_callback_data(subreq,
+ struct cldap_socket);
+ struct cldap_incoming *in = NULL;
+ ssize_t ret;
- talloc_free(tmp_ctx);
+ c->recv_subreq = NULL;
- if (req->async.fn) {
- req->async.fn(req);
+ in = talloc_zero(c, struct cldap_incoming);
+ if (!in) {
+ goto nomem;
}
-}
-
-/*
- handle request timeouts
-*/
-static void cldap_request_timeout(struct tevent_context *event_ctx,
- struct tevent_timer *te, struct timeval t,
- void *private_data)
-{
- struct cldap_request *req = talloc_get_type(private_data, struct cldap_request);
-
- /* possibly try again */
- if (req->num_retries != 0) {
- size_t len = req->encoded.length;
- req->num_retries--;
+ ret = tsocket_recvfrom_recv(subreq,
+ &in->recv_errno,
+ in,
+ &in->buf,
+ &in->src);
+ talloc_free(subreq);
+ subreq = NULL;
+ if (ret >= 0) {
+ in->len = ret;
+ }
+ if (ret == -1 && in->recv_errno == 0) {
+ in->recv_errno = EIO;
+ }
- socket_sendto(req->cldap->sock, &req->encoded, &len,
- req->dest);
+ /* this function should free or steal 'in' */
+ cldap_socket_recv_dgram(c, in);
+ in = NULL;
- req->te = event_add_timed(req->cldap->event_ctx, req,
- timeval_current_ofs(req->timeout, 0),
- cldap_request_timeout, req);
- return;
+ if (!cldap_recvfrom_setup(c)) {
+ goto nomem;
}
- req->state = CLDAP_REQUEST_ERROR;
- req->status = NT_STATUS_IO_TIMEOUT;
- if (req->async.fn) {
- req->async.fn(req);
- }
+ return;
+
+nomem:
+ talloc_free(subreq);
+ talloc_free(in);
+ /*TODO: call a dead socket handler */
+ return;
}
/*
- handle send events on a cldap socket
+ handle recv events on a cldap socket
*/
-static void cldap_socket_send(struct cldap_socket *cldap)
+static void cldap_socket_recv_dgram(struct cldap_socket *c,
+ struct cldap_incoming *in)
{
- struct cldap_request *req;
+ DATA_BLOB blob;
+ struct asn1_data *asn1;
+ void *p;
+ struct cldap_search_state *search;
NTSTATUS status;
- while ((req = cldap->send_queue)) {
- size_t len;
-
- len = req->encoded.length;
- status = socket_sendto(cldap->sock, &req->encoded, &len,
- req->dest);
- if (NT_STATUS_IS_ERR(status)) {
- DEBUG(0,("Failed to send cldap request of length %u to %s:%d\n",
- (unsigned)req->encoded.length, req->dest->addr, req->dest->port));
- DLIST_REMOVE(cldap->send_queue, req);
- req->state = CLDAP_REQUEST_ERROR;
- req->status = status;
- if (req->async.fn) {
- req->async.fn(req);
- }
- continue;
- }
+ if (in->recv_errno != 0) {
+ goto error;
+ }
- if (!NT_STATUS_IS_OK(status)) return;
+ blob = data_blob_const(in->buf, in->len);
- DLIST_REMOVE(cldap->send_queue, req);
+ asn1 = asn1_init(in);
+ if (!asn1) {
+ goto nomem;
+ }
- if (req->is_reply) {
- talloc_free(req);
- } else {
- req->state = CLDAP_REQUEST_WAIT;
+ if (!asn1_load(asn1, blob)) {
+ goto nomem;
+ }
- req->te = event_add_timed(cldap->event_ctx, req,
- timeval_current_ofs(req->timeout, 0),
- cldap_request_timeout, req);
+ in->ldap_msg = talloc(in, struct ldap_message);
+ if (in->ldap_msg == NULL) {
+ goto nomem;
+ }
- EVENT_FD_READABLE(cldap->fde);
- }
+ /* this initial decode is used to find the message id */
+ status = ldap_decode(asn1, NULL, in->ldap_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto nterror;
}
- EVENT_FD_NOT_WRITEABLE(cldap->fde);
- return;
-}
+ /* find the pending request */
+ p = idr_find(c->searches.idr, in->ldap_msg->messageid);
+ if (p == NULL) {
+ if (!c->incoming.handler) {
+ goto done;
+ }
+ /* this function should free or steal 'in' */
+ c->incoming.handler(c, c->incoming.private_data, in);
+ return;
+ }
-/*
- handle fd events on a cldap_socket
-*/
-static void cldap_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
- uint16_t flags, void *private_data)
-{
- struct cldap_socket *cldap = talloc_get_type(private_data, struct cldap_socket);
- if (flags & EVENT_FD_WRITE) {
- cldap_socket_send(cldap);
- }
- if (flags & EVENT_FD_READ) {
- cldap_socket_recv(cldap);
+ search = talloc_get_type(p, struct cldap_search_state);
+ search->response.in = talloc_move(search, &in);
+ search->response.asn1 = asn1;
+ search->response.asn1->ofs = 0;
+
+ tevent_req_done(search->req);
+ goto done;
+
+nomem:
+ in->recv_errno = ENOMEM;
+error:
+ status = map_nt_error_from_unix(in->recv_errno);
+nterror:
+ /* in connected mode the first pending search gets the error */
+ if (!c->connected) {
+ /* otherwise we just ignore the error */
+ goto done;
}
+ if (!c->searches.list) {
+ goto done;
+ }
+ tevent_req_nterror(c->searches.list->req, status);
+done:
+ talloc_free(in);
}
/*
- initialise a cldap_socket. The event_ctx is optional, if provided
- then operations will use that event context
+ initialise a cldap_sock
*/
-struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *event_ctx,
- struct smb_iconv_convenience *iconv_convenience)
+NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct tsocket_address *local_addr,
+ const struct tsocket_address *remote_addr,
+ struct cldap_socket **_cldap)
{
- struct cldap_socket *cldap;
+ struct cldap_socket *c = NULL;
+ struct tsocket_address *any = NULL;
NTSTATUS status;
+ int ret;
- cldap = talloc(mem_ctx, struct cldap_socket);
- if (cldap == NULL) goto failed;
+ c = talloc_zero(mem_ctx, struct cldap_socket);
+ if (!c) {
+ goto nomem;
+ }
- cldap->event_ctx = talloc_reference(cldap, event_ctx);
- if (cldap->event_ctx == NULL) goto failed;
+ if (!ev) {
+ ev = tevent_context_init(c);
+ if (!ev) {
+ goto nomem;
+ }
+ c->event.allow_poll = true;
+ }
+ c->event.ctx = ev;
+
+ if (!local_addr) {
+ ret = tsocket_address_inet_from_strings(c, "ipv4",
+ NULL, 0,
+ &any);
+ if (ret != 0) {
+ status = map_nt_error_from_unix(errno);
+ goto nterror;
+ }
+ local_addr = any;
+ }
- cldap->idr = idr_init(cldap);
- if (cldap->idr == NULL) goto failed;
+ c->searches.idr = idr_init(c);
+ if (!c->searches.idr) {
+ goto nomem;
+ }
- status = socket_create("ip", SOCKET_TYPE_DGRAM, &cldap->sock, 0);
- if (!NT_STATUS_IS_OK(status)) goto failed;
+ ret = tsocket_address_create_socket(local_addr,
+ TSOCKET_TYPE_DGRAM,
+ c, &c->sock);
+ if (ret != 0) {
+ status = map_nt_error_from_unix(errno);
+ goto nterror;
+ }
+ talloc_free(any);
- talloc_steal(cldap, cldap->sock);
+ tsocket_set_event_context(c->sock, c->event.ctx);
- cldap->fde = event_add_fd(cldap->event_ctx, cldap,
- socket_get_fd(cldap->sock), 0,
- cldap_socket_handler, cldap);
+ if (remote_addr) {
+ ret = tsocket_connect(c->sock, remote_addr);
+ if (ret != 0) {
+ status = map_nt_error_from_unix(errno);
+ goto nterror;
+ }
+ c->connected = true;
+ }
- cldap->send_queue = NULL;
- cldap->incoming.handler = NULL;
- cldap->iconv_convenience = iconv_convenience;
-
- return cldap;
+ c->send_queue = tevent_queue_create(c, "cldap_send_queue");
+ if (!c->send_queue) {
+ goto nomem;
+ }
-failed:
- talloc_free(cldap);
- return NULL;
-}
+ talloc_set_destructor(c, cldap_socket_destructor);
+
+ *_cldap = c;
+ return NT_STATUS_OK;
+nomem:
+ status = NT_STATUS_NO_MEMORY;
+nterror:
+ talloc_free(c);
+ return status;
+}
/*
setup a handler for incoming requests
*/
-NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap,
- void (*handler)(struct cldap_socket *, struct ldap_message *,
- struct socket_address *),
- void *private_data)
+NTSTATUS cldap_set_incoming_handler(struct cldap_socket *c,
+ void (*handler)(struct cldap_socket *,
+ void *private_data,
+ struct cldap_incoming *),
+ void *private_data)
{
- cldap->incoming.handler = handler;
- cldap->incoming.private_data = private_data;
- EVENT_FD_READABLE(cldap->fde);
+ if (c->connected) {
+ return NT_STATUS_PIPE_CONNECTED;
+ }
+
+ /* if sync requests are allowed, we don't allow an incoming handler */
+ if (c->event.allow_poll) {
+ return NT_STATUS_INVALID_PIPE_STATE;
+ }
+
+ c->incoming.handler = handler;
+ c->incoming.private_data = private_data;
+
+ if (!cldap_recvfrom_setup(c)) {
+ ZERO_STRUCT(c->incoming);
+ return NT_STATUS_NO_MEMORY;
+ }
+
return NT_STATUS_OK;
}
+struct cldap_reply_state {
+ struct tsocket_address *dest;
+ DATA_BLOB blob;
+};
+
+static void cldap_reply_state_destroy(struct tevent_req *req);
+
/*
- queue a cldap request for send
+ queue a cldap reply for send
*/
-struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
- struct cldap_search *io)
+NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
{
+ struct cldap_reply_state *state = NULL;
struct ldap_message *msg;
- struct cldap_request *req;
- struct ldap_SearchRequest *search;
+ DATA_BLOB blob1, blob2;
+ NTSTATUS status;
+ struct tevent_req *req;
- req = talloc_zero(cldap, struct cldap_request);
- if (req == NULL) goto failed;
+ if (cldap->connected) {
+ return NT_STATUS_PIPE_CONNECTED;
+ }
- req->cldap = cldap;
- req->state = CLDAP_REQUEST_SEND;
- req->timeout = io->in.timeout;
- req->num_retries = io->in.retries;
- req->is_reply = false;
- req->asn1 = asn1_init(req);
- if (!req->asn1) {
- goto failed;
+ if (!io->dest) {
+ return NT_STATUS_INVALID_ADDRESS;
}
- req->dest = socket_address_from_strings(req, cldap->sock->backend_name,
- io->in.dest_address,
- io->in.dest_port);
- if (!req->dest) goto failed;
+ state = talloc(cldap, struct cldap_reply_state);
+ NT_STATUS_HAVE_NO_MEMORY(state);
- req->message_id = idr_get_new_random(cldap->idr, req, UINT16_MAX);
- if (req->message_id == -1) goto failed;
+ state->dest = tsocket_address_copy(io->dest, state);
+ if (!state->dest) {
+ goto nomem;
+ }
- talloc_set_destructor(req, cldap_request_destructor);
+ msg = talloc(state, struct ldap_message);
+ if (!msg) {
+ goto nomem;
+ }
- msg = talloc(req, struct ldap_message);
- if (msg == NULL) goto failed;
- msg->messageid = req->message_id;
- msg->type = LDAP_TAG_SearchRequest;
+ msg->messageid = io->messageid;
msg->controls = NULL;
- search = &msg->r.SearchRequest;
- search->basedn = "";
- search->scope = LDAP_SEARCH_SCOPE_BASE;
- search->deref = LDAP_DEREFERENCE_NEVER;
- search->timelimit = 0;
- search->sizelimit = 0;
- search->attributesonly = false;
- search->num_attributes = str_list_length(io->in.attributes);
- search->attributes = io->in.attributes;
- search->tree = ldb_parse_tree(req, io->in.filter);
- if (search->tree == NULL) {
- goto failed;
+ if (io->response) {
+ msg->type = LDAP_TAG_SearchResultEntry;
+ msg->r.SearchResultEntry = *io->response;
+
+ if (!ldap_encode(msg, NULL, &blob1, state)) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto failed;
+ }
+ } else {
+ blob1 = data_blob(NULL, 0);
}
- if (!ldap_encode(msg, NULL, &req->encoded, req)) {
- DEBUG(0,("Failed to encode cldap message to %s:%d\n",
- req->dest->addr, req->dest->port));
+ msg->type = LDAP_TAG_SearchResultDone;
+ msg->r.SearchResultDone = *io->result;
+
+ if (!ldap_encode(msg, NULL, &blob2, state)) {
+ status = NT_STATUS_INVALID_PARAMETER;
goto failed;
}
+ talloc_free(msg);
- DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *);
+ state->blob = data_blob_talloc(state, NULL, blob1.length + blob2.length);
+ if (!state->blob.data) {
+ goto nomem;
+ }
- EVENT_FD_WRITEABLE(cldap->fde);
+ memcpy(state->blob.data, blob1.data, blob1.length);
+ memcpy(state->blob.data+blob1.length, blob2.data, blob2.length);
+ data_blob_free(&blob1);
+ data_blob_free(&blob2);
+
+ req = tsocket_sendto_queue_send(state,
+ cldap->sock,
+ cldap->send_queue,
+ state->blob.data,
+ state->blob.length,
+ state->dest);
+ if (!req) {
+ goto nomem;
+ }
+ /* the callback will just free the state, as we don't need a result */
+ tevent_req_set_callback(req, cldap_reply_state_destroy, state);
- return req;
+ return NT_STATUS_OK;
+nomem:
+ status = NT_STATUS_NO_MEMORY;
failed:
+ talloc_free(state);
+ return status;
+}
+
+static void cldap_reply_state_destroy(struct tevent_req *req)
+{
+ struct cldap_reply_state *state = tevent_req_callback_data(req,
+ struct cldap_reply_state);
+
+ /* we don't want to know the result here, we just free the state */
talloc_free(req);
- return NULL;
+ talloc_free(state);
+}
+
+static int cldap_search_state_destructor(struct cldap_search_state *s)
+{
+ if (s->caller.cldap) {
+ DLIST_REMOVE(s->caller.cldap->searches.list, s);
+ cldap_recvfrom_stop(s->caller.cldap);
+ ZERO_STRUCT(s->caller);
+ }
+
+ return 0;
}
+static void cldap_search_state_queue_done(struct tevent_req *subreq);
+static void cldap_search_state_wakeup_done(struct tevent_req *subreq);
/*
queue a cldap reply for send
*/
-NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
+struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx,
+ struct cldap_socket *cldap,
+ const struct cldap_search *io)
{
+ struct tevent_req *req, *subreq;
+ struct cldap_search_state *state = NULL;
struct ldap_message *msg;
- struct cldap_request *req;
- DATA_BLOB blob1, blob2;
- NTSTATUS status = NT_STATUS_NO_MEMORY;
+ struct ldap_SearchRequest *search;
+ struct timeval now;
+ struct timeval end;
+ uint32_t i;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct cldap_search_state);
+ if (!req) {
+ return NULL;
+ }
+ state->req = req;
+ state->caller.cldap = cldap;
+
+ if (io->in.dest_address) {
+ if (cldap->connected) {
+ tevent_req_nterror(req, NT_STATUS_PIPE_CONNECTED);
+ goto post;
+ }
+ ret = tsocket_address_inet_from_strings(state,
+ "ipv4",
+ io->in.dest_address,
+ io->in.dest_port,
+ &state->request.dest);
+ if (ret != 0) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ goto post;
+ }
+ } else {
+ if (!cldap->connected) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS);
+ goto post;
+ }
+ state->request.dest = NULL;
+ }
- req = talloc_zero(cldap, struct cldap_request);
- if (req == NULL) goto failed;
+ state->message_id = idr_get_new_random(cldap->searches.idr,
+ state, UINT16_MAX);
+ if (state->message_id == -1) {
+ tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
+ goto post;
+ }
- req->cldap = cldap;
- req->state = CLDAP_REQUEST_SEND;
- req->is_reply = true;
- req->asn1 = asn1_init(req);
- if (!req->asn1) {
- goto failed;
+ msg = talloc(state, struct ldap_message);
+ if (tevent_req_nomem(msg, req)) {
+ goto post;
}
- req->dest = io->dest;
- if (talloc_reference(req, io->dest) == NULL) goto failed;
+ msg->messageid = state->message_id;
+ msg->type = LDAP_TAG_SearchRequest;
+ msg->controls = NULL;
+ search = &msg->r.SearchRequest;
- talloc_set_destructor(req, cldap_request_destructor);
+ search->basedn = "";
+ search->scope = LDAP_SEARCH_SCOPE_BASE;
+ search->deref = LDAP_DEREFERENCE_NEVER;
+ search->timelimit = 0;
+ search->sizelimit = 0;
+ search->attributesonly = false;
+ search->num_attributes = str_list_length(io->in.attributes);
+ search->attributes = io->in.attributes;
+ search->tree = ldb_parse_tree(msg, io->in.filter);
+ if (tevent_req_nomem(search->tree, req)) {
+ goto post;
+ }
- msg = talloc(req, struct ldap_message);
- if (msg == NULL) goto failed;
- msg->messageid = io->messageid;
- msg->controls = NULL;
-
- if (io->response) {
- msg->type = LDAP_TAG_SearchResultEntry;
- msg->r.SearchResultEntry = *io->response;
+ if (!ldap_encode(msg, NULL, &state->request.blob, state)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ goto post;
+ }
+ talloc_free(msg);
+
+ state->request.idx = 0;
+ state->request.delay = 10*1000*1000;
+ state->request.count = 3;
+ if (io->in.timeout > 0) {
+ state->request.delay = io->in.timeout * 1000 * 1000;
+ state->request.count = io->in.retries + 1;
+ }
- if (!ldap_encode(msg, NULL, &blob1, req)) {
- DEBUG(0,("Failed to encode cldap message to %s:%d\n",
- req->dest->addr, req->dest->port));
- status = NT_STATUS_INVALID_PARAMETER;
- goto failed;
- }
- } else {
- blob1 = data_blob(NULL, 0);
+ now = tevent_timeval_current();
+ end = now;
+ for (i = 0; i < state->request.count; i++) {
+ end = tevent_timeval_add(&end, 0, state->request.delay);
}
- msg->type = LDAP_TAG_SearchResultDone;
- msg->r.SearchResultDone = *io->result;
+ if (!tevent_req_set_endtime(req, state->caller.cldap->event.ctx, end)) {
+ tevent_req_nomem(NULL, req);
+ goto post;
+ }
- if (!ldap_encode(msg, NULL, &blob2, req)) {
- DEBUG(0,("Failed to encode cldap message to %s:%d\n",
- req->dest->addr, req->dest->port));
- status = NT_STATUS_INVALID_PARAMETER;
- goto failed;
+ subreq = tsocket_sendto_queue_send(state,
+ state->caller.cldap->sock,
+ state->caller.cldap->send_queue,
+ state->request.blob.data,
+ state->request.blob.length,
+ state->request.dest);
+ if (tevent_req_nomem(subreq, req)) {
+ goto post;
}
+ tevent_req_set_callback(subreq, cldap_search_state_queue_done, req);
- req->encoded = data_blob_talloc(req, NULL, blob1.length + blob2.length);
- if (req->encoded.data == NULL) goto failed;
+ DLIST_ADD_END(cldap->searches.list, state, struct cldap_search_state *);
+ talloc_set_destructor(state, cldap_search_state_destructor);
- memcpy(req->encoded.data, blob1.data, blob1.length);
- memcpy(req->encoded.data+blob1.length, blob2.data, blob2.length);
+ return req;
- DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *);
+ post:
+ return tevent_req_post(req, cldap->event.ctx);
+}
- EVENT_FD_WRITEABLE(cldap->fde);
+static void cldap_search_state_queue_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct cldap_search_state *state = tevent_req_data(req,
+ struct cldap_search_state);
+ ssize_t ret;
+ int sys_errno = 0;
+ struct timeval next;
+
+ ret = tsocket_sendto_queue_recv(subreq, &sys_errno);
+ talloc_free(subreq);
+ if (ret == -1) {
+ NTSTATUS status;
+ status = map_nt_error_from_unix(sys_errno);
+ DLIST_REMOVE(state->caller.cldap->searches.list, state);
+ ZERO_STRUCT(state->caller.cldap);
+ tevent_req_nterror(req, status);
+ return;
+ }
- return NT_STATUS_OK;
+ state->request.idx++;
-failed:
- talloc_free(req);
- return status;
+ /* wait for incoming traffic */
+ if (!cldap_recvfrom_setup(state->caller.cldap)) {
+ tevent_req_nomem(NULL, req);
+ return;
+ }
+
+ if (state->request.idx > state->request.count) {
+ /* we just wait for the response or a timeout */
+ return;
+ }
+
+ next = tevent_timeval_current_ofs(0, state->request.delay);
+ subreq = tevent_wakeup_send(state,
+ state->caller.cldap->event.ctx,
+ next);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, cldap_search_state_wakeup_done, req);
+}
+
+static void cldap_search_state_wakeup_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct cldap_search_state *state = tevent_req_data(req,
+ struct cldap_search_state);
+ bool ok;
+
+ ok = tevent_wakeup_recv(subreq);
+ talloc_free(subreq);
+ if (!ok) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+
+ subreq = tsocket_sendto_queue_send(state,
+ state->caller.cldap->sock,
+ state->caller.cldap->send_queue,
+ state->request.blob.data,
+ state->request.blob.length,
+ state->request.dest);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, cldap_search_state_queue_done, req);
}
/*
receive a cldap reply
*/
-NTSTATUS cldap_search_recv(struct cldap_request *req,
- TALLOC_CTX *mem_ctx,
+NTSTATUS cldap_search_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx,
struct cldap_search *io)
{
+ struct cldap_search_state *state = tevent_req_data(req,
+ struct cldap_search_state);
struct ldap_message *ldap_msg;
NTSTATUS status;
- if (req == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- while (req->state < CLDAP_REQUEST_DONE) {
- if (event_loop_once(req->cldap->event_ctx) != 0) {
- talloc_free(req);
- return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
- }
- }
-
- if (req->state == CLDAP_REQUEST_ERROR) {
- status = req->status;
- talloc_free(req);
- return status;
+ if (tevent_req_is_nterror(req, &status)) {
+ goto failed;
}
ldap_msg = talloc(mem_ctx, struct ldap_message);
- NT_STATUS_HAVE_NO_MEMORY(ldap_msg);
+ if (!ldap_msg) {
+ goto nomem;
+ }
- status = ldap_decode(req->asn1, NULL, ldap_msg);
+ status = ldap_decode(state->response.asn1, NULL, ldap_msg);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(2,("Failed to decode cldap search reply: %s\n", nt_errstr(status)));
- talloc_free(req);
- return status;
+ goto failed;
}
ZERO_STRUCT(io->out);
@@ -475,167 +742,283 @@ NTSTATUS cldap_search_recv(struct cldap_request *req,
/* the first possible form has a search result in first place */
if (ldap_msg->type == LDAP_TAG_SearchResultEntry) {
io->out.response = talloc(mem_ctx, struct ldap_SearchResEntry);
- NT_STATUS_HAVE_NO_MEMORY(io->out.response);
+ if (!io->out.response) {
+ goto nomem;
+ }
*io->out.response = ldap_msg->r.SearchResultEntry;
/* decode the 2nd part */
- status = ldap_decode(req->asn1, NULL, ldap_msg);
+ status = ldap_decode(state->response.asn1, NULL, ldap_msg);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(2,("Failed to decode cldap search result entry: %s\n", nt_errstr(status)));
- talloc_free(req);
- return status;
+ goto failed;
}
}
if (ldap_msg->type != LDAP_TAG_SearchResultDone) {
- talloc_free(req);
- return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+ status = NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
+ goto failed;
}
io->out.result = talloc(mem_ctx, struct ldap_Result);
- NT_STATUS_HAVE_NO_MEMORY(io->out.result);
+ if (!io->out.result) {
+ goto nomem;
+ }
*io->out.result = ldap_msg->r.SearchResultDone;
- talloc_free(req);
-
if (io->out.result->resultcode != LDAP_SUCCESS) {
- return NT_STATUS_LDAP(io->out.result->resultcode);
+ status = NT_STATUS_LDAP(io->out.result->resultcode);
+ goto failed;
}
+
+ tevent_req_received(req);
return NT_STATUS_OK;
+
+nomem:
+ status = NT_STATUS_NO_MEMORY;
+failed:
+ tevent_req_received(req);
+ return status;
}
/*
synchronous cldap search
*/
-NTSTATUS cldap_search(struct cldap_socket *cldap,
- TALLOC_CTX *mem_ctx,
+NTSTATUS cldap_search(struct cldap_socket *cldap,
+ TALLOC_CTX *mem_ctx,
struct cldap_search *io)
{
- struct cldap_request *req = cldap_search_send(cldap, io);
- return cldap_search_recv(req, mem_ctx, io);
-}
+ struct tevent_req *req;
+ NTSTATUS status;
+
+ if (!cldap->event.allow_poll) {
+ return NT_STATUS_INVALID_PIPE_STATE;
+ }
+
+ if (cldap->searches.list) {
+ return NT_STATUS_PIPE_BUSY;
+ }
+ req = cldap_search_send(mem_ctx, cldap, io);
+ NT_STATUS_HAVE_NO_MEMORY(req);
+ if (!tevent_req_poll(req, cldap->event.ctx)) {
+ talloc_free(req);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ status = cldap_search_recv(req, mem_ctx, io);
+ talloc_free(req);
+
+ return status;
+}
+
+struct cldap_netlogon_state {
+ struct cldap_search search;
+};
+
+static void cldap_netlogon_state_done(struct tevent_req *subreq);
/*
queue a cldap netlogon for send
*/
-struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap,
- struct cldap_netlogon *io)
+struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx,
+ struct cldap_socket *cldap,
+ const struct cldap_netlogon *io)
{
- struct cldap_search search;
+ struct tevent_req *req, *subreq;
+ struct cldap_netlogon_state *state;
char *filter;
- struct cldap_request *req;
- const char *attr[] = { "NetLogon", NULL };
- TALLOC_CTX *tmp_ctx = talloc_new(cldap);
+ static const char * const attr[] = { "NetLogon", NULL };
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct cldap_netlogon_state);
+ if (!req) {
+ return NULL;
+ }
- filter = talloc_asprintf(tmp_ctx, "(&(NtVer=%s)",
- ldap_encode_ndr_uint32(tmp_ctx, io->in.version));
- if (filter == NULL) goto failed;
+ filter = talloc_asprintf(state, "(&(NtVer=%s)",
+ ldap_encode_ndr_uint32(state, io->in.version));
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
if (io->in.user) {
filter = talloc_asprintf_append_buffer(filter, "(User=%s)", io->in.user);
- if (filter == NULL) goto failed;
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
}
if (io->in.host) {
filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host);
- if (filter == NULL) goto failed;
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
}
if (io->in.realm) {
filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm);
- if (filter == NULL) goto failed;
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
}
if (io->in.acct_control != -1) {
filter = talloc_asprintf_append_buffer(filter, "(AAC=%s)",
- ldap_encode_ndr_uint32(tmp_ctx, io->in.acct_control));
- if (filter == NULL) goto failed;
+ ldap_encode_ndr_uint32(state, io->in.acct_control));
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
}
if (io->in.domain_sid) {
- struct dom_sid *sid = dom_sid_parse_talloc(tmp_ctx, io->in.domain_sid);
- if (sid == NULL) goto failed;
+ struct dom_sid *sid = dom_sid_parse_talloc(state, io->in.domain_sid);
+ if (tevent_req_nomem(sid, req)) {
+ goto post;
+ }
filter = talloc_asprintf_append_buffer(filter, "(domainSid=%s)",
- ldap_encode_ndr_dom_sid(tmp_ctx, sid));
- if (filter == NULL) goto failed;
+ ldap_encode_ndr_dom_sid(state, sid));
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
}
if (io->in.domain_guid) {
struct GUID guid;
NTSTATUS status;
status = GUID_from_string(io->in.domain_guid, &guid);
- if (!NT_STATUS_IS_OK(status)) goto failed;
+ if (tevent_req_nterror(req, status)) {
+ goto post;
+ }
filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)",
- ldap_encode_ndr_GUID(tmp_ctx, &guid));
- if (filter == NULL) goto failed;
+ ldap_encode_ndr_GUID(state, &guid));
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
}
filter = talloc_asprintf_append_buffer(filter, ")");
- if (filter == NULL) goto failed;
-
- search.in.dest_address = io->in.dest_address;
- search.in.dest_port = io->in.dest_port;
- search.in.filter = filter;
- search.in.attributes = attr;
- search.in.timeout = 2;
- search.in.retries = 2;
+ if (tevent_req_nomem(filter, req)) {
+ goto post;
+ }
- req = cldap_search_send(cldap, &search);
+ if (io->in.dest_address) {
+ state->search.in.dest_address = talloc_strdup(state,
+ io->in.dest_address);
+ if (tevent_req_nomem(state->search.in.dest_address, req)) {
+ goto post;
+ }
+ state->search.in.dest_port = io->in.dest_port;
+ } else {
+ state->search.in.dest_address = NULL;
+ state->search.in.dest_port = 0;
+ }
+ state->search.in.filter = filter;
+ state->search.in.attributes = attr;
+ state->search.in.timeout = 2;
+ state->search.in.retries = 2;
+
+ subreq = cldap_search_send(state, cldap, &state->search);
+ if (tevent_req_nomem(subreq, req)) {
+ goto post;
+ }
+ tevent_req_set_callback(subreq, cldap_netlogon_state_done, req);
- talloc_free(tmp_ctx);
return req;
-failed:
- talloc_free(tmp_ctx);
- return NULL;
+post:
+ return tevent_req_post(req, cldap->event.ctx);
}
+static void cldap_netlogon_state_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct cldap_netlogon_state *state = tevent_req_data(req,
+ struct cldap_netlogon_state);
+ NTSTATUS status;
+
+ status = cldap_search_recv(subreq, state, &state->search);
+ talloc_free(subreq);
+
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ tevent_req_done(req);
+}
/*
receive a cldap netlogon reply
*/
-NTSTATUS cldap_netlogon_recv(struct cldap_request *req,
- TALLOC_CTX *mem_ctx,
+NTSTATUS cldap_netlogon_recv(struct tevent_req *req,
+ struct smb_iconv_convenience *iconv_convenience,
+ TALLOC_CTX *mem_ctx,
struct cldap_netlogon *io)
{
+ struct cldap_netlogon_state *state = tevent_req_data(req,
+ struct cldap_netlogon_state);
NTSTATUS status;
- struct cldap_search search;
- struct cldap_socket *cldap;
DATA_BLOB *data;
- cldap = req->cldap;
-
- status = cldap_search_recv(req, mem_ctx, &search);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (tevent_req_is_nterror(req, &status)) {
+ goto failed;
}
- if (search.out.response == NULL) {
- return NT_STATUS_NOT_FOUND;
+
+ if (state->search.out.response == NULL) {
+ status = NT_STATUS_NOT_FOUND;
+ goto failed;
}
- if (search.out.response->num_attributes != 1 ||
- strcasecmp(search.out.response->attributes[0].name, "netlogon") != 0 ||
- search.out.response->attributes[0].num_values != 1 ||
- search.out.response->attributes[0].values->length < 2) {
- return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+ if (state->search.out.response->num_attributes != 1 ||
+ strcasecmp(state->search.out.response->attributes[0].name, "netlogon") != 0 ||
+ state->search.out.response->attributes[0].num_values != 1 ||
+ state->search.out.response->attributes[0].values->length < 2) {
+ status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+ goto failed;
}
- data = search.out.response->attributes[0].values;
+ data = state->search.out.response->attributes[0].values;
- status = pull_netlogon_samlogon_response(data, mem_ctx, req->cldap->iconv_convenience,
+ status = pull_netlogon_samlogon_response(data, mem_ctx,
+ iconv_convenience,
&io->out.netlogon);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ goto failed;
}
-
+
if (io->in.map_response) {
map_netlogon_samlogon_response(&io->out.netlogon);
}
- return NT_STATUS_OK;
+
+ status = NT_STATUS_OK;
+failed:
+ tevent_req_received(req);
+ return status;
}
/*
sync cldap netlogon search
*/
-NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
- TALLOC_CTX *mem_ctx, struct cldap_netlogon *io)
+NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
+ struct smb_iconv_convenience *iconv_convenience,
+ TALLOC_CTX *mem_ctx,
+ struct cldap_netlogon *io)
{
- struct cldap_request *req = cldap_netlogon_send(cldap, io);
- return cldap_netlogon_recv(req, mem_ctx, io);
+ struct tevent_req *req;
+ NTSTATUS status;
+
+ if (!cldap->event.allow_poll) {
+ return NT_STATUS_INVALID_PIPE_STATE;
+ }
+
+ if (cldap->searches.list) {
+ return NT_STATUS_PIPE_BUSY;
+ }
+
+ req = cldap_netlogon_send(mem_ctx, cldap, io);
+ NT_STATUS_HAVE_NO_MEMORY(req);
+
+ if (!tevent_req_poll(req, cldap->event.ctx)) {
+ talloc_free(req);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ status = cldap_netlogon_recv(req, iconv_convenience, mem_ctx, io);
+ talloc_free(req);
+
+ return status;
}
@@ -643,16 +1026,16 @@ NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
send an empty reply (used on any error, so the client doesn't keep waiting
or send the bad request again)
*/
-NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
+NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
uint32_t message_id,
- struct socket_address *src)
+ struct tsocket_address *dest)
{
NTSTATUS status;
struct cldap_reply reply;
struct ldap_Result result;
reply.messageid = message_id;
- reply.dest = src;
+ reply.dest = dest;
reply.response = NULL;
reply.result = &result;
@@ -667,9 +1050,9 @@ NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
send an error reply (used on any error, so the client doesn't keep waiting
or send the bad request again)
*/
-NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
+NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
uint32_t message_id,
- struct socket_address *src,
+ struct tsocket_address *dest,
int resultcode,
const char *errormessage)
{
@@ -678,7 +1061,7 @@ NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
struct ldap_Result result;
reply.messageid = message_id;
- reply.dest = src;
+ reply.dest = dest;
reply.response = NULL;
reply.result = &result;
@@ -695,9 +1078,10 @@ NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
/*
send a netlogon reply
*/
-NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+ struct smb_iconv_convenience *iconv_convenience,
uint32_t message_id,
- struct socket_address *src,
+ struct tsocket_address *dest,
uint32_t version,
struct netlogon_samlogon_response *netlogon)
{
@@ -708,13 +1092,15 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
TALLOC_CTX *tmp_ctx = talloc_new(cldap);
DATA_BLOB blob;
- status = push_netlogon_samlogon_response(&blob, tmp_ctx, cldap->iconv_convenience,
+ status = push_netlogon_samlogon_response(&blob, tmp_ctx,
+ iconv_convenience,
netlogon);
if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
return status;
}
reply.messageid = message_id;
- reply.dest = src;
+ reply.dest = dest;
reply.response = &response;
reply.result = &result;
@@ -735,4 +1121,3 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
return status;
}
-
diff --git a/source4/libcli/cldap/cldap.h b/source4/libcli/cldap/cldap.h
index 8951daa775a..111fa2cfc45 100644
--- a/source4/libcli/cldap/cldap.h
+++ b/source4/libcli/cldap/cldap.h
@@ -19,89 +19,29 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "../lib/util/asn1.h"
#include "../libcli/netlogon.h"
struct ldap_message;
-
-enum cldap_request_state {CLDAP_REQUEST_SEND,
- CLDAP_REQUEST_WAIT,
- CLDAP_REQUEST_DONE,
- CLDAP_REQUEST_ERROR};
-
-/*
- a cldap request packet
-*/
-struct cldap_request {
- struct cldap_request *next, *prev;
-
- struct cldap_socket *cldap;
-
- enum cldap_request_state state;
- NTSTATUS status;
-
- /* where to send the request */
- struct socket_address *dest;
-
- /* timeout between retries (seconds) */
- int timeout;
- int num_retries;
-
- bool is_reply;
-
- /* the ldap message_id */
- int message_id;
-
- struct tevent_timer *te;
-
- /* the encoded request */
- DATA_BLOB encoded;
-
- /* the reply data */
- struct asn1_data *asn1;
-
- /* information on what to do on completion */
- struct {
- void (*fn)(struct cldap_request *);
- void *private_data;
- } async;
+struct tsocket_address;
+struct cldap_socket;
+
+struct cldap_incoming {
+ int recv_errno;
+ uint8_t *buf;
+ size_t len;
+ struct tsocket_address *src;
+ struct ldap_message *ldap_msg;
};
/*
- context structure for operations on cldap packets
-*/
-struct cldap_socket {
- struct socket_context *sock;
- struct tevent_context *event_ctx;
- struct smb_iconv_convenience *iconv_convenience;
-
- /* the fd event */
- struct tevent_fd *fde;
-
- /* a queue of outgoing requests */
- struct cldap_request *send_queue;
-
- /* mapping from message_id to pending request */
- struct idr_context *idr;
-
- /* what to do with incoming request packets */
- struct {
- void (*handler)(struct cldap_socket *, struct ldap_message *,
- struct socket_address *);
- void *private_data;
- } incoming;
-};
-
-
-/*
- a general cldap search request
+ a general cldap search request
*/
struct cldap_search {
struct {
const char *dest_address;
uint16_t dest_port;
const char *filter;
- const char **attributes;
+ const char * const *attributes;
int timeout;
int retries;
} in;
@@ -111,39 +51,43 @@ struct cldap_search {
} out;
};
-struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx,
- struct tevent_context *event_ctx,
- struct smb_iconv_convenience *iconv_convenience);
+NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct tsocket_address *local_addr,
+ const struct tsocket_address *remote_addr,
+ struct cldap_socket **_cldap);
+
NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap,
- void (*handler)(struct cldap_socket *, struct ldap_message *,
- struct socket_address *),
+ void (*handler)(struct cldap_socket *,
+ void *private_data,
+ struct cldap_incoming *),
void *private_data);
-struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
- struct cldap_search *io);
-NTSTATUS cldap_search_recv(struct cldap_request *req, TALLOC_CTX *mem_ctx,
+struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx,
+ struct cldap_socket *cldap,
+ const struct cldap_search *io);
+NTSTATUS cldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
struct cldap_search *io);
-NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx,
+NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx,
struct cldap_search *io);
-
/*
a general cldap reply
*/
struct cldap_reply {
uint32_t messageid;
- struct socket_address *dest;
+ struct tsocket_address *dest;
struct ldap_SearchResEntry *response;
struct ldap_Result *result;
};
NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io);
-NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
+NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
uint32_t message_id,
- struct socket_address *src);
-NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
+ struct tsocket_address *dst);
+NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
uint32_t message_id,
- struct socket_address *src,
+ struct tsocket_address *dst,
int resultcode,
const char *errormessage);
@@ -168,15 +112,22 @@ struct cldap_netlogon {
} out;
};
-struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap,
- struct cldap_netlogon *io);
-NTSTATUS cldap_netlogon_recv(struct cldap_request *req,
- TALLOC_CTX *mem_ctx,
+struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx,
+ struct cldap_socket *cldap,
+ const struct cldap_netlogon *io);
+NTSTATUS cldap_netlogon_recv(struct tevent_req *req,
+ struct smb_iconv_convenience *iconv_convenience,
+ TALLOC_CTX *mem_ctx,
struct cldap_netlogon *io);
-NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
- TALLOC_CTX *mem_ctx, struct cldap_netlogon *io);
-NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
+ struct smb_iconv_convenience *iconv_convenience,
+ TALLOC_CTX *mem_ctx,
+ struct cldap_netlogon *io);
+
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+ struct smb_iconv_convenience *iconv_convenience,
uint32_t message_id,
- struct socket_address *src,
+ struct tsocket_address *dst,
uint32_t version,
struct netlogon_samlogon_response *netlogon);
+
diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk
index dc3431ab9fc..1b87530af80 100644
--- a/source4/libcli/config.mk
+++ b/source4/libcli/config.mk
@@ -98,7 +98,7 @@ LIBCLI_DGRAM_OBJ_FILES = $(addprefix $(libclisrcdir)/dgram/, \
[SUBSYSTEM::LIBCLI_CLDAP]
PUBLIC_DEPENDENCIES = LIBCLI_LDAP
-PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL LIBLDB LIBCLI_NETLOGON
+PRIVATE_DEPENDENCIES = LIBTSOCKET LIBSAMBA-UTIL UTIL_TEVENT LIBLDB LIBCLI_NETLOGON
LIBCLI_CLDAP_OBJ_FILES = $(libclisrcdir)/cldap/cldap.o
# PUBLIC_HEADERS += $(libclisrcdir)/cldap/cldap.h
diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c
index bf046745e6a..dbbabd6a6da 100644
--- a/source4/libnet/libnet_become_dc.c
+++ b/source4/libnet/libnet_become_dc.c
@@ -731,12 +731,12 @@ struct libnet_BecomeDC_state {
struct libnet_BecomeDC_Callbacks callbacks;
};
-static void becomeDC_recv_cldap(struct cldap_request *req);
+static void becomeDC_recv_cldap(struct tevent_req *req);
static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
{
struct composite_context *c = s->creq;
- struct cldap_request *req;
+ struct tevent_req *req;
s->cldap.io.in.dest_address = s->source_dsa.address;
s->cldap.io.in.dest_port = lp_cldap_port(s->libnet->lp_ctx);
@@ -749,25 +749,27 @@ static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s)
s->cldap.io.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
s->cldap.io.in.map_response = true;
- s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx,
- lp_iconv_convenience(s->libnet->lp_ctx));
- if (composite_nomem(s->cldap.sock, c)) return;
+ c->status = cldap_socket_init(s, s->libnet->event_ctx,
+ NULL, NULL, &s->cldap.sock);//TODO
+ if (!composite_is_ok(c)) return;
- req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
+ req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io);
if (composite_nomem(req, c)) return;
- req->async.fn = becomeDC_recv_cldap;
- req->async.private_data = s;
+ tevent_req_set_callback(req, becomeDC_recv_cldap, s);
}
static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s);
-static void becomeDC_recv_cldap(struct cldap_request *req)
+static void becomeDC_recv_cldap(struct tevent_req *req)
{
- struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data,
+ struct libnet_BecomeDC_state *s = tevent_req_callback_data(req,
struct libnet_BecomeDC_state);
struct composite_context *c = s->creq;
- c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
+ c->status = cldap_netlogon_recv(req,
+ lp_iconv_convenience(s->libnet->lp_ctx),
+ s, &s->cldap.io);
+ talloc_free(req);
if (!composite_is_ok(c)) return;
s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
diff --git a/source4/libnet/libnet_site.c b/source4/libnet/libnet_site.c
index 4a32ab92ed5..8a002b24a4b 100644
--- a/source4/libnet/libnet_site.c
+++ b/source4/libnet/libnet_site.c
@@ -56,8 +56,14 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_context *lctx, struct li
search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
search.in.map_response = true;
- cldap = cldap_socket_init(tmp_ctx, lctx->event_ctx, lp_iconv_convenience(lctx->lp_ctx));
- status = cldap_netlogon(cldap, tmp_ctx, &search);
+ /* we want to use non async calls, so we're not passing an event context */
+ status = cldap_socket_init(tmp_ctx, NULL, NULL, NULL, &cldap);//TODO
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ r->out.error_string = NULL;
+ return status;
+ }
+ status = cldap_netlogon(cldap, lp_iconv_convenience(lctx->lp_ctx), tmp_ctx, &search);
if (!NT_STATUS_IS_OK(status)
|| !search.out.netlogon.data.nt5_ex.client_site) {
/*
diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c
index 3f92daab281..e0e5e421151 100644
--- a/source4/libnet/libnet_unbecome_dc.c
+++ b/source4/libnet/libnet_unbecome_dc.c
@@ -250,12 +250,12 @@ struct libnet_UnbecomeDC_state {
} dest_dsa;
};
-static void unbecomeDC_recv_cldap(struct cldap_request *req);
+static void unbecomeDC_recv_cldap(struct tevent_req *req);
static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
{
struct composite_context *c = s->creq;
- struct cldap_request *req;
+ struct tevent_req *req;
s->cldap.io.in.dest_address = s->source_dsa.address;
s->cldap.io.in.dest_port = lp_cldap_port(s->libnet->lp_ctx);
@@ -268,25 +268,27 @@ static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s)
s->cldap.io.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
s->cldap.io.in.map_response = true;
- s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx,
- lp_iconv_convenience(s->libnet->lp_ctx));
- if (composite_nomem(s->cldap.sock, c)) return;
+ c->status = cldap_socket_init(s, s->libnet->event_ctx,
+ NULL, NULL, &s->cldap.sock);//TODO
+ if (!composite_is_ok(c)) return;
- req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io);
+ req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io);
if (composite_nomem(req, c)) return;
- req->async.fn = unbecomeDC_recv_cldap;
- req->async.private_data = s;
+ tevent_req_set_callback(req, unbecomeDC_recv_cldap, s);
}
static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s);
-static void unbecomeDC_recv_cldap(struct cldap_request *req)
+static void unbecomeDC_recv_cldap(struct tevent_req *req)
{
- struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private_data,
+ struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(req,
struct libnet_UnbecomeDC_state);
struct composite_context *c = s->creq;
- c->status = cldap_netlogon_recv(req, s, &s->cldap.io);
+ c->status = cldap_netlogon_recv(req,
+ lp_iconv_convenience(s->libnet->lp_ctx),
+ s, &s->cldap.io);
+ talloc_free(req);
if (!composite_is_ok(c)) return;
s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex;
diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c
index 1ddc628a5c6..98669288a8f 100644
--- a/source4/torture/ldap/cldap.c
+++ b/source4/torture/ldap/cldap.c
@@ -28,6 +28,7 @@
#include "torture/torture.h"
#include "lib/ldb/include/ldb.h"
#include "param/param.h"
+#include "../lib/tsocket/tsocket.h"
#define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status")
@@ -45,12 +46,21 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
struct netlogon_samlogon_response n1;
struct GUID guid;
int i;
+ struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
+ struct tsocket_address *dest_addr;
+ int ret;
- cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ ret = tsocket_address_inet_from_strings(tctx, "ip",
+ dest,
+ lp_cldap_port(tctx->lp_ctx),
+ &dest_addr);
+
+ status = cldap_socket_init(tctx, NULL, NULL, dest_addr, &cldap);
+ CHECK_STATUS(status, NT_STATUS_OK);
ZERO_STRUCT(search);
- search.in.dest_address = dest;
- search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+ search.in.dest_address = NULL;//dest;
+ search.in.dest_port = 0;//lp_cldap_port(tctx->lp_ctx);
search.in.acct_control = -1;
search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
search.in.map_response = true;
@@ -59,7 +69,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying without any attributes\n");
search = empty_search;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
n1 = search.out.netlogon;
@@ -72,7 +82,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
for (i=0;i<256;i++) {
search.in.version = i;
printf("Trying netlogon level %d\n", i);
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
}
@@ -80,19 +90,19 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
for (i=0;i<31;i++) {
search.in.version = (1<<i);
printf("Trying netlogon level 0x%x\n", i);
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
}
search.in.version = NETLOGON_NT_VERSION_5|NETLOGON_NT_VERSION_5EX|NETLOGON_NT_VERSION_IP;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
printf("Trying with User=NULL\n");
search.in.user = NULL;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
@@ -100,20 +110,20 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with User=Administrator\n");
search.in.user = "Administrator";
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
search.in.version = NETLOGON_NT_VERSION_5;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
printf("Trying with User=NULL\n");
search.in.user = NULL;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE);
@@ -121,7 +131,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with User=Administrator\n");
search.in.user = "Administrator";
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
@@ -132,7 +142,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with a GUID\n");
search.in.realm = NULL;
search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
CHECK_STRING(GUID_string(tctx, &search.out.netlogon.data.nt5_ex.domain_uuid), search.in.domain_guid);
@@ -141,13 +151,13 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
guid = GUID_random();
search.in.user = NULL;
search.in.domain_guid = GUID_string(tctx, &guid);
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
printf("Trying with a AAC\n");
search.in.acct_control = ACB_WSTRUST|ACB_SVRTRUST;
search.in.realm = n1.data.nt5_ex.dns_domain;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -155,7 +165,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with a zero AAC\n");
search.in.acct_control = 0x0;
search.in.realm = n1.data.nt5_ex.dns_domain;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -164,7 +174,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
search.in.acct_control = 0x0;
search.in.user = "Administrator";
search.in.realm = n1.data.nt5_ex.dns_domain;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_USER_UNKNOWN_EX);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "Administrator");
@@ -173,7 +183,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
search.in.user = NULL;
search.in.acct_control = 0xFF00FF00;
search.in.realm = n1.data.nt5_ex.dns_domain;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_VAL(search.out.netlogon.data.nt5_ex.command, LOGON_SAM_LOGON_RESPONSE_EX);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -181,14 +191,14 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with a user only\n");
search = empty_search;
search.in.user = "Administrator";
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
printf("Trying with just a bad username\n");
search.in.user = "___no_such_user___";
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, search.in.user);
CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
@@ -197,12 +207,12 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with just a bad domain\n");
search = empty_search;
search.in.realm = "___no_such_domain___";
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
printf("Trying with a incorrect domain and correct guid\n");
search.in.domain_guid = GUID_string(tctx, &n1.data.nt5_ex.domain_uuid);
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -210,7 +220,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with a incorrect domain and incorrect guid\n");
search.in.domain_guid = GUID_string(tctx, &guid);
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -219,7 +229,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
printf("Trying with a incorrect GUID and correct domain\n");
search.in.domain_guid = GUID_string(tctx, &guid);
search.in.realm = n1.data.nt5_ex.dns_domain;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
CHECK_STRING(search.out.netlogon.data.nt5_ex.dns_domain, n1.data.nt5_ex.dns_domain);
CHECK_STRING(search.out.netlogon.data.nt5_ex.user_name, "");
@@ -239,10 +249,12 @@ static bool test_cldap_netlogon_flags(struct torture_context *tctx,
struct cldap_netlogon search;
struct netlogon_samlogon_response n1;
uint32_t server_type;
+ struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
- cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
+ CHECK_STATUS(status, NT_STATUS_OK);
- printf("Printing out netlogon server type flags:\n");
+ printf("Printing out netlogon server type flags: %s\n", dest);
ZERO_STRUCT(search);
search.in.dest_address = dest;
@@ -251,7 +263,7 @@ static bool test_cldap_netlogon_flags(struct torture_context *tctx,
search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
search.in.map_response = true;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
n1 = search.out.netlogon;
@@ -348,10 +360,12 @@ static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx,
struct cldap_netlogon search;
uint32_t server_type;
struct netlogon_samlogon_response n1;
+ struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx);
bool result = true;
- cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
+ CHECK_STATUS(status, NT_STATUS_OK);
printf("Testing netlogon server type flag NBT_SERVER_DS_DNS_FOREST: ");
@@ -362,7 +376,7 @@ static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx,
search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
search.in.map_response = true;
- status = cldap_netlogon(cldap, tctx, &search);
+ status = cldap_netlogon(cldap, iconv_convenience, tctx, &search);
CHECK_STATUS(status, NT_STATUS_OK);
n1 = search.out.netlogon;
@@ -423,7 +437,8 @@ static bool test_cldap_generic(struct torture_context *tctx, const char *dest)
const char *attrs2[] = { "currentTime", "highestCommittedUSN", "netlogon", NULL };
const char *attrs3[] = { "netlogon", NULL };
- cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap);
+ CHECK_STATUS(status, NT_STATUS_OK);
ZERO_STRUCT(search);
search.in.dest_address = dest;
diff --git a/source4/torture/ldap/cldapbench.c b/source4/torture/ldap/cldapbench.c
index ae2cb808360..a422732b039 100644
--- a/source4/torture/ldap/cldapbench.c
+++ b/source4/torture/ldap/cldapbench.c
@@ -20,24 +20,28 @@
*/
#include "includes.h"
-#include "lib/events/events.h"
+#include <tevent.h>
#include "libcli/cldap/cldap.h"
#include "libcli/resolve/resolve.h"
#include "torture/torture.h"
#include "param/param.h"
struct bench_state {
+ struct torture_context *tctx;
int pass_count, fail_count;
};
-static void request_netlogon_handler(struct cldap_request *req)
+static void request_netlogon_handler(struct tevent_req *req)
{
struct cldap_netlogon io;
- struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state);
+ struct bench_state *state = tevent_req_callback_data(req, struct bench_state);
NTSTATUS status;
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
io.in.version = 6;
- status = cldap_netlogon_recv(req, tmp_ctx, &io);
+ status = cldap_netlogon_recv(req,
+ lp_iconv_convenience(state->tctx->lp_ctx),
+ tmp_ctx, &io);
+ talloc_free(req);
if (NT_STATUS_IS_OK(status)) {
state->pass_count++;
} else {
@@ -58,10 +62,13 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
int timelimit = torture_setting_int(tctx, "timelimit", 10);
struct cldap_netlogon search;
struct bench_state *state;
+ NTSTATUS status;
- cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ status = cldap_socket_init(tctx, tctx->ev, NULL, NULL, &cldap);
+ torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
state = talloc_zero(tctx, struct bench_state);
+ state->tctx = tctx;
ZERO_STRUCT(search);
search.in.dest_address = address;
@@ -72,11 +79,11 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
printf("Running CLDAP/netlogon for %d seconds\n", timelimit);
while (timeval_elapsed(&tv) < timelimit) {
while (num_sent - (state->pass_count+state->fail_count) < 10) {
- struct cldap_request *req;
- req = cldap_netlogon_send(cldap, &search);
+ struct tevent_req *req;
+ req = cldap_netlogon_send(state, cldap, &search);
+
+ tevent_req_set_callback(req, request_netlogon_handler, state);
- req->async.private_data = state;
- req->async.fn = request_netlogon_handler;
num_sent++;
if (num_sent % 50 == 0) {
if (torture_setting_bool(tctx, "progress", true)) {
@@ -88,11 +95,11 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
}
}
- event_loop_once(cldap->event_ctx);
+ tevent_loop_once(tctx->ev);
}
while (num_sent != (state->pass_count + state->fail_count)) {
- event_loop_once(cldap->event_ctx);
+ tevent_loop_once(tctx->ev);
}
printf("%.1f queries per second (%d failures) \n",
@@ -103,13 +110,14 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre
return ret;
}
-static void request_rootdse_handler(struct cldap_request *req)
+static void request_rootdse_handler(struct tevent_req *req)
{
struct cldap_search io;
- struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state);
+ struct bench_state *state = tevent_req_callback_data(req, struct bench_state);
NTSTATUS status;
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
status = cldap_search_recv(req, tmp_ctx, &io);
+ talloc_free(req);
if (NT_STATUS_IS_OK(status)) {
state->pass_count++;
} else {
@@ -130,8 +138,10 @@ static bool bench_cldap_rootdse(struct torture_context *tctx, const char *addres
int timelimit = torture_setting_int(tctx, "timelimit", 10);
struct cldap_search search;
struct bench_state *state;
+ NTSTATUS status;
- cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ status = cldap_socket_init(tctx, tctx->ev, NULL, NULL, &cldap);
+ torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
state = talloc_zero(tctx, struct bench_state);
@@ -145,11 +155,11 @@ static bool bench_cldap_rootdse(struct torture_context *tctx, const char *addres
printf("Running CLDAP/rootdse for %d seconds\n", timelimit);
while (timeval_elapsed(&tv) < timelimit) {
while (num_sent - (state->pass_count+state->fail_count) < 10) {
- struct cldap_request *req;
- req = cldap_search_send(cldap, &search);
+ struct tevent_req *req;
+ req = cldap_search_send(state, cldap, &search);
+
+ tevent_req_set_callback(req, request_rootdse_handler, state);
- req->async.private_data = state;
- req->async.fn = request_rootdse_handler;
num_sent++;
if (num_sent % 50 == 0) {
if (torture_setting_bool(tctx, "progress", true)) {
diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c
index 847b32827b8..1aaf914ceb8 100644
--- a/source4/torture/rpc/dssync.c
+++ b/source4/torture/rpc/dssync.c
@@ -273,7 +273,12 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
struct cldap_socket *cldap;
struct cldap_netlogon search;
- cldap = cldap_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+ status = cldap_socket_init(ctx, NULL, NULL, NULL, &cldap);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("failed to setup cldap socket - %s\n",
+ nt_errstr(status));
+ return false;
+ }
r.in.bind_handle = &ctx->admin.drsuapi.bind_handle;
r.in.level = 1;
@@ -311,7 +316,7 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx)
search.in.acct_control = -1;
search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
search.in.map_response = true;
- status = cldap_netlogon(cldap, ctx, &search);
+ status = cldap_netlogon(cldap, lp_iconv_convenience(tctx->lp_ctx), ctx, &search);
if (!NT_STATUS_IS_OK(status)) {
const char *errstr = nt_errstr(status);
ctx->site_name = talloc_asprintf(ctx, "%s", "Default-First-Site-Name");