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