More updates - more node-type doco is required.
[Samba/gebeck_regimport.git] / source3 / libsmb / trusts_util.c
blob20ac0143fd74bbebf794890cbc85e287a0224aa2
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 unsigned char new_trust_passwd_hash[16],
35 uint32 sec_channel_type)
37 NTSTATUS result;
39 /* Check if the netlogon pipe is open using schannel. If so we
40 already have valid creds. If not we must set them up. */
42 if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
43 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
45 result = rpccli_netlogon_setup_creds(cli,
46 cli->desthost, /* server name */
47 lp_workgroup(), /* domain */
48 global_myname(), /* client name */
49 global_myname(), /* machine account name */
50 orig_trust_passwd_hash,
51 sec_channel_type,
52 &neg_flags);
54 if (!NT_STATUS_IS_OK(result)) {
55 DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
56 nt_errstr(result)));
57 return result;
62 struct netr_Authenticator clnt_creds, srv_cred;
63 struct samr_Password new_password;
65 netlogon_creds_client_step(cli->dc, &clnt_creds);
67 cred_hash3(new_password.hash,
68 new_trust_passwd_hash,
69 cli->dc->sess_key, 1);
71 result = rpccli_netr_ServerPasswordSet(cli, mem_ctx,
72 cli->dc->remote_machine,
73 cli->dc->mach_acct,
74 sec_channel_type,
75 global_myname(),
76 &clnt_creds,
77 &srv_cred,
78 &new_password);
80 /* Always check returned credentials. */
81 if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
82 DEBUG(0,("rpccli_netr_ServerPasswordSet: "
83 "credentials chain check failed\n"));
84 return NT_STATUS_ACCESS_DENIED;
88 if (!NT_STATUS_IS_OK(result)) {
89 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
90 nt_errstr(result)));
92 return result;
95 /*********************************************************
96 Change the domain password on the PDC.
97 Store the password ourselves, but use the supplied password
98 Caller must have already setup the connection to the NETLOGON pipe
99 **********************************************************/
101 NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
102 const char *domain,
103 unsigned char orig_trust_passwd_hash[16],
104 uint32 sec_channel_type)
106 unsigned char new_trust_passwd_hash[16];
107 char *new_trust_passwd;
108 char *str;
109 NTSTATUS nt_status;
111 /* Create a random machine account password */
112 str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
114 if ((new_trust_passwd = talloc_strdup(mem_ctx, str)) == NULL) {
115 DEBUG(0, ("talloc_strdup failed\n"));
116 return NT_STATUS_NO_MEMORY;
119 E_md4hash(new_trust_passwd, new_trust_passwd_hash);
121 nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
122 new_trust_passwd_hash, sec_channel_type);
124 if (NT_STATUS_IS_OK(nt_status)) {
125 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
126 current_timestring(debug_ctx(), False)));
128 * Return the result of trying to write the new password
129 * back into the trust account file.
131 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
132 nt_status = NT_STATUS_UNSUCCESSFUL;
136 return nt_status;
139 /*********************************************************
140 Change the domain password on the PDC.
141 Do most of the legwork ourselfs. Caller must have
142 already setup the connection to the NETLOGON pipe
143 **********************************************************/
145 NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli,
146 TALLOC_CTX *mem_ctx,
147 const char *domain)
149 unsigned char old_trust_passwd_hash[16];
150 uint32 sec_channel_type = 0;
152 if (!secrets_fetch_trust_account_password(domain,
153 old_trust_passwd_hash,
154 NULL, &sec_channel_type)) {
155 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
156 return NT_STATUS_UNSUCCESSFUL;
159 return trust_pw_change_and_store_it(cli, mem_ctx, domain,
160 old_trust_passwd_hash,
161 sec_channel_type);
164 /*********************************************************************
165 Enumerate the list of trusted domains from a DC
166 *********************************************************************/
168 bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
169 char ***domain_names, uint32 *num_domains,
170 DOM_SID **sids )
172 POLICY_HND pol;
173 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
174 fstring dc_name;
175 struct sockaddr_storage dc_ss;
176 uint32 enum_ctx = 0;
177 struct cli_state *cli = NULL;
178 struct rpc_pipe_client *lsa_pipe;
179 bool retry;
180 struct lsa_DomainList dom_list;
181 int i;
183 *domain_names = NULL;
184 *num_domains = 0;
185 *sids = NULL;
187 /* lookup a DC first */
189 if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) {
190 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
191 domain));
192 return False;
195 /* setup the anonymous connection */
197 result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC",
198 "", "", "", 0, Undefined, &retry);
199 if ( !NT_STATUS_IS_OK(result) )
200 goto done;
202 /* open the LSARPC_PIPE */
204 lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
205 if ( !lsa_pipe) {
206 goto done;
209 /* get a handle */
211 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
212 LSA_POLICY_VIEW_LOCAL_INFORMATION, &pol);
213 if ( !NT_STATUS_IS_OK(result) )
214 goto done;
216 /* Lookup list of trusted domains */
218 result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx,
219 &pol,
220 &enum_ctx,
221 &dom_list,
222 (uint32_t)-1);
223 if ( !NT_STATUS_IS_OK(result) )
224 goto done;
226 *num_domains = dom_list.count;
228 *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains);
229 if (!*domain_names) {
230 result = NT_STATUS_NO_MEMORY;
231 goto done;
234 *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains);
235 if (!*sids) {
236 result = NT_STATUS_NO_MEMORY;
237 goto done;
240 for (i=0; i< *num_domains; i++) {
241 (*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
242 (*sids)[i] = *dom_list.domains[i].sid;
245 done:
246 /* cleanup */
247 if (cli) {
248 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
249 cli_shutdown( cli );
252 return NT_STATUS_IS_OK(result);