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/>.
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
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
)
39 uint32_t neg_flags
= NETLOGON_NEG_AUTH2_ADS_FLAGS
;
40 struct netr_Authenticator clnt_creds
, srv_cred
;
42 result
= rpccli_netlogon_setup_creds(cli
,
43 cli
->desthost
, /* server name */
44 lp_workgroup(), /* domain */
45 global_myname(), /* client name */
46 global_myname(), /* machine account name */
47 orig_trust_passwd_hash
,
51 if (!NT_STATUS_IS_OK(result
)) {
52 DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
57 netlogon_creds_client_step(cli
->dc
, &clnt_creds
);
59 if (neg_flags
& NETLOGON_NEG_PASSWORD_SET2
) {
61 struct netr_CryptPassword new_password
;
63 init_netr_CryptPassword(new_trust_pwd_cleartext
,
67 result
= rpccli_netr_ServerPasswordSet2(cli
, mem_ctx
,
68 cli
->dc
->remote_machine
,
75 if (!NT_STATUS_IS_OK(result
)) {
76 DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n",
82 struct samr_Password new_password
;
84 cred_hash3(new_password
.hash
,
85 new_trust_passwd_hash
,
86 cli
->dc
->sess_key
, 1);
88 result
= rpccli_netr_ServerPasswordSet(cli
, mem_ctx
,
89 cli
->dc
->remote_machine
,
96 if (!NT_STATUS_IS_OK(result
)) {
97 DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n",
103 /* Always check returned credentials. */
104 if (!netlogon_creds_client_check(cli
->dc
, &srv_cred
.cred
)) {
105 DEBUG(0,("credentials chain check failed\n"));
106 return NT_STATUS_ACCESS_DENIED
;
112 /*********************************************************
113 Change the domain password on the PDC.
114 Store the password ourselves, but use the supplied password
115 Caller must have already setup the connection to the NETLOGON pipe
116 **********************************************************/
118 NTSTATUS
trust_pw_change_and_store_it(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
120 unsigned char orig_trust_passwd_hash
[16],
121 uint32 sec_channel_type
)
123 unsigned char new_trust_passwd_hash
[16];
124 char *new_trust_passwd
;
128 /* Create a random machine account password */
129 str
= generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
);
131 if ((new_trust_passwd
= talloc_strdup(mem_ctx
, str
)) == NULL
) {
132 DEBUG(0, ("talloc_strdup failed\n"));
133 return NT_STATUS_NO_MEMORY
;
136 E_md4hash(new_trust_passwd
, new_trust_passwd_hash
);
138 nt_status
= just_change_the_password(cli
, mem_ctx
,
139 orig_trust_passwd_hash
,
141 new_trust_passwd_hash
,
144 if (NT_STATUS_IS_OK(nt_status
)) {
145 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
146 current_timestring(debug_ctx(), False
)));
148 * Return the result of trying to write the new password
149 * back into the trust account file.
151 if (!secrets_store_machine_password(new_trust_passwd
, domain
, sec_channel_type
)) {
152 nt_status
= NT_STATUS_UNSUCCESSFUL
;
159 /*********************************************************
160 Change the domain password on the PDC.
161 Do most of the legwork ourselfs. Caller must have
162 already setup the connection to the NETLOGON pipe
163 **********************************************************/
165 NTSTATUS
trust_pw_find_change_and_store_it(struct rpc_pipe_client
*cli
,
169 unsigned char old_trust_passwd_hash
[16];
170 uint32 sec_channel_type
= 0;
172 if (!secrets_fetch_trust_account_password(domain
,
173 old_trust_passwd_hash
,
174 NULL
, &sec_channel_type
)) {
175 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain
));
176 return NT_STATUS_UNSUCCESSFUL
;
179 return trust_pw_change_and_store_it(cli
, mem_ctx
, domain
,
180 old_trust_passwd_hash
,
184 /*********************************************************************
185 Enumerate the list of trusted domains from a DC
186 *********************************************************************/
188 bool enumerate_domain_trusts( TALLOC_CTX
*mem_ctx
, const char *domain
,
189 char ***domain_names
, uint32
*num_domains
,
193 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
195 struct sockaddr_storage dc_ss
;
197 struct cli_state
*cli
= NULL
;
198 struct rpc_pipe_client
*lsa_pipe
;
200 struct lsa_DomainList dom_list
;
203 *domain_names
= NULL
;
207 /* lookup a DC first */
209 if ( !get_dc_name(domain
, NULL
, dc_name
, &dc_ss
) ) {
210 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
215 /* setup the anonymous connection */
217 result
= cli_full_connection( &cli
, global_myname(), dc_name
, &dc_ss
, 0, "IPC$", "IPC",
218 "", "", "", 0, Undefined
, &retry
);
219 if ( !NT_STATUS_IS_OK(result
) )
222 /* open the LSARPC_PIPE */
224 result
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_lsarpc
.syntax_id
,
226 if (!NT_STATUS_IS_OK(result
)) {
232 result
= rpccli_lsa_open_policy(lsa_pipe
, mem_ctx
, True
,
233 LSA_POLICY_VIEW_LOCAL_INFORMATION
, &pol
);
234 if ( !NT_STATUS_IS_OK(result
) )
237 /* Lookup list of trusted domains */
239 result
= rpccli_lsa_EnumTrustDom(lsa_pipe
, mem_ctx
,
244 if ( !NT_STATUS_IS_OK(result
) )
247 *num_domains
= dom_list
.count
;
249 *domain_names
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, *num_domains
);
250 if (!*domain_names
) {
251 result
= NT_STATUS_NO_MEMORY
;
255 *sids
= TALLOC_ZERO_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
257 result
= NT_STATUS_NO_MEMORY
;
261 for (i
=0; i
< *num_domains
; i
++) {
262 (*domain_names
)[i
] = CONST_DISCARD(char *, dom_list
.domains
[i
].name
.string
);
263 (*sids
)[i
] = *dom_list
.domains
[i
].sid
;
269 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
273 return NT_STATUS_IS_OK(result
);