r23779: Change from v2 or later to v3 or later.
[sfrench/samba-autobuild/.git] / source / 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, 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 **********************************************************/
32
33 static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
34                                          const unsigned char orig_trust_passwd_hash[16],
35                                          const unsigned char new_trust_passwd_hash[16],
36                                          uint32 sec_channel_type)
37 {
38         NTSTATUS result;
39
40         /* Check if the netlogon pipe is open using schannel. If so we
41            already have valid creds. If not we must set them up. */
42
43         if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
44                 uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
45
46                 result = rpccli_netlogon_setup_creds(cli, 
47                                         cli->cli->desthost, /* server name */
48                                         lp_workgroup(), /* domain */
49                                         global_myname(), /* client name */
50                                         global_myname(), /* machine account name */
51                                         orig_trust_passwd_hash,
52                                         sec_channel_type,
53                                         &neg_flags);
54
55                 if (!NT_STATUS_IS_OK(result)) {
56                         DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
57                                  nt_errstr(result)));
58                         return result;
59                 }
60         }
61
62         result = rpccli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
63
64         if (!NT_STATUS_IS_OK(result)) {
65                 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
66                          nt_errstr(result)));
67         }
68         return result;
69 }
70
71 /*********************************************************
72  Change the domain password on the PDC.
73  Store the password ourselves, but use the supplied password
74  Caller must have already setup the connection to the NETLOGON pipe
75 **********************************************************/
76
77 NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
78                                       const char *domain,
79                                       unsigned char orig_trust_passwd_hash[16],
80                                       uint32 sec_channel_type)
81 {
82         unsigned char new_trust_passwd_hash[16];
83         char *new_trust_passwd;
84         char *str;
85         NTSTATUS nt_status;
86                 
87         /* Create a random machine account password */
88         str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
89
90         if ((new_trust_passwd = talloc_strdup(mem_ctx, str)) == NULL) {
91                 DEBUG(0, ("talloc_strdup failed\n"));
92                 return NT_STATUS_NO_MEMORY;
93         }
94         
95         E_md4hash(new_trust_passwd, new_trust_passwd_hash);
96
97         nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
98                                              new_trust_passwd_hash, sec_channel_type);
99         
100         if (NT_STATUS_IS_OK(nt_status)) {
101                 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", 
102                          current_timestring(False)));
103                 /*
104                  * Return the result of trying to write the new password
105                  * back into the trust account file.
106                  */
107                 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
108                         nt_status = NT_STATUS_UNSUCCESSFUL;
109                 }
110         }
111
112         return nt_status;
113 }
114
115 /*********************************************************
116  Change the domain password on the PDC.
117  Do most of the legwork ourselfs.  Caller must have
118  already setup the connection to the NETLOGON pipe
119 **********************************************************/
120
121 NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, 
122                                            TALLOC_CTX *mem_ctx, 
123                                            const char *domain) 
124 {
125         unsigned char old_trust_passwd_hash[16];
126         uint32 sec_channel_type = 0;
127
128         if (!secrets_fetch_trust_account_password(domain,
129                                                   old_trust_passwd_hash, 
130                                                   NULL, &sec_channel_type)) {
131                 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
132                 return NT_STATUS_UNSUCCESSFUL;
133         }
134         
135         return trust_pw_change_and_store_it(cli, mem_ctx, domain,
136                                             old_trust_passwd_hash,
137                                             sec_channel_type);
138 }
139
140 /*********************************************************************
141  Enumerate the list of trusted domains from a DC
142 *********************************************************************/
143
144 BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
145                                      char ***domain_names, uint32 *num_domains,
146                                      DOM_SID **sids )
147 {
148         POLICY_HND      pol;
149         NTSTATUS        result = NT_STATUS_UNSUCCESSFUL;
150         fstring         dc_name;
151         struct in_addr  dc_ip;
152         uint32          enum_ctx = 0;
153         struct cli_state *cli = NULL;
154         struct rpc_pipe_client *lsa_pipe;
155         BOOL            retry;
156
157         *domain_names = NULL;
158         *num_domains = 0;
159         *sids = NULL;
160
161         /* lookup a DC first */
162
163         if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
164                 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
165                         domain));
166                 return False;
167         }
168
169         /* setup the anonymous connection */
170
171         result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC",
172                 "", "", "", 0, Undefined, &retry);
173         if ( !NT_STATUS_IS_OK(result) )
174                 goto done;
175
176         /* open the LSARPC_PIPE */
177
178         lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
179         if ( !lsa_pipe) {
180                 goto done;
181         }
182
183         /* get a handle */
184
185         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
186                 POLICY_VIEW_LOCAL_INFORMATION, &pol);
187         if ( !NT_STATUS_IS_OK(result) )
188                 goto done;
189
190         /* Lookup list of trusted domains */
191
192         result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx,
193                 num_domains, domain_names, sids);
194         if ( !NT_STATUS_IS_OK(result) )
195                 goto done;
196
197 done:
198         /* cleanup */
199         if (cli) {
200                 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
201                 cli_shutdown( cli );
202         }
203
204         return NT_STATUS_IS_OK(result);
205 }