Use rpccli_lsa_EnumTrustDom all over the place.
[ira/wip.git] / source3 / libsmb / trusts_util.c
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 3 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, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "includes.h"
22
23 /*********************************************************
24  Change the domain password on the PDC.
25
26  Just changes the password betwen the two values specified.
27
28  Caller must have the cli connected to the netlogon pipe
29  already.
30 **********************************************************/
31
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)
36 {
37         NTSTATUS result;
38
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. */
41
42         if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
43                 uint32 neg_flags = NETLOGON_NEG_SELECT_AUTH2_FLAGS;
44
45                 result = rpccli_netlogon_setup_creds(cli, 
46                                         cli->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);
53
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;
58                 }
59         }
60
61         result = rpccli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
62
63         if (!NT_STATUS_IS_OK(result)) {
64                 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
65                          nt_errstr(result)));
66         }
67         return result;
68 }
69
70 /*********************************************************
71  Change the domain password on the PDC.
72  Store the password ourselves, but use the supplied password
73  Caller must have already setup the connection to the NETLOGON pipe
74 **********************************************************/
75
76 NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
77                                       const char *domain,
78                                       unsigned char orig_trust_passwd_hash[16],
79                                       uint32 sec_channel_type)
80 {
81         unsigned char new_trust_passwd_hash[16];
82         char *new_trust_passwd;
83         char *str;
84         NTSTATUS nt_status;
85                 
86         /* Create a random machine account password */
87         str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
88
89         if ((new_trust_passwd = talloc_strdup(mem_ctx, str)) == NULL) {
90                 DEBUG(0, ("talloc_strdup failed\n"));
91                 return NT_STATUS_NO_MEMORY;
92         }
93         
94         E_md4hash(new_trust_passwd, new_trust_passwd_hash);
95
96         nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
97                                              new_trust_passwd_hash, sec_channel_type);
98         
99         if (NT_STATUS_IS_OK(nt_status)) {
100                 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", 
101                          current_timestring(False)));
102                 /*
103                  * Return the result of trying to write the new password
104                  * back into the trust account file.
105                  */
106                 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
107                         nt_status = NT_STATUS_UNSUCCESSFUL;
108                 }
109         }
110
111         return nt_status;
112 }
113
114 /*********************************************************
115  Change the domain password on the PDC.
116  Do most of the legwork ourselfs.  Caller must have
117  already setup the connection to the NETLOGON pipe
118 **********************************************************/
119
120 NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, 
121                                            TALLOC_CTX *mem_ctx, 
122                                            const char *domain) 
123 {
124         unsigned char old_trust_passwd_hash[16];
125         uint32 sec_channel_type = 0;
126
127         if (!secrets_fetch_trust_account_password(domain,
128                                                   old_trust_passwd_hash, 
129                                                   NULL, &sec_channel_type)) {
130                 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
131                 return NT_STATUS_UNSUCCESSFUL;
132         }
133         
134         return trust_pw_change_and_store_it(cli, mem_ctx, domain,
135                                             old_trust_passwd_hash,
136                                             sec_channel_type);
137 }
138
139 /*********************************************************************
140  Enumerate the list of trusted domains from a DC
141 *********************************************************************/
142
143 bool enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
144                                      char ***domain_names, uint32 *num_domains,
145                                      DOM_SID **sids )
146 {
147         POLICY_HND      pol;
148         NTSTATUS        result = NT_STATUS_UNSUCCESSFUL;
149         fstring         dc_name;
150         struct sockaddr_storage dc_ss;
151         uint32          enum_ctx = 0;
152         struct cli_state *cli = NULL;
153         struct rpc_pipe_client *lsa_pipe;
154         bool            retry;
155         struct lsa_DomainList dom_list;
156         int i;
157
158         *domain_names = NULL;
159         *num_domains = 0;
160         *sids = NULL;
161
162         /* lookup a DC first */
163
164         if ( !get_dc_name(domain, NULL, dc_name, &dc_ss) ) {
165                 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
166                         domain));
167                 return False;
168         }
169
170         /* setup the anonymous connection */
171
172         result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ss, 0, "IPC$", "IPC",
173                 "", "", "", 0, Undefined, &retry);
174         if ( !NT_STATUS_IS_OK(result) )
175                 goto done;
176
177         /* open the LSARPC_PIPE */
178
179         lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
180         if ( !lsa_pipe) {
181                 goto done;
182         }
183
184         /* get a handle */
185
186         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
187                 POLICY_VIEW_LOCAL_INFORMATION, &pol);
188         if ( !NT_STATUS_IS_OK(result) )
189                 goto done;
190
191         /* Lookup list of trusted domains */
192
193         result = rpccli_lsa_EnumTrustDom(lsa_pipe, mem_ctx,
194                                          &pol,
195                                          &enum_ctx,
196                                          &dom_list,
197                                          (uint32_t)-1);
198         if ( !NT_STATUS_IS_OK(result) )
199                 goto done;
200
201         *num_domains = dom_list.count;
202
203         *domain_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, *num_domains);
204         if (!*domain_names) {
205                 result = NT_STATUS_NO_MEMORY;
206                 goto done;
207         }
208
209         *sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, *num_domains);
210         if (!*sids) {
211                 result = NT_STATUS_NO_MEMORY;
212                 goto done;
213         }
214
215         for (i=0; i< *num_domains; i++) {
216                 (*domain_names)[i] = CONST_DISCARD(char *, dom_list.domains[i].name.string);
217                 (*sids)[i] = *dom_list.domains[i].sid;
218         }
219
220 done:
221         /* cleanup */
222         if (cli) {
223                 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
224                 cli_shutdown( cli );
225         }
226
227         return NT_STATUS_IS_OK(result);
228 }