netlogon: use init_netr_CryptPassword in "just_change_the_password"
[Samba.git] / source / libsmb / trusts_util.c
blob9265c60665d6b7e7956d071dcc8fe53e8ec84cdc
1 /*
2 * Unix SMB/CIFS implementation.
3 * Routines to operate on various trust relationships
4 * Copyright (C) Andrew Bartlett 2001
5 * Copyright (C) Rafal Szczesniak 2003
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
23 /*********************************************************
24 Change the domain password on the PDC.
26 Just changes the password betwen the two values specified.
28 Caller must have the cli connected to the netlogon pipe
29 already.
30 **********************************************************/
32 static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
33 const unsigned char orig_trust_passwd_hash[16],
34 const char *new_trust_pwd_cleartext,
35 const unsigned char new_trust_passwd_hash[16],
36 uint32 sec_channel_type)
38 NTSTATUS result;
39 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
41 result = rpccli_netlogon_setup_creds(cli,
42 cli->desthost, /* server name */
43 lp_workgroup(), /* domain */
44 global_myname(), /* client name */
45 global_myname(), /* machine account name */
46 orig_trust_passwd_hash,
47 sec_channel_type,
48 &neg_flags);
50 if (!NT_STATUS_IS_OK(result)) {
51 DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
52 nt_errstr(result)));
53 return result;
56 if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
58 struct netr_Authenticator clnt_creds, srv_cred;
59 struct netr_CryptPassword new_password;
61 netlogon_creds_client_step(cli->dc, &clnt_creds);
63 init_netr_CryptPassword(new_trust_pwd_cleartext,
64 cli->dc->sess_key,
65 &new_password);
67 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
68 cli->dc->remote_machine,
69 cli->dc->mach_acct,
70 sec_channel_type,
71 global_myname(),
72 &clnt_creds,
73 &srv_cred,
74 &new_password);
76 /* Always check returned credentials. */
77 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
78 DEBUG(0,("rpccli_netr_ServerPasswordSet2: "
79 "credentials chain check failed\n"));
80 return NT_STATUS_ACCESS_DENIED;
83 } else {
85 struct netr_Authenticator clnt_creds, srv_cred;
86 struct samr_Password new_password;
88 netlogon_creds_client_step(cli->dc, &clnt_creds);
90 cred_hash3(new_password.hash,
91 new_trust_passwd_hash,
92 cli->dc->sess_key, 1);
94 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
95 cli->dc->remote_machine,
96 cli->dc->mach_acct,
97 sec_channel_type,
98 global_myname(),
99 &clnt_creds,
100 &srv_cred,
101 &new_password);
103 /* Always check returned credentials. */
104 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
105 DEBUG(0,("rpccli_netr_ServerPasswordSet: "
106 "credentials chain check failed\n"));
107 return NT_STATUS_ACCESS_DENIED;
111 if (!NT_STATUS_IS_OK(result)) {
112 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
113 nt_errstr(result)));
115 return result;
118 /*********************************************************
119 Change the domain password on the PDC.
120 Store the password ourselves, but use the supplied password
121 Caller must have already setup the connection to the NETLOGON pipe
122 **********************************************************/
124 NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
125 const char *domain,
126 unsigned char orig_trust_passwd_hash[16],
127 uint32 sec_channel_type)
129 unsigned char new_trust_passwd_hash[16];
130 char *new_trust_passwd;
131 char *str;
132 NTSTATUS nt_status;
134 /* Create a random machine account password */
135 str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
137 if ((new_trust_passwd = talloc_strdup(mem_ctx, str)) == NULL) {
138 DEBUG(0, ("talloc_strdup failed\n"));
139 return NT_STATUS_NO_MEMORY;
142 E_md4hash(new_trust_passwd, new_trust_passwd_hash);
144 nt_status = just_change_the_password(cli, mem_ctx,
145 orig_trust_passwd_hash,
146 new_trust_passwd,
147 new_trust_passwd_hash,
148 sec_channel_type);
150 if (NT_STATUS_IS_OK(nt_status)) {
151 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
152 current_timestring(debug_ctx(), False)));
154 * Return the result of trying to write the new password
155 * back into the trust account file.
157 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
158 nt_status = NT_STATUS_UNSUCCESSFUL;
162 return nt_status;
165 /*********************************************************
166 Change the domain password on the PDC.
167 Do most of the legwork ourselfs. Caller must have
168 already setup the connection to the NETLOGON pipe
169 **********************************************************/
171 NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli,
172 TALLOC_CTX *mem_ctx,
173 const char *domain)
175 unsigned char old_trust_passwd_hash[16];
176 uint32 sec_channel_type = 0;
178 if (!secrets_fetch_trust_account_password(domain,
179 old_trust_passwd_hash,
180 NULL, &sec_channel_type)) {
181 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
182 return NT_STATUS_UNSUCCESSFUL;
185 return trust_pw_change_and_store_it(cli, mem_ctx, domain,
186 old_trust_passwd_hash,
187 sec_channel_type);
190 /*********************************************************************
191 Enumerate the list of trusted domains from a DC
192 *********************************************************************/
194 bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
195 char ***domain_names, uint32 *num_domains,
196 DOM_SID **sids )
198 POLICY_HND pol;
199 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
200 fstring dc_name;
201 struct sockaddr_storage dc_ss;
202 uint32 enum_ctx = 0;
203 struct cli_state *cli = NULL;
204 struct rpc_pipe_client *lsa_pipe;
205 bool retry;
206 struct lsa_DomainList dom_list;
207 int i;
209 *domain_names = NULL;
210 *num_domains = 0;
211 *sids = NULL;
213 /* lookup a DC first */
215 if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) {
216 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
217 domain));
218 return False;
221 /* setup the anonymous connection */
223 result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC",
224 "", "", "", 0, Undefined, &retry);
225 if ( !NT_STATUS_IS_OK(result) )
226 goto done;
228 /* open the LSARPC_PIPE */
230 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
231 &lsa_pipe);
232 if (!NT_STATUS_IS_OK(result)) {
233 goto done;
236 /* get a handle */
238 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
239 LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol);
240 if ( !NT_STATUS_IS_OK(result) )
241 goto done;
243 /* Lookup list of trusted domains */
245 result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx,
246 &pol,
247 &enum_ctx,
248 &dom_list,
249 (uint32_t)-1);
250 if ( !NT_STATUS_IS_OK(result) )
251 goto done;
253 *num_domains = dom_list.count;
255 *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains);
256 if (!*domain_names) {
257 result = NT_STATUS_NO_MEMORY;
258 goto done;
261 *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains);
262 if (!*sids) {
263 result = NT_STATUS_NO_MEMORY;
264 goto done;
267 for (i=0; i< *num_domains; i++) {
268 (*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
269 (*sids)[i] = *dom_list.domains[i].sid;
272 done:
273 /* cleanup */
274 if (cli) {
275 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
276 cli_shutdown( cli );
279 return NT_STATUS_IS_OK(result);