much better ADS error handling system
[tprouty/samba.git] / source / 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
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                 );
42         return -1;
43 }
44
45
46 static int net_ads_info(int argc, const char **argv)
47 {
48         ADS_STRUCT *ads;
49
50         ads = ads_init(NULL, NULL, NULL, NULL);
51         ads_connect(ads);
52
53         if (!ads) {
54                 d_printf("Didn't find the ldap server!\n");
55                 return -1;
56         }
57
58         d_printf("LDAP server: %s\n", ads->ldap_server);
59         d_printf("LDAP server name: %s\n", ads->ldap_server_name);
60         d_printf("Realm: %s\n", ads->realm);
61         d_printf("Bind Path: %s\n", ads->bind_path);
62         d_printf("LDAP port: %d\n", ads->ldap_port);
63
64         return 0;
65 }
66
67
68 static ADS_STRUCT *ads_startup(void)
69 {
70         ADS_STRUCT *ads;
71         ADS_STATUS status;
72         extern char *opt_password;
73         extern char *opt_user_name;
74
75         ads = ads_init(NULL, NULL, NULL, NULL);
76
77         if (!opt_user_name) {
78                 opt_user_name = "administrator";
79         }
80
81         if (!opt_password) {
82                 char *prompt;
83                 asprintf(&prompt,"%s password: ", opt_user_name);
84                 opt_password = getpass(prompt);
85                 free(prompt);
86         }
87         ads->password = strdup(opt_password);
88         ads->user_name = strdup(opt_user_name);
89
90         status = ads_connect(ads);
91         if (!ADS_ERR_OK(status)) {
92                 d_printf("ads_connect: %s\n", ads_errstr(status));
93                 return NULL;
94         }
95         return ads;
96 }
97
98 static int net_ads_user(int argc, const char **argv)
99 {
100         ADS_STRUCT *ads;
101         ADS_STATUS rc;
102         void *res;
103         const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL};
104
105         if (!(ads = ads_startup())) return -1;
106         rc = ads_search(ads, &res, "(objectclass=user)", attrs);
107         if (!ADS_ERR_OK(rc)) {
108                 d_printf("ads_search: %s\n", ads_errstr(rc));
109                 return -1;
110         }
111
112         if (ads_count_replies(ads, res) == 0) {
113                 d_printf("No users found\n");
114                 return -1;
115         }
116
117         ads_dump(ads, res);
118         ads_destroy(&ads);
119         return 0;
120 }
121
122 static int net_ads_group(int argc, const char **argv)
123 {
124         ADS_STRUCT *ads;
125         ADS_STATUS rc;
126         void *res;
127         const char *attrs[] = {"sAMAccountName", "name", "objectSid", NULL};
128
129         if (!(ads = ads_startup())) return -1;
130         rc = ads_search(ads, &res, "(objectclass=group)", attrs);
131         if (!ADS_ERR_OK(rc)) {
132                 d_printf("ads_search: %s\n", ads_errstr(rc));
133                 return -1;
134         }
135
136         if (ads_count_replies(ads, res) == 0) {
137                 d_printf("No groups found\n");
138                 return -1;
139         }
140
141         ads_dump(ads, res);
142         return 0;
143 }
144
145 static int net_ads_status(int argc, const char **argv)
146 {
147         ADS_STRUCT *ads;
148         ADS_STATUS rc;
149         extern pstring global_myname;
150         void *res;
151
152         if (!(ads = ads_startup())) return -1;
153
154         rc = ads_find_machine_acct(ads, &res, global_myname);
155         if (!ADS_ERR_OK(rc)) {
156                 d_printf("ads_find_machine_acct: %s\n", ads_errstr(rc));
157                 return -1;
158         }
159
160         if (ads_count_replies(ads, res) == 0) {
161                 d_printf("No machine account for '%s' found\n", global_myname);
162                 return -1;
163         }
164
165         ads_dump(ads, res);
166
167         return 0;
168 }
169
170 static int net_ads_leave(int argc, const char **argv)
171 {
172         ADS_STRUCT *ads = NULL;
173         ADS_STATUS rc;
174         extern pstring global_myname;
175
176         if (!(ads = ads_startup())) {
177                 return -1;
178         }
179
180         if (!secrets_init()) {
181                 DEBUG(1,("Failed to initialise secrets database\n"));
182                 return -1;
183         }
184
185         rc = ads_leave_realm(ads, global_myname);
186         if (!ADS_ERR_OK(rc)) {
187             d_printf("Failed to delete host '%s' from the '%s' realm.\n", 
188                      global_myname, ads->realm);
189             return -1;
190         }
191
192         d_printf("Removed '%s' from realm '%s'\n", global_myname, ads->realm);
193
194         return 0;
195 }
196
197 static int net_ads_join(int argc, const char **argv)
198 {
199         ADS_STRUCT *ads;
200         ADS_STATUS rc;
201         char *password;
202         char *tmp_password;
203         extern pstring global_myname;
204         const char *org_unit = "Computers";
205         char *dn;
206         void *res;
207
208         if (argc > 0) org_unit = argv[0];
209
210         if (!secrets_init()) {
211                 DEBUG(1,("Failed to initialise secrets database\n"));
212                 return -1;
213         }
214
215         tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
216         password = strdup(tmp_password);
217
218         if (!(ads = ads_startup())) return -1;
219
220         asprintf(&dn, "cn=%s,%s", org_unit, ads->bind_path);
221
222         rc = ads_search_dn(ads, &res, dn, NULL);
223         free(dn);
224         ads_msgfree(ads, res);
225
226         if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) {
227                 d_printf("ads_join_realm: organisational unit %s does not exist\n", org_unit);
228                 return -1;
229         }
230
231         if (!ADS_ERR_OK(rc)) {
232                 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
233                 return -1;
234         }       
235
236         rc = ads_join_realm(ads, global_myname, org_unit);
237         if (!ADS_ERR_OK(rc)) {
238                 d_printf("ads_join_realm: %s\n", ads_errstr(rc));
239                 return -1;
240         }
241
242         rc = ads_set_machine_password(ads, global_myname, password);
243         if (!ADS_ERR_OK(rc)) {
244                 d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
245                 return -1;
246         }
247
248         if (!secrets_store_machine_password(password)) {
249                 DEBUG(1,("Failed to save machine password\n"));
250                 return -1;
251         }
252
253         d_printf("Joined '%s' to realm '%s'\n", global_myname, ads->realm);
254
255         free(password);
256
257         return 0;
258 }
259
260 int net_ads(int argc, const char **argv)
261 {
262         struct functable func[] = {
263                 {"INFO", net_ads_info},
264                 {"JOIN", net_ads_join},
265                 {"LEAVE", net_ads_leave},
266                 {"STATUS", net_ads_status},
267                 {"USER", net_ads_user},
268                 {"GROUP", net_ads_group},
269                 {NULL, NULL}
270         };
271         
272         return net_run_function(argc, argv, func, net_ads_usage);
273 }
274
275 #else
276
277 int net_ads_usage(int argc, const char **argv)
278 {
279         d_printf("ADS support not compiled in\n");
280         return -1;
281 }
282
283 int net_ads(int argc, const char **argv)
284 {
285         return net_ads_usage(argc, argv);
286 }
287
288 #endif