source: branches/samba-3.2.x/source/libsmb/trusts_util.c

Last change on this file was 204, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 branch to 3.2.4

File size: 8.5 KB
Line 
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
6 *
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.
11 *
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.
16 *
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/>.
19 */
20
21#include "includes.h"
22
23/*********************************************************
24 Change the domain password on the PDC.
25
26 Just changes the password betwen the two values specified.
27
28 Caller must have the cli connected to the netlogon pipe
29 already.
30**********************************************************/
31
32static 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)
37{
38 NTSTATUS result;
39 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
40
41 result = rpccli_netlogon_setup_creds(cli,
42 cli->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);
49
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;
54 }
55
56 if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) {
57
58 struct netr_Authenticator clnt_creds, srv_cred;
59 struct netr_CryptPassword new_password;
60 struct samr_CryptPassword password_buf;
61
62 netlogon_creds_client_step(cli->dc, &clnt_creds);
63
64 encode_pw_buffer(password_buf.data, new_trust_pwd_cleartext, STR_UNICODE);
65
66 SamOEMhash(password_buf.data, cli->dc->sess_key, 516);
67 memcpy(new_password.data, password_buf.data, 512);
68 new_password.length = IVAL(password_buf.data, 512);
69
70 result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx,
71 cli->dc->remote_machine,
72 cli->dc->mach_acct,
73 sec_channel_type,
74 global_myname(),
75 &clnt_creds,
76 &srv_cred,
77 &new_password);
78
79 /* Always check returned credentials. */
80 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
81 DEBUG(0,("rpccli_netr_ServerPasswordSet2: "
82 "credentials chain check failed\n"));
83 return NT_STATUS_ACCESS_DENIED;
84 }
85
86 } else {
87
88 struct netr_Authenticator clnt_creds, srv_cred;
89 struct samr_Password new_password;
90
91 netlogon_creds_client_step(cli->dc, &clnt_creds);
92
93 cred_hash3(new_password.hash,
94 new_trust_passwd_hash,
95 cli->dc->sess_key, 1);
96
97 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
98 cli->dc->remote_machine,
99 cli->dc->mach_acct,
100 sec_channel_type,
101 global_myname(),
102 &clnt_creds,
103 &srv_cred,
104 &new_password);
105
106 /* Always check returned credentials. */
107 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
108 DEBUG(0,("rpccli_netr_ServerPasswordSet: "
109 "credentials chain check failed\n"));
110 return NT_STATUS_ACCESS_DENIED;
111 }
112 }
113
114 if (!NT_STATUS_IS_OK(result)) {
115 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
116 nt_errstr(result)));
117 }
118 return result;
119}
120
121/*********************************************************
122 Change the domain password on the PDC.
123 Store the password ourselves, but use the supplied password
124 Caller must have already setup the connection to the NETLOGON pipe
125**********************************************************/
126
127NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
128 const char *domain,
129 unsigned char orig_trust_passwd_hash[16],
130 uint32 sec_channel_type)
131{
132 unsigned char new_trust_passwd_hash[16];
133 char *new_trust_passwd;
134 char *str;
135 NTSTATUS nt_status;
136
137 /* Create a random machine account password */
138 str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
139
140 if ((new_trust_passwd = talloc_strdup(mem_ctx, str)) == NULL) {
141 DEBUG(0, ("talloc_strdup failed\n"));
142 return NT_STATUS_NO_MEMORY;
143 }
144
145 E_md4hash(new_trust_passwd, new_trust_passwd_hash);
146
147 nt_status = just_change_the_password(cli, mem_ctx,
148 orig_trust_passwd_hash,
149 new_trust_passwd,
150 new_trust_passwd_hash,
151 sec_channel_type);
152
153 if (NT_STATUS_IS_OK(nt_status)) {
154 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
155 current_timestring(debug_ctx(), False)));
156 /*
157 * Return the result of trying to write the new password
158 * back into the trust account file.
159 */
160 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
161 nt_status = NT_STATUS_UNSUCCESSFUL;
162 }
163 }
164
165 return nt_status;
166}
167
168/*********************************************************
169 Change the domain password on the PDC.
170 Do most of the legwork ourselfs. Caller must have
171 already setup the connection to the NETLOGON pipe
172**********************************************************/
173
174NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli,
175 TALLOC_CTX *mem_ctx,
176 const char *domain)
177{
178 unsigned char old_trust_passwd_hash[16];
179 uint32 sec_channel_type = 0;
180
181 if (!secrets_fetch_trust_account_password(domain,
182 old_trust_passwd_hash,
183 NULL, &sec_channel_type)) {
184 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
185 return NT_STATUS_UNSUCCESSFUL;
186 }
187
188 return trust_pw_change_and_store_it(cli, mem_ctx, domain,
189 old_trust_passwd_hash,
190 sec_channel_type);
191}
192
193/*********************************************************************
194 Enumerate the list of trusted domains from a DC
195*********************************************************************/
196
197bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
198 char ***domain_names, uint32 *num_domains,
199 DOM_SID **sids )
200{
201 POLICY_HND pol;
202 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
203 fstring dc_name;
204 struct sockaddr_storage dc_ss;
205 uint32 enum_ctx = 0;
206 struct cli_state *cli = NULL;
207 struct rpc_pipe_client *lsa_pipe;
208 bool retry;
209 struct lsa_DomainList dom_list;
210 int i;
211
212 *domain_names = NULL;
213 *num_domains = 0;
214 *sids = NULL;
215
216 /* lookup a DC first */
217
218 if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) {
219 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
220 domain));
221 return False;
222 }
223
224 /* setup the anonymous connection */
225
226 result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC",
227 "", "", "", 0, Undefined, &retry);
228 if ( !NT_STATUS_IS_OK(result) )
229 goto done;
230
231 /* open the LSARPC_PIPE */
232
233 lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
234 if ( !lsa_pipe) {
235 goto done;
236 }
237
238 /* get a handle */
239
240 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
241 LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol);
242 if ( !NT_STATUS_IS_OK(result) )
243 goto done;
244
245 /* Lookup list of trusted domains */
246
247 result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx,
248 &pol,
249 &enum_ctx,
250 &dom_list,
251 (uint32_t)-1);
252 if ( !NT_STATUS_IS_OK(result) )
253 goto done;
254
255 *num_domains = dom_list.count;
256
257 *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains);
258 if (!*domain_names) {
259 result = NT_STATUS_NO_MEMORY;
260 goto done;
261 }
262
263 *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains);
264 if (!*sids) {
265 result = NT_STATUS_NO_MEMORY;
266 goto done;
267 }
268
269 for (i=0; i< *num_domains; i++) {
270 (*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
271 (*sids)[i] = *dom_list.domains[i].sid;
272 }
273
274done:
275 /* cleanup */
276 if (cli) {
277 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
278 cli_shutdown( cli );
279 }
280
281 return NT_STATUS_IS_OK(result);
282}
Note: See TracBrowser for help on using the repository browser.