r10656: BIG merge from trunk. Features not copied over
[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 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 **********************************************************/
32
33 static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
34                                          unsigned char orig_trust_passwd_hash[16],
35                                          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,
48                                         lp_workgroup(),
49                                         global_myname(),
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         new_trust_passwd = talloc_strdup(mem_ctx, str);
89         
90         E_md4hash(new_trust_passwd, new_trust_passwd_hash);
91
92         nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
93                                              new_trust_passwd_hash, sec_channel_type);
94         
95         if (NT_STATUS_IS_OK(nt_status)) {
96                 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", 
97                          timestring(False)));
98                 /*
99                  * Return the result of trying to write the new password
100                  * back into the trust account file.
101                  */
102                 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
103                         nt_status = NT_STATUS_UNSUCCESSFUL;
104                 }
105         }
106
107         return nt_status;
108 }
109
110 /*********************************************************
111  Change the domain password on the PDC.
112  Do most of the legwork ourselfs.  Caller must have
113  already setup the connection to the NETLOGON pipe
114 **********************************************************/
115
116 NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, 
117                                            TALLOC_CTX *mem_ctx, 
118                                            const char *domain) 
119 {
120         unsigned char old_trust_passwd_hash[16];
121         uint32 sec_channel_type = 0;
122
123         if (!secrets_fetch_trust_account_password(domain,
124                                                   old_trust_passwd_hash, 
125                                                   NULL, &sec_channel_type)) {
126                 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
127                 return NT_STATUS_UNSUCCESSFUL;
128         }
129         
130         return trust_pw_change_and_store_it(cli, mem_ctx, domain,
131                                             old_trust_passwd_hash,
132                                             sec_channel_type);
133 }
134
135 /*********************************************************************
136  Enumerate the list of trusted domains from a DC
137 *********************************************************************/
138
139 BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
140                                      char ***domain_names, uint32 *num_domains,
141                                      DOM_SID **sids )
142 {
143         POLICY_HND      pol;
144         NTSTATUS        result = NT_STATUS_UNSUCCESSFUL;
145         fstring         dc_name;
146         struct in_addr  dc_ip;
147         uint32          enum_ctx = 0;
148         struct cli_state *cli = NULL;
149         struct rpc_pipe_client *lsa_pipe;
150         BOOL            retry;
151
152         *domain_names = NULL;
153         *num_domains = 0;
154         *sids = NULL;
155
156         /* lookup a DC first */
157
158         if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
159                 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
160                         domain));
161                 return False;
162         }
163
164         /* setup the anonymous connection */
165
166         result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC",
167                 "", "", "", 0, Undefined, &retry);
168         if ( !NT_STATUS_IS_OK(result) )
169                 goto done;
170
171         /* open the LSARPC_PIPE */
172
173         lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
174         if ( !lsa_pipe) {
175                 goto done;
176         }
177
178         /* get a handle */
179
180         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
181                 POLICY_VIEW_LOCAL_INFORMATION, &pol);
182         if ( !NT_STATUS_IS_OK(result) )
183                 goto done;
184
185         /* Lookup list of trusted domains */
186
187         result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx,
188                 num_domains, domain_names, sids);
189         if ( !NT_STATUS_IS_OK(result) )
190                 goto done;
191
192 done:
193         /* cleanup */
194         if (cli) {
195                 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
196                 cli_shutdown( cli );
197         }
198
199         return NT_STATUS_IS_OK(result);
200 }