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
;
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
,
50 if (!NT_STATUS_IS_OK(result
)) {
51 DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
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
,
67 result
= rpccli_netr_ServerPasswordSet2(cli
, mem_ctx
,
68 cli
->dc
->remote_machine
,
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
;
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
,
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",
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
,
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
;
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
,
147 new_trust_passwd_hash
,
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
;
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
,
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
,
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
,
199 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
201 struct sockaddr_storage dc_ss
;
203 struct cli_state
*cli
= NULL
;
204 struct rpc_pipe_client
*lsa_pipe
;
206 struct lsa_DomainList dom_list
;
209 *domain_names
= 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",
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
) )
228 /* open the LSARPC_PIPE */
230 result
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_lsarpc
.syntax_id
,
232 if (!NT_STATUS_IS_OK(result
)) {
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
) )
243 /* Lookup list of trusted domains */
245 result
= rpccli_lsa_EnumTrustDom(lsa_pipe
, mem_ctx
,
250 if ( !NT_STATUS_IS_OK(result
) )
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
;
261 *sids
= TALLOC_ZERO_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
263 result
= NT_STATUS_NO_MEMORY
;
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
;
275 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
279 return NT_STATUS_IS_OK(result
);