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