From a3306e352dad74c3c6ce441610defc472d570f4f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 6 Oct 2009 18:26:33 +0200 Subject: s3-winbindd: add wbint_ChangeMachineAccount implementation. Guenther --- source3/winbindd/winbindd.c | 2 + source3/winbindd/winbindd_cache.c | 1 + source3/winbindd/winbindd_change_machine_acct.c | 93 +++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 62 +++++++++++++++++ source3/winbindd/winbindd_proto.h | 7 ++ 5 files changed, 165 insertions(+) create mode 100644 source3/winbindd/winbindd_change_machine_acct.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index f0160fcb78..e09374c5cb 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -547,6 +547,8 @@ static struct winbindd_async_dispatch_table async_priv_table[] = { winbindd_remove_mapping_send, winbindd_remove_mapping_recv }, { WINBINDD_SET_HWM, "SET_HWM", winbindd_set_hwm_send, winbindd_set_hwm_recv }, + { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC", + winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv }, { 0, NULL, NULL, NULL } }; diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 543b8b12b7..c4bc936a5d 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -4360,6 +4360,7 @@ static bool wcache_opnum_cacheable(uint32_t opnum) case NDR_WBINT_ALLOCATEUID: case NDR_WBINT_ALLOCATEGID: case NDR_WBINT_CHECKMACHINEACCOUNT: + case NDR_WBINT_CHANGEMACHINEACCOUNT: return false; } return true; diff --git a/source3/winbindd/winbindd_change_machine_acct.c b/source3/winbindd/winbindd_change_machine_acct.c new file mode 100644 index 0000000000..a49315d1be --- /dev/null +++ b/source3/winbindd/winbindd_change_machine_acct.c @@ -0,0 +1,93 @@ +/* + 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 . +*/ + +#include "includes.h" +#include "winbindd.h" +#include "librpc/gen_ndr/cli_wbint.h" + +struct winbindd_change_machine_acct_state { + uint8_t dummy; +}; + +static void winbindd_change_machine_acct_done(struct tevent_req *subreq); + +struct tevent_req *winbindd_change_machine_acct_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct winbindd_cli_state *cli, + struct winbindd_request *request) +{ + struct tevent_req *req, *subreq; + struct winbindd_change_machine_acct_state *state; + struct winbindd_domain *domain; + + req = tevent_req_create(mem_ctx, &state, + struct winbindd_change_machine_acct_state); + if (req == NULL) { + return NULL; + } + + domain = find_domain_from_name(request->domain_name); + if (domain == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN); + return tevent_req_post(req, ev); + } + if (domain->internal) { + /* + * Internal domains are passdb based, we can always + * contact them. + */ + tevent_req_done(req); + return tevent_req_post(req, ev); + } + + subreq = rpccli_wbint_ChangeMachineAccount_send(state, ev, + domain->child.rpccli); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, winbindd_change_machine_acct_done, req); + return req; +} + +static void winbindd_change_machine_acct_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct winbindd_change_machine_acct_state *state = tevent_req_data( + req, struct winbindd_change_machine_acct_state); + NTSTATUS status, result; + + status = rpccli_wbint_ChangeMachineAccount_recv(subreq, state, &result); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + if (!NT_STATUS_IS_OK(result)) { + tevent_req_nterror(req, result); + return; + } + tevent_req_done(req); +} + +NTSTATUS winbindd_change_machine_acct_recv(struct tevent_req *req, + struct winbindd_response *presp) +{ + return tevent_req_simple_recv_ntstatus(req); +} diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 337486107f..f0bbee9f31 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -4,6 +4,7 @@ In-Child server implementation of the routines defined in wbint.idl 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 @@ -448,6 +449,67 @@ again: return status; } +NTSTATUS _wbint_ChangeMachineAccount(pipes_struct *p, + struct wbint_ChangeMachineAccount *r) +{ + struct winbindd_domain *domain; + int num_retries = 0; + NTSTATUS status; + struct rpc_pipe_client *netlogon_pipe; + TALLOC_CTX *tmp_ctx; + +again: + domain = wb_child_domain(); + if (domain == NULL) { + return NT_STATUS_REQUEST_NOT_ACCEPTED; + } + + invalidate_cm_connection(&domain->conn); + + { + status = cm_connect_netlogon(domain, &netlogon_pipe); + } + + /* There is a race condition between fetching the trust account + password and the periodic machine password change. So it's + possible that the trust account password has been changed on us. + We are returned NT_STATUS_ACCESS_DENIED if this happens. */ + +#define MAX_RETRIES 3 + + if ((num_retries < MAX_RETRIES) + && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + num_retries++; + goto again; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("could not open handle to NETLOGON pipe\n")); + goto done; + } + + tmp_ctx = talloc_new(p->mem_ctx); + + status = trust_pw_find_change_and_store_it(netlogon_pipe, + tmp_ctx, + domain->name); + talloc_destroy(tmp_ctx); + + /* Pass back result code - zero for success, other values for + specific failures. */ + + DEBUG(3,("domain %s secret %s\n", domain->name, + NT_STATUS_IS_OK(status) ? "changed" : "unchanged")); + + done: + DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2, + ("Changing the trust account password for domain %s returned %s\n", + domain->name, nt_errstr(status))); + + return status; +} + + NTSTATUS _wbint_SetMapping(pipes_struct *p, struct wbint_SetMapping *r) { struct id_map map; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 307225877f..21feddf6d6 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -995,6 +995,13 @@ struct tevent_req *winbindd_check_machine_acct_send(TALLOC_CTX *mem_ctx, NTSTATUS winbindd_check_machine_acct_recv(struct tevent_req *req, struct winbindd_response *presp); +struct tevent_req *winbindd_change_machine_acct_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct winbindd_cli_state *cli, + struct winbindd_request *request); +NTSTATUS winbindd_change_machine_acct_recv(struct tevent_req *req, + struct winbindd_response *presp); + struct tevent_req *winbindd_set_mapping_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct winbindd_cli_state *cli, -- cgit