diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/headermap.txt | 2 | ||||
-rw-r--r-- | source4/libcli/cldap/cldap.c | 1123 | ||||
-rw-r--r-- | source4/libcli/cldap/cldap.h | 133 | ||||
-rw-r--r-- | source4/libcli/config.mk | 7 |
4 files changed, 1 insertions, 1264 deletions
diff --git a/source4/headermap.txt b/source4/headermap.txt index d0d0a575d8..280d60beb2 100644 --- a/source4/headermap.txt +++ b/source4/headermap.txt @@ -25,7 +25,7 @@ lib/registry/registry.h: registry.h libcli/util/werror.h: core/werror.h libcli/util/doserr.h: core/doserr.h libcli/util/ntstatus.h: core/ntstatus.h -libcli/cldap/cldap.h: cldap.h +../libcli/cldap/cldap.h: cldap.h auth/credentials/credentials.h: credentials.h auth/credentials/credentials_krb5.h: credentials/krb5.h rpc_server/dcerpc_server.h: dcerpc_server.h diff --git a/source4/libcli/cldap/cldap.c b/source4/libcli/cldap/cldap.c deleted file mode 100644 index 0f2175b42d..0000000000 --- a/source4/libcli/cldap/cldap.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - 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 - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - see RFC1798 for details of CLDAP - - basic properties - - carried over UDP on port 389 - - request and response matched by message ID - - request consists of only a single searchRequest element - - response can be in one of two forms - - a single searchResponse, followed by a searchResult - - a single searchResult -*/ - -#include "includes.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/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" - -/* - context structure for operations on cldap packets -*/ -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) -{ - 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; -} - -static void cldap_recvfrom_done(struct tevent_req *subreq); - -static bool cldap_recvfrom_setup(struct cldap_socket *c) -{ - if (c->recv_subreq) { - return true; - } - - if (!c->searches.list && !c->incoming.handler) { - return true; - } - - c->recv_subreq = tsocket_recvfrom_send(c->sock, c); - if (!c->recv_subreq) { - return false; - } - tevent_req_set_callback(c->recv_subreq, cldap_recvfrom_done, c); - - return true; -} - -static void cldap_recvfrom_stop(struct cldap_socket *c) -{ - if (!c->recv_subreq) { - return; - } - - if (c->searches.list || c->incoming.handler) { - return; - } - - talloc_free(c->recv_subreq); - c->recv_subreq = NULL; -} - -static void cldap_socket_recv_dgram(struct cldap_socket *c, - struct cldap_incoming *in); - -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; - - c->recv_subreq = NULL; - - in = talloc_zero(c, struct cldap_incoming); - if (!in) { - goto nomem; - } - - 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; - } - - /* this function should free or steal 'in' */ - cldap_socket_recv_dgram(c, in); - in = NULL; - - if (!cldap_recvfrom_setup(c)) { - goto nomem; - } - - return; - -nomem: - talloc_free(subreq); - talloc_free(in); - /*TODO: call a dead socket handler */ - return; -} - -/* - handle recv events on a cldap socket -*/ -static void cldap_socket_recv_dgram(struct cldap_socket *c, - struct cldap_incoming *in) -{ - DATA_BLOB blob; - struct asn1_data *asn1; - void *p; - struct cldap_search_state *search; - NTSTATUS status; - - if (in->recv_errno != 0) { - goto error; - } - - blob = data_blob_const(in->buf, in->len); - - asn1 = asn1_init(in); - if (!asn1) { - goto nomem; - } - - if (!asn1_load(asn1, blob)) { - goto nomem; - } - - in->ldap_msg = talloc(in, struct ldap_message); - if (in->ldap_msg == NULL) { - goto nomem; - } - - /* 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; - } - - /* 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; - } - - 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_sock -*/ -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 *c = NULL; - struct tsocket_address *any = NULL; - NTSTATUS status; - int ret; - - c = talloc_zero(mem_ctx, struct cldap_socket); - if (!c) { - goto nomem; - } - - 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; - } - - c->searches.idr = idr_init(c); - if (!c->searches.idr) { - goto nomem; - } - - 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); - - tsocket_set_event_context(c->sock, c->event.ctx); - - 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; - } - - c->send_queue = tevent_queue_create(c, "cldap_send_queue"); - if (!c->send_queue) { - goto nomem; - } - - 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 *c, - void (*handler)(struct cldap_socket *, - void *private_data, - struct cldap_incoming *), - void *private_data) -{ - 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 reply for send -*/ -NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io) -{ - struct cldap_reply_state *state = NULL; - struct ldap_message *msg; - DATA_BLOB blob1, blob2; - NTSTATUS status; - struct tevent_req *req; - - if (cldap->connected) { - return NT_STATUS_PIPE_CONNECTED; - } - - if (!io->dest) { - return NT_STATUS_INVALID_ADDRESS; - } - - state = talloc(cldap, struct cldap_reply_state); - NT_STATUS_HAVE_NO_MEMORY(state); - - state->dest = tsocket_address_copy(io->dest, state); - if (!state->dest) { - goto nomem; - } - - msg = talloc(state, struct ldap_message); - if (!msg) { - goto nomem; - } - - 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, &blob1, state)) { - status = NT_STATUS_INVALID_PARAMETER; - goto failed; - } - } else { - blob1 = data_blob(NULL, 0); - } - - 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); - - state->blob = data_blob_talloc(state, NULL, blob1.length + blob2.length); - if (!state->blob.data) { - goto nomem; - } - - 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 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); - 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 -*/ -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 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; - } - - 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; - } - - msg = talloc(state, struct ldap_message); - if (tevent_req_nomem(msg, req)) { - goto post; - } - - msg->messageid = state->message_id; - msg->type = LDAP_TAG_SearchRequest; - 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(msg, io->in.filter); - if (tevent_req_nomem(search->tree, req)) { - goto post; - } - - 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; - } - - now = tevent_timeval_current(); - end = now; - for (i = 0; i < state->request.count; i++) { - end = tevent_timeval_add(&end, 0, state->request.delay); - } - - if (!tevent_req_set_endtime(req, state->caller.cldap->event.ctx, end)) { - tevent_req_nomem(NULL, req); - goto post; - } - - 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); - - DLIST_ADD_END(cldap->searches.list, state, struct cldap_search_state *); - talloc_set_destructor(state, cldap_search_state_destructor); - - return req; - - post: - return tevent_req_post(req, cldap->event.ctx); -} - -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; - } - - state->request.idx++; - - /* 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 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 (tevent_req_is_nterror(req, &status)) { - goto failed; - } - - ldap_msg = talloc(mem_ctx, struct ldap_message); - if (!ldap_msg) { - goto nomem; - } - - status = ldap_decode(state->response.asn1, NULL, ldap_msg); - if (!NT_STATUS_IS_OK(status)) { - goto failed; - } - - ZERO_STRUCT(io->out); - - /* 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); - if (!io->out.response) { - goto nomem; - } - *io->out.response = ldap_msg->r.SearchResultEntry; - - /* decode the 2nd part */ - status = ldap_decode(state->response.asn1, NULL, ldap_msg); - if (!NT_STATUS_IS_OK(status)) { - goto failed; - } - } - - if (ldap_msg->type != LDAP_TAG_SearchResultDone) { - status = NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); - goto failed; - } - - io->out.result = talloc(mem_ctx, struct ldap_Result); - if (!io->out.result) { - goto nomem; - } - *io->out.result = ldap_msg->r.SearchResultDone; - - if (io->out.result->resultcode != LDAP_SUCCESS) { - 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, - struct cldap_search *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 tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, - struct cldap_socket *cldap, - const struct cldap_netlogon *io) -{ - struct tevent_req *req, *subreq; - struct cldap_netlogon_state *state; - char *filter; - 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(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 (tevent_req_nomem(filter, req)) { - goto post; - } - } - if (io->in.host) { - filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - if (io->in.realm) { - filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm); - 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(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(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(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 (tevent_req_nterror(req, status)) { - goto post; - } - filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)", - ldap_encode_ndr_GUID(state, &guid)); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - filter = talloc_asprintf_append_buffer(filter, ")"); - if (tevent_req_nomem(filter, req)) { - goto post; - } - - 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); - - return req; -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 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; - DATA_BLOB *data; - - if (tevent_req_is_nterror(req, &status)) { - goto failed; - } - - if (state->search.out.response == NULL) { - status = NT_STATUS_NOT_FOUND; - goto failed; - } - - 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 = state->search.out.response->attributes[0].values; - - status = pull_netlogon_samlogon_response(data, mem_ctx, - iconv_convenience, - &io->out.netlogon); - if (!NT_STATUS_IS_OK(status)) { - goto failed; - } - - if (io->in.map_response) { - map_netlogon_samlogon_response(&io->out.netlogon); - } - - status = NT_STATUS_OK; -failed: - tevent_req_received(req); - return status; -} - -/* - sync cldap netlogon search -*/ -NTSTATUS cldap_netlogon(struct cldap_socket *cldap, - struct smb_iconv_convenience *iconv_convenience, - TALLOC_CTX *mem_ctx, - struct cldap_netlogon *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; -} - - -/* - 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, - struct tsocket_address *dest) -{ - NTSTATUS status; - struct cldap_reply reply; - struct ldap_Result result; - - reply.messageid = message_id; - reply.dest = dest; - reply.response = NULL; - reply.result = &result; - - ZERO_STRUCT(result); - - status = cldap_reply_send(cldap, &reply); - - return status; -} - -/* - 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, - uint32_t message_id, - struct tsocket_address *dest, - int resultcode, - const char *errormessage) -{ - NTSTATUS status; - struct cldap_reply reply; - struct ldap_Result result; - - reply.messageid = message_id; - reply.dest = dest; - reply.response = NULL; - reply.result = &result; - - ZERO_STRUCT(result); - result.resultcode = resultcode; - result.errormessage = errormessage; - - status = cldap_reply_send(cldap, &reply); - - return status; -} - - -/* - send a netlogon reply -*/ -NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, - struct smb_iconv_convenience *iconv_convenience, - uint32_t message_id, - struct tsocket_address *dest, - uint32_t version, - struct netlogon_samlogon_response *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 = 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 = dest; - reply.response = &response; - reply.result = &result; - - ZERO_STRUCT(result); - - response.dn = ""; - response.num_attributes = 1; - response.attributes = talloc(tmp_ctx, struct ldb_message_element); - 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 deleted file mode 100644 index 111fa2cfc4..0000000000 --- a/source4/libcli/cldap/cldap.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - a async CLDAP library - - Copyright (C) Andrew Tridgell 2005 - - 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 - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "../libcli/netlogon.h" - -struct ldap_message; -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; -}; - -/* - a general cldap search request -*/ -struct cldap_search { - struct { - const char *dest_address; - uint16_t dest_port; - const char *filter; - const char * const *attributes; - int timeout; - int retries; - } in; - struct { - struct ldap_SearchResEntry *response; - struct ldap_Result *result; - } out; -}; - -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 *, - void *private_data, - struct cldap_incoming *), - void *private_data); -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, - struct cldap_search *io); - -/* - a general cldap reply -*/ -struct cldap_reply { - uint32_t messageid; - 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, - uint32_t message_id, - struct tsocket_address *dst); -NTSTATUS cldap_error_reply(struct cldap_socket *cldap, - uint32_t message_id, - struct tsocket_address *dst, - int resultcode, - const char *errormessage); - -/* - a netlogon cldap request -*/ -struct cldap_netlogon { - struct { - const char *dest_address; - uint16_t dest_port; - const char *realm; - const char *host; - const char *user; - const char *domain_guid; - const char *domain_sid; - int acct_control; - uint32_t version; - bool map_response; - } in; - struct { - struct netlogon_samlogon_response netlogon; - } out; -}; - -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, - 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 tsocket_address *dst, - uint32_t version, - struct netlogon_samlogon_response *netlogon); - diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 1b87530af8..5b50bdfcbe 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -96,13 +96,6 @@ LIBCLI_DGRAM_OBJ_FILES = $(addprefix $(libclisrcdir)/dgram/, \ netlogon.o \ browse.o) -[SUBSYSTEM::LIBCLI_CLDAP] -PUBLIC_DEPENDENCIES = LIBCLI_LDAP -PRIVATE_DEPENDENCIES = LIBTSOCKET LIBSAMBA-UTIL UTIL_TEVENT LIBLDB LIBCLI_NETLOGON - -LIBCLI_CLDAP_OBJ_FILES = $(libclisrcdir)/cldap/cldap.o -# PUBLIC_HEADERS += $(libclisrcdir)/cldap/cldap.h - [SUBSYSTEM::LIBCLI_WREPL] PUBLIC_DEPENDENCIES = NDR_WINSREPL samba_socket LIBEVENTS LIBPACKET |