* fix the trustdom_cache to work when winbindd is not running.
[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 static 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         uint32 neg_flags = 0x000001ff;
39
40         result = cli_nt_setup_creds(cli, sec_channel_type, orig_trust_passwd_hash, &neg_flags, 2);
41         
42         if (!NT_STATUS_IS_OK(result)) {
43                 DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
44                          nt_errstr(result)));
45                 return result;
46         }
47
48         result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
49
50         if (!NT_STATUS_IS_OK(result)) {
51                 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
52                          nt_errstr(result)));
53         }
54         return result;
55 }
56
57 /*********************************************************
58  Change the domain password on the PDC.
59  Store the password ourselves, but use the supplied password
60  Caller must have already setup the connection to the NETLOGON pipe
61 **********************************************************/
62
63 NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
64                                       const char *domain,
65                                       unsigned char orig_trust_passwd_hash[16],
66                                       uint32 sec_channel_type)
67 {
68         unsigned char new_trust_passwd_hash[16];
69         char *new_trust_passwd;
70         char *str;
71         NTSTATUS nt_status;
72                 
73         /* Create a random machine account password */
74         str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
75         new_trust_passwd = talloc_strdup(mem_ctx, str);
76         
77         E_md4hash(new_trust_passwd, new_trust_passwd_hash);
78
79         nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
80                                              new_trust_passwd_hash, sec_channel_type);
81         
82         if (NT_STATUS_IS_OK(nt_status)) {
83                 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", 
84                          timestring(False)));
85                 /*
86                  * Return the result of trying to write the new password
87                  * back into the trust account file.
88                  */
89                 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
90                         nt_status = NT_STATUS_UNSUCCESSFUL;
91                 }
92         }
93
94         return nt_status;
95 }
96
97 /*********************************************************
98  Change the domain password on the PDC.
99  Do most of the legwork ourselfs.  Caller must have
100  already setup the connection to the NETLOGON pipe
101 **********************************************************/
102
103 NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, 
104                                            TALLOC_CTX *mem_ctx, 
105                                            const char *domain) 
106 {
107         unsigned char old_trust_passwd_hash[16];
108         char *up_domain;
109         uint32 sec_channel_type = 0;
110
111         up_domain = talloc_strdup(mem_ctx, domain);
112
113         if (!secrets_fetch_trust_account_password(domain,
114                                                   old_trust_passwd_hash, 
115                                                   NULL, &sec_channel_type)) {
116                 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
117                 return NT_STATUS_UNSUCCESSFUL;
118         }
119         
120         return trust_pw_change_and_store_it(cli, mem_ctx, domain,
121                                             old_trust_passwd_hash,
122                                             sec_channel_type);
123         
124 }
125
126 /*********************************************************************
127  Enumerate the list of trusted domains from a DC
128 *********************************************************************/
129
130 BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, 
131                                      char ***domain_names, uint32 *num_domains, 
132                                      DOM_SID **sids )
133 {
134         POLICY_HND      pol;
135         NTSTATUS        result = NT_STATUS_UNSUCCESSFUL;
136         fstring         dc_name;
137         struct in_addr  dc_ip;
138         uint32          enum_ctx = 0;
139         struct cli_state *cli = NULL;
140         BOOL            retry;
141         
142         *domain_names = NULL;
143         *num_domains = 0;
144         *sids = NULL;
145         
146         /* lookup a DC first */
147         
148         if ( !get_dc_name(domain, dc_name, &dc_ip) ) {
149                 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
150                         domain));
151                 return False;
152         }
153         
154         /* setup the anonymous connection */
155                 
156         result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC", 
157                 "", "", "", 0, &retry);
158         if ( !NT_STATUS_IS_OK(result) )
159                 goto done;
160         
161         /* open the LSARPC_PIPE */
162         
163         if ( !cli_nt_session_open( cli, PI_LSARPC ) ) {
164                 result = NT_STATUS_UNSUCCESSFUL;
165                 goto done;
166         }
167                 
168         /* get a handle */
169         
170         result = cli_lsa_open_policy(cli, mem_ctx, True, 
171                 POLICY_VIEW_LOCAL_INFORMATION, &pol);
172         if ( !NT_STATUS_IS_OK(result) )
173                 goto done;
174
175         /* Lookup list of trusted domains */
176
177         result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
178                 num_domains, domain_names, sids);
179         if ( !NT_STATUS_IS_OK(result) ) 
180                 goto done;
181         
182 done:   
183         /* cleanup */
184         
185         cli_nt_session_close( cli );
186         cli_shutdown( cli );
187                 
188         return NT_STATUS_IS_OK(result);
189 }
190
191
192 /**
193  * Verify whether or not given domain is trusted.
194  *
195  * @param domain_name name of the domain to be verified
196  * @return true if domain is one of the trusted once or
197  *         false if otherwise
198  **/
199  
200 BOOL is_trusted_domain(const char* dom_name)
201 {
202         DOM_SID trustdom_sid;
203         char *pass = NULL;
204         time_t lct;
205         BOOL ret;
206
207         /* if we are a DC, then check for a direct trust relationships */
208         
209         if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) {
210                 ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct);
211                 SAFE_FREE(pass);
212                 if (ret) 
213                         return True;
214         }
215         
216         /* if winbindd is not up then we need to update the trustdom_cache ourselves */
217
218         if ( !winbind_ping() )
219                 update_trustdom_cache();
220         
221         /* now the trustdom cache should be available a DC could still 
222          * have a transitive trust so fall back to the cache of trusted 
223          * domains (like a domain member would use  */
224         
225         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
226                 return True;
227         }
228
229         return False;
230 }
231