From: Volker Lendecke Date: Thu, 24 Oct 2024 11:55:35 +0000 (+0200) Subject: libads: Add netlogon_pings() X-Git-Tag: tdb-1.4.13~596 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf66ff3d1b0cd0e6dbc8091ba0f184c336ef6126;p=thirdparty%2Fsamba.git libads: Add netlogon_pings() This encapsulates our logic that we send CLDAP requests on UDP/389, sending them with 100msec timeouts until someone replies. It also contains the code to do this over LDAP/389 or LDAPS/636. It also contains code to filter for domain controller flags like DS_ONLY_LDAP_NEEDED, this logic exists in several places right now. Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher --- diff --git a/source3/libads/netlogon_ping.c b/source3/libads/netlogon_ping.c new file mode 100644 index 00000000000..4fd776a2efe --- /dev/null +++ b/source3/libads/netlogon_ping.c @@ -0,0 +1,830 @@ +/* + * Samba Unix/Linux SMB client library + * + * 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 . + */ + +#include "replace.h" +#include +#include "netlogon_ping.h" +#include "libcli/netlogon/netlogon_proto.h" +#include "libcli/ldap/ldap_ndr.h" +#include "libcli/ldap/ldap_message.h" +#include "libcli/cldap/cldap.h" +#include "source3/include/tldap.h" +#include "source3/include/tldap_util.h" +#include "source3/lib/tldap_tls_connect.h" +#include "lib/util/tevent_unix.h" +#include "lib/util/tevent_ntstatus.h" +#include "source4/lib/tls/tls.h" +#include "source3/libads/cldap.h" + +struct ldap_netlogon_state { + struct tevent_context *ev; + struct tsocket_address *local; + struct tsocket_address *remote; + enum client_netlogon_ping_protocol proto; + const char *filter; + + struct tstream_context *plain; + struct tldap_context *tldap; + struct tstream_tls_params *tls_params; + + struct netlogon_samlogon_response *response; +}; + +static void ldap_netlogon_connected(struct tevent_req *subreq); +static void ldap_netlogon_starttls_done(struct tevent_req *subreq); +static void ldap_netlogon_tls_set_up(struct tevent_req *subreq); +static void ldap_netlogon_search(struct tevent_req *req); +static void ldap_netlogon_searched(struct tevent_req *subreq); + +static struct tevent_req *ldap_netlogon_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const struct tsocket_address *server, + enum client_netlogon_ping_protocol proto, + const char *filter) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct ldap_netlogon_state *state = NULL; + uint16_t port; + int ret; + + req = tevent_req_create(mem_ctx, &state, struct ldap_netlogon_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->filter = filter; + state->proto = proto; + + state->remote = tsocket_address_copy(server, state); + if (tevent_req_nomem(state->remote, req)) { + return tevent_req_post(req, ev); + } + + port = (proto == CLIENT_NETLOGON_PING_LDAPS) ? 636 : 389; + + ret = tsocket_address_inet_set_port(state->remote, port); + if (ret != 0) { + tevent_req_nterror(req, map_nt_error_from_unix_common(errno)); + return tevent_req_post(req, ev); + } + + ret = tsocket_address_inet_from_strings( + state, "ip", NULL, 0, &state->local); + if (ret != 0) { + tevent_req_nterror(req, map_nt_error_from_unix_common(errno)); + return tevent_req_post(req, ev); + } + + subreq = tstream_inet_tcp_connect_send(state, + state->ev, + state->local, + state->remote); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, ldap_netlogon_connected, req); + + return req; +} + +static void ldap_netlogon_connected(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ldap_netlogon_state *state = tevent_req_data( + req, struct ldap_netlogon_state); + int ret, err; + NTSTATUS status; + + ret = tstream_inet_tcp_connect_recv( + subreq, &err, state, &state->plain, NULL); + TALLOC_FREE(subreq); + if (ret == -1) { + tevent_req_nterror(req, map_nt_error_from_unix_common(err)); + return; + } + + state->tldap = tldap_context_create_from_plain_stream( + state, &state->plain); + if (tevent_req_nomem(state->tldap, req)) { + return; + } + + if (state->proto == CLIENT_NETLOGON_PING_LDAP) { + ldap_netlogon_search(req); + return; + } + + status = tstream_tls_params_client(state, + false, + NULL, + NULL, + NULL, + "NORMAL", + TLS_VERIFY_PEER_NO_CHECK, + NULL, + &state->tls_params); + if (tevent_req_nterror(req, status)) { + DBG_ERR("tstream_tls_params_client(NO_CHECK): %s\n", + nt_errstr(status)); + return; + } + + if (state->proto == CLIENT_NETLOGON_PING_STARTTLS) { + subreq = tldap_extended_send(state, + state->ev, + state->tldap, + LDB_EXTENDED_START_TLS_OID, + NULL, + NULL, + 0, + NULL, + 0); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, + ldap_netlogon_starttls_done, + req); + return; + } + + subreq = tldap_tls_connect_send(state, + state->ev, + state->tldap, + state->tls_params); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, ldap_netlogon_tls_set_up, req); +} + +static void ldap_netlogon_starttls_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ldap_netlogon_state *state = tevent_req_data( + req, struct ldap_netlogon_state); + TLDAPRC rc; + + rc = tldap_extended_recv(subreq, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!TLDAP_RC_IS_SUCCESS(rc)) { + tevent_req_nterror(req, NT_STATUS_LDAP(TLDAP_RC_V(rc))); + return; + } + + subreq = tldap_tls_connect_send(state, + state->ev, + state->tldap, + state->tls_params); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, ldap_netlogon_tls_set_up, req); +} + +static void ldap_netlogon_tls_set_up(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + TLDAPRC rc; + + rc = tldap_tls_connect_recv(subreq); + TALLOC_FREE(subreq); + if (!TLDAP_RC_IS_SUCCESS(rc)) { + tevent_req_nterror(req, NT_STATUS_LDAP(TLDAP_RC_V(rc))); + return; + } + + ldap_netlogon_search(req); +} + +static void ldap_netlogon_search(struct tevent_req *req) +{ + struct ldap_netlogon_state *state = tevent_req_data( + req, struct ldap_netlogon_state); + static const char *attrs[] = {"netlogon"}; + struct tevent_req *subreq = NULL; + + subreq = tldap_search_all_send(state, + state->ev, + state->tldap, + "", + TLDAP_SCOPE_BASE, + state->filter, + attrs, + ARRAY_SIZE(attrs), + 0, + NULL, + 0, + NULL, + 0, + 0, + 0, + 0); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, ldap_netlogon_searched, req); +} + +static void ldap_netlogon_searched(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ldap_netlogon_state *state = tevent_req_data( + req, struct ldap_netlogon_state); + struct tldap_message **msgs = NULL; + DATA_BLOB blob = {.data = NULL}; + NTSTATUS status; + TLDAPRC rc; + bool ok; + + rc = tldap_search_all_recv(subreq, state, &msgs, NULL); + TALLOC_FREE(subreq); + if (!TLDAP_RC_IS_SUCCESS(rc)) { + tevent_req_nterror(req, NT_STATUS_LDAP(TLDAP_RC_V(rc))); + return; + } + + if (talloc_array_length(msgs) != 1) { + tevent_req_nterror(req, + NT_STATUS_LDAP(TLDAP_RC_V( + TLDAP_NO_RESULTS_RETURNED))); + return; + } + + ok = tldap_get_single_valueblob(msgs[0], "netlogon", &blob); + if (!ok) { + tevent_req_nterror(req, + NT_STATUS_LDAP(TLDAP_RC_V( + TLDAP_NO_RESULTS_RETURNED))); + return; + } + + state->response = talloc(state, struct netlogon_samlogon_response); + if (tevent_req_nomem(state->response, req)) { + return; + } + + status = pull_netlogon_samlogon_response(&blob, + state->response, + state->response); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + + tevent_req_done(req); +} + +static NTSTATUS ldap_netlogon_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response **response) +{ + struct ldap_netlogon_state *state = tevent_req_data( + req, struct ldap_netlogon_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *response = talloc_move(mem_ctx, &state->response); + tevent_req_received(req); + return NT_STATUS_OK; +} + +struct cldap_netlogon_ping_state { + struct cldap_socket *sock; + struct cldap_search search; + struct netlogon_samlogon_response *response; +}; + +static void cldap_netlogon_ping_done(struct tevent_req *subreq); + +static struct tevent_req *cldap_netlogon_ping_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const struct tsocket_address *server, + const char *filter) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct cldap_netlogon_ping_state *state = NULL; + struct tsocket_address *server_389 = NULL; + static const char *const attr[] = {"NetLogon", NULL}; + int ret; + NTSTATUS status; + + req = tevent_req_create(mem_ctx, + &state, + struct cldap_netlogon_ping_state); + if (req == NULL) { + return NULL; + } + + server_389 = tsocket_address_copy(server, state); + if (tevent_req_nomem(server_389, req)) { + return tevent_req_post(req, ev); + } + + ret = tsocket_address_inet_set_port(server_389, 389); + if (ret != 0) { + tevent_req_nterror(req, map_nt_error_from_unix_common(errno)); + return tevent_req_post(req, ev); + } + + status = cldap_socket_init(state, NULL, server_389, &state->sock); + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); + } + + state->search = (struct cldap_search){ + .in.filter = filter, + .in.attributes = attr, + .in.timeout = 2, + .in.retries = 2, + }; + + subreq = cldap_search_send(state, ev, state->sock, &state->search); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cldap_netlogon_ping_done, req); + return req; +} + +static void cldap_netlogon_ping_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct cldap_netlogon_ping_state *state = tevent_req_data( + req, struct cldap_netlogon_ping_state); + struct ldap_SearchResEntry *resp = NULL; + NTSTATUS status; + + status = cldap_search_recv(subreq, state, &state->search); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + TALLOC_FREE(state->sock); + + resp = state->search.out.response; + + if (resp == NULL) { + tevent_req_nterror(req, NT_STATUS_NOT_FOUND); + return; + } + + if (resp->num_attributes != 1 || + !strequal(resp->attributes[0].name, "netlogon") || + resp->attributes[0].num_values != 1 || + resp->attributes[0].values->length < 2) + { + tevent_req_nterror(req, NT_STATUS_UNEXPECTED_NETWORK_ERROR); + return; + } + + state->response = talloc(state, struct netlogon_samlogon_response); + if (tevent_req_nomem(state->response, req)) { + return; + } + + status = pull_netlogon_samlogon_response(resp->attributes[0].values, + state->response, + state->response); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); +} + +static NTSTATUS cldap_netlogon_ping_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response **response) +{ + struct cldap_netlogon_ping_state *state = tevent_req_data( + req, struct cldap_netlogon_ping_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *response = talloc_move(mem_ctx, &state->response); + tevent_req_received(req); + return NT_STATUS_OK; +} + +struct netlogon_ping_state { + struct netlogon_samlogon_response *response; +}; + +static void netlogon_ping_done_cldap(struct tevent_req *subreq); +static void netlogon_ping_done_ldaps(struct tevent_req *subreq); + +static struct tevent_req *netlogon_ping_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tsocket_address *server, + enum client_netlogon_ping_protocol proto, + const char *filter, + struct timeval timeout) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct netlogon_ping_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct netlogon_ping_state); + if (req == NULL) { + return NULL; + } + + switch (proto) { + case CLIENT_NETLOGON_PING_CLDAP: + subreq = cldap_netlogon_ping_send(state, ev, server, filter); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, netlogon_ping_done_cldap, req); + break; + case CLIENT_NETLOGON_PING_LDAP: + case CLIENT_NETLOGON_PING_LDAPS: + case CLIENT_NETLOGON_PING_STARTTLS: + subreq = ldap_netlogon_send(state, ev, server, proto, filter); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, netlogon_ping_done_ldaps, req); + break; + default: + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + break; + } + + return req; +} + +static void netlogon_ping_done_cldap(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_ping_state *state = tevent_req_data( + req, struct netlogon_ping_state); + NTSTATUS status; + + status = cldap_netlogon_ping_recv(subreq, state, &state->response); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); +} + +static void netlogon_ping_done_ldaps(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_ping_state *state = tevent_req_data( + req, struct netlogon_ping_state); + NTSTATUS status; + + status = ldap_netlogon_recv(subreq, state, &state->response); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); +} + +static NTSTATUS netlogon_ping_recv( + struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response **response) +{ + struct netlogon_ping_state *state = tevent_req_data( + req, struct netlogon_ping_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *response = talloc_move(mem_ctx, &state->response); + return NT_STATUS_OK; +} + +struct netlogon_pings_state { + struct tevent_context *ev; + + struct tsocket_address **servers; + size_t num_servers; + size_t min_servers; + struct timeval timeout; + enum client_netlogon_ping_protocol proto; + uint32_t required_flags; + + char *filter; + size_t num_sent; + size_t num_received; + size_t num_good_received; + struct tevent_req **reqs; + struct netlogon_samlogon_response **responses; +}; + +static void netlogon_pings_next(struct tevent_req *subreq); +static void netlogon_pings_done(struct tevent_req *subreq); + +struct tevent_req *netlogon_pings_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + enum client_netlogon_ping_protocol proto, + struct tsocket_address **servers, + size_t num_servers, + struct netlogon_ping_filter filter, + size_t min_servers, + struct timeval timeout) +{ + struct tevent_req *req = NULL; + struct netlogon_pings_state *state = NULL; + char *filter_str = NULL; + size_t i; + + req = tevent_req_create(mem_ctx, &state, struct netlogon_pings_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->proto = proto; + state->servers = servers; + state->num_servers = num_servers; + state->min_servers = min_servers; + state->timeout = timeout; + state->required_flags = filter.required_flags; + + state->reqs = talloc_zero_array(state, + struct tevent_req *, + num_servers); + if (tevent_req_nomem(state->reqs, req)) { + return tevent_req_post(req, ev); + } + + state->responses = talloc_zero_array( + state, struct netlogon_samlogon_response *, num_servers); + if (tevent_req_nomem(state->responses, req)) { + return tevent_req_post(req, ev); + } + + filter_str = talloc_asprintf(state, + "(&(NtVer=%s)", + ldap_encode_ndr_uint32(state, + filter.ntversion)); + if (filter.domain != NULL) { + talloc_asprintf_addbuf(&filter_str, + "(DnsDomain=%s)", + filter.domain); + } + if (filter.acct_ctrl != -1) { + talloc_asprintf_addbuf( + &filter_str, + "(AAC=%s)", + ldap_encode_ndr_uint32(mem_ctx, filter.acct_ctrl)); + } + if (filter.domain_sid != NULL) { + talloc_asprintf_addbuf( + &filter_str, + "(domainSid=%s)", + ldap_encode_ndr_dom_sid(mem_ctx, filter.domain_sid)); + } + if (filter.domain_guid != NULL) { + talloc_asprintf_addbuf( + &filter_str, + "(DomainGuid=%s)", + ldap_encode_ndr_GUID(mem_ctx, filter.domain_guid)); + } + if (filter.hostname != NULL) { + talloc_asprintf_addbuf(&filter_str, + "(Host=%s)", + filter.hostname); + } + if (filter.user != NULL) { + talloc_asprintf_addbuf(&filter_str, "(User=%s)", filter.user); + } + talloc_asprintf_addbuf(&filter_str, ")"); + + if (tevent_req_nomem(filter_str, req)) { + return tevent_req_post(req, ev); + } + state->filter = filter_str; + + for (i = 0; i < min_servers; i++) { + state->reqs[i] = netlogon_ping_send(state->reqs, + state->ev, + state->servers[i], + state->proto, + state->filter, + state->timeout); + if (tevent_req_nomem(state->reqs[i], req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(state->reqs[i], + netlogon_pings_done, + req); + } + state->num_sent = min_servers; + if (state->num_sent < state->num_servers) { + /* + * After 100 milliseconds fire the next one + */ + struct tevent_req *subreq = tevent_wakeup_send( + state, state->ev, timeval_current_ofs(0, 100000)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, netlogon_pings_next, req); + } + + return req; +} + +static void netlogon_pings_next(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_pings_state *state = tevent_req_data( + req, struct netlogon_pings_state); + bool ret; + + ret = tevent_wakeup_recv(subreq); + TALLOC_FREE(subreq); + if (!ret) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + subreq = netlogon_ping_send(state->reqs, + state->ev, + state->servers[state->num_sent], + state->proto, + state->filter, + state->timeout); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, netlogon_pings_done, req); + state->reqs[state->num_sent] = subreq; + state->num_sent += 1; + + if (state->num_sent < state->num_servers) { + /* + * After 100 milliseconds fire the next one + */ + subreq = tevent_wakeup_send(state, + state->ev, + timeval_current_ofs(0, 100000)); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, netlogon_pings_next, req); + } +} + +static void netlogon_pings_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct netlogon_pings_state *state = tevent_req_data( + req, struct netlogon_pings_state); + struct netlogon_samlogon_response *response = NULL; + NTSTATUS status; + size_t i; + + for (i = 0; i < state->num_sent; i++) { + if (state->reqs[i] == subreq) { + break; + } + } + + if (i == state->num_sent) { + /* + * Got a response we did not fire... + */ + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + state->reqs[i] = NULL; + + status = netlogon_ping_recv(subreq, state, &response); + TALLOC_FREE(subreq); + state->num_received += 1; + + if (NT_STATUS_IS_OK(status)) { + uint32_t ret_flags; + bool ok; + + switch (response->ntver) { + case NETLOGON_NT_VERSION_5EX: + ret_flags = response->data.nt5_ex.server_type; + break; + case NETLOGON_NT_VERSION_5: + ret_flags = response->data.nt5.server_type; + break; + default: + ret_flags = 0; + break; + } + + ok = check_cldap_reply_required_flags(ret_flags, + state->required_flags); + if (ok) { + state->responses[i] = talloc_move(state->responses, + &response); + state->num_good_received += 1; + } + } + + if (state->num_good_received >= state->min_servers) { + tevent_req_done(req); + return; + } + if (state->num_received == state->num_servers) { + /* + * Everybody replied, but we did not get enough good + * answers (see above) + */ + tevent_req_nterror(req, NT_STATUS_NOT_FOUND); + return; + } + /* + * Wait for more answers + */ +} + +NTSTATUS netlogon_pings_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response ***responses) +{ + struct netlogon_pings_state *state = tevent_req_data( + req, struct netlogon_pings_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *responses = talloc_move(mem_ctx, &state->responses); + tevent_req_received(req); + return NT_STATUS_OK; +} + +NTSTATUS netlogon_pings(TALLOC_CTX *mem_ctx, + enum client_netlogon_ping_protocol proto, + struct tsocket_address **servers, + int num_servers, + struct netlogon_ping_filter filter, + int min_servers, + struct timeval timeout, + struct netlogon_samlogon_response ***responses) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = netlogon_pings_send(frame, + ev, + proto, + servers, + num_servers, + filter, + min_servers, + timeout); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = netlogon_pings_recv(req, mem_ctx, responses); + fail: + TALLOC_FREE(frame); + return status; +} diff --git a/source3/libads/netlogon_ping.h b/source3/libads/netlogon_ping.h new file mode 100644 index 00000000000..dc238bd1c62 --- /dev/null +++ b/source3/libads/netlogon_ping.h @@ -0,0 +1,60 @@ +/* + * Samba Unix/Linux SMB client library + * + * 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 . + */ + +#ifndef _LIBADS_NETLOGON_PING_H_ +#define _LIBADS_NETLOGON_PING_H_ + +#include "replace.h" +#include "lib/tsocket/tsocket.h" +#include "librpc/gen_ndr/nbt.h" +#include "libcli/util/ntstatus.h" +#include "lib/param/loadparm.h" + +struct netlogon_samlogon_response; + +struct netlogon_ping_filter { + unsigned ntversion; + const char *domain; + const struct dom_sid *domain_sid; + const struct GUID *domain_guid; + const char *hostname; + const char *user; + int acct_ctrl; + uint32_t required_flags; +}; + +struct tevent_req *netlogon_pings_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + enum client_netlogon_ping_protocol proto, + struct tsocket_address **servers, + size_t num_servers, + struct netlogon_ping_filter filter, + size_t min_servers, + struct timeval timeout); +NTSTATUS netlogon_pings_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct netlogon_samlogon_response ***responses); +NTSTATUS netlogon_pings(TALLOC_CTX *mem_ctx, + enum client_netlogon_ping_protocol proto, + struct tsocket_address **servers, + int num_servers, + struct netlogon_ping_filter filter, + int min_servers, + struct timeval timeout, + struct netlogon_samlogon_response ***responses); + +#endif /* _LIBADS_NETLOGON_PING_H_ */ diff --git a/source3/wscript_build b/source3/wscript_build index 93dffdebd90..0c9f6ad3143 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -469,9 +469,13 @@ bld.SAMBA3_LIBRARY('libsmb', ''', private_library=True) +bld.SAMBA3_SUBSYSTEM('NETLOGON_PING', + source='libads/netlogon_ping.c', + deps='TLDAP cli_cldap') + bld.SAMBA3_SUBSYSTEM('CLDAP', source='libads/cldap.c', - deps='cli-ldap-common cli_cldap LIBTSOCKET') + deps='cli-ldap-common cli_cldap LIBTSOCKET NETLOGON_PING') # NOTE: The secrets3 library is a low level library used by several subsystems. # PLEASE DO NOT make it depend on high level libraries like PDB, if you are