summaryrefslogtreecommitdiff
path: root/source4/libcli/cldap
diff options
context:
space:
mode:
Diffstat (limited to 'source4/libcli/cldap')
-rw-r--r--source4/libcli/cldap/cldap.c166
-rw-r--r--source4/libcli/cldap/cldap.h25
2 files changed, 184 insertions, 7 deletions
diff --git a/source4/libcli/cldap/cldap.c b/source4/libcli/cldap/cldap.c
index 75ce0a67db..2f4d1e73a9 100644
--- a/source4/libcli/cldap/cldap.c
+++ b/source4/libcli/cldap/cldap.c
@@ -51,7 +51,7 @@ static int cldap_request_destructor(void *ptr)
if (req->state == CLDAP_REQUEST_SEND) {
DLIST_REMOVE(req->cldap->send_queue, req);
}
- if (req->message_id != 0) {
+ if (!req->is_reply && req->message_id != 0) {
idr_remove(req->cldap->idr, req->message_id);
req->message_id = 0;
}
@@ -191,13 +191,17 @@ static void cldap_socket_send(struct cldap_socket *cldap)
DLIST_REMOVE(cldap->send_queue, req);
- req->state = CLDAP_REQUEST_WAIT;
+ if (req->is_reply) {
+ talloc_free(req);
+ } else {
+ req->state = CLDAP_REQUEST_WAIT;
- req->te = event_add_timed(cldap->event_ctx, req,
- timeval_current_ofs(req->timeout, 0),
- cldap_request_timeout, req);
+ req->te = event_add_timed(cldap->event_ctx, req,
+ timeval_current_ofs(req->timeout, 0),
+ cldap_request_timeout, req);
- EVENT_FD_READABLE(cldap->fde);
+ EVENT_FD_READABLE(cldap->fde);
+ }
}
EVENT_FD_NOT_WRITEABLE(cldap->fde);
@@ -293,6 +297,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
req->state = CLDAP_REQUEST_SEND;
req->timeout = io->in.timeout;
req->num_retries = io->in.retries;
+ req->is_reply = False;
req->dest_addr = talloc_strdup(req, io->in.dest_address);
if (req->dest_addr == NULL) goto failed;
@@ -303,7 +308,7 @@ struct cldap_request *cldap_search_send(struct cldap_socket *cldap,
talloc_set_destructor(req, cldap_request_destructor);
- msg.mem_ctx = cldap;
+ msg.mem_ctx = req;
msg.messageid = req->message_id;
msg.type = LDAP_TAG_SearchRequest;
msg.num_controls = 0;
@@ -338,6 +343,78 @@ failed:
return NULL;
}
+
+/*
+ queue a cldap reply for send
+*/
+NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io)
+{
+ struct ldap_message msg;
+ struct cldap_request *req;
+ DATA_BLOB blob1, blob2;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
+
+ req = talloc_zero(cldap, struct cldap_request);
+ if (req == NULL) goto failed;
+
+ req->cldap = cldap;
+ req->state = CLDAP_REQUEST_SEND;
+ req->is_reply = True;
+
+ req->dest_addr = talloc_strdup(req, io->dest_address);
+ if (req->dest_addr == NULL) goto failed;
+ req->dest_port = io->dest_port;
+
+ talloc_set_destructor(req, cldap_request_destructor);
+
+ msg.mem_ctx = req;
+ msg.messageid = io->messageid;
+ msg.num_controls = 0;
+ msg.controls = NULL;
+
+ if (io->response) {
+ msg.type = LDAP_TAG_SearchResultEntry;
+ msg.r.SearchResultEntry = *io->response;
+
+ if (!ldap_encode(&msg, &blob1)) {
+ DEBUG(0,("Failed to encode cldap message to %s:%d\n",
+ req->dest_addr, req->dest_port));
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto failed;
+ }
+ talloc_steal(req, blob1.data);
+ } else {
+ blob1 = data_blob(NULL, 0);
+ }
+
+ msg.type = LDAP_TAG_SearchResultDone;
+ msg.r.SearchResultDone = *io->result;
+
+ if (!ldap_encode(&msg, &blob2)) {
+ DEBUG(0,("Failed to encode cldap message to %s:%d\n",
+ req->dest_addr, req->dest_port));
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto failed;
+ }
+ talloc_steal(req, blob2.data);
+
+ req->encoded = data_blob_talloc(req, NULL, blob1.length + blob2.length);
+ if (req->encoded.data == NULL) goto failed;
+
+ memcpy(req->encoded.data, blob1.data, blob1.length);
+ memcpy(req->encoded.data+blob1.length, blob2.data, blob2.length);
+
+ DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *);
+
+ EVENT_FD_WRITEABLE(cldap->fde);
+
+ return NT_STATUS_OK;
+
+failed:
+ talloc_free(req);
+ return status;
+}
+
/*
receive a cldap reply
*/
@@ -490,3 +567,78 @@ NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
struct cldap_request *req = cldap_netlogon_send(cldap, io);
return cldap_netlogon_recv(req, mem_ctx, io);
}
+
+
+/*
+ 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,
+ uint32_t message_id,
+ const char *src_address, int src_port)
+{
+ NTSTATUS status;
+ struct cldap_reply reply;
+ struct ldap_Result result;
+
+ reply.messageid = message_id;
+ reply.dest_address = src_address;
+ reply.dest_port = src_port;
+ reply.response = NULL;
+ reply.result = &result;
+
+ ZERO_STRUCT(result);
+
+ status = cldap_reply_send(cldap, &reply);
+
+ return status;
+}
+
+
+/*
+ send a netlogon reply
+*/
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+ uint32_t message_id,
+ const char *src_address, int src_port,
+ uint32_t version,
+ union nbt_cldap_netlogon *netlogon)
+{
+ NTSTATUS status;
+ struct cldap_reply reply;
+ struct ldap_SearchResEntry response;
+ struct ldap_Result result;
+ TALLOC_CTX *tmp_ctx = talloc_new(cldap);
+ DATA_BLOB blob;
+
+ status = ndr_push_union_blob(&blob, tmp_ctx, netlogon, version & 0xF,
+ (ndr_push_flags_fn_t)ndr_push_nbt_cldap_netlogon);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ reply.messageid = message_id;
+ reply.dest_address = src_address;
+ reply.dest_port = src_port;
+ reply.response = &response;
+ reply.result = &result;
+
+ ZERO_STRUCT(result);
+
+ response.dn = "";
+ response.num_attributes = 1;
+ response.attributes = talloc(tmp_ctx, struct ldap_attribute);
+ NT_STATUS_HAVE_NO_MEMORY(response.attributes);
+ response.attributes->name = "netlogon";
+ response.attributes->num_values = 1;
+ response.attributes->values = &blob;
+
+ status = cldap_reply_send(cldap, &reply);
+
+ talloc_free(tmp_ctx);
+
+ return status;
+}
+
+
diff --git a/source4/libcli/cldap/cldap.h b/source4/libcli/cldap/cldap.h
index 8a678b4539..fbdaada8c9 100644
--- a/source4/libcli/cldap/cldap.h
+++ b/source4/libcli/cldap/cldap.h
@@ -46,6 +46,8 @@ struct cldap_request {
int timeout;
int num_retries;
+ BOOL is_reply;
+
/* the ldap message_id */
int message_id;
@@ -121,6 +123,19 @@ NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx,
/*
+ a general cldap reply
+*/
+struct cldap_reply {
+ uint32_t messageid;
+ const char *dest_address;
+ int dest_port;
+ struct ldap_SearchResEntry *response;
+ struct ldap_Result *result;
+};
+
+NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io);
+
+/*
a netlogon cldap request
*/
struct cldap_netlogon {
@@ -142,3 +157,13 @@ NTSTATUS cldap_netlogon_recv(struct cldap_request *req,
struct cldap_netlogon *io);
NTSTATUS cldap_netlogon(struct cldap_socket *cldap,
TALLOC_CTX *mem_ctx, struct cldap_netlogon *io);
+
+
+NTSTATUS cldap_empty_reply(struct cldap_socket *cldap,
+ uint32_t message_id,
+ const char *src_address, int src_port);
+NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap,
+ uint32_t message_id,
+ const char *src_address, int src_port,
+ uint32_t version,
+ union nbt_cldap_netlogon *netlogon);