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 2 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, write to the Free Software
19 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include "includes.h"
23
24/*********************************************************
25 Change the domain password on the PDC.
26
27 Just changes the password betwen the two values specified.
28
29 Caller must have the cli connected to the netlogon pipe
30 already.
31**********************************************************/
32static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ctx,
33					 unsigned char orig_trust_passwd_hash[16],
34					 unsigned char new_trust_passwd_hash[16],
35					 uint32 sec_channel_type)
36{
37	NTSTATUS result;
38
39	/* ensure that schannel uses the right domain */
40	fstrcpy(cli->domain, lp_workgroup());
41	if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, sec_channel_type, orig_trust_passwd_hash))) {
42		DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
43			 nt_errstr(result)));
44		return result;
45	}
46
47	result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
48
49	if (!NT_STATUS_IS_OK(result)) {
50		DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
51			 nt_errstr(result)));
52	}
53	return result;
54}
55
56/*********************************************************
57 Change the domain password on the PDC.
58 Store the password ourselves, but use the supplied password
59 Caller must have already setup the connection to the NETLOGON pipe
60**********************************************************/
61
62NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx,
63				      const char *domain,
64				      unsigned char orig_trust_passwd_hash[16],
65				      uint32 sec_channel_type)
66{
67	unsigned char new_trust_passwd_hash[16];
68	char *new_trust_passwd;
69	char *str;
70	NTSTATUS nt_status;
71
72	/* Create a random machine account password */
73	str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
74	new_trust_passwd = talloc_strdup(mem_ctx, str);
75
76	E_md4hash(new_trust_passwd, new_trust_passwd_hash);
77
78	nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
79					     new_trust_passwd_hash, sec_channel_type);
80
81	if (NT_STATUS_IS_OK(nt_status)) {
82		DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
83			 timestring(False)));
84		/*
85		 * Return the result of trying to write the new password
86		 * back into the trust account file.
87		 */
88		if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
89			nt_status = NT_STATUS_UNSUCCESSFUL;
90		}
91	}
92
93	return nt_status;
94}
95
96/*********************************************************
97 Change the domain password on the PDC.
98 Do most of the legwork ourselfs.  Caller must have
99 already setup the connection to the NETLOGON pipe
100**********************************************************/
101
102NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli,
103					   TALLOC_CTX *mem_ctx,
104					   const char *domain)
105{
106	unsigned char old_trust_passwd_hash[16];
107	char *up_domain;
108	uint32 sec_channel_type = 0;
109
110	up_domain = talloc_strdup(mem_ctx, domain);
111
112	if (!secrets_fetch_trust_account_password(domain,
113						  old_trust_passwd_hash,
114						  NULL, &sec_channel_type)) {
115		DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
116		return NT_STATUS_UNSUCCESSFUL;
117	}
118
119	return trust_pw_change_and_store_it(cli, mem_ctx, domain,
120					    old_trust_passwd_hash,
121					    sec_channel_type);
122
123}
124
125/*********************************************************************
126 Enumerate the list of trusted domains from a DC
127*********************************************************************/
128
129BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
130                                     char ***domain_names, uint32 *num_domains,
131				     DOM_SID **sids )
132{
133	POLICY_HND 	pol;
134	NTSTATUS 	result = NT_STATUS_UNSUCCESSFUL;
135	fstring 	dc_name;
136	struct in_addr 	dc_ip;
137	uint32 		enum_ctx = 0;
138	struct cli_state *cli = NULL;
139	BOOL 		retry;
140
141	*domain_names = NULL;
142	*num_domains = 0;
143	*sids = NULL;
144
145	/* lookup a DC first */
146
147	if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
148		DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
149			domain));
150		return False;
151	}
152
153	/* setup the anonymous connection */
154
155	result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC",
156		"", "", "", 0, Undefined, &retry);
157	if ( !NT_STATUS_IS_OK(result) )
158		goto done;
159
160	/* open the LSARPC_PIPE	*/
161
162	if ( !cli_nt_session_open( cli, PI_LSARPC ) ) {
163		result = NT_STATUS_UNSUCCESSFUL;
164		goto done;
165	}
166
167	/* get a handle */
168
169	result = cli_lsa_open_policy(cli, mem_ctx, True,
170		POLICY_VIEW_LOCAL_INFORMATION, &pol);
171	if ( !NT_STATUS_IS_OK(result) )
172		goto done;
173
174	/* Lookup list of trusted domains */
175
176	result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
177		num_domains, domain_names, sids);
178	if ( !NT_STATUS_IS_OK(result) )
179		goto done;
180
181done:
182	/* cleanup */
183	if (cli) {
184		DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
185		cli_shutdown( cli );
186	}
187
188	return NT_STATUS_IS_OK(result);
189}
190
191