r23801: The FSF has moved around a lot. This fixes their Mass Ave address.
[nivanova/samba-autobuild/.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_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 in_addr  dc_ip;
151         uint32          enum_ctx = 0;
152         struct cli_state *cli = NULL;
153         struct rpc_pipe_client *lsa_pipe;
154         BOOL            retry;
155
156         *domain_names = NULL;
157         *num_domains = 0;
158         *sids = NULL;
159
160         /* lookup a DC first */
161
162         if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
163                 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
164                         domain));
165                 return False;
166         }
167
168         /* setup the anonymous connection */
169
170         result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC",
171                 "", "", "", 0, Undefined, &retry);
172         if ( !NT_STATUS_IS_OK(result) )
173                 goto done;
174
175         /* open the LSARPC_PIPE */
176
177         lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
178         if ( !lsa_pipe) {
179                 goto done;
180         }
181
182         /* get a handle */
183
184         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
185                 POLICY_VIEW_LOCAL_INFORMATION, &pol);
186         if ( !NT_STATUS_IS_OK(result) )
187                 goto done;
188
189         /* Lookup list of trusted domains */
190
191         result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx,
192                 num_domains, domain_names, sids);
193         if ( !NT_STATUS_IS_OK(result) )
194                 goto done;
195
196 done:
197         /* cleanup */
198         if (cli) {
199                 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
200                 cli_shutdown( cli );
201         }
202
203         return NT_STATUS_IS_OK(result);
204 }