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
;
60 struct samr_CryptPassword password_buf
;
62 netlogon_creds_client_step(cli
->dc
, &clnt_creds
);
64 encode_pw_buffer(password_buf
.data
, new_trust_pwd_cleartext
, STR_UNICODE
);
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);
70 result
= rpccli_netr_ServerPasswordSet2(cli
, mem_ctx
,
71 cli
->dc
->remote_machine
,
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
;
88 struct netr_Authenticator clnt_creds
, srv_cred
;
89 struct samr_Password new_password
;
91 netlogon_creds_client_step(cli
->dc
, &clnt_creds
);
93 cred_hash3(new_password
.hash
,
94 new_trust_passwd_hash
,
95 cli
->dc
->sess_key
, 1);
97 result
= rpccli_netr_ServerPasswordSet(cli
, mem_ctx
,
98 cli
->dc
->remote_machine
,
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
;
114 if (!NT_STATUS_IS_OK(result
)) {
115 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
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 **********************************************************/
127 NTSTATUS
trust_pw_change_and_store_it(struct rpc_pipe_client
*cli
, TALLOC_CTX
*mem_ctx
,
129 unsigned char orig_trust_passwd_hash
[16],
130 uint32 sec_channel_type
)
132 unsigned char new_trust_passwd_hash
[16];
133 char *new_trust_passwd
;
137 /* Create a random machine account password */
138 str
= generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
);
140 if ((new_trust_passwd
= talloc_strdup(mem_ctx
, str
)) == NULL
) {
141 DEBUG(0, ("talloc_strdup failed\n"));
142 return NT_STATUS_NO_MEMORY
;
145 E_md4hash(new_trust_passwd
, new_trust_passwd_hash
);
147 nt_status
= just_change_the_password(cli
, mem_ctx
,
148 orig_trust_passwd_hash
,
150 new_trust_passwd_hash
,
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
)));
157 * Return the result of trying to write the new password
158 * back into the trust account file.
160 if (!secrets_store_machine_password(new_trust_passwd
, domain
, sec_channel_type
)) {
161 nt_status
= NT_STATUS_UNSUCCESSFUL
;
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 **********************************************************/
174 NTSTATUS
trust_pw_find_change_and_store_it(struct rpc_pipe_client
*cli
,
178 unsigned char old_trust_passwd_hash
[16];
179 uint32 sec_channel_type
= 0;
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
;
188 return trust_pw_change_and_store_it(cli
, mem_ctx
, domain
,
189 old_trust_passwd_hash
,
193 /*********************************************************************
194 Enumerate the list of trusted domains from a DC
195 *********************************************************************/
197 bool enumerate_domain_trusts( TALLOC_CTX
*mem_ctx
, const char *domain
,
198 char ***domain_names
, uint32
*num_domains
,
202 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
204 struct sockaddr_storage dc_ss
;
206 struct cli_state
*cli
= NULL
;
207 struct rpc_pipe_client
*lsa_pipe
;
209 struct lsa_DomainList dom_list
;
212 *domain_names
= NULL
;
216 /* lookup a DC first */
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",
224 /* setup the anonymous connection */
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
) )
231 /* open the LSARPC_PIPE */
233 result
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_lsarpc
.syntax_id
,
235 if (!NT_STATUS_IS_OK(result
)) {
241 result
= rpccli_lsa_open_policy(lsa_pipe
, mem_ctx
, True
,
242 LSA_POLICY_VIEW_LOCAL_INFORMATION
, &pol
);
243 if ( !NT_STATUS_IS_OK(result
) )
246 /* Lookup list of trusted domains */
248 result
= rpccli_lsa_EnumTrustDom(lsa_pipe
, mem_ctx
,
253 if ( !NT_STATUS_IS_OK(result
) )
256 *num_domains
= dom_list
.count
;
258 *domain_names
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, *num_domains
);
259 if (!*domain_names
) {
260 result
= NT_STATUS_NO_MEMORY
;
264 *sids
= TALLOC_ZERO_ARRAY(mem_ctx
, DOM_SID
, *num_domains
);
266 result
= NT_STATUS_NO_MEMORY
;
270 for (i
=0; i
< *num_domains
; i
++) {
271 (*domain_names
)[i
] = CONST_DISCARD(char *, dom_list
.domains
[i
].name
.string
);
272 (*sids
)[i
] = *dom_list
.domains
[i
].sid
;
278 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
282 return NT_STATUS_IS_OK(result
);