Line data Source code
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 : Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 : Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "utils/net.h"
25 : #include "libsmb/namequery.h"
26 : #include "rpc_client/cli_pipe.h"
27 : #include "librpc/gen_ndr/ndr_krb5pac.h"
28 : #include "../librpc/gen_ndr/ndr_spoolss.h"
29 : #include "nsswitch/libwbclient/wbclient.h"
30 : #include "ads.h"
31 : #include "libads/cldap.h"
32 : #include "../lib/addns/dnsquery.h"
33 : #include "../libds/common/flags.h"
34 : #include "librpc/gen_ndr/libnet_join.h"
35 : #include "libnet/libnet_join.h"
36 : #include "smb_krb5.h"
37 : #include "secrets.h"
38 : #include "krb5_env.h"
39 : #include "../libcli/security/security.h"
40 : #include "libsmb/libsmb.h"
41 : #include "lib/param/loadparm.h"
42 : #include "utils/net_dns.h"
43 : #include "auth/kerberos/pac_utils.h"
44 : #include "lib/util/string_wrappers.h"
45 :
46 : #ifdef HAVE_JANSSON
47 : #include <jansson.h>
48 : #include "audit_logging.h" /* various JSON helpers */
49 : #include "auth/common_auth.h"
50 : #endif /* [HAVE_JANSSON] */
51 :
52 : #ifdef HAVE_ADS
53 :
54 : /* when we do not have sufficient input parameters to contact a remote domain
55 : * we always fall back to our own realm - Guenther*/
56 :
57 26 : static const char *assume_own_realm(struct net_context *c)
58 : {
59 26 : if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
60 14 : return lp_realm();
61 : }
62 :
63 12 : return NULL;
64 : }
65 :
66 : #ifdef HAVE_JANSSON
67 :
68 : /*
69 : * note: JSON output deliberately bypasses gettext so as to provide the same
70 : * output irrespective of the locale.
71 : */
72 :
73 4 : static int output_json(const struct json_object *jsobj)
74 : {
75 4 : TALLOC_CTX *ctx = NULL;
76 4 : char *json = NULL;
77 :
78 4 : if (json_is_invalid(jsobj)) {
79 0 : return -1;
80 : }
81 :
82 4 : ctx = talloc_new(NULL);
83 4 : if (ctx == NULL) {
84 0 : d_fprintf(stderr, _("Out of memory\n"));
85 0 : return -1;
86 : }
87 :
88 4 : json = json_to_string(ctx, jsobj);
89 4 : if (!json) {
90 0 : d_fprintf(stderr, _("error encoding to JSON\n"));
91 0 : return -1;
92 : }
93 :
94 4 : d_printf("%s\n", json);
95 4 : TALLOC_FREE(ctx);
96 :
97 4 : return 0;
98 : }
99 :
100 2 : static int net_ads_cldap_netlogon_json
101 : (ADS_STRUCT *ads,
102 : const char *addr,
103 : const struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply)
104 : {
105 2 : struct json_object jsobj = json_new_object();
106 2 : struct json_object flagsobj = json_new_object();
107 2 : char response_type [32] = { '\0' };
108 2 : int ret = 0;
109 :
110 2 : if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
111 0 : d_fprintf(stderr, _("error setting up JSON value\n"));
112 :
113 0 : goto failure;
114 : }
115 :
116 2 : switch (reply->command) {
117 0 : case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
118 0 : strncpy(response_type,
119 : "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
120 : sizeof(response_type));
121 0 : break;
122 2 : case LOGON_SAM_LOGON_RESPONSE_EX:
123 2 : strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
124 : sizeof(response_type));
125 2 : break;
126 0 : default:
127 0 : snprintf(response_type, sizeof(response_type), "0x%x",
128 0 : reply->command);
129 0 : break;
130 : }
131 :
132 2 : ret = json_add_string(&jsobj, "Information for Domain Controller",
133 : addr);
134 2 : if (ret != 0) {
135 0 : goto failure;
136 : }
137 :
138 2 : ret = json_add_string(&jsobj, "Response Type", response_type);
139 2 : if (ret != 0) {
140 0 : goto failure;
141 : }
142 :
143 2 : ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
144 2 : if (ret != 0) {
145 0 : goto failure;
146 : }
147 :
148 2 : ret = json_add_bool(&flagsobj, "Is a PDC",
149 2 : reply->server_type & NBT_SERVER_PDC);
150 2 : if (ret != 0) {
151 0 : goto failure;
152 : }
153 :
154 2 : ret = json_add_bool(&flagsobj, "Is a GC of the forest",
155 2 : reply->server_type & NBT_SERVER_GC);
156 2 : if (ret != 0) {
157 0 : goto failure;
158 : }
159 :
160 2 : ret = json_add_bool(&flagsobj, "Is an LDAP server",
161 2 : reply->server_type & NBT_SERVER_LDAP);
162 2 : if (ret != 0) {
163 0 : goto failure;
164 : }
165 :
166 2 : ret = json_add_bool(&flagsobj, "Supports DS",
167 2 : reply->server_type & NBT_SERVER_DS);
168 2 : if (ret != 0) {
169 0 : goto failure;
170 : }
171 :
172 2 : ret = json_add_bool(&flagsobj, "Is running a KDC",
173 2 : reply->server_type & NBT_SERVER_KDC);
174 2 : if (ret != 0) {
175 0 : goto failure;
176 : }
177 :
178 2 : ret = json_add_bool(&flagsobj, "Is running time services",
179 2 : reply->server_type & NBT_SERVER_TIMESERV);
180 2 : if (ret != 0) {
181 0 : goto failure;
182 : }
183 :
184 2 : ret = json_add_bool(&flagsobj, "Is the closest DC",
185 2 : reply->server_type & NBT_SERVER_CLOSEST);
186 2 : if (ret != 0) {
187 0 : goto failure;
188 : }
189 :
190 2 : ret = json_add_bool(&flagsobj, "Is writable",
191 2 : reply->server_type & NBT_SERVER_WRITABLE);
192 2 : if (ret != 0) {
193 0 : goto failure;
194 : }
195 :
196 2 : ret = json_add_bool(&flagsobj, "Has a hardware clock",
197 2 : reply->server_type & NBT_SERVER_GOOD_TIMESERV);
198 2 : if (ret != 0) {
199 0 : goto failure;
200 : }
201 :
202 2 : ret = json_add_bool(&flagsobj,
203 : "Is a non-domain NC serviced by LDAP server",
204 2 : reply->server_type & NBT_SERVER_NDNC);
205 2 : if (ret != 0) {
206 0 : goto failure;
207 : }
208 :
209 2 : ret = json_add_bool
210 : (&flagsobj, "Is NT6 DC that has some secrets",
211 2 : reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
212 2 : if (ret != 0) {
213 0 : goto failure;
214 : }
215 :
216 2 : ret = json_add_bool
217 : (&flagsobj, "Is NT6 DC that has all secrets",
218 2 : reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
219 2 : if (ret != 0) {
220 0 : goto failure;
221 : }
222 :
223 2 : ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services",
224 2 : reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
225 2 : if (ret != 0) {
226 0 : goto failure;
227 : }
228 :
229 2 : ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later",
230 2 : reply->server_type & NBT_SERVER_DS_8);
231 2 : if (ret != 0) {
232 0 : goto failure;
233 : }
234 :
235 2 : ret = json_add_string(&jsobj, "Forest", reply->forest);
236 2 : if (ret != 0) {
237 0 : goto failure;
238 : }
239 :
240 2 : ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
241 2 : if (ret != 0) {
242 0 : goto failure;
243 : }
244 :
245 2 : ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
246 2 : if (ret != 0) {
247 0 : goto failure;
248 : }
249 :
250 :
251 2 : ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
252 2 : if (ret != 0) {
253 0 : goto failure;
254 : }
255 :
256 2 : ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
257 2 : if (ret != 0) {
258 0 : goto failure;
259 : }
260 :
261 2 : if (*reply->user_name) {
262 0 : ret = json_add_string(&jsobj, "User name", reply->user_name);
263 0 : if (ret != 0) {
264 0 : goto failure;
265 : }
266 : }
267 :
268 2 : ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
269 2 : if (ret != 0) {
270 0 : goto failure;
271 : }
272 :
273 2 : ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
274 2 : if (ret != 0) {
275 0 : goto failure;
276 : }
277 :
278 2 : ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
279 2 : if (ret != 0) {
280 0 : goto failure;
281 : }
282 :
283 2 : ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
284 2 : if (ret != 0) {
285 0 : goto failure;
286 : }
287 :
288 2 : ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
289 2 : if (ret != 0) {
290 0 : goto failure;
291 : }
292 :
293 2 : ret = json_add_object(&jsobj, "Flags", &flagsobj);
294 2 : if (ret != 0) {
295 0 : goto failure;
296 : }
297 :
298 2 : ret = output_json(&jsobj);
299 2 : json_free(&jsobj); /* frees flagsobj recursively */
300 :
301 2 : return ret;
302 :
303 0 : failure:
304 0 : json_free(&flagsobj);
305 0 : json_free(&jsobj);
306 :
307 0 : return ret;
308 : }
309 :
310 : #else /* [HAVE_JANSSON] */
311 :
312 : static int net_ads_cldap_netlogon_json
313 : (ADS_STRUCT *ads,
314 : const char *addr,
315 : const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
316 : {
317 : d_fprintf(stderr, _("JSON support not available\n"));
318 :
319 : return -1;
320 : }
321 :
322 : #endif /* [HAVE_JANSSON] */
323 :
324 : /*
325 : do a cldap netlogon query
326 : */
327 3 : static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
328 : {
329 : char addr[INET6_ADDRSTRLEN];
330 : struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
331 :
332 3 : print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
333 :
334 3 : if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
335 0 : d_fprintf(stderr, _("CLDAP query failed!\n"));
336 0 : return -1;
337 : }
338 :
339 3 : if (c->opt_json) {
340 2 : return net_ads_cldap_netlogon_json(ads, addr, &reply);
341 : }
342 :
343 1 : d_printf(_("Information for Domain Controller: %s\n\n"),
344 : addr);
345 :
346 1 : d_printf(_("Response Type: "));
347 1 : switch (reply.command) {
348 0 : case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
349 0 : d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
350 0 : break;
351 1 : case LOGON_SAM_LOGON_RESPONSE_EX:
352 1 : d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
353 1 : break;
354 0 : default:
355 0 : d_printf("0x%x\n", reply.command);
356 0 : break;
357 : }
358 :
359 1 : d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
360 :
361 14 : d_printf(_("Flags:\n"
362 : "\tIs a PDC: %s\n"
363 : "\tIs a GC of the forest: %s\n"
364 : "\tIs an LDAP server: %s\n"
365 : "\tSupports DS: %s\n"
366 : "\tIs running a KDC: %s\n"
367 : "\tIs running time services: %s\n"
368 : "\tIs the closest DC: %s\n"
369 : "\tIs writable: %s\n"
370 : "\tHas a hardware clock: %s\n"
371 : "\tIs a non-domain NC serviced by LDAP server: %s\n"
372 : "\tIs NT6 DC that has some secrets: %s\n"
373 : "\tIs NT6 DC that has all secrets: %s\n"
374 : "\tRuns Active Directory Web Services: %s\n"
375 : "\tRuns on Windows 2012 or later: %s\n"),
376 1 : (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
377 1 : (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
378 1 : (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
379 1 : (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
380 1 : (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
381 1 : (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
382 1 : (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
383 1 : (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
384 1 : (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
385 1 : (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
386 1 : (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
387 1 : (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
388 1 : (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
389 1 : (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"));
390 :
391 :
392 1 : printf(_("Forest: %s\n"), reply.forest);
393 1 : printf(_("Domain: %s\n"), reply.dns_domain);
394 1 : printf(_("Domain Controller: %s\n"), reply.pdc_dns_name);
395 :
396 1 : printf(_("Pre-Win2k Domain: %s\n"), reply.domain_name);
397 1 : printf(_("Pre-Win2k Hostname: %s\n"), reply.pdc_name);
398 :
399 1 : if (*reply.user_name) printf(_("User name: %s\n"), reply.user_name);
400 :
401 1 : printf(_("Server Site Name: %s\n"), reply.server_site);
402 1 : printf(_("Client Site Name: %s\n"), reply.client_site);
403 :
404 1 : d_printf(_("NT Version: %d\n"), reply.nt_version);
405 1 : d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
406 1 : d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
407 :
408 1 : return 0;
409 : }
410 :
411 : /*
412 : this implements the CLDAP based netlogon lookup requests
413 : for finding the domain controller of a ADS domain
414 : */
415 3 : static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
416 : {
417 3 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
418 3 : ADS_STRUCT *ads = NULL;
419 : ADS_STATUS status;
420 3 : int ret = -1;
421 :
422 3 : if (c->display_usage) {
423 0 : d_printf("%s\n"
424 : "net ads lookup\n"
425 : " %s",
426 : _("Usage:"),
427 : _("Find the ADS DC using CLDAP lookup.\n"));
428 0 : TALLOC_FREE(tmp_ctx);
429 0 : return -1;
430 : }
431 :
432 3 : status = ads_startup_nobind(c, false, tmp_ctx, &ads);
433 3 : if (!ADS_ERR_OK(status)) {
434 0 : d_fprintf(stderr, _("Didn't find the cldap server!\n"));
435 0 : goto out;
436 : }
437 :
438 3 : if (!ads->config.realm) {
439 0 : ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
440 0 : if (ads->config.realm == NULL) {
441 0 : d_fprintf(stderr, _("Out of memory\n"));
442 0 : goto out;
443 : }
444 0 : ads->ldap.port = 389;
445 : }
446 :
447 3 : ret = net_ads_cldap_netlogon(c, ads);
448 3 : out:
449 3 : TALLOC_FREE(tmp_ctx);
450 3 : return ret;
451 : }
452 :
453 :
454 : #ifdef HAVE_JANSSON
455 :
456 2 : static int net_ads_info_json(ADS_STRUCT *ads)
457 : {
458 2 : int ret = 0;
459 : char addr[INET6_ADDRSTRLEN];
460 : time_t pass_time;
461 2 : struct json_object jsobj = json_new_object();
462 :
463 2 : if (json_is_invalid(&jsobj)) {
464 0 : d_fprintf(stderr, _("error setting up JSON value\n"));
465 :
466 0 : goto failure;
467 : }
468 :
469 2 : pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
470 :
471 2 : print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
472 :
473 2 : ret = json_add_string (&jsobj, "LDAP server", addr);
474 2 : if (ret != 0) {
475 0 : goto failure;
476 : }
477 :
478 2 : ret = json_add_string (&jsobj, "LDAP server name",
479 2 : ads->config.ldap_server_name);
480 2 : if (ret != 0) {
481 0 : goto failure;
482 : }
483 :
484 2 : ret = json_add_string (&jsobj, "Realm", ads->config.realm);
485 2 : if (ret != 0) {
486 0 : goto failure;
487 : }
488 :
489 2 : ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
490 2 : if (ret != 0) {
491 0 : goto failure;
492 : }
493 :
494 2 : ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
495 2 : if (ret != 0) {
496 0 : goto failure;
497 : }
498 :
499 2 : ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
500 2 : if (ret != 0) {
501 0 : goto failure;
502 : }
503 :
504 2 : ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
505 2 : if (ret != 0) {
506 0 : goto failure;
507 : }
508 :
509 2 : ret = json_add_int (&jsobj, "Server time offset",
510 : ads->auth.time_offset);
511 2 : if (ret != 0) {
512 0 : goto failure;
513 : }
514 :
515 2 : ret = json_add_int (&jsobj, "Last machine account password change",
516 : pass_time);
517 2 : if (ret != 0) {
518 0 : goto failure;
519 : }
520 :
521 2 : ret = output_json(&jsobj);
522 2 : failure:
523 2 : json_free(&jsobj);
524 :
525 2 : return ret;
526 : }
527 :
528 : #else /* [HAVE_JANSSON] */
529 :
530 : static int net_ads_info_json(ADS_STRUCT *ads)
531 : {
532 : d_fprintf(stderr, _("JSON support not available\n"));
533 :
534 : return -1;
535 : }
536 :
537 : #endif /* [HAVE_JANSSON] */
538 :
539 :
540 :
541 3 : static int net_ads_info(struct net_context *c, int argc, const char **argv)
542 : {
543 3 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
544 3 : ADS_STRUCT *ads = NULL;
545 : ADS_STATUS status;
546 : char addr[INET6_ADDRSTRLEN];
547 : time_t pass_time;
548 3 : int ret = -1;
549 :
550 3 : if (c->display_usage) {
551 0 : d_printf("%s\n"
552 : "net ads info\n"
553 : " %s",
554 : _("Usage:"),
555 : _("Display information about an Active Directory "
556 : "server.\n"));
557 0 : TALLOC_FREE(tmp_ctx);
558 0 : return -1;
559 : }
560 :
561 3 : status = ads_startup_nobind(c, false, tmp_ctx, &ads);
562 3 : if (!ADS_ERR_OK(status)) {
563 0 : d_fprintf(stderr, _("Didn't find the ldap server!\n"));
564 0 : goto out;
565 : }
566 :
567 3 : if (!ads || !ads->config.realm) {
568 0 : d_fprintf(stderr, _("Didn't find the ldap server!\n"));
569 0 : goto out;
570 : }
571 :
572 : /* Try to set the server's current time since we didn't do a full
573 : TCP LDAP session initially */
574 :
575 3 : if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
576 0 : d_fprintf( stderr, _("Failed to get server's current time!\n"));
577 : }
578 :
579 3 : if (c->opt_json) {
580 2 : ret = net_ads_info_json(ads);
581 2 : goto out;
582 : }
583 :
584 1 : pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
585 :
586 1 : print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
587 :
588 1 : d_printf(_("LDAP server: %s\n"), addr);
589 1 : d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
590 1 : d_printf(_("Realm: %s\n"), ads->config.realm);
591 1 : d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
592 1 : d_printf(_("LDAP port: %d\n"), ads->ldap.port);
593 1 : d_printf(_("Server time: %s\n"),
594 1 : http_timestring(tmp_ctx, ads->config.current_time));
595 :
596 1 : d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
597 1 : d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
598 :
599 1 : d_printf(_("Last machine account password change: %s\n"),
600 : http_timestring(tmp_ctx, pass_time));
601 :
602 1 : ret = 0;
603 3 : out:
604 3 : TALLOC_FREE(tmp_ctx);
605 3 : return ret;
606 : }
607 :
608 38 : static ADS_STATUS ads_startup_int(struct net_context *c,
609 : bool only_own_domain,
610 : uint32_t auth_flags,
611 : TALLOC_CTX *mem_ctx,
612 : ADS_STRUCT **ads_ret)
613 : {
614 38 : ADS_STRUCT *ads = NULL;
615 : ADS_STATUS status;
616 38 : bool need_password = false;
617 38 : bool second_time = false;
618 : char *cp;
619 38 : const char *realm = NULL;
620 38 : bool tried_closest_dc = false;
621 38 : enum credentials_use_kerberos krb5_state =
622 : CRED_USE_KERBEROS_DISABLED;
623 :
624 : /* lp_realm() should be handled by a command line param,
625 : However, the join requires that realm be set in smb.conf
626 : and compares our realm with the remote server's so this is
627 : ok until someone needs more flexibility */
628 :
629 38 : *ads_ret = NULL;
630 :
631 38 : retry_connect:
632 38 : if (only_own_domain) {
633 12 : realm = lp_realm();
634 : } else {
635 26 : realm = assume_own_realm(c);
636 : }
637 :
638 38 : ads = ads_init(mem_ctx,
639 : realm,
640 : c->opt_target_workgroup,
641 : c->opt_host,
642 : ADS_SASL_PLAIN);
643 38 : if (ads == NULL) {
644 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
645 : }
646 :
647 38 : if (!c->opt_user_name) {
648 0 : c->opt_user_name = "administrator";
649 : }
650 :
651 38 : if (c->opt_user_specified) {
652 32 : need_password = true;
653 : }
654 :
655 44 : retry:
656 38 : if (!c->opt_password && need_password && !c->opt_machine_pass) {
657 32 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
658 32 : if (!c->opt_password) {
659 0 : TALLOC_FREE(ads);
660 0 : return ADS_ERROR(LDAP_NO_MEMORY);
661 : }
662 : }
663 :
664 38 : if (c->opt_password) {
665 32 : use_in_memory_ccache();
666 32 : TALLOC_FREE(ads->auth.password);
667 32 : ads->auth.password = talloc_strdup(ads, c->opt_password);
668 32 : if (ads->auth.password == NULL) {
669 0 : TALLOC_FREE(ads);
670 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
671 : }
672 : }
673 :
674 38 : TALLOC_FREE(ads->auth.user_name);
675 38 : ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
676 38 : if (ads->auth.user_name == NULL) {
677 0 : TALLOC_FREE(ads);
678 0 : return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
679 : }
680 :
681 38 : ads->auth.flags |= auth_flags;
682 :
683 : /* The ADS code will handle FIPS mode */
684 38 : krb5_state = cli_credentials_get_kerberos_state(c->creds);
685 38 : switch (krb5_state) {
686 0 : case CRED_USE_KERBEROS_REQUIRED:
687 0 : ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
688 0 : ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
689 0 : break;
690 36 : case CRED_USE_KERBEROS_DESIRED:
691 36 : ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
692 36 : ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
693 36 : break;
694 2 : case CRED_USE_KERBEROS_DISABLED:
695 2 : ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
696 2 : ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
697 2 : break;
698 : }
699 :
700 : /*
701 : * If the username is of the form "name@realm",
702 : * extract the realm and convert to upper case.
703 : * This is only used to establish the connection.
704 : */
705 38 : if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
706 0 : *cp++ = '\0';
707 0 : TALLOC_FREE(ads->auth.realm);
708 0 : ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
709 0 : if (ads->auth.realm == NULL) {
710 0 : TALLOC_FREE(ads);
711 0 : return ADS_ERROR(LDAP_NO_MEMORY);
712 : }
713 38 : } else if (ads->auth.realm == NULL) {
714 38 : const char *c_realm = cli_credentials_get_realm(c->creds);
715 :
716 38 : if (c_realm != NULL) {
717 38 : ads->auth.realm = talloc_strdup(ads, c_realm);
718 38 : if (ads->auth.realm == NULL) {
719 0 : TALLOC_FREE(ads);
720 0 : return ADS_ERROR(LDAP_NO_MEMORY);
721 : }
722 : }
723 : }
724 :
725 38 : status = ads_connect(ads);
726 :
727 38 : if (!ADS_ERR_OK(status)) {
728 :
729 1 : if (NT_STATUS_EQUAL(ads_ntstatus(status),
730 : NT_STATUS_NO_LOGON_SERVERS)) {
731 0 : DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
732 0 : TALLOC_FREE(ads);
733 0 : return status;
734 : }
735 :
736 1 : if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
737 0 : need_password = true;
738 0 : second_time = true;
739 0 : goto retry;
740 : } else {
741 1 : TALLOC_FREE(ads);
742 1 : return status;
743 : }
744 : }
745 :
746 : /* when contacting our own domain, make sure we use the closest DC.
747 : * This is done by reconnecting to ADS because only the first call to
748 : * ads_connect will give us our own sitename */
749 :
750 37 : if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
751 :
752 25 : tried_closest_dc = true; /* avoid loop */
753 :
754 25 : if (!ads_closest_dc(ads)) {
755 :
756 0 : namecache_delete(ads->server.realm, 0x1C);
757 0 : namecache_delete(ads->server.workgroup, 0x1C);
758 :
759 0 : TALLOC_FREE(ads);
760 :
761 0 : goto retry_connect;
762 : }
763 : }
764 :
765 37 : *ads_ret = talloc_move(mem_ctx, &ads);
766 37 : return status;
767 : }
768 :
769 32 : ADS_STATUS ads_startup(struct net_context *c,
770 : bool only_own_domain,
771 : TALLOC_CTX *mem_ctx,
772 : ADS_STRUCT **ads)
773 : {
774 32 : return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
775 : }
776 :
777 6 : ADS_STATUS ads_startup_nobind(struct net_context *c,
778 : bool only_own_domain,
779 : TALLOC_CTX *mem_ctx,
780 : ADS_STRUCT **ads)
781 : {
782 6 : return ads_startup_int(c,
783 : only_own_domain,
784 : ADS_AUTH_NO_BIND,
785 : mem_ctx,
786 : ads);
787 : }
788 :
789 : /*
790 : Check to see if connection can be made via ads.
791 : ads_startup() stores the password in opt_password if it needs to so
792 : that rpc or rap can use it without re-prompting.
793 : */
794 26 : static int net_ads_check_int(struct net_context *c,
795 : const char *realm,
796 : const char *workgroup,
797 : const char *host)
798 : {
799 26 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
800 : ADS_STRUCT *ads;
801 : ADS_STATUS status;
802 26 : int ret = -1;
803 :
804 26 : ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
805 26 : if (ads == NULL) {
806 0 : goto out;
807 : }
808 :
809 26 : ads->auth.flags |= ADS_AUTH_NO_BIND;
810 :
811 26 : status = ads_connect(ads);
812 26 : if ( !ADS_ERR_OK(status) ) {
813 0 : goto out;
814 : }
815 :
816 26 : ret = 0;
817 26 : out:
818 26 : TALLOC_FREE(tmp_ctx);
819 26 : return ret;
820 : }
821 :
822 20 : int net_ads_check_our_domain(struct net_context *c)
823 : {
824 20 : return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
825 : }
826 :
827 6 : int net_ads_check(struct net_context *c)
828 : {
829 6 : return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
830 : }
831 :
832 : /*
833 : determine the netbios workgroup name for a domain
834 : */
835 0 : static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
836 : {
837 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
838 0 : ADS_STRUCT *ads = NULL;
839 : ADS_STATUS status;
840 : struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
841 0 : bool ok = false;
842 0 : int ret = -1;
843 :
844 0 : if (c->display_usage) {
845 0 : d_printf ("%s\n"
846 : "net ads workgroup\n"
847 : " %s\n",
848 : _("Usage:"),
849 : _("Print the workgroup name"));
850 0 : TALLOC_FREE(tmp_ctx);
851 0 : return -1;
852 : }
853 :
854 0 : status = ads_startup_nobind(c, false, tmp_ctx, &ads);
855 0 : if (!ADS_ERR_OK(status)) {
856 0 : d_fprintf(stderr, _("Didn't find the cldap server!\n"));
857 0 : goto out;
858 : }
859 :
860 0 : if (!ads->config.realm) {
861 0 : ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
862 0 : if (ads->config.realm == NULL) {
863 0 : d_fprintf(stderr, _("Out of memory\n"));
864 0 : goto out;
865 : }
866 0 : ads->ldap.port = 389;
867 : }
868 :
869 0 : ok = ads_cldap_netlogon_5(tmp_ctx,
870 0 : &ads->ldap.ss, ads->server.realm, &reply);
871 0 : if (!ok) {
872 0 : d_fprintf(stderr, _("CLDAP query failed!\n"));
873 0 : goto out;
874 : }
875 :
876 0 : d_printf(_("Workgroup: %s\n"), reply.domain_name);
877 :
878 0 : ret = 0;
879 0 : out:
880 0 : TALLOC_FREE(tmp_ctx);
881 :
882 0 : return ret;
883 : }
884 :
885 :
886 :
887 0 : static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
888 : {
889 0 : char **disp_fields = (char **) data_area;
890 :
891 0 : if (!field) { /* must be end of record */
892 0 : if (disp_fields[0]) {
893 0 : if (!strchr_m(disp_fields[0], '$')) {
894 0 : if (disp_fields[1])
895 0 : d_printf("%-21.21s %s\n",
896 0 : disp_fields[0], disp_fields[1]);
897 : else
898 0 : d_printf("%s\n", disp_fields[0]);
899 : }
900 : }
901 0 : SAFE_FREE(disp_fields[0]);
902 0 : SAFE_FREE(disp_fields[1]);
903 0 : return true;
904 : }
905 0 : if (!values) /* must be new field, indicate string field */
906 0 : return true;
907 0 : if (strcasecmp_m(field, "sAMAccountName") == 0) {
908 0 : disp_fields[0] = SMB_STRDUP((char *) values[0]);
909 : }
910 0 : if (strcasecmp_m(field, "description") == 0)
911 0 : disp_fields[1] = SMB_STRDUP((char *) values[0]);
912 0 : return true;
913 : }
914 :
915 0 : static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
916 : {
917 0 : return net_user_usage(c, argc, argv);
918 : }
919 :
920 4 : static int ads_user_add(struct net_context *c, int argc, const char **argv)
921 : {
922 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
923 4 : ADS_STRUCT *ads = NULL;
924 : ADS_STATUS status;
925 : char *upn, *userdn;
926 4 : LDAPMessage *res=NULL;
927 4 : int rc = -1;
928 4 : char *ou_str = NULL;
929 :
930 4 : if (argc < 1 || c->display_usage) {
931 0 : TALLOC_FREE(tmp_ctx);
932 0 : return net_ads_user_usage(c, argc, argv);
933 : }
934 :
935 4 : status = ads_startup(c, false, tmp_ctx, &ads);
936 4 : if (!ADS_ERR_OK(status)) {
937 0 : goto done;
938 : }
939 :
940 4 : status = ads_find_user_acct(ads, &res, argv[0]);
941 4 : if (!ADS_ERR_OK(status)) {
942 0 : d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
943 0 : goto done;
944 : }
945 :
946 4 : if (ads_count_replies(ads, res)) {
947 0 : d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
948 : argv[0]);
949 0 : goto done;
950 : }
951 :
952 4 : if (c->opt_container) {
953 0 : ou_str = SMB_STRDUP(c->opt_container);
954 : } else {
955 4 : ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
956 : }
957 :
958 4 : status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
959 4 : if (!ADS_ERR_OK(status)) {
960 0 : d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
961 : ads_errstr(status));
962 0 : goto done;
963 : }
964 :
965 : /* if no password is to be set, we're done */
966 4 : if (argc == 1) {
967 0 : d_printf(_("User %s added\n"), argv[0]);
968 0 : rc = 0;
969 0 : goto done;
970 : }
971 :
972 : /* try setting the password */
973 4 : upn = talloc_asprintf(tmp_ctx,
974 : "%s@%s",
975 : argv[0],
976 4 : ads->config.realm);
977 4 : if (upn == NULL) {
978 0 : goto done;
979 : }
980 :
981 4 : status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
982 4 : ads->auth.time_offset);
983 4 : if (ADS_ERR_OK(status)) {
984 4 : d_printf(_("User %s added\n"), argv[0]);
985 4 : rc = 0;
986 4 : goto done;
987 : }
988 0 : TALLOC_FREE(upn);
989 :
990 : /* password didn't set, delete account */
991 0 : d_fprintf(stderr, _("Could not add user %s. "
992 : "Error setting password %s\n"),
993 : argv[0], ads_errstr(status));
994 :
995 0 : ads_msgfree(ads, res);
996 0 : res = NULL;
997 :
998 0 : status=ads_find_user_acct(ads, &res, argv[0]);
999 0 : if (ADS_ERR_OK(status)) {
1000 0 : userdn = ads_get_dn(ads, tmp_ctx, res);
1001 0 : ads_del_dn(ads, userdn);
1002 0 : TALLOC_FREE(userdn);
1003 : }
1004 :
1005 2 : done:
1006 4 : ads_msgfree(ads, res);
1007 4 : SAFE_FREE(ou_str);
1008 4 : TALLOC_FREE(tmp_ctx);
1009 4 : return rc;
1010 : }
1011 :
1012 0 : static int ads_user_info(struct net_context *c, int argc, const char **argv)
1013 : {
1014 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1015 0 : ADS_STRUCT *ads = NULL;
1016 : ADS_STATUS status;
1017 0 : LDAPMessage *res = NULL;
1018 0 : int ret = -1;
1019 : wbcErr wbc_status;
1020 0 : const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1021 0 : char *searchstring = NULL;
1022 0 : char **grouplist = NULL;
1023 0 : char *primary_group = NULL;
1024 0 : char *escaped_user = NULL;
1025 : struct dom_sid primary_group_sid;
1026 : uint32_t group_rid;
1027 : enum wbcSidType type;
1028 :
1029 0 : if (argc < 1 || c->display_usage) {
1030 0 : TALLOC_FREE(tmp_ctx);
1031 0 : return net_ads_user_usage(c, argc, argv);
1032 : }
1033 :
1034 0 : escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1035 0 : if (!escaped_user) {
1036 0 : d_fprintf(stderr,
1037 0 : _("ads_user_info: failed to escape user %s\n"),
1038 : argv[0]);
1039 0 : goto out;
1040 : }
1041 :
1042 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1043 0 : if (!ADS_ERR_OK(status)) {
1044 0 : goto out;
1045 : }
1046 :
1047 0 : searchstring = talloc_asprintf(tmp_ctx,
1048 : "(sAMAccountName=%s)",
1049 : escaped_user);
1050 0 : if (searchstring == NULL) {
1051 0 : goto out;
1052 : }
1053 :
1054 0 : status = ads_search(ads, &res, searchstring, attrs);
1055 0 : if (!ADS_ERR_OK(status)) {
1056 0 : d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1057 0 : goto out;
1058 : }
1059 :
1060 0 : if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1061 0 : d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1062 0 : goto out;
1063 : }
1064 :
1065 0 : status = ads_domain_sid(ads, &primary_group_sid);
1066 0 : if (!ADS_ERR_OK(status)) {
1067 0 : d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1068 0 : goto out;
1069 : }
1070 :
1071 0 : sid_append_rid(&primary_group_sid, group_rid);
1072 :
1073 0 : wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1074 : NULL, /* don't look up domain */
1075 : &primary_group,
1076 : &type);
1077 0 : if (!WBC_ERROR_IS_OK(wbc_status)) {
1078 0 : d_fprintf(stderr, "wbcLookupSid: %s\n",
1079 : wbcErrorString(wbc_status));
1080 0 : goto out;
1081 : }
1082 :
1083 0 : d_printf("%s\n", primary_group);
1084 :
1085 0 : wbcFreeMemory(primary_group);
1086 :
1087 0 : grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1088 : (LDAPMessage *)res, "memberOf");
1089 :
1090 0 : if (grouplist) {
1091 : int i;
1092 : char **groupname;
1093 0 : for (i=0;grouplist[i];i++) {
1094 0 : groupname = ldap_explode_dn(grouplist[i], 1);
1095 0 : d_printf("%s\n", groupname[0]);
1096 0 : ldap_value_free(groupname);
1097 : }
1098 0 : ldap_value_free(grouplist);
1099 : }
1100 :
1101 0 : ret = 0;
1102 0 : out:
1103 0 : ads_msgfree(ads, res);
1104 0 : TALLOC_FREE(tmp_ctx);
1105 0 : return ret;
1106 : }
1107 :
1108 2 : static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1109 : {
1110 2 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1111 2 : ADS_STRUCT *ads = NULL;
1112 : ADS_STATUS status;
1113 2 : LDAPMessage *res = NULL;
1114 2 : char *userdn = NULL;
1115 2 : int ret = -1;
1116 :
1117 2 : if (argc < 1) {
1118 0 : TALLOC_FREE(tmp_ctx);
1119 0 : return net_ads_user_usage(c, argc, argv);
1120 : }
1121 :
1122 2 : status = ads_startup(c, false, tmp_ctx, &ads);
1123 2 : if (!ADS_ERR_OK(status)) {
1124 0 : goto out;
1125 : }
1126 :
1127 2 : status = ads_find_user_acct(ads, &res, argv[0]);
1128 2 : if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1129 0 : d_printf(_("User %s does not exist.\n"), argv[0]);
1130 0 : goto out;
1131 : }
1132 :
1133 2 : userdn = ads_get_dn(ads, tmp_ctx, res);
1134 2 : if (userdn == NULL) {
1135 0 : goto out;
1136 : }
1137 :
1138 2 : status = ads_del_dn(ads, userdn);
1139 2 : if (!ADS_ERR_OK(status)) {
1140 0 : d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1141 : ads_errstr(status));
1142 0 : goto out;
1143 : }
1144 :
1145 2 : d_printf(_("User %s deleted\n"), argv[0]);
1146 :
1147 2 : ret = 0;
1148 2 : out:
1149 2 : ads_msgfree(ads, res);
1150 2 : TALLOC_FREE(tmp_ctx);
1151 2 : return ret;
1152 : }
1153 :
1154 6 : int net_ads_user(struct net_context *c, int argc, const char **argv)
1155 : {
1156 6 : struct functable func[] = {
1157 : {
1158 : "add",
1159 : ads_user_add,
1160 : NET_TRANSPORT_ADS,
1161 : N_("Add an AD user"),
1162 : N_("net ads user add\n"
1163 : " Add an AD user")
1164 : },
1165 : {
1166 : "info",
1167 : ads_user_info,
1168 : NET_TRANSPORT_ADS,
1169 : N_("Display information about an AD user"),
1170 : N_("net ads user info\n"
1171 : " Display information about an AD user")
1172 : },
1173 : {
1174 : "delete",
1175 : ads_user_delete,
1176 : NET_TRANSPORT_ADS,
1177 : N_("Delete an AD user"),
1178 : N_("net ads user delete\n"
1179 : " Delete an AD user")
1180 : },
1181 : {NULL, NULL, 0, NULL, NULL}
1182 : };
1183 6 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1184 6 : ADS_STRUCT *ads = NULL;
1185 : ADS_STATUS status;
1186 6 : const char *shortattrs[] = {"sAMAccountName", NULL};
1187 6 : const char *longattrs[] = {"sAMAccountName", "description", NULL};
1188 6 : char *disp_fields[2] = {NULL, NULL};
1189 6 : int ret = -1;
1190 :
1191 6 : if (argc > 0) {
1192 6 : TALLOC_FREE(tmp_ctx);
1193 6 : return net_run_function(c, argc, argv, "net ads user", func);
1194 : }
1195 :
1196 0 : if (c->display_usage) {
1197 0 : d_printf( "%s\n"
1198 : "net ads user\n"
1199 : " %s\n",
1200 : _("Usage:"),
1201 : _("List AD users"));
1202 0 : net_display_usage_from_functable(func);
1203 0 : TALLOC_FREE(tmp_ctx);
1204 0 : return -1;
1205 : }
1206 :
1207 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1208 0 : if (!ADS_ERR_OK(status)) {
1209 0 : goto out;
1210 : }
1211 :
1212 0 : if (c->opt_long_list_entries)
1213 0 : d_printf(_("\nUser name Comment"
1214 : "\n-----------------------------\n"));
1215 :
1216 0 : status = ads_do_search_all_fn(ads,
1217 0 : ads->config.bind_path,
1218 : LDAP_SCOPE_SUBTREE,
1219 : "(objectCategory=user)",
1220 0 : c->opt_long_list_entries ?
1221 : longattrs : shortattrs,
1222 : usergrp_display,
1223 : disp_fields);
1224 0 : if (!ADS_ERR_OK(status)) {
1225 0 : goto out;
1226 : }
1227 :
1228 0 : ret = 0;
1229 0 : out:
1230 0 : TALLOC_FREE(tmp_ctx);
1231 0 : return ret;
1232 : }
1233 :
1234 0 : static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1235 : {
1236 0 : return net_group_usage(c, argc, argv);
1237 : }
1238 :
1239 0 : static int ads_group_add(struct net_context *c, int argc, const char **argv)
1240 : {
1241 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1242 0 : ADS_STRUCT *ads = NULL;
1243 : ADS_STATUS status;
1244 0 : LDAPMessage *res = NULL;
1245 0 : int ret = -1;
1246 0 : char *ou_str = NULL;
1247 :
1248 0 : if (argc < 1 || c->display_usage) {
1249 0 : TALLOC_FREE(tmp_ctx);
1250 0 : return net_ads_group_usage(c, argc, argv);
1251 : }
1252 :
1253 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1254 0 : if (!ADS_ERR_OK(status)) {
1255 0 : goto out;
1256 : }
1257 :
1258 0 : status = ads_find_user_acct(ads, &res, argv[0]);
1259 0 : if (!ADS_ERR_OK(status)) {
1260 0 : d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1261 0 : goto out;
1262 : }
1263 :
1264 0 : if (ads_count_replies(ads, res)) {
1265 0 : d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1266 0 : goto out;
1267 : }
1268 :
1269 0 : if (c->opt_container) {
1270 0 : ou_str = SMB_STRDUP(c->opt_container);
1271 : } else {
1272 0 : ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1273 : }
1274 :
1275 0 : status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1276 0 : if (!ADS_ERR_OK(status)) {
1277 0 : d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1278 : ads_errstr(status));
1279 0 : goto out;
1280 : }
1281 :
1282 0 : d_printf(_("Group %s added\n"), argv[0]);
1283 :
1284 0 : ret = 0;
1285 0 : out:
1286 0 : ads_msgfree(ads, res);
1287 0 : SAFE_FREE(ou_str);
1288 0 : TALLOC_FREE(tmp_ctx);
1289 0 : return ret;
1290 : }
1291 :
1292 0 : static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1293 : {
1294 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1295 0 : ADS_STRUCT *ads = NULL;
1296 : ADS_STATUS status;
1297 0 : LDAPMessage *res = NULL;
1298 0 : char *groupdn = NULL;
1299 0 : int ret = -1;
1300 :
1301 0 : if (argc < 1 || c->display_usage) {
1302 0 : TALLOC_FREE(tmp_ctx);
1303 0 : return net_ads_group_usage(c, argc, argv);
1304 : }
1305 :
1306 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1307 0 : if (!ADS_ERR_OK(status)) {
1308 0 : goto out;
1309 : }
1310 :
1311 0 : status = ads_find_user_acct(ads, &res, argv[0]);
1312 0 : if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1313 0 : d_printf(_("Group %s does not exist.\n"), argv[0]);
1314 0 : goto out;
1315 : }
1316 :
1317 0 : groupdn = ads_get_dn(ads, tmp_ctx, res);
1318 0 : if (groupdn == NULL) {
1319 0 : goto out;
1320 : }
1321 :
1322 0 : status = ads_del_dn(ads, groupdn);
1323 0 : if (!ADS_ERR_OK(status)) {
1324 0 : d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1325 : ads_errstr(status));
1326 0 : goto out;
1327 : }
1328 0 : d_printf(_("Group %s deleted\n"), argv[0]);
1329 :
1330 0 : ret = 0;
1331 0 : out:
1332 0 : ads_msgfree(ads, res);
1333 0 : TALLOC_FREE(tmp_ctx);
1334 0 : return ret;
1335 : }
1336 :
1337 0 : int net_ads_group(struct net_context *c, int argc, const char **argv)
1338 : {
1339 0 : struct functable func[] = {
1340 : {
1341 : "add",
1342 : ads_group_add,
1343 : NET_TRANSPORT_ADS,
1344 : N_("Add an AD group"),
1345 : N_("net ads group add\n"
1346 : " Add an AD group")
1347 : },
1348 : {
1349 : "delete",
1350 : ads_group_delete,
1351 : NET_TRANSPORT_ADS,
1352 : N_("Delete an AD group"),
1353 : N_("net ads group delete\n"
1354 : " Delete an AD group")
1355 : },
1356 : {NULL, NULL, 0, NULL, NULL}
1357 : };
1358 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1359 0 : ADS_STRUCT *ads = NULL;
1360 : ADS_STATUS status;
1361 0 : const char *shortattrs[] = {"sAMAccountName", NULL};
1362 0 : const char *longattrs[] = {"sAMAccountName", "description", NULL};
1363 0 : char *disp_fields[2] = {NULL, NULL};
1364 0 : int ret = -1;
1365 :
1366 0 : if (argc >= 0) {
1367 0 : TALLOC_FREE(tmp_ctx);
1368 0 : return net_run_function(c, argc, argv, "net ads group", func);
1369 : }
1370 :
1371 0 : if (c->display_usage) {
1372 0 : d_printf( "%s\n"
1373 : "net ads group\n"
1374 : " %s\n",
1375 : _("Usage:"),
1376 : _("List AD groups"));
1377 0 : net_display_usage_from_functable(func);
1378 0 : TALLOC_FREE(tmp_ctx);
1379 0 : return -1;
1380 : }
1381 :
1382 0 : status = ads_startup(c, false, tmp_ctx, &ads);
1383 0 : if (!ADS_ERR_OK(status)) {
1384 0 : goto out;
1385 : }
1386 :
1387 0 : if (c->opt_long_list_entries)
1388 0 : d_printf(_("\nGroup name Comment"
1389 : "\n-----------------------------\n"));
1390 :
1391 0 : status = ads_do_search_all_fn(ads,
1392 0 : ads->config.bind_path,
1393 : LDAP_SCOPE_SUBTREE,
1394 : "(objectCategory=group)",
1395 0 : c->opt_long_list_entries ?
1396 : longattrs : shortattrs,
1397 : usergrp_display,
1398 : disp_fields);
1399 0 : if (!ADS_ERR_OK(status)) {
1400 0 : goto out;
1401 : }
1402 :
1403 0 : ret = 0;
1404 0 : out:
1405 0 : TALLOC_FREE(tmp_ctx);
1406 0 : return ret;
1407 : }
1408 :
1409 0 : static int net_ads_status(struct net_context *c, int argc, const char **argv)
1410 : {
1411 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1412 0 : ADS_STRUCT *ads = NULL;
1413 : ADS_STATUS status;
1414 0 : LDAPMessage *res = NULL;
1415 0 : int ret = -1;
1416 :
1417 0 : if (c->display_usage) {
1418 0 : d_printf( "%s\n"
1419 : "net ads status\n"
1420 : " %s\n",
1421 : _("Usage:"),
1422 : _("Display machine account details"));
1423 0 : TALLOC_FREE(tmp_ctx);
1424 0 : return -1;
1425 : }
1426 :
1427 0 : net_warn_member_options();
1428 :
1429 0 : status = ads_startup(c, true, tmp_ctx, &ads);
1430 0 : if (!ADS_ERR_OK(status)) {
1431 0 : goto out;
1432 : }
1433 :
1434 0 : status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1435 0 : if (!ADS_ERR_OK(status)) {
1436 0 : d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1437 : ads_errstr(status));
1438 0 : goto out;
1439 : }
1440 :
1441 0 : if (ads_count_replies(ads, res) == 0) {
1442 0 : d_fprintf(stderr, _("No machine account for '%s' found\n"),
1443 : lp_netbios_name());
1444 0 : goto out;
1445 : }
1446 :
1447 0 : ads_dump(ads, res);
1448 :
1449 0 : ret = 0;
1450 0 : out:
1451 0 : ads_msgfree(ads, res);
1452 0 : TALLOC_FREE(tmp_ctx);
1453 0 : return ret;
1454 : }
1455 :
1456 : /*******************************************************************
1457 : Leave an AD domain. Windows XP disables the machine account.
1458 : We'll try the same. The old code would do an LDAP delete.
1459 : That only worked using the machine creds because added the machine
1460 : with full control to the computer object's ACL.
1461 : *******************************************************************/
1462 :
1463 0 : static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1464 : {
1465 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1466 0 : struct libnet_UnjoinCtx *r = NULL;
1467 : WERROR werr;
1468 0 : int ret = -1;
1469 :
1470 0 : if (c->display_usage) {
1471 0 : d_printf( "%s\n"
1472 : "net ads leave [--keep-account]\n"
1473 : " %s\n",
1474 : _("Usage:"),
1475 : _("Leave an AD domain"));
1476 0 : TALLOC_FREE(tmp_ctx);
1477 0 : return -1;
1478 : }
1479 :
1480 0 : if (!*lp_realm()) {
1481 0 : d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1482 0 : TALLOC_FREE(tmp_ctx);
1483 0 : return -1;
1484 : }
1485 :
1486 0 : if (!c->opt_kerberos) {
1487 0 : use_in_memory_ccache();
1488 : }
1489 :
1490 0 : if (!c->msg_ctx) {
1491 0 : d_fprintf(stderr, _("Could not initialise message context. "
1492 : "Try running as root\n"));
1493 0 : goto done;
1494 : }
1495 :
1496 0 : werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1497 0 : if (!W_ERROR_IS_OK(werr)) {
1498 0 : d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1499 0 : goto done;
1500 : }
1501 :
1502 0 : r->in.debug = true;
1503 0 : r->in.use_kerberos = c->opt_kerberos;
1504 0 : r->in.dc_name = c->opt_host;
1505 0 : r->in.domain_name = lp_realm();
1506 0 : r->in.admin_account = c->opt_user_name;
1507 0 : r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1508 0 : r->in.modify_config = lp_config_backend_is_registry();
1509 :
1510 : /* Try to delete it, but if that fails, disable it. The
1511 : WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1512 0 : r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1513 : WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1514 0 : if (c->opt_keep_account) {
1515 0 : r->in.delete_machine_account = false;
1516 : } else {
1517 0 : r->in.delete_machine_account = true;
1518 : }
1519 :
1520 0 : r->in.msg_ctx = c->msg_ctx;
1521 :
1522 0 : werr = libnet_Unjoin(tmp_ctx, r);
1523 0 : if (!W_ERROR_IS_OK(werr)) {
1524 0 : d_printf(_("Failed to leave domain: %s\n"),
1525 0 : r->out.error_string ? r->out.error_string :
1526 0 : get_friendly_werror_msg(werr));
1527 0 : goto done;
1528 : }
1529 :
1530 0 : if (r->out.deleted_machine_account) {
1531 0 : d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1532 0 : r->in.machine_name, r->out.dns_domain_name);
1533 0 : ret = 0;
1534 0 : goto done;
1535 : }
1536 :
1537 : /* We couldn't delete it - see if the disable succeeded. */
1538 0 : if (r->out.disabled_machine_account) {
1539 0 : d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1540 0 : r->in.machine_name, r->out.dns_domain_name);
1541 0 : ret = 0;
1542 0 : goto done;
1543 : }
1544 :
1545 : /* Based on what we requested, we shouldn't get here, but if
1546 : we did, it means the secrets were removed, and therefore
1547 : we have left the domain */
1548 0 : d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1549 0 : r->in.machine_name, r->out.dns_domain_name);
1550 :
1551 0 : ret = 0;
1552 0 : done:
1553 0 : TALLOC_FREE(tmp_ctx);
1554 0 : return ret;
1555 : }
1556 :
1557 0 : static ADS_STATUS net_ads_join_ok(struct net_context *c)
1558 : {
1559 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1560 0 : ADS_STRUCT *ads = NULL;
1561 : ADS_STATUS status;
1562 : fstring dc_name;
1563 : struct sockaddr_storage dcip;
1564 :
1565 0 : if (!secrets_init()) {
1566 0 : DEBUG(1,("Failed to initialise secrets database\n"));
1567 0 : TALLOC_FREE(tmp_ctx);
1568 0 : return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1569 : }
1570 :
1571 0 : net_warn_member_options();
1572 :
1573 0 : net_use_krb_machine_account(c);
1574 :
1575 0 : get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1576 :
1577 0 : status = ads_startup(c, true, tmp_ctx, &ads);
1578 0 : if (!ADS_ERR_OK(status)) {
1579 0 : goto out;
1580 : }
1581 :
1582 0 : status = ADS_ERROR_NT(NT_STATUS_OK);
1583 0 : out:
1584 0 : TALLOC_FREE(tmp_ctx);
1585 0 : return status;
1586 : }
1587 :
1588 : /*
1589 : check that an existing join is OK
1590 : */
1591 0 : int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1592 : {
1593 : ADS_STATUS status;
1594 0 : use_in_memory_ccache();
1595 :
1596 0 : if (c->display_usage) {
1597 0 : d_printf( "%s\n"
1598 : "net ads testjoin\n"
1599 : " %s\n",
1600 : _("Usage:"),
1601 : _("Test if the existing join is ok"));
1602 0 : return -1;
1603 : }
1604 :
1605 0 : net_warn_member_options();
1606 :
1607 : /* Display success or failure */
1608 0 : status = net_ads_join_ok(c);
1609 0 : if (!ADS_ERR_OK(status)) {
1610 0 : fprintf(stderr, _("Join to domain is not valid: %s\n"),
1611 : get_friendly_nt_error_msg(ads_ntstatus(status)));
1612 0 : return -1;
1613 : }
1614 :
1615 0 : printf(_("Join is OK\n"));
1616 0 : return 0;
1617 : }
1618 :
1619 : /*******************************************************************
1620 : Simple config checks before beginning the join
1621 : ********************************************************************/
1622 :
1623 20 : static WERROR check_ads_config( void )
1624 : {
1625 20 : if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1626 0 : d_printf(_("Host is not configured as a member server.\n"));
1627 0 : return WERR_INVALID_DOMAIN_ROLE;
1628 : }
1629 :
1630 20 : if (strlen(lp_netbios_name()) > 15) {
1631 0 : d_printf(_("Our netbios name can be at most 15 chars long, "
1632 : "\"%s\" is %u chars long\n"), lp_netbios_name(),
1633 0 : (unsigned int)strlen(lp_netbios_name()));
1634 0 : return WERR_INVALID_COMPUTERNAME;
1635 : }
1636 :
1637 20 : if ( lp_security() == SEC_ADS && !*lp_realm()) {
1638 0 : d_fprintf(stderr, _("realm must be set in in %s for ADS "
1639 : "join to succeed.\n"), get_dyn_CONFIGFILE());
1640 0 : return WERR_INVALID_PARAMETER;
1641 : }
1642 :
1643 20 : return WERR_OK;
1644 : }
1645 :
1646 : /*******************************************************************
1647 : ********************************************************************/
1648 :
1649 0 : static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1650 : {
1651 0 : d_printf(_("net ads join [--no-dns-updates] [options]\n"
1652 : "Valid options:\n"));
1653 0 : d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1654 : " The default is in the form netbiosname.dnsdomain\n"));
1655 0 : d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1656 : " The default UPN is in the form host/netbiosname@REALM.\n"));
1657 0 : d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1658 : " The OU string read from top to bottom without RDNs\n"
1659 : " and delimited by a '/'.\n"
1660 : " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1661 : " NB: A backslash '\\' is used as escape at multiple\n"
1662 : " levels and may need to be doubled or even\n"
1663 : " quadrupled. It is not used as a separator.\n"));
1664 0 : d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1665 : " the join. The default password is random.\n"));
1666 0 : d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1667 0 : d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1668 : " NB: osName and osVer must be specified together for\n"
1669 : " either to take effect. The operatingSystemService\n"
1670 : " attribute is then also set along with the two\n"
1671 : " other attributes.\n"));
1672 0 : d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1673 : " during the join.\n"
1674 : " NB: If not specified then by default the samba\n"
1675 : " version string is used instead.\n"));
1676 0 : return -1;
1677 : }
1678 :
1679 :
1680 20 : int net_ads_join(struct net_context *c, int argc, const char **argv)
1681 : {
1682 20 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1683 20 : struct libnet_JoinCtx *r = NULL;
1684 20 : const char *domain = lp_realm();
1685 20 : WERROR werr = WERR_NERR_SETUPNOTJOINED;
1686 20 : bool createupn = false;
1687 20 : const char *dnshostname = NULL;
1688 20 : const char *machineupn = NULL;
1689 20 : const char *machine_password = NULL;
1690 20 : const char *create_in_ou = NULL;
1691 : int i;
1692 20 : const char *os_name = NULL;
1693 20 : const char *os_version = NULL;
1694 20 : const char *os_servicepack = NULL;
1695 20 : bool modify_config = lp_config_backend_is_registry();
1696 20 : enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1697 20 : int ret = -1;
1698 :
1699 20 : if (c->display_usage) {
1700 0 : TALLOC_FREE(tmp_ctx);
1701 0 : return net_ads_join_usage(c, argc, argv);
1702 : }
1703 :
1704 20 : net_warn_member_options();
1705 :
1706 20 : if (!modify_config) {
1707 20 : werr = check_ads_config();
1708 20 : if (!W_ERROR_IS_OK(werr)) {
1709 0 : d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1710 0 : goto fail;
1711 : }
1712 : }
1713 :
1714 20 : if (!c->opt_kerberos) {
1715 10 : use_in_memory_ccache();
1716 : }
1717 :
1718 20 : werr = libnet_init_JoinCtx(tmp_ctx, &r);
1719 20 : if (!W_ERROR_IS_OK(werr)) {
1720 0 : goto fail;
1721 : }
1722 :
1723 : /* process additional command line args */
1724 :
1725 20 : for ( i=0; i<argc; i++ ) {
1726 0 : if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1727 0 : dnshostname = get_string_param(argv[i]);
1728 : }
1729 0 : else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1730 0 : createupn = true;
1731 0 : machineupn = get_string_param(argv[i]);
1732 : }
1733 0 : else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1734 0 : if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1735 0 : d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1736 0 : werr = WERR_INVALID_PARAMETER;
1737 0 : goto fail;
1738 : }
1739 : }
1740 0 : else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1741 0 : if ( (os_name = get_string_param(argv[i])) == NULL ) {
1742 0 : d_fprintf(stderr, _("Please supply a operating system name.\n"));
1743 0 : werr = WERR_INVALID_PARAMETER;
1744 0 : goto fail;
1745 : }
1746 : }
1747 0 : else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1748 0 : if ( (os_version = get_string_param(argv[i])) == NULL ) {
1749 0 : d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1750 0 : werr = WERR_INVALID_PARAMETER;
1751 0 : goto fail;
1752 : }
1753 : }
1754 0 : else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1755 0 : if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1756 0 : d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1757 0 : werr = WERR_INVALID_PARAMETER;
1758 0 : goto fail;
1759 : }
1760 : }
1761 0 : else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1762 0 : if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1763 0 : d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1764 0 : werr = WERR_INVALID_PARAMETER;
1765 0 : goto fail;
1766 : }
1767 : } else {
1768 0 : domain = argv[i];
1769 0 : if (strchr(domain, '.') == NULL) {
1770 0 : domain_name_type = JoinDomNameTypeUnknown;
1771 : } else {
1772 0 : domain_name_type = JoinDomNameTypeDNS;
1773 : }
1774 : }
1775 : }
1776 :
1777 20 : if (!*domain) {
1778 0 : d_fprintf(stderr, _("Please supply a valid domain name\n"));
1779 0 : werr = WERR_INVALID_PARAMETER;
1780 0 : goto fail;
1781 : }
1782 :
1783 20 : if (!c->msg_ctx) {
1784 0 : d_fprintf(stderr, _("Could not initialise message context. "
1785 : "Try running as root\n"));
1786 0 : werr = WERR_ACCESS_DENIED;
1787 0 : goto fail;
1788 : }
1789 :
1790 : /* Do the domain join here */
1791 :
1792 20 : r->in.domain_name = domain;
1793 20 : r->in.domain_name_type = domain_name_type;
1794 20 : r->in.create_upn = createupn;
1795 20 : r->in.upn = machineupn;
1796 20 : r->in.dnshostname = dnshostname;
1797 20 : r->in.account_ou = create_in_ou;
1798 20 : r->in.os_name = os_name;
1799 20 : r->in.os_version = os_version;
1800 20 : r->in.os_servicepack = os_servicepack;
1801 20 : r->in.dc_name = c->opt_host;
1802 20 : r->in.admin_account = c->opt_user_name;
1803 20 : r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1804 20 : r->in.machine_password = machine_password;
1805 20 : r->in.debug = true;
1806 20 : r->in.use_kerberos = c->opt_kerberos;
1807 20 : r->in.modify_config = modify_config;
1808 20 : r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1809 : WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1810 : WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1811 20 : r->in.msg_ctx = c->msg_ctx;
1812 :
1813 20 : werr = libnet_Join(tmp_ctx, r);
1814 21 : if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1815 1 : strequal(domain, lp_realm())) {
1816 1 : r->in.domain_name = lp_workgroup();
1817 1 : r->in.domain_name_type = JoinDomNameTypeNBT;
1818 1 : werr = libnet_Join(tmp_ctx, r);
1819 : }
1820 20 : if (!W_ERROR_IS_OK(werr)) {
1821 0 : goto fail;
1822 : }
1823 :
1824 : /* Check the short name of the domain */
1825 :
1826 20 : if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1827 0 : d_printf(_("The workgroup in %s does not match the short\n"
1828 : "domain name obtained from the server.\n"
1829 : "Using the name [%s] from the server.\n"
1830 : "You should set \"workgroup = %s\" in %s.\n"),
1831 0 : get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1832 0 : r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1833 : }
1834 :
1835 20 : d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1836 :
1837 20 : if (r->out.dns_domain_name) {
1838 20 : d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1839 20 : r->out.dns_domain_name);
1840 : } else {
1841 0 : d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1842 0 : r->out.netbios_domain_name);
1843 : }
1844 :
1845 : /* print out informative error string in case there is one */
1846 20 : if (r->out.error_string != NULL) {
1847 0 : d_printf("%s\n", r->out.error_string);
1848 : }
1849 :
1850 : /*
1851 : * We try doing the dns update (if it was compiled in
1852 : * and if it was not disabled on the command line).
1853 : * If the dns update fails, we still consider the join
1854 : * operation as succeeded if we came this far.
1855 : */
1856 20 : if (!c->opt_no_dns_updates) {
1857 20 : net_ads_join_dns_updates(c, tmp_ctx, r);
1858 : }
1859 :
1860 20 : ret = 0;
1861 :
1862 20 : fail:
1863 20 : if (ret != 0) {
1864 : /* issue an overall failure message at the end. */
1865 0 : d_printf(_("Failed to join domain: %s\n"),
1866 0 : r && r->out.error_string ? r->out.error_string :
1867 0 : get_friendly_werror_msg(werr));
1868 : }
1869 :
1870 20 : TALLOC_FREE(tmp_ctx);
1871 :
1872 20 : return ret;
1873 : }
1874 :
1875 : /*******************************************************************
1876 : ********************************************************************/
1877 :
1878 8 : static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1879 : {
1880 : #if defined(HAVE_KRB5)
1881 8 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1882 8 : ADS_STRUCT *ads = NULL;
1883 : ADS_STATUS status;
1884 : NTSTATUS ntstatus;
1885 8 : const char *hostname = NULL;
1886 8 : const char **addrs_list = NULL;
1887 8 : struct sockaddr_storage *addrs = NULL;
1888 8 : int num_addrs = 0;
1889 : int count;
1890 8 : int ret = -1;
1891 :
1892 : #ifdef DEVELOPER
1893 8 : talloc_enable_leak_report();
1894 : #endif
1895 :
1896 8 : if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1897 0 : d_fprintf(stderr, _("Refusing DNS updates with automatic "
1898 : "detection of addresses in a clustered "
1899 : "setup.\n"));
1900 0 : c->display_usage = true;
1901 : }
1902 :
1903 8 : if (c->display_usage) {
1904 0 : d_printf( "%s\n"
1905 : "net ads dns register [hostname [IP [IP...]]]\n"
1906 : " %s\n",
1907 : _("Usage:"),
1908 : _("Register hostname with DNS\n"));
1909 0 : TALLOC_FREE(tmp_ctx);
1910 0 : return -1;
1911 : }
1912 :
1913 8 : if (argc >= 1) {
1914 8 : hostname = argv[0];
1915 : }
1916 :
1917 8 : if (argc > 1) {
1918 8 : num_addrs = argc - 1;
1919 8 : addrs_list = &argv[1];
1920 0 : } else if (lp_clustering()) {
1921 0 : addrs_list = lp_cluster_addresses();
1922 0 : num_addrs = str_list_length(addrs_list);
1923 : }
1924 :
1925 8 : if (num_addrs > 0) {
1926 8 : addrs = talloc_zero_array(tmp_ctx,
1927 : struct sockaddr_storage,
1928 : num_addrs);
1929 8 : if (addrs == NULL) {
1930 0 : d_fprintf(stderr, _("Error allocating memory!\n"));
1931 0 : goto out;
1932 : }
1933 : }
1934 :
1935 18 : for (count = 0; count < num_addrs; count++) {
1936 10 : if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1937 0 : d_fprintf(stderr, "%s '%s'.\n",
1938 : _("Cannot interpret address"),
1939 0 : addrs_list[count]);
1940 0 : goto out;
1941 : }
1942 : }
1943 :
1944 8 : status = ads_startup(c, true, tmp_ctx, &ads);
1945 8 : if ( !ADS_ERR_OK(status) ) {
1946 0 : DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1947 0 : goto out;
1948 : }
1949 :
1950 8 : ntstatus = net_update_dns_ext(c,
1951 : tmp_ctx,
1952 : ads,
1953 : hostname,
1954 : addrs,
1955 : num_addrs,
1956 : false);
1957 8 : if (!NT_STATUS_IS_OK(ntstatus)) {
1958 2 : d_fprintf( stderr, _("DNS update failed!\n") );
1959 2 : goto out;
1960 : }
1961 :
1962 6 : d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1963 :
1964 6 : ret = 0;
1965 8 : out:
1966 8 : TALLOC_FREE(tmp_ctx);
1967 :
1968 8 : return ret;
1969 : #else
1970 : d_fprintf(stderr,
1971 : _("DNS update support not enabled at compile time!\n"));
1972 : return -1;
1973 : #endif
1974 : }
1975 :
1976 4 : static int net_ads_dns_unregister(struct net_context *c,
1977 : int argc,
1978 : const char **argv)
1979 : {
1980 : #if defined(HAVE_KRB5)
1981 4 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
1982 4 : ADS_STRUCT *ads = NULL;
1983 : ADS_STATUS status;
1984 : NTSTATUS ntstatus;
1985 4 : const char *hostname = NULL;
1986 4 : int ret = -1;
1987 :
1988 : #ifdef DEVELOPER
1989 4 : talloc_enable_leak_report();
1990 : #endif
1991 :
1992 4 : if (argc != 1) {
1993 0 : c->display_usage = true;
1994 : }
1995 :
1996 4 : if (c->display_usage) {
1997 0 : d_printf( "%s\n"
1998 : "net ads dns unregister [hostname]\n"
1999 : " %s\n",
2000 : _("Usage:"),
2001 : _("Remove all IP Address entires for a given\n"
2002 : " hostname from the Active Directory server.\n"));
2003 0 : TALLOC_FREE(tmp_ctx);
2004 0 : return -1;
2005 : }
2006 :
2007 : /* Get the hostname for un-registering */
2008 4 : hostname = argv[0];
2009 :
2010 4 : status = ads_startup(c, true, tmp_ctx, &ads);
2011 4 : if ( !ADS_ERR_OK(status) ) {
2012 0 : DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2013 0 : goto out;
2014 : }
2015 :
2016 4 : ntstatus = net_update_dns_ext(c,
2017 : tmp_ctx,
2018 : ads,
2019 : hostname,
2020 : NULL,
2021 : 0,
2022 : true);
2023 4 : if (!NT_STATUS_IS_OK(ntstatus)) {
2024 0 : d_fprintf( stderr, _("DNS update failed!\n") );
2025 0 : goto out;
2026 : }
2027 :
2028 4 : d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2029 :
2030 4 : ret = 0;
2031 4 : out:
2032 4 : TALLOC_FREE(tmp_ctx);
2033 :
2034 4 : return ret;
2035 : #else
2036 : d_fprintf(stderr,
2037 : _("DNS update support not enabled at compile time!\n"));
2038 : return -1;
2039 : #endif
2040 : }
2041 :
2042 :
2043 2 : static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2044 : {
2045 2 : size_t num_names = 0;
2046 2 : char **hostnames = NULL;
2047 2 : size_t i = 0;
2048 2 : struct samba_sockaddr *addrs = NULL;
2049 : NTSTATUS status;
2050 :
2051 2 : if (argc != 1 || c->display_usage) {
2052 0 : d_printf( "%s\n"
2053 : " %s\n"
2054 : " %s\n",
2055 : _("Usage:"),
2056 : _("net ads dns async <name>\n"),
2057 : _(" Async look up hostname from the DNS server\n"
2058 : " hostname\tName to look up\n"));
2059 0 : return -1;
2060 : }
2061 :
2062 2 : status = ads_dns_lookup_a(talloc_tos(),
2063 : argv[0],
2064 : &num_names,
2065 : &hostnames,
2066 : &addrs);
2067 2 : if (!NT_STATUS_IS_OK(status)) {
2068 0 : d_printf("Looking up A record for %s got error %s\n",
2069 : argv[0],
2070 : nt_errstr(status));
2071 0 : return -1;
2072 : }
2073 2 : d_printf("Async A record lookup - got %u names for %s\n",
2074 : (unsigned int)num_names,
2075 : argv[0]);
2076 4 : for (i = 0; i < num_names; i++) {
2077 : char addr_buf[INET6_ADDRSTRLEN];
2078 2 : print_sockaddr(addr_buf,
2079 : sizeof(addr_buf),
2080 2 : &addrs[i].u.ss);
2081 2 : d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2082 : (unsigned int)i,
2083 2 : hostnames[i],
2084 : addr_buf);
2085 : }
2086 :
2087 : #if defined(HAVE_IPV6)
2088 2 : status = ads_dns_lookup_aaaa(talloc_tos(),
2089 : argv[0],
2090 : &num_names,
2091 : &hostnames,
2092 : &addrs);
2093 2 : if (!NT_STATUS_IS_OK(status)) {
2094 0 : d_printf("Looking up AAAA record for %s got error %s\n",
2095 : argv[0],
2096 : nt_errstr(status));
2097 0 : return -1;
2098 : }
2099 2 : d_printf("Async AAAA record lookup - got %u names for %s\n",
2100 : (unsigned int)num_names,
2101 : argv[0]);
2102 4 : for (i = 0; i < num_names; i++) {
2103 : char addr_buf[INET6_ADDRSTRLEN];
2104 2 : print_sockaddr(addr_buf,
2105 : sizeof(addr_buf),
2106 2 : &addrs[i].u.ss);
2107 2 : d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2108 : (unsigned int)i,
2109 2 : hostnames[i],
2110 : addr_buf);
2111 : }
2112 : #endif
2113 2 : return 0;
2114 : }
2115 :
2116 :
2117 14 : static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2118 : {
2119 14 : struct functable func[] = {
2120 : {
2121 : "register",
2122 : net_ads_dns_register,
2123 : NET_TRANSPORT_ADS,
2124 : N_("Add host dns entry to AD"),
2125 : N_("net ads dns register\n"
2126 : " Add host dns entry to AD")
2127 : },
2128 : {
2129 : "unregister",
2130 : net_ads_dns_unregister,
2131 : NET_TRANSPORT_ADS,
2132 : N_("Remove host dns entry from AD"),
2133 : N_("net ads dns unregister\n"
2134 : " Remove host dns entry from AD")
2135 : },
2136 : {
2137 : "async",
2138 : net_ads_dns_async,
2139 : NET_TRANSPORT_ADS,
2140 : N_("Look up host"),
2141 : N_("net ads dns async\n"
2142 : " Look up host using async DNS")
2143 : },
2144 : {NULL, NULL, 0, NULL, NULL}
2145 : };
2146 :
2147 14 : return net_run_function(c, argc, argv, "net ads dns", func);
2148 : }
2149 :
2150 : /*******************************************************************
2151 : ********************************************************************/
2152 :
2153 0 : int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2154 : {
2155 0 : d_printf(_(
2156 : "\nnet ads printer search <printer>"
2157 : "\n\tsearch for a printer in the directory\n"
2158 : "\nnet ads printer info <printer> <server>"
2159 : "\n\tlookup info in directory for printer on server"
2160 : "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2161 : "\nnet ads printer publish <printername>"
2162 : "\n\tpublish printer in directory"
2163 : "\n\t(note: printer name is required)\n"
2164 : "\nnet ads printer remove <printername>"
2165 : "\n\tremove printer from directory"
2166 : "\n\t(note: printer name is required)\n"));
2167 0 : return -1;
2168 : }
2169 :
2170 : /*******************************************************************
2171 : ********************************************************************/
2172 :
2173 0 : static int net_ads_printer_search(struct net_context *c,
2174 : int argc,
2175 : const char **argv)
2176 : {
2177 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2178 0 : ADS_STRUCT *ads = NULL;
2179 : ADS_STATUS status;
2180 0 : LDAPMessage *res = NULL;
2181 0 : int ret = -1;
2182 :
2183 0 : if (c->display_usage) {
2184 0 : d_printf( "%s\n"
2185 : "net ads printer search\n"
2186 : " %s\n",
2187 : _("Usage:"),
2188 : _("List printers in the AD"));
2189 0 : TALLOC_FREE(tmp_ctx);
2190 0 : return -1;
2191 : }
2192 :
2193 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2194 0 : if (!ADS_ERR_OK(status)) {
2195 0 : goto out;
2196 : }
2197 :
2198 0 : status = ads_find_printers(ads, &res);
2199 0 : if (!ADS_ERR_OK(status)) {
2200 0 : d_fprintf(stderr, _("ads_find_printer: %s\n"),
2201 : ads_errstr(status));
2202 0 : goto out;
2203 : }
2204 :
2205 0 : if (ads_count_replies(ads, res) == 0) {
2206 0 : d_fprintf(stderr, _("No results found\n"));
2207 0 : goto out;
2208 : }
2209 :
2210 0 : ads_dump(ads, res);
2211 :
2212 0 : ret = 0;
2213 0 : out:
2214 0 : ads_msgfree(ads, res);
2215 0 : TALLOC_FREE(tmp_ctx);
2216 0 : return ret;
2217 : }
2218 :
2219 0 : static int net_ads_printer_info(struct net_context *c,
2220 : int argc,
2221 : const char **argv)
2222 : {
2223 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2224 0 : ADS_STRUCT *ads = NULL;
2225 : ADS_STATUS status;
2226 0 : const char *servername = NULL;
2227 0 : const char *printername = NULL;
2228 0 : LDAPMessage *res = NULL;
2229 0 : int ret = -1;
2230 :
2231 0 : if (c->display_usage) {
2232 0 : d_printf("%s\n%s",
2233 : _("Usage:"),
2234 : _("net ads printer info [printername [servername]]\n"
2235 : " Display printer info from AD\n"
2236 : " printername\tPrinter name or wildcard\n"
2237 : " servername\tName of the print server\n"));
2238 0 : TALLOC_FREE(tmp_ctx);
2239 0 : return -1;
2240 : }
2241 :
2242 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2243 0 : if (!ADS_ERR_OK(status)) {
2244 0 : goto out;
2245 : }
2246 :
2247 0 : if (argc > 0) {
2248 0 : printername = argv[0];
2249 : } else {
2250 0 : printername = "*";
2251 : }
2252 :
2253 0 : if (argc > 1) {
2254 0 : servername = argv[1];
2255 : } else {
2256 0 : servername = lp_netbios_name();
2257 : }
2258 :
2259 0 : status = ads_find_printer_on_server(ads, &res, printername, servername);
2260 0 : if (!ADS_ERR_OK(status)) {
2261 0 : d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2262 : servername, ads_errstr(status));
2263 0 : goto out;
2264 : }
2265 :
2266 0 : if (ads_count_replies(ads, res) == 0) {
2267 0 : d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2268 0 : goto out;
2269 : }
2270 :
2271 0 : ads_dump(ads, res);
2272 :
2273 0 : ret = 0;
2274 0 : out:
2275 0 : ads_msgfree(ads, res);
2276 0 : TALLOC_FREE(tmp_ctx);
2277 0 : return ret;
2278 : }
2279 :
2280 0 : static int net_ads_printer_publish(struct net_context *c,
2281 : int argc,
2282 : const char **argv)
2283 : {
2284 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2285 0 : ADS_STRUCT *ads = NULL;
2286 : ADS_STATUS status;
2287 0 : const char *servername = NULL;
2288 0 : const char *printername = NULL;
2289 0 : struct cli_state *cli = NULL;
2290 0 : struct rpc_pipe_client *pipe_hnd = NULL;
2291 0 : struct sockaddr_storage server_ss = { 0 };
2292 : NTSTATUS nt_status;
2293 0 : ADS_MODLIST mods = NULL;
2294 0 : char *prt_dn = NULL;
2295 0 : char *srv_dn = NULL;
2296 0 : char **srv_cn = NULL;
2297 0 : char *srv_cn_escaped = NULL;
2298 0 : char *printername_escaped = NULL;
2299 0 : LDAPMessage *res = NULL;
2300 : bool ok;
2301 0 : int ret = -1;
2302 :
2303 0 : if (argc < 1 || c->display_usage) {
2304 0 : d_printf("%s\n%s",
2305 : _("Usage:"),
2306 : _("net ads printer publish <printername> [servername]\n"
2307 : " Publish printer in AD\n"
2308 : " printername\tName of the printer\n"
2309 : " servername\tName of the print server\n"));
2310 0 : TALLOC_FREE(tmp_ctx);
2311 0 : return -1;
2312 : }
2313 :
2314 0 : mods = ads_init_mods(tmp_ctx);
2315 0 : if (mods == NULL) {
2316 0 : d_fprintf(stderr, _("Out of memory\n"));
2317 0 : goto out;
2318 : }
2319 :
2320 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2321 0 : if (!ADS_ERR_OK(status)) {
2322 0 : goto out;
2323 : }
2324 :
2325 0 : printername = argv[0];
2326 :
2327 0 : if (argc == 2) {
2328 0 : servername = argv[1];
2329 : } else {
2330 0 : servername = lp_netbios_name();
2331 : }
2332 :
2333 : /* Get printer data from SPOOLSS */
2334 :
2335 0 : ok = resolve_name(servername, &server_ss, 0x20, false);
2336 0 : if (!ok) {
2337 0 : d_fprintf(stderr, _("Could not find server %s\n"),
2338 : servername);
2339 0 : goto out;
2340 : }
2341 :
2342 0 : cli_credentials_set_kerberos_state(c->creds,
2343 : CRED_USE_KERBEROS_REQUIRED,
2344 : CRED_SPECIFIED);
2345 :
2346 0 : nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2347 : &server_ss, 0,
2348 : "IPC$", "IPC",
2349 : c->creds,
2350 : CLI_FULL_CONNECTION_IPC);
2351 :
2352 0 : if (NT_STATUS_IS_ERR(nt_status)) {
2353 0 : d_fprintf(stderr, _("Unable to open a connection to %s to "
2354 : "obtain data for %s\n"),
2355 : servername, printername);
2356 0 : goto out;
2357 : }
2358 :
2359 : /* Publish on AD server */
2360 :
2361 0 : ads_find_machine_acct(ads, &res, servername);
2362 :
2363 0 : if (ads_count_replies(ads, res) == 0) {
2364 0 : d_fprintf(stderr, _("Could not find machine account for server "
2365 : "%s\n"),
2366 : servername);
2367 0 : goto out;
2368 : }
2369 :
2370 0 : srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2371 0 : srv_cn = ldap_explode_dn(srv_dn, 1);
2372 :
2373 0 : srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2374 0 : printername_escaped = escape_rdn_val_string_alloc(printername);
2375 0 : if (!srv_cn_escaped || !printername_escaped) {
2376 0 : SAFE_FREE(srv_cn_escaped);
2377 0 : SAFE_FREE(printername_escaped);
2378 0 : d_fprintf(stderr, _("Internal error, out of memory!"));
2379 0 : goto out;
2380 : }
2381 :
2382 0 : prt_dn = talloc_asprintf(tmp_ctx,
2383 : "cn=%s-%s,%s",
2384 : srv_cn_escaped,
2385 : printername_escaped,
2386 : srv_dn);
2387 0 : if (prt_dn == NULL) {
2388 0 : SAFE_FREE(srv_cn_escaped);
2389 0 : SAFE_FREE(printername_escaped);
2390 0 : d_fprintf(stderr, _("Internal error, out of memory!"));
2391 0 : goto out;
2392 : }
2393 :
2394 0 : SAFE_FREE(srv_cn_escaped);
2395 0 : SAFE_FREE(printername_escaped);
2396 :
2397 0 : nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2398 0 : if (!NT_STATUS_IS_OK(nt_status)) {
2399 0 : d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2400 : servername);
2401 0 : goto out;
2402 : }
2403 :
2404 0 : if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2405 : tmp_ctx,
2406 : &mods,
2407 : printername))) {
2408 0 : goto out;
2409 : }
2410 :
2411 0 : status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2412 0 : if (!ADS_ERR_OK(status)) {
2413 0 : d_fprintf(stderr, "ads_publish_printer: %s\n",
2414 : ads_errstr(status));
2415 0 : goto out;
2416 : }
2417 :
2418 0 : d_printf("published printer\n");
2419 :
2420 0 : ret = 0;
2421 0 : out:
2422 0 : talloc_destroy(tmp_ctx);
2423 :
2424 0 : return ret;
2425 : }
2426 :
2427 0 : static int net_ads_printer_remove(struct net_context *c,
2428 : int argc,
2429 : const char **argv)
2430 : {
2431 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2432 0 : ADS_STRUCT *ads = NULL;
2433 : ADS_STATUS status;
2434 0 : const char *servername = NULL;
2435 0 : char *prt_dn = NULL;
2436 0 : LDAPMessage *res = NULL;
2437 0 : int ret = -1;
2438 :
2439 0 : if (argc < 1 || c->display_usage) {
2440 0 : d_printf("%s\n%s",
2441 : _("Usage:"),
2442 : _("net ads printer remove <printername> [servername]\n"
2443 : " Remove a printer from the AD\n"
2444 : " printername\tName of the printer\n"
2445 : " servername\tName of the print server\n"));
2446 0 : TALLOC_FREE(tmp_ctx);
2447 0 : return -1;
2448 : }
2449 :
2450 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2451 0 : if (!ADS_ERR_OK(status)) {
2452 0 : goto out;
2453 : }
2454 :
2455 0 : if (argc > 1) {
2456 0 : servername = argv[1];
2457 : } else {
2458 0 : servername = lp_netbios_name();
2459 : }
2460 :
2461 0 : status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2462 0 : if (!ADS_ERR_OK(status)) {
2463 0 : d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2464 : ads_errstr(status));
2465 0 : goto out;
2466 : }
2467 :
2468 0 : if (ads_count_replies(ads, res) == 0) {
2469 0 : d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2470 0 : goto out;
2471 : }
2472 :
2473 0 : prt_dn = ads_get_dn(ads, tmp_ctx, res);
2474 0 : if (prt_dn == NULL) {
2475 0 : d_fprintf(stderr, _("Out of memory\n"));
2476 0 : goto out;
2477 : }
2478 :
2479 0 : status = ads_del_dn(ads, prt_dn);
2480 0 : if (!ADS_ERR_OK(status)) {
2481 0 : d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2482 0 : goto out;
2483 : }
2484 :
2485 0 : ret = 0;
2486 0 : out:
2487 0 : ads_msgfree(ads, res);
2488 0 : TALLOC_FREE(tmp_ctx);
2489 0 : return ret;
2490 : }
2491 :
2492 0 : static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2493 : {
2494 0 : struct functable func[] = {
2495 : {
2496 : "search",
2497 : net_ads_printer_search,
2498 : NET_TRANSPORT_ADS,
2499 : N_("Search for a printer"),
2500 : N_("net ads printer search\n"
2501 : " Search for a printer")
2502 : },
2503 : {
2504 : "info",
2505 : net_ads_printer_info,
2506 : NET_TRANSPORT_ADS,
2507 : N_("Display printer information"),
2508 : N_("net ads printer info\n"
2509 : " Display printer information")
2510 : },
2511 : {
2512 : "publish",
2513 : net_ads_printer_publish,
2514 : NET_TRANSPORT_ADS,
2515 : N_("Publish a printer"),
2516 : N_("net ads printer publish\n"
2517 : " Publish a printer")
2518 : },
2519 : {
2520 : "remove",
2521 : net_ads_printer_remove,
2522 : NET_TRANSPORT_ADS,
2523 : N_("Delete a printer"),
2524 : N_("net ads printer remove\n"
2525 : " Delete a printer")
2526 : },
2527 : {NULL, NULL, 0, NULL, NULL}
2528 : };
2529 :
2530 0 : return net_run_function(c, argc, argv, "net ads printer", func);
2531 : }
2532 :
2533 :
2534 2 : static int net_ads_password(struct net_context *c, int argc, const char **argv)
2535 : {
2536 2 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2537 2 : ADS_STRUCT *ads = NULL;
2538 2 : const char *auth_principal = cli_credentials_get_username(c->creds);
2539 2 : const char *auth_password = cli_credentials_get_password(c->creds);
2540 2 : const char *realm = NULL;
2541 2 : char *new_password = NULL;
2542 2 : char *chr = NULL;
2543 2 : char *prompt = NULL;
2544 2 : const char *user = NULL;
2545 2 : char pwd[256] = {0};
2546 : ADS_STATUS status;
2547 2 : int ret = 0;
2548 :
2549 2 : if (c->display_usage) {
2550 0 : d_printf("%s\n%s",
2551 : _("Usage:"),
2552 : _("net ads password <username>\n"
2553 : " Change password for user\n"
2554 : " username\tName of user to change password for\n"));
2555 0 : TALLOC_FREE(tmp_ctx);
2556 0 : return -1;
2557 : }
2558 :
2559 2 : if (auth_principal == NULL || auth_password == NULL) {
2560 0 : d_fprintf(stderr, _("You must supply an administrator "
2561 : "username/password\n"));
2562 0 : TALLOC_FREE(tmp_ctx);
2563 0 : return -1;
2564 : }
2565 :
2566 2 : if (argc < 1) {
2567 0 : d_fprintf(stderr, _("ERROR: You must say which username to "
2568 : "change password for\n"));
2569 0 : TALLOC_FREE(tmp_ctx);
2570 0 : return -1;
2571 : }
2572 :
2573 2 : if (strchr_m(argv[0], '@')) {
2574 2 : user = talloc_strdup(tmp_ctx, argv[0]);
2575 : } else {
2576 0 : user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2577 : }
2578 2 : if (user == NULL) {
2579 0 : d_fprintf(stderr, _("Out of memory\n"));
2580 0 : goto out;
2581 : }
2582 :
2583 2 : use_in_memory_ccache();
2584 2 : chr = strchr_m(auth_principal, '@');
2585 2 : if (chr) {
2586 2 : realm = ++chr;
2587 : } else {
2588 0 : realm = lp_realm();
2589 : }
2590 :
2591 : /* use the realm so we can eventually change passwords for users
2592 : in realms other than default */
2593 2 : ads = ads_init(tmp_ctx,
2594 : realm,
2595 : c->opt_workgroup,
2596 : c->opt_host,
2597 : ADS_SASL_PLAIN);
2598 2 : if (ads == NULL) {
2599 0 : goto out;
2600 : }
2601 :
2602 : /* we don't actually need a full connect, but it's the easy way to
2603 : fill in the KDC's addresss */
2604 2 : ads_connect(ads);
2605 :
2606 2 : if (!ads->config.realm) {
2607 0 : d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2608 0 : goto out;
2609 : }
2610 :
2611 2 : if (argv[1] != NULL) {
2612 2 : new_password = talloc_strdup(tmp_ctx, argv[1]);
2613 : } else {
2614 : int rc;
2615 :
2616 0 : prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2617 0 : if (prompt == NULL) {
2618 0 : d_fprintf(stderr, _("Out of memory\n"));
2619 0 : goto out;
2620 : }
2621 :
2622 0 : rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2623 0 : if (rc < 0) {
2624 0 : goto out;
2625 : }
2626 0 : new_password = talloc_strdup(tmp_ctx, pwd);
2627 0 : memset(pwd, '\0', sizeof(pwd));
2628 : }
2629 :
2630 2 : if (new_password == NULL) {
2631 0 : d_fprintf(stderr, _("Out of memory\n"));
2632 0 : goto out;
2633 : }
2634 :
2635 2 : status = kerberos_set_password(ads->auth.kdc_server,
2636 : auth_principal,
2637 : auth_password,
2638 : user,
2639 : new_password,
2640 : ads->auth.time_offset);
2641 2 : memset(new_password, '\0', strlen(new_password));
2642 2 : if (!ADS_ERR_OK(status)) {
2643 0 : d_fprintf(stderr, _("Password change failed: %s\n"),
2644 : ads_errstr(status));
2645 0 : goto out;
2646 : }
2647 :
2648 2 : d_printf(_("Password change for %s completed.\n"), user);
2649 :
2650 2 : ret = 0;
2651 2 : out:
2652 2 : TALLOC_FREE(tmp_ctx);
2653 2 : return ret;
2654 : }
2655 :
2656 0 : int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2657 : {
2658 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2659 0 : ADS_STRUCT *ads = NULL;
2660 0 : char *host_principal = NULL;
2661 0 : char *my_name = NULL;
2662 : ADS_STATUS status;
2663 0 : int ret = -1;
2664 :
2665 0 : if (c->display_usage) {
2666 0 : d_printf( "%s\n"
2667 : "net ads changetrustpw\n"
2668 : " %s\n",
2669 : _("Usage:"),
2670 : _("Change the machine account's trust password"));
2671 0 : TALLOC_FREE(tmp_ctx);
2672 0 : return -1;
2673 : }
2674 :
2675 0 : if (!secrets_init()) {
2676 0 : DEBUG(1,("Failed to initialise secrets database\n"));
2677 0 : goto out;
2678 : }
2679 :
2680 0 : net_warn_member_options();
2681 :
2682 0 : net_use_krb_machine_account(c);
2683 :
2684 0 : use_in_memory_ccache();
2685 :
2686 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2687 0 : if (!ADS_ERR_OK(status)) {
2688 0 : goto out;
2689 : }
2690 :
2691 0 : my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2692 0 : if (my_name == NULL) {
2693 0 : d_fprintf(stderr, _("Out of memory\n"));
2694 0 : goto out;
2695 : }
2696 :
2697 0 : host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2698 0 : if (host_principal == NULL) {
2699 0 : d_fprintf(stderr, _("Out of memory\n"));
2700 0 : goto out;
2701 : }
2702 :
2703 0 : d_printf(_("Changing password for principal: %s\n"), host_principal);
2704 :
2705 0 : status = ads_change_trust_account_password(ads, host_principal);
2706 0 : if (!ADS_ERR_OK(status)) {
2707 0 : d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2708 0 : goto out;
2709 : }
2710 :
2711 0 : d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2712 :
2713 0 : if (USE_SYSTEM_KEYTAB) {
2714 0 : d_printf(_("Attempting to update system keytab with new password.\n"));
2715 0 : if (ads_keytab_create_default(ads)) {
2716 0 : d_printf(_("Failed to update system keytab.\n"));
2717 : }
2718 : }
2719 :
2720 0 : ret = 0;
2721 0 : out:
2722 0 : TALLOC_FREE(tmp_ctx);
2723 :
2724 0 : return ret;
2725 : }
2726 :
2727 : /*
2728 : help for net ads search
2729 : */
2730 0 : static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2731 : {
2732 0 : d_printf(_(
2733 : "\nnet ads search <expression> <attributes...>\n"
2734 : "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2735 : "The expression is a standard LDAP search expression, and the\n"
2736 : "attributes are a list of LDAP fields to show in the results.\n\n"
2737 : "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2738 : ));
2739 0 : net_common_flags_usage(c, argc, argv);
2740 0 : return -1;
2741 : }
2742 :
2743 :
2744 : /*
2745 : general ADS search function. Useful in diagnosing problems in ADS
2746 : */
2747 14 : static int net_ads_search(struct net_context *c, int argc, const char **argv)
2748 : {
2749 14 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2750 14 : ADS_STRUCT *ads = NULL;
2751 : ADS_STATUS status;
2752 14 : const char *ldap_exp = NULL;
2753 14 : const char **attrs = NULL;
2754 14 : LDAPMessage *res = NULL;
2755 14 : int ret = -1;
2756 :
2757 14 : if (argc < 1 || c->display_usage) {
2758 0 : TALLOC_FREE(tmp_ctx);
2759 0 : return net_ads_search_usage(c, argc, argv);
2760 : }
2761 :
2762 14 : status = ads_startup(c, false, tmp_ctx, &ads);
2763 14 : if (!ADS_ERR_OK(status)) {
2764 1 : goto out;
2765 : }
2766 :
2767 13 : ldap_exp = argv[0];
2768 13 : attrs = (argv + 1);
2769 :
2770 13 : status = ads_do_search_retry(ads,
2771 13 : ads->config.bind_path,
2772 : LDAP_SCOPE_SUBTREE,
2773 : ldap_exp,
2774 : attrs,
2775 : &res);
2776 13 : if (!ADS_ERR_OK(status)) {
2777 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2778 0 : goto out;
2779 : }
2780 :
2781 13 : d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2782 :
2783 : /* dump the results */
2784 13 : ads_dump(ads, res);
2785 :
2786 13 : ret = 0;
2787 14 : out:
2788 14 : ads_msgfree(ads, res);
2789 14 : TALLOC_FREE(tmp_ctx);
2790 14 : return ret;
2791 : }
2792 :
2793 :
2794 : /*
2795 : help for net ads search
2796 : */
2797 0 : static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2798 : {
2799 0 : d_printf(_(
2800 : "\nnet ads dn <dn> <attributes...>\n"
2801 : "\nperform a raw LDAP search on a ADS server and dump the results\n"
2802 : "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2803 : "to show in the results\n\n"
2804 : "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2805 : "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2806 : ));
2807 0 : net_common_flags_usage(c, argc, argv);
2808 0 : return -1;
2809 : }
2810 :
2811 :
2812 : /*
2813 : general ADS search function. Useful in diagnosing problems in ADS
2814 : */
2815 0 : static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2816 : {
2817 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2818 0 : ADS_STRUCT *ads = NULL;
2819 : ADS_STATUS status;
2820 0 : const char *dn = NULL;
2821 0 : const char **attrs = NULL;
2822 0 : LDAPMessage *res = NULL;
2823 0 : int ret = -1;
2824 :
2825 0 : if (argc < 1 || c->display_usage) {
2826 0 : TALLOC_FREE(tmp_ctx);
2827 0 : return net_ads_dn_usage(c, argc, argv);
2828 : }
2829 :
2830 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2831 0 : if (!ADS_ERR_OK(status)) {
2832 0 : goto out;
2833 : }
2834 :
2835 0 : dn = argv[0];
2836 0 : attrs = (argv + 1);
2837 :
2838 0 : status = ads_do_search_all(ads,
2839 : dn,
2840 : LDAP_SCOPE_BASE,
2841 : "(objectclass=*)",
2842 : attrs,
2843 : &res);
2844 0 : if (!ADS_ERR_OK(status)) {
2845 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2846 0 : goto out;
2847 : }
2848 :
2849 0 : d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2850 :
2851 : /* dump the results */
2852 0 : ads_dump(ads, res);
2853 :
2854 0 : ret = 0;
2855 0 : out:
2856 0 : ads_msgfree(ads, res);
2857 0 : TALLOC_FREE(tmp_ctx);
2858 0 : return ret;
2859 : }
2860 :
2861 : /*
2862 : help for net ads sid search
2863 : */
2864 0 : static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2865 : {
2866 0 : d_printf(_(
2867 : "\nnet ads sid <sid> <attributes...>\n"
2868 : "\nperform a raw LDAP search on a ADS server and dump the results\n"
2869 : "The SID is in string format, and the attributes are a list of LDAP fields \n"
2870 : "to show in the results\n\n"
2871 : "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2872 : ));
2873 0 : net_common_flags_usage(c, argc, argv);
2874 0 : return -1;
2875 : }
2876 :
2877 :
2878 : /*
2879 : general ADS search function. Useful in diagnosing problems in ADS
2880 : */
2881 0 : static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2882 : {
2883 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2884 0 : ADS_STRUCT *ads = NULL;
2885 : ADS_STATUS status;
2886 0 : const char *sid_string = NULL;
2887 0 : const char **attrs = NULL;
2888 0 : LDAPMessage *res = NULL;
2889 0 : struct dom_sid sid = { 0 };
2890 0 : int ret = -1;
2891 :
2892 0 : if (argc < 1 || c->display_usage) {
2893 0 : TALLOC_FREE(tmp_ctx);
2894 0 : return net_ads_sid_usage(c, argc, argv);
2895 : }
2896 :
2897 0 : status = ads_startup(c, false, tmp_ctx, &ads);
2898 0 : if (!ADS_ERR_OK(status)) {
2899 0 : goto out;
2900 : }
2901 :
2902 0 : sid_string = argv[0];
2903 0 : attrs = (argv + 1);
2904 :
2905 0 : if (!string_to_sid(&sid, sid_string)) {
2906 0 : d_fprintf(stderr, _("could not convert sid\n"));
2907 0 : goto out;
2908 : }
2909 :
2910 0 : status = ads_search_retry_sid(ads, &res, &sid, attrs);
2911 0 : if (!ADS_ERR_OK(status)) {
2912 0 : d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2913 0 : goto out;
2914 : }
2915 :
2916 0 : d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2917 :
2918 : /* dump the results */
2919 0 : ads_dump(ads, res);
2920 :
2921 0 : ret = 0;
2922 0 : out:
2923 0 : ads_msgfree(ads, res);
2924 0 : TALLOC_FREE(tmp_ctx);
2925 0 : return ret;
2926 : }
2927 :
2928 0 : static int net_ads_keytab_flush(struct net_context *c,
2929 : int argc,
2930 : const char **argv)
2931 : {
2932 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2933 0 : ADS_STRUCT *ads = NULL;
2934 : ADS_STATUS status;
2935 0 : int ret = -1;
2936 :
2937 0 : if (c->display_usage) {
2938 0 : d_printf( "%s\n"
2939 : "net ads keytab flush\n"
2940 : " %s\n",
2941 : _("Usage:"),
2942 : _("Delete the whole keytab"));
2943 0 : TALLOC_FREE(tmp_ctx);
2944 0 : return -1;
2945 : }
2946 :
2947 0 : if (!c->opt_user_specified && c->opt_password == NULL) {
2948 0 : net_use_krb_machine_account(c);
2949 : }
2950 :
2951 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2952 0 : if (!ADS_ERR_OK(status)) {
2953 0 : goto out;
2954 : }
2955 :
2956 0 : ret = ads_keytab_flush(ads);
2957 0 : out:
2958 0 : TALLOC_FREE(tmp_ctx);
2959 0 : return ret;
2960 : }
2961 :
2962 0 : static int net_ads_keytab_add(struct net_context *c,
2963 : int argc,
2964 : const char **argv,
2965 : bool update_ads)
2966 : {
2967 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2968 0 : ADS_STRUCT *ads = NULL;
2969 : ADS_STATUS status;
2970 : int i;
2971 0 : int ret = -1;
2972 :
2973 0 : if (c->display_usage) {
2974 0 : d_printf("%s\n%s",
2975 : _("Usage:"),
2976 : _("net ads keytab add <principal> [principal ...]\n"
2977 : " Add principals to local keytab\n"
2978 : " principal\tKerberos principal to add to "
2979 : "keytab\n"));
2980 0 : TALLOC_FREE(tmp_ctx);
2981 0 : return -1;
2982 : }
2983 :
2984 0 : net_warn_member_options();
2985 :
2986 0 : d_printf(_("Processing principals to add...\n"));
2987 :
2988 0 : if (!c->opt_user_specified && c->opt_password == NULL) {
2989 0 : net_use_krb_machine_account(c);
2990 : }
2991 :
2992 0 : status = ads_startup(c, true, tmp_ctx, &ads);
2993 0 : if (!ADS_ERR_OK(status)) {
2994 0 : goto out;
2995 : }
2996 :
2997 0 : for (ret = 0, i = 0; i < argc; i++) {
2998 0 : ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
2999 : }
3000 0 : out:
3001 0 : TALLOC_FREE(tmp_ctx);
3002 0 : return ret;
3003 : }
3004 :
3005 0 : static int net_ads_keytab_add_default(struct net_context *c,
3006 : int argc,
3007 : const char **argv)
3008 : {
3009 0 : return net_ads_keytab_add(c, argc, argv, false);
3010 : }
3011 :
3012 0 : static int net_ads_keytab_add_update_ads(struct net_context *c,
3013 : int argc,
3014 : const char **argv)
3015 : {
3016 0 : return net_ads_keytab_add(c, argc, argv, true);
3017 : }
3018 :
3019 0 : static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3020 : {
3021 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3022 0 : ADS_STRUCT *ads = NULL;
3023 : ADS_STATUS status;
3024 0 : int ret = -1;
3025 :
3026 0 : if (c->display_usage) {
3027 0 : d_printf( "%s\n"
3028 : "net ads keytab create\n"
3029 : " %s\n",
3030 : _("Usage:"),
3031 : _("Create new default keytab"));
3032 0 : TALLOC_FREE(tmp_ctx);
3033 0 : return -1;
3034 : }
3035 :
3036 0 : net_warn_member_options();
3037 :
3038 0 : if (!c->opt_user_specified && c->opt_password == NULL) {
3039 0 : net_use_krb_machine_account(c);
3040 : }
3041 :
3042 0 : status = ads_startup(c, true, tmp_ctx, &ads);
3043 0 : if (!ADS_ERR_OK(status)) {
3044 0 : goto out;
3045 : }
3046 :
3047 0 : ret = ads_keytab_create_default(ads);
3048 0 : out:
3049 0 : TALLOC_FREE(tmp_ctx);
3050 0 : return ret;
3051 : }
3052 :
3053 0 : static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3054 : {
3055 0 : const char *keytab = NULL;
3056 :
3057 0 : if (c->display_usage) {
3058 0 : d_printf("%s\n%s",
3059 : _("Usage:"),
3060 : _("net ads keytab list [keytab]\n"
3061 : " List a local keytab\n"
3062 : " keytab\tKeytab to list\n"));
3063 0 : return -1;
3064 : }
3065 :
3066 0 : if (argc >= 1) {
3067 0 : keytab = argv[0];
3068 : }
3069 :
3070 0 : return ads_keytab_list(keytab);
3071 : }
3072 :
3073 :
3074 0 : int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3075 : {
3076 0 : struct functable func[] = {
3077 : {
3078 : "add",
3079 : net_ads_keytab_add_default,
3080 : NET_TRANSPORT_ADS,
3081 : N_("Add a service principal"),
3082 : N_("net ads keytab add\n"
3083 : " Add a service principal, updates keytab file only.")
3084 : },
3085 : {
3086 : "add_update_ads",
3087 : net_ads_keytab_add_update_ads,
3088 : NET_TRANSPORT_ADS,
3089 : N_("Add a service principal"),
3090 : N_("net ads keytab add_update_ads\n"
3091 : " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3092 : },
3093 : {
3094 : "create",
3095 : net_ads_keytab_create,
3096 : NET_TRANSPORT_ADS,
3097 : N_("Create a fresh keytab"),
3098 : N_("net ads keytab create\n"
3099 : " Create a fresh keytab or update existing one.")
3100 : },
3101 : {
3102 : "flush",
3103 : net_ads_keytab_flush,
3104 : NET_TRANSPORT_ADS,
3105 : N_("Remove all keytab entries"),
3106 : N_("net ads keytab flush\n"
3107 : " Remove all keytab entries")
3108 : },
3109 : {
3110 : "list",
3111 : net_ads_keytab_list,
3112 : NET_TRANSPORT_ADS,
3113 : N_("List a keytab"),
3114 : N_("net ads keytab list\n"
3115 : " List a keytab")
3116 : },
3117 : {NULL, NULL, 0, NULL, NULL}
3118 : };
3119 :
3120 0 : if (!USE_KERBEROS_KEYTAB) {
3121 0 : d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3122 : "keytab method to use keytab functions.\n"));
3123 : }
3124 :
3125 0 : return net_run_function(c, argc, argv, "net ads keytab", func);
3126 : }
3127 :
3128 0 : static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3129 : {
3130 0 : int ret = -1;
3131 :
3132 0 : if (c->display_usage) {
3133 0 : d_printf( "%s\n"
3134 : "net ads kerberos renew\n"
3135 : " %s\n",
3136 : _("Usage:"),
3137 : _("Renew TGT from existing credential cache"));
3138 0 : return -1;
3139 : }
3140 :
3141 0 : ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3142 0 : if (ret) {
3143 0 : d_printf(_("failed to renew kerberos ticket: %s\n"),
3144 : error_message(ret));
3145 : }
3146 0 : return ret;
3147 : }
3148 :
3149 0 : static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3150 : struct PAC_DATA_CTR **pac_data_ctr)
3151 : {
3152 : NTSTATUS status;
3153 0 : int ret = -1;
3154 0 : const char *impersonate_princ_s = NULL;
3155 0 : const char *local_service = NULL;
3156 : int i;
3157 :
3158 0 : for (i=0; i<argc; i++) {
3159 0 : if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3160 0 : impersonate_princ_s = get_string_param(argv[i]);
3161 0 : if (impersonate_princ_s == NULL) {
3162 0 : return -1;
3163 : }
3164 : }
3165 0 : if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3166 0 : local_service = get_string_param(argv[i]);
3167 0 : if (local_service == NULL) {
3168 0 : return -1;
3169 : }
3170 : }
3171 : }
3172 :
3173 0 : if (local_service == NULL) {
3174 0 : local_service = talloc_asprintf(c, "%s$@%s",
3175 : lp_netbios_name(), lp_realm());
3176 0 : if (local_service == NULL) {
3177 0 : goto out;
3178 : }
3179 : }
3180 :
3181 0 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
3182 :
3183 0 : status = kerberos_return_pac(c,
3184 : c->opt_user_name,
3185 : c->opt_password,
3186 : 0,
3187 : NULL,
3188 : NULL,
3189 : NULL,
3190 : true,
3191 : true,
3192 : 2592000, /* one month */
3193 : impersonate_princ_s,
3194 : local_service,
3195 : NULL,
3196 : NULL,
3197 : pac_data_ctr);
3198 0 : if (!NT_STATUS_IS_OK(status)) {
3199 0 : d_printf(_("failed to query kerberos PAC: %s\n"),
3200 : nt_errstr(status));
3201 0 : goto out;
3202 : }
3203 :
3204 0 : ret = 0;
3205 0 : out:
3206 0 : return ret;
3207 : }
3208 :
3209 0 : static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3210 : {
3211 0 : struct PAC_DATA_CTR *pac_data_ctr = NULL;
3212 : int i, num_buffers;
3213 0 : int ret = -1;
3214 0 : enum PAC_TYPE type = 0;
3215 :
3216 0 : if (c->display_usage) {
3217 0 : d_printf( "%s\n"
3218 : "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3219 : " %s\n",
3220 : _("Usage:"),
3221 : _("Dump the Kerberos PAC"));
3222 0 : return -1;
3223 : }
3224 :
3225 0 : for (i=0; i<argc; i++) {
3226 0 : if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3227 0 : type = get_int_param(argv[i]);
3228 : }
3229 : }
3230 :
3231 0 : ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3232 0 : if (ret) {
3233 0 : return ret;
3234 : }
3235 :
3236 0 : if (type == 0) {
3237 :
3238 0 : char *s = NULL;
3239 :
3240 0 : s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3241 : pac_data_ctr->pac_data);
3242 0 : if (s != NULL) {
3243 0 : d_printf(_("The Pac: %s\n"), s);
3244 0 : talloc_free(s);
3245 : }
3246 :
3247 0 : return 0;
3248 : }
3249 :
3250 0 : num_buffers = pac_data_ctr->pac_data->num_buffers;
3251 :
3252 0 : for (i=0; i<num_buffers; i++) {
3253 :
3254 0 : char *s = NULL;
3255 :
3256 0 : if (pac_data_ctr->pac_data->buffers[i].type != type) {
3257 0 : continue;
3258 : }
3259 :
3260 0 : s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3261 : pac_data_ctr->pac_data->buffers[i].info);
3262 0 : if (s != NULL) {
3263 0 : d_printf(_("The Pac: %s\n"), s);
3264 0 : talloc_free(s);
3265 : }
3266 0 : break;
3267 : }
3268 :
3269 0 : return 0;
3270 : }
3271 :
3272 0 : static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3273 : {
3274 0 : struct PAC_DATA_CTR *pac_data_ctr = NULL;
3275 0 : char *filename = NULL;
3276 0 : int ret = -1;
3277 : int i;
3278 :
3279 0 : if (c->display_usage) {
3280 0 : d_printf( "%s\n"
3281 : "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3282 : " %s\n",
3283 : _("Usage:"),
3284 : _("Save the Kerberos PAC"));
3285 0 : return -1;
3286 : }
3287 :
3288 0 : for (i=0; i<argc; i++) {
3289 0 : if (strnequal(argv[i], "filename", strlen("filename"))) {
3290 0 : filename = get_string_param(argv[i]);
3291 0 : if (filename == NULL) {
3292 0 : return -1;
3293 : }
3294 : }
3295 : }
3296 :
3297 0 : ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3298 0 : if (ret) {
3299 0 : return ret;
3300 : }
3301 :
3302 0 : if (filename == NULL) {
3303 0 : d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3304 0 : return -1;
3305 : }
3306 :
3307 : /* save the raw format */
3308 0 : if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3309 0 : d_printf(_("failed to save PAC in %s\n"), filename);
3310 0 : return -1;
3311 : }
3312 :
3313 0 : return 0;
3314 : }
3315 :
3316 0 : static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3317 : {
3318 0 : struct functable func[] = {
3319 : {
3320 : "dump",
3321 : net_ads_kerberos_pac_dump,
3322 : NET_TRANSPORT_ADS,
3323 : N_("Dump Kerberos PAC"),
3324 : N_("net ads kerberos pac dump\n"
3325 : " Dump a Kerberos PAC to stdout")
3326 : },
3327 : {
3328 : "save",
3329 : net_ads_kerberos_pac_save,
3330 : NET_TRANSPORT_ADS,
3331 : N_("Save Kerberos PAC"),
3332 : N_("net ads kerberos pac save\n"
3333 : " Save a Kerberos PAC in a file")
3334 : },
3335 :
3336 : {NULL, NULL, 0, NULL, NULL}
3337 : };
3338 :
3339 0 : return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3340 : }
3341 :
3342 0 : static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3343 : {
3344 0 : int ret = -1;
3345 : NTSTATUS status;
3346 :
3347 0 : if (c->display_usage) {
3348 0 : d_printf( "%s\n"
3349 : "net ads kerberos kinit\n"
3350 : " %s\n",
3351 : _("Usage:"),
3352 : _("Get Ticket Granting Ticket (TGT) for the user"));
3353 0 : return -1;
3354 : }
3355 :
3356 0 : c->opt_password = net_prompt_pass(c, c->opt_user_name);
3357 :
3358 0 : ret = kerberos_kinit_password_ext(c->opt_user_name,
3359 : c->opt_password,
3360 : 0,
3361 : NULL,
3362 : NULL,
3363 : NULL,
3364 : true,
3365 : true,
3366 : 2592000, /* one month */
3367 : NULL,
3368 : NULL,
3369 : NULL,
3370 : &status);
3371 0 : if (ret) {
3372 0 : d_printf(_("failed to kinit password: %s\n"),
3373 : nt_errstr(status));
3374 : }
3375 0 : return ret;
3376 : }
3377 :
3378 0 : int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3379 : {
3380 0 : struct functable func[] = {
3381 : {
3382 : "kinit",
3383 : net_ads_kerberos_kinit,
3384 : NET_TRANSPORT_ADS,
3385 : N_("Retrieve Ticket Granting Ticket (TGT)"),
3386 : N_("net ads kerberos kinit\n"
3387 : " Receive Ticket Granting Ticket (TGT)")
3388 : },
3389 : {
3390 : "renew",
3391 : net_ads_kerberos_renew,
3392 : NET_TRANSPORT_ADS,
3393 : N_("Renew Ticket Granting Ticket from credential cache"),
3394 : N_("net ads kerberos renew\n"
3395 : " Renew Ticket Granting Ticket (TGT) from "
3396 : "credential cache")
3397 : },
3398 : {
3399 : "pac",
3400 : net_ads_kerberos_pac,
3401 : NET_TRANSPORT_ADS,
3402 : N_("Dump Kerberos PAC"),
3403 : N_("net ads kerberos pac\n"
3404 : " Dump Kerberos PAC")
3405 : },
3406 : {NULL, NULL, 0, NULL, NULL}
3407 : };
3408 :
3409 0 : return net_run_function(c, argc, argv, "net ads kerberos", func);
3410 : }
3411 :
3412 0 : static int net_ads_setspn_list(struct net_context *c,
3413 : int argc,
3414 : const char **argv)
3415 : {
3416 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3417 0 : ADS_STRUCT *ads = NULL;
3418 : ADS_STATUS status;
3419 0 : bool ok = false;
3420 0 : int ret = -1;
3421 :
3422 0 : if (c->display_usage) {
3423 0 : d_printf("%s\n%s",
3424 : _("Usage:"),
3425 : _("net ads setspn list <machinename>\n"));
3426 0 : TALLOC_FREE(tmp_ctx);
3427 0 : return -1;
3428 : }
3429 :
3430 0 : status = ads_startup(c, true, tmp_ctx, &ads);
3431 0 : if (!ADS_ERR_OK(status)) {
3432 0 : goto out;
3433 : }
3434 :
3435 0 : if (argc) {
3436 0 : ok = ads_setspn_list(ads, argv[0]);
3437 : } else {
3438 0 : ok = ads_setspn_list(ads, lp_netbios_name());
3439 : }
3440 :
3441 0 : ret = ok ? 0 : -1;
3442 0 : out:
3443 0 : TALLOC_FREE(tmp_ctx);
3444 0 : return ret;
3445 : }
3446 :
3447 0 : static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3448 : {
3449 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3450 0 : ADS_STRUCT *ads = NULL;
3451 : ADS_STATUS status;
3452 0 : bool ok = false;
3453 0 : int ret = -1;
3454 :
3455 0 : if (c->display_usage || argc < 1) {
3456 0 : d_printf("%s\n%s",
3457 : _("Usage:"),
3458 : _("net ads setspn add <machinename> SPN\n"));
3459 0 : TALLOC_FREE(tmp_ctx);
3460 0 : return -1;
3461 : }
3462 :
3463 0 : status = ads_startup(c, true, tmp_ctx, &ads);
3464 0 : if (!ADS_ERR_OK(status)) {
3465 0 : goto out;
3466 : }
3467 :
3468 0 : if (argc > 1) {
3469 0 : ok = ads_setspn_add(ads, argv[0], argv[1]);
3470 : } else {
3471 0 : ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3472 : }
3473 :
3474 0 : ret = ok ? 0 : -1;
3475 0 : out:
3476 0 : TALLOC_FREE(tmp_ctx);
3477 0 : return ret;
3478 : }
3479 :
3480 0 : static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3481 : {
3482 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3483 0 : ADS_STRUCT *ads = NULL;
3484 : ADS_STATUS status;
3485 0 : bool ok = false;
3486 0 : int ret = -1;
3487 :
3488 0 : if (c->display_usage || argc < 1) {
3489 0 : d_printf("%s\n%s",
3490 : _("Usage:"),
3491 : _("net ads setspn delete <machinename> SPN\n"));
3492 0 : TALLOC_FREE(tmp_ctx);
3493 0 : return -1;
3494 : }
3495 :
3496 0 : status = ads_startup(c, true, tmp_ctx, &ads);
3497 0 : if (!ADS_ERR_OK(status)) {
3498 0 : goto out;
3499 : }
3500 :
3501 0 : if (argc > 1) {
3502 0 : ok = ads_setspn_delete(ads, argv[0], argv[1]);
3503 : } else {
3504 0 : ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3505 : }
3506 :
3507 0 : ret = ok ? 0 : -1;
3508 0 : out:
3509 0 : TALLOC_FREE(tmp_ctx);
3510 0 : return ret;
3511 : }
3512 :
3513 0 : int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3514 : {
3515 0 : struct functable func[] = {
3516 : {
3517 : "list",
3518 : net_ads_setspn_list,
3519 : NET_TRANSPORT_ADS,
3520 : N_("List Service Principal Names (SPN)"),
3521 : N_("net ads setspn list machine\n"
3522 : " List Service Principal Names (SPN)")
3523 : },
3524 : {
3525 : "add",
3526 : net_ads_setspn_add,
3527 : NET_TRANSPORT_ADS,
3528 : N_("Add Service Principal Names (SPN)"),
3529 : N_("net ads setspn add machine spn\n"
3530 : " Add Service Principal Names (SPN)")
3531 : },
3532 : {
3533 : "delete",
3534 : net_ads_setspn_delete,
3535 : NET_TRANSPORT_ADS,
3536 : N_("Delete Service Principal Names (SPN)"),
3537 : N_("net ads setspn delete machine spn\n"
3538 : " Delete Service Principal Names (SPN)")
3539 : },
3540 : {NULL, NULL, 0, NULL, NULL}
3541 : };
3542 :
3543 0 : return net_run_function(c, argc, argv, "net ads setspn", func);
3544 : }
3545 :
3546 0 : static int net_ads_enctype_lookup_account(struct net_context *c,
3547 : ADS_STRUCT *ads,
3548 : const char *account,
3549 : LDAPMessage **res,
3550 : const char **enctype_str)
3551 : {
3552 : const char *filter;
3553 0 : const char *attrs[] = {
3554 : "msDS-SupportedEncryptionTypes",
3555 : NULL
3556 : };
3557 : int count;
3558 0 : int ret = -1;
3559 : ADS_STATUS status;
3560 :
3561 0 : filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3562 : account);
3563 0 : if (filter == NULL) {
3564 0 : goto done;
3565 : }
3566 :
3567 0 : status = ads_search(ads, res, filter, attrs);
3568 0 : if (!ADS_ERR_OK(status)) {
3569 0 : d_printf(_("no account found with filter: %s\n"), filter);
3570 0 : goto done;
3571 : }
3572 :
3573 0 : count = ads_count_replies(ads, *res);
3574 0 : switch (count) {
3575 0 : case 1:
3576 0 : break;
3577 0 : case 0:
3578 0 : d_printf(_("no account found with filter: %s\n"), filter);
3579 0 : goto done;
3580 0 : default:
3581 0 : d_printf(_("multiple accounts found with filter: %s\n"), filter);
3582 0 : goto done;
3583 : }
3584 :
3585 0 : if (enctype_str) {
3586 0 : *enctype_str = ads_pull_string(ads, c, *res,
3587 : "msDS-SupportedEncryptionTypes");
3588 0 : if (*enctype_str == NULL) {
3589 0 : d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3590 0 : goto done;
3591 : }
3592 : }
3593 :
3594 0 : ret = 0;
3595 0 : done:
3596 0 : return ret;
3597 : }
3598 :
3599 0 : static void net_ads_enctype_dump_enctypes(const char *username,
3600 : const char *enctype_str)
3601 : {
3602 0 : int enctypes = atoi(enctype_str);
3603 :
3604 0 : d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3605 : username, enctypes, enctypes);
3606 :
3607 0 : printf("[%s] 0x%08x DES-CBC-CRC\n",
3608 0 : enctypes & ENC_CRC32 ? "X" : " ",
3609 : ENC_CRC32);
3610 0 : printf("[%s] 0x%08x DES-CBC-MD5\n",
3611 0 : enctypes & ENC_RSA_MD5 ? "X" : " ",
3612 : ENC_RSA_MD5);
3613 0 : printf("[%s] 0x%08x RC4-HMAC\n",
3614 0 : enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3615 : ENC_RC4_HMAC_MD5);
3616 0 : printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3617 0 : enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3618 : ENC_HMAC_SHA1_96_AES128);
3619 0 : printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3620 0 : enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3621 : ENC_HMAC_SHA1_96_AES256);
3622 0 : printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3623 0 : enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3624 : ENC_HMAC_SHA1_96_AES256_SK);
3625 0 : printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3626 0 : enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3627 : KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3628 0 : }
3629 :
3630 0 : static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3631 : {
3632 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3633 : ADS_STATUS status;
3634 0 : ADS_STRUCT *ads = NULL;
3635 0 : LDAPMessage *res = NULL;
3636 0 : const char *str = NULL;
3637 0 : int ret = -1;
3638 :
3639 0 : if (c->display_usage || (argc < 1)) {
3640 0 : d_printf( "%s\n"
3641 : "net ads enctypes list\n"
3642 : " %s\n",
3643 : _("Usage:"),
3644 : _("List supported enctypes"));
3645 0 : TALLOC_FREE(tmp_ctx);
3646 0 : return -1;
3647 : }
3648 :
3649 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3650 0 : if (!ADS_ERR_OK(status)) {
3651 0 : goto out;
3652 : }
3653 :
3654 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3655 0 : if (ret) {
3656 0 : goto out;
3657 : }
3658 :
3659 0 : net_ads_enctype_dump_enctypes(argv[0], str);
3660 :
3661 0 : ret = 0;
3662 0 : out:
3663 0 : ads_msgfree(ads, res);
3664 0 : TALLOC_FREE(tmp_ctx);
3665 0 : return ret;
3666 : }
3667 :
3668 0 : static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3669 : {
3670 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3671 0 : int ret = -1;
3672 : ADS_STATUS status;
3673 0 : ADS_STRUCT *ads = NULL;
3674 0 : LDAPMessage *res = NULL;
3675 0 : const char *etype_list_str = NULL;
3676 0 : const char *dn = NULL;
3677 0 : ADS_MODLIST mods = NULL;
3678 : uint32_t etype_list;
3679 0 : const char *str = NULL;
3680 :
3681 0 : if (c->display_usage || argc < 1) {
3682 0 : d_printf( "%s\n"
3683 : "net ads enctypes set <sAMAccountName> [enctypes]\n"
3684 : " %s\n",
3685 : _("Usage:"),
3686 : _("Set supported enctypes"));
3687 0 : TALLOC_FREE(tmp_ctx);
3688 0 : return -1;
3689 : }
3690 :
3691 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3692 0 : if (!ADS_ERR_OK(status)) {
3693 0 : goto done;
3694 : }
3695 :
3696 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3697 0 : if (ret) {
3698 0 : goto done;
3699 : }
3700 :
3701 0 : dn = ads_get_dn(ads, tmp_ctx, res);
3702 0 : if (dn == NULL) {
3703 0 : goto done;
3704 : }
3705 :
3706 0 : etype_list = 0;
3707 0 : etype_list |= ENC_RC4_HMAC_MD5;
3708 0 : etype_list |= ENC_HMAC_SHA1_96_AES128;
3709 0 : etype_list |= ENC_HMAC_SHA1_96_AES256;
3710 :
3711 0 : if (argv[1] != NULL) {
3712 0 : sscanf(argv[1], "%i", &etype_list);
3713 : }
3714 :
3715 0 : etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3716 0 : if (!etype_list_str) {
3717 0 : goto done;
3718 : }
3719 :
3720 0 : mods = ads_init_mods(tmp_ctx);
3721 0 : if (!mods) {
3722 0 : goto done;
3723 : }
3724 :
3725 0 : status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3726 : etype_list_str);
3727 0 : if (!ADS_ERR_OK(status)) {
3728 0 : goto done;
3729 : }
3730 :
3731 0 : status = ads_gen_mod(ads, dn, mods);
3732 0 : if (!ADS_ERR_OK(status)) {
3733 0 : d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3734 : ads_errstr(status));
3735 0 : goto done;
3736 : }
3737 :
3738 0 : ads_msgfree(ads, res);
3739 0 : res = NULL;
3740 :
3741 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3742 0 : if (ret) {
3743 0 : goto done;
3744 : }
3745 :
3746 0 : net_ads_enctype_dump_enctypes(argv[0], str);
3747 :
3748 0 : ret = 0;
3749 0 : done:
3750 0 : ads_msgfree(ads, res);
3751 0 : TALLOC_FREE(tmp_ctx);
3752 0 : return ret;
3753 : }
3754 :
3755 0 : static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3756 : {
3757 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
3758 0 : int ret = -1;
3759 : ADS_STATUS status;
3760 0 : ADS_STRUCT *ads = NULL;
3761 0 : LDAPMessage *res = NULL;
3762 0 : const char *dn = NULL;
3763 0 : ADS_MODLIST mods = NULL;
3764 :
3765 0 : if (c->display_usage || argc < 1) {
3766 0 : d_printf( "%s\n"
3767 : "net ads enctypes delete <sAMAccountName>\n"
3768 : " %s\n",
3769 : _("Usage:"),
3770 : _("Delete supported enctypes"));
3771 0 : TALLOC_FREE(tmp_ctx);
3772 0 : return -1;
3773 : }
3774 :
3775 0 : status = ads_startup(c, false, tmp_ctx, &ads);
3776 0 : if (!ADS_ERR_OK(status)) {
3777 0 : goto done;
3778 : }
3779 :
3780 0 : ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3781 0 : if (ret) {
3782 0 : goto done;
3783 : }
3784 :
3785 0 : dn = ads_get_dn(ads, tmp_ctx, res);
3786 0 : if (dn == NULL) {
3787 0 : goto done;
3788 : }
3789 :
3790 0 : mods = ads_init_mods(tmp_ctx);
3791 0 : if (!mods) {
3792 0 : goto done;
3793 : }
3794 :
3795 0 : status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3796 0 : if (!ADS_ERR_OK(status)) {
3797 0 : goto done;
3798 : }
3799 :
3800 0 : status = ads_gen_mod(ads, dn, mods);
3801 0 : if (!ADS_ERR_OK(status)) {
3802 0 : d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3803 : ads_errstr(status));
3804 0 : goto done;
3805 : }
3806 :
3807 0 : ret = 0;
3808 :
3809 0 : done:
3810 0 : ads_msgfree(ads, res);
3811 0 : TALLOC_FREE(tmp_ctx);
3812 0 : return ret;
3813 : }
3814 :
3815 0 : static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3816 : {
3817 0 : struct functable func[] = {
3818 : {
3819 : "list",
3820 : net_ads_enctypes_list,
3821 : NET_TRANSPORT_ADS,
3822 : N_("List the supported encryption types"),
3823 : N_("net ads enctypes list\n"
3824 : " List the supported encryption types")
3825 : },
3826 : {
3827 : "set",
3828 : net_ads_enctypes_set,
3829 : NET_TRANSPORT_ADS,
3830 : N_("Set the supported encryption types"),
3831 : N_("net ads enctypes set\n"
3832 : " Set the supported encryption types")
3833 : },
3834 : {
3835 : "delete",
3836 : net_ads_enctypes_delete,
3837 : NET_TRANSPORT_ADS,
3838 : N_("Delete the supported encryption types"),
3839 : N_("net ads enctypes delete\n"
3840 : " Delete the supported encryption types")
3841 : },
3842 :
3843 : {NULL, NULL, 0, NULL, NULL}
3844 : };
3845 :
3846 0 : return net_run_function(c, argc, argv, "net ads enctypes", func);
3847 : }
3848 :
3849 :
3850 36 : int net_ads(struct net_context *c, int argc, const char **argv)
3851 : {
3852 36 : struct functable func[] = {
3853 : {
3854 : "info",
3855 : net_ads_info,
3856 : NET_TRANSPORT_ADS,
3857 : N_("Display details on remote ADS server"),
3858 : N_("net ads info\n"
3859 : " Display details on remote ADS server")
3860 : },
3861 : {
3862 : "join",
3863 : net_ads_join,
3864 : NET_TRANSPORT_ADS,
3865 : N_("Join the local machine to ADS realm"),
3866 : N_("net ads join\n"
3867 : " Join the local machine to ADS realm")
3868 : },
3869 : {
3870 : "testjoin",
3871 : net_ads_testjoin,
3872 : NET_TRANSPORT_ADS,
3873 : N_("Validate machine account"),
3874 : N_("net ads testjoin\n"
3875 : " Validate machine account")
3876 : },
3877 : {
3878 : "leave",
3879 : net_ads_leave,
3880 : NET_TRANSPORT_ADS,
3881 : N_("Remove the local machine from ADS"),
3882 : N_("net ads leave\n"
3883 : " Remove the local machine from ADS")
3884 : },
3885 : {
3886 : "status",
3887 : net_ads_status,
3888 : NET_TRANSPORT_ADS,
3889 : N_("Display machine account details"),
3890 : N_("net ads status\n"
3891 : " Display machine account details")
3892 : },
3893 : {
3894 : "user",
3895 : net_ads_user,
3896 : NET_TRANSPORT_ADS,
3897 : N_("List/modify users"),
3898 : N_("net ads user\n"
3899 : " List/modify users")
3900 : },
3901 : {
3902 : "group",
3903 : net_ads_group,
3904 : NET_TRANSPORT_ADS,
3905 : N_("List/modify groups"),
3906 : N_("net ads group\n"
3907 : " List/modify groups")
3908 : },
3909 : {
3910 : "dns",
3911 : net_ads_dns,
3912 : NET_TRANSPORT_ADS,
3913 : N_("Issue dynamic DNS update"),
3914 : N_("net ads dns\n"
3915 : " Issue dynamic DNS update")
3916 : },
3917 : {
3918 : "password",
3919 : net_ads_password,
3920 : NET_TRANSPORT_ADS,
3921 : N_("Change user passwords"),
3922 : N_("net ads password\n"
3923 : " Change user passwords")
3924 : },
3925 : {
3926 : "changetrustpw",
3927 : net_ads_changetrustpw,
3928 : NET_TRANSPORT_ADS,
3929 : N_("Change trust account password"),
3930 : N_("net ads changetrustpw\n"
3931 : " Change trust account password")
3932 : },
3933 : {
3934 : "printer",
3935 : net_ads_printer,
3936 : NET_TRANSPORT_ADS,
3937 : N_("List/modify printer entries"),
3938 : N_("net ads printer\n"
3939 : " List/modify printer entries")
3940 : },
3941 : {
3942 : "search",
3943 : net_ads_search,
3944 : NET_TRANSPORT_ADS,
3945 : N_("Issue LDAP search using filter"),
3946 : N_("net ads search\n"
3947 : " Issue LDAP search using filter")
3948 : },
3949 : {
3950 : "dn",
3951 : net_ads_dn,
3952 : NET_TRANSPORT_ADS,
3953 : N_("Issue LDAP search by DN"),
3954 : N_("net ads dn\n"
3955 : " Issue LDAP search by DN")
3956 : },
3957 : {
3958 : "sid",
3959 : net_ads_sid,
3960 : NET_TRANSPORT_ADS,
3961 : N_("Issue LDAP search by SID"),
3962 : N_("net ads sid\n"
3963 : " Issue LDAP search by SID")
3964 : },
3965 : {
3966 : "workgroup",
3967 : net_ads_workgroup,
3968 : NET_TRANSPORT_ADS,
3969 : N_("Display workgroup name"),
3970 : N_("net ads workgroup\n"
3971 : " Display the workgroup name")
3972 : },
3973 : {
3974 : "lookup",
3975 : net_ads_lookup,
3976 : NET_TRANSPORT_ADS,
3977 : N_("Perform CLDAP query on DC"),
3978 : N_("net ads lookup\n"
3979 : " Find the ADS DC using CLDAP lookups")
3980 : },
3981 : {
3982 : "keytab",
3983 : net_ads_keytab,
3984 : NET_TRANSPORT_ADS,
3985 : N_("Manage local keytab file"),
3986 : N_("net ads keytab\n"
3987 : " Manage local keytab file")
3988 : },
3989 : {
3990 : "setspn",
3991 : net_ads_setspn,
3992 : NET_TRANSPORT_ADS,
3993 : N_("Manage Service Principal Names (SPN)s"),
3994 : N_("net ads spnset\n"
3995 : " Manage Service Principal Names (SPN)s")
3996 : },
3997 : {
3998 : "gpo",
3999 : net_ads_gpo,
4000 : NET_TRANSPORT_ADS,
4001 : N_("Manage group policy objects"),
4002 : N_("net ads gpo\n"
4003 : " Manage group policy objects")
4004 : },
4005 : {
4006 : "kerberos",
4007 : net_ads_kerberos,
4008 : NET_TRANSPORT_ADS,
4009 : N_("Manage kerberos keytab"),
4010 : N_("net ads kerberos\n"
4011 : " Manage kerberos keytab")
4012 : },
4013 : {
4014 : "enctypes",
4015 : net_ads_enctypes,
4016 : NET_TRANSPORT_ADS,
4017 : N_("List/modify supported encryption types"),
4018 : N_("net ads enctypes\n"
4019 : " List/modify enctypes")
4020 : },
4021 : {NULL, NULL, 0, NULL, NULL}
4022 : };
4023 :
4024 36 : return net_run_function(c, argc, argv, "net ads", func);
4025 : }
4026 :
4027 : #else
4028 :
4029 : static int net_ads_noads(void)
4030 : {
4031 : d_fprintf(stderr, _("ADS support not compiled in\n"));
4032 : return -1;
4033 : }
4034 :
4035 : int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4036 : {
4037 : return net_ads_noads();
4038 : }
4039 :
4040 : int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4041 : {
4042 : return net_ads_noads();
4043 : }
4044 :
4045 : int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4046 : {
4047 : return net_ads_noads();
4048 : }
4049 :
4050 : int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4051 : {
4052 : return net_ads_noads();
4053 : }
4054 :
4055 : int net_ads_join(struct net_context *c, int argc, const char **argv)
4056 : {
4057 : return net_ads_noads();
4058 : }
4059 :
4060 : int net_ads_user(struct net_context *c, int argc, const char **argv)
4061 : {
4062 : return net_ads_noads();
4063 : }
4064 :
4065 : int net_ads_group(struct net_context *c, int argc, const char **argv)
4066 : {
4067 : return net_ads_noads();
4068 : }
4069 :
4070 : int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4071 : {
4072 : return net_ads_noads();
4073 : }
4074 :
4075 : /* this one shouldn't display a message */
4076 : int net_ads_check(struct net_context *c)
4077 : {
4078 : return -1;
4079 : }
4080 :
4081 : int net_ads_check_our_domain(struct net_context *c)
4082 : {
4083 : return -1;
4084 : }
4085 :
4086 : int net_ads(struct net_context *c, int argc, const char **argv)
4087 : {
4088 : return net_ads_noads();
4089 : }
4090 :
4091 : #endif /* HAVE_ADS */
|