mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
s3-winbindd: Listen on IRPC and do forwarded DNS updates on an RODC
Change-Id: Ib87933c318f510d95f7008e122216d73803ede68 Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
This commit is contained in:
parent
cb79cc342e
commit
223fbdaf38
@ -2568,3 +2568,268 @@ NTSTATUS netlogon_creds_cli_LogonSamLogon(
|
||||
TALLOC_FREE(frame);
|
||||
return status;
|
||||
}
|
||||
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state {
|
||||
struct tevent_context *ev;
|
||||
struct netlogon_creds_cli_context *context;
|
||||
struct dcerpc_binding_handle *binding_handle;
|
||||
|
||||
char *srv_name_slash;
|
||||
enum dcerpc_AuthType auth_type;
|
||||
enum dcerpc_AuthLevel auth_level;
|
||||
|
||||
const char *site_name;
|
||||
uint32_t dns_ttl;
|
||||
struct NL_DNS_NAME_INFO_ARRAY *dns_names;
|
||||
|
||||
struct netlogon_creds_CredentialState *creds;
|
||||
struct netlogon_creds_CredentialState tmp_creds;
|
||||
struct netr_Authenticator req_auth;
|
||||
struct netr_Authenticator rep_auth;
|
||||
};
|
||||
|
||||
static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
|
||||
NTSTATUS status);
|
||||
static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq);
|
||||
|
||||
struct tevent_req *netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct netlogon_creds_cli_context *context,
|
||||
struct dcerpc_binding_handle *b,
|
||||
const char *site_name,
|
||||
uint32_t dns_ttl,
|
||||
struct NL_DNS_NAME_INFO_ARRAY *dns_names)
|
||||
{
|
||||
struct tevent_req *req;
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state;
|
||||
struct tevent_req *subreq;
|
||||
bool ok;
|
||||
|
||||
req = tevent_req_create(mem_ctx, &state,
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->ev = ev;
|
||||
state->context = context;
|
||||
state->binding_handle = b;
|
||||
|
||||
state->srv_name_slash = talloc_asprintf(state, "\\\\%s",
|
||||
context->server.computer);
|
||||
if (tevent_req_nomem(state->srv_name_slash, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
state->site_name = site_name;
|
||||
state->dns_ttl = dns_ttl;
|
||||
state->dns_names = dns_names;
|
||||
|
||||
dcerpc_binding_handle_auth_info(state->binding_handle,
|
||||
&state->auth_type,
|
||||
&state->auth_level);
|
||||
|
||||
subreq = netlogon_creds_cli_lock_send(state, state->ev,
|
||||
state->context);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
|
||||
tevent_req_set_callback(subreq,
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked,
|
||||
req);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(struct tevent_req *req,
|
||||
NTSTATUS status)
|
||||
{
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
|
||||
tevent_req_data(req,
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
|
||||
|
||||
if (state->creds == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED) &&
|
||||
!NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) &&
|
||||
!NT_STATUS_EQUAL(status, NT_STATUS_DOWNGRADE_DETECTED) &&
|
||||
!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
|
||||
!NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
|
||||
TALLOC_FREE(state->creds);
|
||||
return;
|
||||
}
|
||||
|
||||
netlogon_creds_cli_delete(state->context, &state->creds);
|
||||
}
|
||||
|
||||
static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq);
|
||||
|
||||
static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_locked(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct tevent_req);
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
|
||||
tevent_req_data(req,
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
|
||||
NTSTATUS status;
|
||||
|
||||
status = netlogon_creds_cli_lock_recv(subreq, state,
|
||||
&state->creds);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) {
|
||||
switch (state->auth_level) {
|
||||
case DCERPC_AUTH_LEVEL_INTEGRITY:
|
||||
case DCERPC_AUTH_LEVEL_PRIVACY:
|
||||
break;
|
||||
default:
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
uint32_t tmp = state->creds->negotiate_flags;
|
||||
|
||||
if (tmp & NETLOGON_NEG_AUTHENTICATED_RPC) {
|
||||
/*
|
||||
* if DCERPC_AUTH_TYPE_SCHANNEL is supported
|
||||
* it should be used, which means
|
||||
* we had a chance to verify no downgrade
|
||||
* happened.
|
||||
*
|
||||
* This relies on netlogon_creds_cli_check*
|
||||
* being called before, as first request after
|
||||
* the DCERPC bind.
|
||||
*/
|
||||
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER_MIX);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* we defer all callbacks in order to cleanup
|
||||
* the database record.
|
||||
*/
|
||||
tevent_req_defer_callback(req, state->ev);
|
||||
|
||||
state->tmp_creds = *state->creds;
|
||||
netlogon_creds_client_authenticator(&state->tmp_creds,
|
||||
&state->req_auth);
|
||||
ZERO_STRUCT(state->rep_auth);
|
||||
|
||||
subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_send(state, state->ev,
|
||||
state->binding_handle,
|
||||
state->srv_name_slash,
|
||||
state->tmp_creds.computer_name,
|
||||
&state->req_auth,
|
||||
&state->rep_auth,
|
||||
state->site_name,
|
||||
state->dns_ttl,
|
||||
state->dns_names);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_set_callback(subreq,
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done,
|
||||
req);
|
||||
}
|
||||
|
||||
static void netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct tevent_req);
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state *state =
|
||||
tevent_req_data(req,
|
||||
struct netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_state);
|
||||
NTSTATUS status;
|
||||
NTSTATUS result;
|
||||
bool ok;
|
||||
|
||||
status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_recv(subreq, state,
|
||||
&result);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
ok = netlogon_creds_client_check(&state->tmp_creds,
|
||||
&state->rep_auth.cred);
|
||||
if (!ok) {
|
||||
status = NT_STATUS_ACCESS_DENIED;
|
||||
tevent_req_nterror(req, status);
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tevent_req_nterror(req, result)) {
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, result);
|
||||
return;
|
||||
}
|
||||
|
||||
*state->creds = state->tmp_creds;
|
||||
status = netlogon_creds_cli_store(state->context,
|
||||
&state->creds);
|
||||
if (tevent_req_nterror(req, status)) {
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
|
||||
return;
|
||||
}
|
||||
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req *req)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if (tevent_req_is_nterror(req, &status)) {
|
||||
netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_cleanup(req, status);
|
||||
tevent_req_received(req);
|
||||
return status;
|
||||
}
|
||||
|
||||
tevent_req_received(req);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
|
||||
struct netlogon_creds_cli_context *context,
|
||||
struct dcerpc_binding_handle *b,
|
||||
const char *site_name,
|
||||
uint32_t dns_ttl,
|
||||
struct NL_DNS_NAME_INFO_ARRAY *dns_names)
|
||||
{
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct tevent_context *ev;
|
||||
struct tevent_req *req;
|
||||
NTSTATUS status = NT_STATUS_NO_MEMORY;
|
||||
|
||||
ev = samba_tevent_context_init(frame);
|
||||
if (ev == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
req = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(frame, ev, context, b,
|
||||
site_name,
|
||||
dns_ttl,
|
||||
dns_names);
|
||||
if (req == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
if (!tevent_req_poll_ntstatus(req, ev, &status)) {
|
||||
goto fail;
|
||||
}
|
||||
status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(req);
|
||||
fail:
|
||||
TALLOC_FREE(frame);
|
||||
return status;
|
||||
}
|
||||
|
@ -132,5 +132,19 @@ NTSTATUS netlogon_creds_cli_LogonSamLogon(
|
||||
union netr_Validation **validation,
|
||||
uint8_t *authoritative,
|
||||
uint32_t *flags);
|
||||
struct tevent_req *netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_send(TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct netlogon_creds_cli_context *context,
|
||||
struct dcerpc_binding_handle *b,
|
||||
const char *site_name,
|
||||
uint32_t dns_ttl,
|
||||
struct NL_DNS_NAME_INFO_ARRAY *dns_names);
|
||||
NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords_recv(struct tevent_req *req);
|
||||
NTSTATUS netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(
|
||||
struct netlogon_creds_cli_context *context,
|
||||
struct dcerpc_binding_handle *b,
|
||||
const char *site_name,
|
||||
uint32_t dns_ttl,
|
||||
struct NL_DNS_NAME_INFO_ARRAY *dns_names);
|
||||
|
||||
#endif /* NETLOGON_CREDS_CLI_H */
|
||||
|
@ -167,4 +167,10 @@ interface wbint
|
||||
NTSTATUS wbint_PingDc(
|
||||
[out,string,charset(UTF8)] char **dcname
|
||||
);
|
||||
|
||||
NTSTATUS wbint_DsrUpdateReadOnlyServerDnsRecords(
|
||||
[in,unique] [string,charset(UTF16)] uint16 *site_name,
|
||||
[in] uint32 dns_ttl,
|
||||
[in,out,ref] NL_DNS_NAME_INFO_ARRAY *dns_names
|
||||
);
|
||||
}
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "source4/lib/messaging/irpc.h"
|
||||
#include "source4/lib/messaging/messaging.h"
|
||||
#include "lib/param/param.h"
|
||||
#include "source4/librpc/gen_ndr/ndr_winbind.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_WINBIND
|
||||
@ -1147,6 +1148,7 @@ bool winbindd_use_cache(void)
|
||||
static void winbindd_register_handlers(struct messaging_context *msg_ctx,
|
||||
bool foreground)
|
||||
{
|
||||
NTSTATUS status;
|
||||
/* Setup signal handlers */
|
||||
|
||||
if (!winbindd_setup_sig_term_handler(true))
|
||||
@ -1246,6 +1248,12 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
status = IRPC_REGISTER(winbind_imessaging_context(), winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
|
||||
wb_irpc_DsrUpdateReadOnlyServerDnsRecords, NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0, ("Could not register IRPC handler for wb_irpc_DsrUpdateReadOnlyServerDnsRecords\n"));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
struct winbindd_addrchanged_state {
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../librpc/gen_ndr/ndr_netlogon_c.h"
|
||||
#include "idmap.h"
|
||||
#include "../libcli/security/security.h"
|
||||
#include "../libcli/auth/netlogon_creds_cli.h"
|
||||
|
||||
void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
|
||||
{
|
||||
@ -717,3 +718,41 @@ NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
|
||||
DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS _wbint_DsrUpdateReadOnlyServerDnsRecords(struct pipes_struct *p,
|
||||
struct wbint_DsrUpdateReadOnlyServerDnsRecords *r)
|
||||
{
|
||||
struct winbindd_domain *domain;
|
||||
NTSTATUS status;
|
||||
struct rpc_pipe_client *netlogon_pipe;
|
||||
|
||||
domain = wb_child_domain();
|
||||
if (domain == NULL) {
|
||||
return NT_STATUS_REQUEST_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
status = cm_connect_netlogon(domain, &netlogon_pipe);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = netlogon_creds_cli_DsrUpdateReadOnlyServerDnsRecords(domain->conn.netlogon_creds,
|
||||
netlogon_pipe->binding_handle,
|
||||
r->in.site_name,
|
||||
r->in.dns_ttl,
|
||||
r->in.dns_names);
|
||||
|
||||
/* Pass back result code - zero for success, other values for
|
||||
specific failures. */
|
||||
|
||||
DEBUG(3,("DNS records for domain %s %s\n", domain->name,
|
||||
NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
|
||||
|
||||
done:
|
||||
DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
|
||||
("Update of DNS records via RW DC %s returned %s\n",
|
||||
domain->name, nt_errstr(status)));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -908,4 +908,9 @@ NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
|
||||
/* The following definitions come from winbindd/winbindd_ads.c */
|
||||
ADS_STATUS ads_idmap_cached_connection(ADS_STRUCT **adsp, const char *dom_name);
|
||||
|
||||
/* The following definitions come from winbindd/winbindd_update_rodc_dns.c */
|
||||
struct irpc_message;
|
||||
struct winbind_DsrUpdateReadOnlyServerDnsRecords;
|
||||
NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *msg,
|
||||
struct winbind_DsrUpdateReadOnlyServerDnsRecords *req);
|
||||
#endif /* _WINBINDD_PROTO_H_ */
|
||||
|
85
source3/winbindd/winbindd_update_rodc_dns.c
Normal file
85
source3/winbindd/winbindd_update_rodc_dns.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
async implementation of WINBINDD_CHANGE_MACHINE_ACCT
|
||||
Copyright (C) Volker Lendecke 2009
|
||||
Copyright (C) Guenther Deschner 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/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "winbindd.h"
|
||||
#include "librpc/gen_ndr/ndr_wbint_c.h"
|
||||
#include "librpc/gen_ndr/ndr_winbind_c.h"
|
||||
#include "source4/lib/messaging/irpc.h"
|
||||
|
||||
struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state {
|
||||
struct irpc_message *msg;
|
||||
struct winbind_DsrUpdateReadOnlyServerDnsRecords *req;
|
||||
};
|
||||
|
||||
static void wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback(struct tevent_req *subreq);
|
||||
|
||||
NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *msg,
|
||||
struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
|
||||
{
|
||||
struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state *s;
|
||||
struct tevent_req *subreq;
|
||||
struct winbindd_domain *domain;
|
||||
|
||||
DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords called\n"));
|
||||
|
||||
s = talloc(msg, struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state);
|
||||
NT_STATUS_HAVE_NO_MEMORY(s);
|
||||
|
||||
s->msg = msg;
|
||||
s->req = req;
|
||||
|
||||
domain = find_our_domain();
|
||||
if (domain == NULL) {
|
||||
return NT_STATUS_NO_SUCH_DOMAIN;
|
||||
}
|
||||
|
||||
subreq = dcerpc_wbint_DsrUpdateReadOnlyServerDnsRecords_send(s, winbind_event_context(),
|
||||
dom_child_handle(domain),
|
||||
req->in.site_name,
|
||||
req->in.dns_ttl,
|
||||
req->in.dns_names);
|
||||
if (!subreq) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
tevent_req_set_callback(subreq,
|
||||
wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback,
|
||||
s);
|
||||
|
||||
msg->defer_reply = true;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static void wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback(struct tevent_req *subreq)
|
||||
{
|
||||
struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state *s =
|
||||
tevent_req_callback_data(subreq,
|
||||
struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state);
|
||||
NTSTATUS status, result;
|
||||
|
||||
DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback called\n"));
|
||||
|
||||
status = dcerpc_wbint_DsrUpdateReadOnlyServerDnsRecords_recv(subreq, s, &result);
|
||||
any_nt_status_not_ok(status, result, &status);
|
||||
TALLOC_FREE(subreq);
|
||||
|
||||
irpc_send_reply(s->msg, status);
|
||||
}
|
@ -943,6 +943,7 @@ bld.SAMBA3_BINARY('winbindd/winbindd',
|
||||
winbindd/winbindd_list_groups.c
|
||||
winbindd/winbindd_check_machine_acct.c
|
||||
winbindd/winbindd_change_machine_acct.c
|
||||
winbindd/winbindd_update_rodc_dns.c
|
||||
winbindd/winbindd_ping_dc.c
|
||||
winbindd/winbindd_pam_auth.c
|
||||
winbindd/winbindd_pam_logoff.c
|
||||
|
Loading…
Reference in New Issue
Block a user