aab0d7d151745887958fee39912b9169cfadb848
[vlendec/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 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
39         /* ensure that schannel uses the right domain */
40         fstrcpy(cli->domain, lp_workgroup());
41         if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, sec_channel_type, orig_trust_passwd_hash))) {
42                 DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
43                          nt_errstr(result)));
44                 return result;
45         }
46         
47         result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
48
49         if (!NT_STATUS_IS_OK(result)) {
50                 DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
51                          nt_errstr(result)));
52         }
53         return result;
54 }
55
56 /*********************************************************
57  Change the domain password on the PDC.
58  Store the password ourselves, but use the supplied password
59  Caller must have already setup the connection to the NETLOGON pipe
60 **********************************************************/
61
62 NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
63                                       const char *domain,
64                                       unsigned char orig_trust_passwd_hash[16],
65                                       uint32 sec_channel_type)
66 {
67         unsigned char new_trust_passwd_hash[16];
68         char *new_trust_passwd;
69         char *str;
70         NTSTATUS nt_status;
71                 
72         /* Create a random machine account password */
73         str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
74         new_trust_passwd = talloc_strdup(mem_ctx, str);
75         
76         E_md4hash(new_trust_passwd, new_trust_passwd_hash);
77
78         nt_status = just_change_the_password(cli, mem_ctx, orig_trust_passwd_hash,
79                                              new_trust_passwd_hash, sec_channel_type);
80         
81         if (NT_STATUS_IS_OK(nt_status)) {
82                 DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", 
83                          timestring(False)));
84                 /*
85                  * Return the result of trying to write the new password
86                  * back into the trust account file.
87                  */
88                 if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
89                         nt_status = NT_STATUS_UNSUCCESSFUL;
90                 }
91         }
92
93         return nt_status;
94 }
95
96 /*********************************************************
97  Change the domain password on the PDC.
98  Do most of the legwork ourselfs.  Caller must have
99  already setup the connection to the NETLOGON pipe
100 **********************************************************/
101
102 NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, 
103                                            TALLOC_CTX *mem_ctx, 
104                                            const char *domain) 
105 {
106         unsigned char old_trust_passwd_hash[16];
107         uint32 sec_channel_type = 0;
108
109         if (!secrets_fetch_trust_account_password(domain,
110                                                   old_trust_passwd_hash, 
111                                                   NULL, &sec_channel_type)) {
112                 DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
113                 return NT_STATUS_UNSUCCESSFUL;
114         }
115         
116         return trust_pw_change_and_store_it(cli, mem_ctx, domain,
117                                             old_trust_passwd_hash,
118                                             sec_channel_type);
119         
120 }
121
122 /*********************************************************************
123  Enumerate the list of trusted domains from a DC
124 *********************************************************************/
125
126 BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
127                                      char ***domain_names, uint32 *num_domains,
128                                      DOM_SID **sids )
129 {
130         POLICY_HND      pol;
131         NTSTATUS        result = NT_STATUS_UNSUCCESSFUL;
132         fstring         dc_name;
133         struct in_addr  dc_ip;
134         uint32          enum_ctx = 0;
135         struct cli_state *cli = NULL;
136         BOOL            retry;
137
138         *domain_names = NULL;
139         *num_domains = 0;
140         *sids = NULL;
141
142         /* lookup a DC first */
143
144         if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
145                 DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
146                         domain));
147                 return False;
148         }
149
150         /* setup the anonymous connection */
151
152         result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC",
153                 "", "", "", 0, Undefined, &retry);
154         if ( !NT_STATUS_IS_OK(result) )
155                 goto done;
156
157         /* open the LSARPC_PIPE */
158
159         if ( !cli_nt_session_open( cli, PI_LSARPC ) ) {
160                 result = NT_STATUS_UNSUCCESSFUL;
161                 goto done;
162         }
163
164         /* get a handle */
165
166         result = cli_lsa_open_policy(cli, mem_ctx, True,
167                 POLICY_VIEW_LOCAL_INFORMATION, &pol);
168         if ( !NT_STATUS_IS_OK(result) )
169                 goto done;
170
171         /* Lookup list of trusted domains */
172
173         result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
174                 num_domains, domain_names, sids);
175         if ( !NT_STATUS_IS_OK(result) )
176                 goto done;
177
178 done:
179         /* cleanup */
180         if (cli) {
181                 DEBUG(10,("enumerate_domain_trusts: shutting down connection...\n"));
182                 cli_shutdown( cli );
183         }
184
185         return NT_STATUS_IS_OK(result);
186 }
187