ae7bf5d446729a41a754088bbadf10015432b806
[vlendec/samba-autobuild/.git] / source3 / utils / net_ads.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Version 3.0
4    net ads commands
5    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
6    Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
21 */
22
23 #include "includes.h"
24
25 #ifdef HAVE_ADS
26
27 int net_ads_usage(int argc, const char **argv)
28 {
29         d_printf(
30 "\nnet ads join <org_unit>"\
31 "\n\tjoins the local machine to a ADS realm\n"\
32 "\nnet ads leave"\
33 "\n\tremoves the local machine from a ADS realm\n"\
34 "\nnet ads user"\
35 "\n\tlist users in the realm\n"\
36 "\nnet ads group"\
37 "\n\tlist groups in the realm\n"\
38 "\nnet ads info"\
39 "\n\tshows some info on the server\n"\
40 "\nnet ads status"\
41 "\n\tdump the machine account details to stdout\n"
42 "\nnet ads password <username@realm> -Uadmin_username@realm%%admin_pass"\
43 "\n\tchange a user's password using an admin account"
44 "\n\t(note: use realm in UPPERCASE)\n"
45 "\nnet ads chostpass"
46 "\n\tchange the trust account password of this machine in the AD tree\n"
47                 );
48         return -1;
49 }
50
51
52 static int net_ads_info(int argc, const char **argv)
53 {
54         ADS_STRUCT *ads;
55
56         ads = ads_init(NULL, NULL, NULL, NULL);
57         ads_connect(ads);
58
59         if (!ads) {
60                 d_printf("Didn't find the ldap server!\n");
61                 return -1;
62         }
63
64         d_printf("LDAP server: %s\n", ads->ldap_server);
65         d_printf("LDAP server name: %s\n", ads->ldap_server_name);
66         d_printf("Realm: %s\n", ads->realm);
67         d_printf("Bind Path: %s\n", ads->bind_path);
68         d_printf("LDAP port: %d\n", ads->ldap_port);
69
70         return 0;
71 }
72
73
74 static ADS_STRUCT *ads_startup(void)
75 {
76         ADS_STRUCT *ads;
77         ADS_STATUS status;
78         BOOL need_password = False;
79         BOOL second_time = False;
80         extern char *opt_password;
81         extern char *opt_user_name;
82         extern BOOL opt_user_specified;
83
84
85         ads = ads_init(NULL, NULL, NULL, NULL);
86
87         if (!opt_user_name) {
88                 opt_user_name = "administrator";
89         }
90
91         if (opt_user_specified)
92                 need_password = True;
93
94 retry:
95         if (!opt_password && need_password) {
96                 char *prompt;
97                 asprintf(&prompt,"%s password: ", opt_user_name);
98                 opt_password = getpass(prompt);
99                 free(prompt);
100                 ads->password = strdup(opt_password);
101         }
102
103         ads->user_name = strdup(opt_user_name);
104
105         status = ads_connect(ads);
106         if (!ADS_ERR_OK(status)) {
107                 if (!need_password && !second_time) {
108                         need_password = True;
109                         second_time = True;
110                         goto retry;
111                 } else {
112                         d_printf("ads_connect: %s\n", ads_errstr(status));
113                         return NULL;
114                 }
115         }
116         return ads;
117 }
118
119 static int net_ads_user(int argc, const char **argv)
120 {
121         ADS_STRUCT *ads;
122         ADS_STATUS rc;
123         void *res;
124         const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL};
125
126         if (!(ads = ads_startup())) return -1;
127         rc = ads_search(ads, &res, "(objectclass=user)", attrs);
128         if (!ADS_ERR_OK(rc)) {
129                 d_printf("ads_search: %s\n", ads_errstr(rc));
130                 return -1;
131         }
132
133         if (ads_count_replies(ads, res) == 0) {
134                 d_printf("No users found\n");
135                 return -1;
136         }
137
138         ads_dump(ads, res);
139         ads_destroy(&ads);
140         return 0;
141 }
142
143 static int net_ads_group(int argc, const char **argv)
144 {
145         ADS_STRUCT *ads;
146         ADS_STATUS rc;
147         void *res;
148         const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL};
149
150         if (!(ads = ads_startup())) return -1;
151         rc = ads_search(ads, &res, "(objectclass=group)", attrs);
152         if (!ADS_ERR_OK(rc)) {
153                 d_printf("ads_search: %s\n", ads_errstr(rc));
154                 return -1;
155         }
156
157         if (ads_count_replies(ads, res) == 0) {
158                 d_printf("No groups found\n");
159                 return -1;
160         }
161
162         ads_dump(ads, res);
163         return 0;
164 }
165
166 static int net_ads_status(int argc, const char **argv)
167 {
168         ADS_STRUCT *ads;
169         ADS_STATUS rc;
170         extern pstring global_myname;
171         void *res;
172
173         if (!(ads = ads_startup())) return -1;
174
175         rc = ads_find_machine_acct(ads, &res, global_myname);
176         if (!ADS_ERR_OK(rc)) {
177                 d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
178                 return -1;
179         }
180
181         if (ads_count_replies(ads, res) == 0) {
182                 d_printf("No machine account for '%s' found\n", global_myname);
183                 return -1;
184         }
185
186         ads_dump(ads, res);
187
188         return 0;
189 }
190
191 static int net_ads_leave(int argc, const char **argv)
192 {
193         ADS_STRUCT *ads = NULL;
194         ADS_STATUS rc;
195         extern pstring global_myname;
196
197         if (!(ads = ads_startup())) {
198                 return -1;
199         }
200
201         if (!secrets_init()) {
202                 DEBUG(1,("Failed to initialise secrets database\n"));
203                 return -1;
204         }
205
206         rc = ads_leave_realm(ads, global_myname);
207         if (!ADS_ERR_OK(rc)) {
208             d_printf("Failed to delete host '%s' from the '%s' realm.\n", 
209                      global_myname, ads->realm);
210             return -1;
211         }
212
213         d_printf("Removed '%s' from realm '%s'\n", global_myname, ads->realm);
214
215         return 0;
216 }
217
218 static int net_ads_join(int argc, const char **argv)
219 {
220         ADS_STRUCT *ads;
221         ADS_STATUS rc;
222         char *password;
223         char *tmp_password;
224         extern pstring global_myname;
225         const char *org_unit = "Computers";
226         char *dn;
227         void *res;
228         DOM_SID dom_sid;
229         char *ou_str;
230
231         if (argc > 0) org_unit = argv[0];
232
233         if (!secrets_init()) {
234                 DEBUG(1,("Failed to initialise secrets database\n"));
235                 return -1;
236         }
237
238         tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
239         password = strdup(tmp_password);
240
241         if (!(ads = ads_startup())) return -1;
242
243         ou_str = ads_ou_string(org_unit);
244         asprintf(&dn, "%s,%s", ou_str, ads->bind_path);
245         free(ou_str);
246
247         rc = ads_search_dn(ads, &res, dn, NULL);
248         ads_msgfree(ads, res);
249
250         if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) {
251                 d_printf("ads_join_realm: organisational unit %s does not exist (dn:%s)\n", 
252                          org_unit, dn);
253                 return -1;
254         }
255         free(dn);
256
257         if (!ADS_ERR_OK(rc)) {
258                 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
259                 return -1;
260         }       
261
262         rc = ads_join_realm(ads, global_myname, org_unit);
263         if (!ADS_ERR_OK(rc)) {
264                 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
265                 return -1;
266         }
267
268         rc = ads_set_machine_password(ads, global_myname, password);
269         if (!ADS_ERR_OK(rc)) {
270                 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
271                 return -1;
272         }
273
274         rc = ads_domain_sid(ads, &dom_sid);
275         if (!ADS_ERR_OK(rc)) {
276                 d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
277                 return -1;
278         }
279
280         if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
281                 DEBUG(1,("Failed to save domain sid\n"));
282                 return -1;
283         }
284
285         if (!secrets_store_machine_password(password)) {
286                 DEBUG(1,("Failed to save machine password\n"));
287                 return -1;
288         }
289
290         d_printf("Joined '%s' to realm '%s'\n", global_myname, ads->realm);
291
292         free(password);
293
294         return 0;
295 }
296
297
298 static int net_ads_password(int argc, const char **argv)
299 {
300     ADS_STRUCT *ads;
301     extern char *opt_user_name;
302     extern char *opt_password;
303     char *auth_principal = opt_user_name;
304     char *auth_password = opt_password;
305     char *realm = NULL;
306     char *new_password = NULL;
307     char *c;
308     char *prompt;
309     ADS_STATUS ret;
310
311     
312     if ((argc != 1) || (opt_user_name == NULL) || 
313         (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) ||
314         (strchr(argv[0], '@') == NULL)) {
315         return net_ads_usage(argc, argv);
316     }
317     
318     c = strchr(auth_principal, '@');
319     realm = ++c;
320
321     /* use the realm so we can eventually change passwords for users 
322     in realms other than default */
323     if (!(ads = ads_init(realm, NULL, NULL, NULL))) return -1;
324
325     asprintf(&prompt, "Enter new password for %s:", argv[0]);
326
327     new_password = getpass(prompt);
328
329     ret = kerberos_set_password(ads->kdc_server, auth_principal, 
330                                 auth_password, argv[0], new_password);
331     if (!ADS_ERR_OK(ret)) {
332         d_printf("Password change failed :-( ...\n");
333         ads_destroy(&ads);
334         free(prompt);
335         return -1;
336     }
337
338     d_printf("Password change for %s completed.\n", argv[0]);
339     ads_destroy(&ads);
340     free(prompt);
341
342     return 0;
343 }
344
345
346 static int net_ads_change_localhost_pass(int argc, const char **argv)
347 {    
348     ADS_STRUCT *ads;
349     extern pstring global_myname;
350     char *host_principal;
351     char *hostname;
352     ADS_STATUS ret;
353
354
355     if (!(ads = ads_init(NULL, NULL, NULL, NULL))) return -1;
356
357     hostname = strdup(global_myname);
358     strlower(hostname);
359     asprintf(&host_principal, "%s@%s", hostname, ads->realm);
360     SAFE_FREE(hostname);
361     d_printf("Changing password for principal: HOST/%s\n", host_principal);
362     
363     ret = ads_change_trust_account_password(ads, host_principal);
364
365     if (!ADS_ERR_OK(ret)) {
366         d_printf("Password change failed :-( ...\n");
367         ads_destroy(&ads);
368         SAFE_FREE(host_principal);
369         return -1;
370     }
371     
372     d_printf("Password change for principal HOST/%s succeeded.\n", host_principal);
373     ads_destroy(&ads);
374     SAFE_FREE(host_principal);
375
376     return 0;
377 }
378
379
380 int net_ads(int argc, const char **argv)
381 {
382         struct functable func[] = {
383                 {"INFO", net_ads_info},
384                 {"JOIN", net_ads_join},
385                 {"LEAVE", net_ads_leave},
386                 {"STATUS", net_ads_status},
387                 {"USER", net_ads_user},
388                 {"GROUP", net_ads_group},
389                 {"PASSWORD", net_ads_password},
390                 {"CHOSTPASS", net_ads_change_localhost_pass},
391                 {NULL, NULL}
392         };
393         
394         return net_run_function(argc, argv, func, net_ads_usage);
395 }
396
397 #else
398
399 int net_ads_usage(int argc, const char **argv)
400 {
401         d_printf("ADS support not compiled in\n");
402         return -1;
403 }
404
405 int net_ads(int argc, const char **argv)
406 {
407         return net_ads_usage(argc, argv);
408 }
409
410 #endif