python: models: rename argument ldb to samdb
[samba.git] / source3 / utils / net_ads.c
blob2eb62a3e4b9113d4e2dda6db7ebeef90f6420240
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)
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.
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.
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/>.
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 #include "lib/util/util_file.h"
47 #ifdef HAVE_JANSSON
48 #include <jansson.h>
49 #include "audit_logging.h" /* various JSON helpers */
50 #include "auth/common_auth.h"
51 #endif /* [HAVE_JANSSON] */
53 #ifdef HAVE_ADS
55 /* when we do not have sufficient input parameters to contact a remote domain
56 * we always fall back to our own realm - Guenther*/
58 static const char *assume_own_realm(struct net_context *c)
60 if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
61 return lp_realm();
64 return NULL;
67 #ifdef HAVE_JANSSON
70 * note: JSON output deliberately bypasses gettext so as to provide the same
71 * output irrespective of the locale.
74 static int output_json(const struct json_object *jsobj)
76 TALLOC_CTX *ctx = NULL;
77 char *json = NULL;
79 if (json_is_invalid(jsobj)) {
80 return -1;
83 ctx = talloc_new(NULL);
84 if (ctx == NULL) {
85 d_fprintf(stderr, _("Out of memory\n"));
86 return -1;
89 json = json_to_string(ctx, jsobj);
90 if (!json) {
91 d_fprintf(stderr, _("error encoding to JSON\n"));
92 return -1;
95 d_printf("%s\n", json);
96 TALLOC_FREE(ctx);
98 return 0;
101 static int net_ads_cldap_netlogon_json
102 (ADS_STRUCT *ads,
103 const char *addr,
104 const struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply)
106 struct json_object jsobj = json_new_object();
107 struct json_object flagsobj = json_new_object();
108 char response_type [32] = { '\0' };
109 int ret = 0;
111 if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
112 d_fprintf(stderr, _("error setting up JSON value\n"));
114 goto failure;
117 switch (reply->command) {
118 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
119 strncpy(response_type,
120 "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
121 sizeof(response_type));
122 break;
123 case LOGON_SAM_LOGON_RESPONSE_EX:
124 strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
125 sizeof(response_type));
126 break;
127 default:
128 snprintf(response_type, sizeof(response_type), "0x%x",
129 reply->command);
130 break;
133 ret = json_add_string(&jsobj, "Information for Domain Controller",
134 addr);
135 if (ret != 0) {
136 goto failure;
139 ret = json_add_string(&jsobj, "Response Type", response_type);
140 if (ret != 0) {
141 goto failure;
144 ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
145 if (ret != 0) {
146 goto failure;
149 ret = json_add_bool(&flagsobj, "Is a PDC",
150 reply->server_type & NBT_SERVER_PDC);
151 if (ret != 0) {
152 goto failure;
155 ret = json_add_bool(&flagsobj, "Is a GC of the forest",
156 reply->server_type & NBT_SERVER_GC);
157 if (ret != 0) {
158 goto failure;
161 ret = json_add_bool(&flagsobj, "Is an LDAP server",
162 reply->server_type & NBT_SERVER_LDAP);
163 if (ret != 0) {
164 goto failure;
167 ret = json_add_bool(&flagsobj, "Supports DS",
168 reply->server_type & NBT_SERVER_DS);
169 if (ret != 0) {
170 goto failure;
173 ret = json_add_bool(&flagsobj, "Is running a KDC",
174 reply->server_type & NBT_SERVER_KDC);
175 if (ret != 0) {
176 goto failure;
179 ret = json_add_bool(&flagsobj, "Is running time services",
180 reply->server_type & NBT_SERVER_TIMESERV);
181 if (ret != 0) {
182 goto failure;
185 ret = json_add_bool(&flagsobj, "Is the closest DC",
186 reply->server_type & NBT_SERVER_CLOSEST);
187 if (ret != 0) {
188 goto failure;
191 ret = json_add_bool(&flagsobj, "Is writable",
192 reply->server_type & NBT_SERVER_WRITABLE);
193 if (ret != 0) {
194 goto failure;
197 ret = json_add_bool(&flagsobj, "Has a hardware clock",
198 reply->server_type & NBT_SERVER_GOOD_TIMESERV);
199 if (ret != 0) {
200 goto failure;
203 ret = json_add_bool(&flagsobj,
204 "Is a non-domain NC serviced by LDAP server",
205 reply->server_type & NBT_SERVER_NDNC);
206 if (ret != 0) {
207 goto failure;
210 ret = json_add_bool
211 (&flagsobj, "Is NT6 DC that has some secrets",
212 reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
213 if (ret != 0) {
214 goto failure;
217 ret = json_add_bool
218 (&flagsobj, "Is NT6 DC that has all secrets",
219 reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
220 if (ret != 0) {
221 goto failure;
224 ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services",
225 reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
226 if (ret != 0) {
227 goto failure;
230 ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later",
231 reply->server_type & NBT_SERVER_DS_8);
232 if (ret != 0) {
233 goto failure;
236 ret = json_add_bool(&flagsobj, "Runs on Windows 2012R2 or later",
237 reply->server_type & NBT_SERVER_DS_9);
238 if (ret != 0) {
239 goto failure;
242 ret = json_add_bool(&flagsobj, "Runs on Windows 2016 or later",
243 reply->server_type & NBT_SERVER_DS_10);
244 if (ret != 0) {
245 goto failure;
248 ret = json_add_bool(&flagsobj, "Has a DNS name",
249 reply->server_type & NBT_SERVER_HAS_DNS_NAME);
250 if (ret != 0) {
251 goto failure;
254 ret = json_add_bool(&flagsobj, "Is a default NC",
255 reply->server_type & NBT_SERVER_IS_DEFAULT_NC);
256 if (ret != 0) {
257 goto failure;
260 ret = json_add_bool(&flagsobj, "Is the forest root",
261 reply->server_type & NBT_SERVER_FOREST_ROOT);
262 if (ret != 0) {
263 goto failure;
266 ret = json_add_string(&jsobj, "Forest", reply->forest);
267 if (ret != 0) {
268 goto failure;
271 ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
272 if (ret != 0) {
273 goto failure;
276 ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
277 if (ret != 0) {
278 goto failure;
282 ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
283 if (ret != 0) {
284 goto failure;
287 ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
288 if (ret != 0) {
289 goto failure;
292 if (*reply->user_name) {
293 ret = json_add_string(&jsobj, "User name", reply->user_name);
294 if (ret != 0) {
295 goto failure;
299 ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
300 if (ret != 0) {
301 goto failure;
304 ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
305 if (ret != 0) {
306 goto failure;
309 ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
310 if (ret != 0) {
311 goto failure;
314 ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
315 if (ret != 0) {
316 goto failure;
319 ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
320 if (ret != 0) {
321 goto failure;
324 ret = json_add_object(&jsobj, "Flags", &flagsobj);
325 if (ret != 0) {
326 goto failure;
329 ret = output_json(&jsobj);
330 json_free(&jsobj); /* frees flagsobj recursively */
332 return ret;
334 failure:
335 json_free(&flagsobj);
336 json_free(&jsobj);
338 return ret;
341 #else /* [HAVE_JANSSON] */
343 static int net_ads_cldap_netlogon_json
344 (ADS_STRUCT *ads,
345 const char *addr,
346 const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
348 d_fprintf(stderr, _("JSON support not available\n"));
350 return -1;
353 #endif /* [HAVE_JANSSON] */
356 do a cldap netlogon query
358 static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
360 char addr[INET6_ADDRSTRLEN];
361 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
363 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
365 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
366 d_fprintf(stderr, _("CLDAP query failed!\n"));
367 return -1;
370 if (c->opt_json) {
371 return net_ads_cldap_netlogon_json(ads, addr, &reply);
374 d_printf(_("Information for Domain Controller: %s\n\n"),
375 addr);
377 d_printf(_("Response Type: "));
378 switch (reply.command) {
379 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
380 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
381 break;
382 case LOGON_SAM_LOGON_RESPONSE_EX:
383 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
384 break;
385 default:
386 d_printf("0x%x\n", reply.command);
387 break;
390 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
392 d_printf(_("Flags:\n"
393 "\tIs a PDC: %s\n"
394 "\tIs a GC of the forest: %s\n"
395 "\tIs an LDAP server: %s\n"
396 "\tSupports DS: %s\n"
397 "\tIs running a KDC: %s\n"
398 "\tIs running time services: %s\n"
399 "\tIs the closest DC: %s\n"
400 "\tIs writable: %s\n"
401 "\tHas a hardware clock: %s\n"
402 "\tIs a non-domain NC serviced by LDAP server: %s\n"
403 "\tIs NT6 DC that has some secrets: %s\n"
404 "\tIs NT6 DC that has all secrets: %s\n"
405 "\tRuns Active Directory Web Services: %s\n"
406 "\tRuns on Windows 2012 or later: %s\n"
407 "\tRuns on Windows 2012R2 or later: %s\n"
408 "\tRuns on Windows 2016 or later: %s\n"
409 "\tHas a DNS name: %s\n"
410 "\tIs a default NC: %s\n"
411 "\tIs the forest root: %s\n"),
412 (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
413 (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
414 (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
415 (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
416 (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
417 (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
418 (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
419 (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
420 (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
421 (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
422 (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
423 (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
424 (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
425 (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"),
426 (reply.server_type & NBT_SERVER_DS_9) ? _("yes") : _("no"),
427 (reply.server_type & NBT_SERVER_DS_10) ? _("yes") : _("no"),
428 (reply.server_type & NBT_SERVER_HAS_DNS_NAME) ? _("yes") : _("no"),
429 (reply.server_type & NBT_SERVER_IS_DEFAULT_NC) ? _("yes") : _("no"),
430 (reply.server_type & NBT_SERVER_FOREST_ROOT) ? _("yes") : _("no"));
433 printf(_("Forest: %s\n"), reply.forest);
434 printf(_("Domain: %s\n"), reply.dns_domain);
435 printf(_("Domain Controller: %s\n"), reply.pdc_dns_name);
437 printf(_("Pre-Win2k Domain: %s\n"), reply.domain_name);
438 printf(_("Pre-Win2k Hostname: %s\n"), reply.pdc_name);
440 if (*reply.user_name) printf(_("User name: %s\n"), reply.user_name);
442 printf(_("Server Site Name: %s\n"), reply.server_site);
443 printf(_("Client Site Name: %s\n"), reply.client_site);
445 d_printf(_("NT Version: %d\n"), reply.nt_version);
446 d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
447 d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
449 return 0;
453 this implements the CLDAP based netlogon lookup requests
454 for finding the domain controller of a ADS domain
456 static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
458 TALLOC_CTX *tmp_ctx = talloc_stackframe();
459 ADS_STRUCT *ads = NULL;
460 ADS_STATUS status;
461 int ret = -1;
463 if (c->display_usage) {
464 d_printf("%s\n"
465 "net ads lookup\n"
466 " %s",
467 _("Usage:"),
468 _("Find the ADS DC using CLDAP lookup.\n"));
469 TALLOC_FREE(tmp_ctx);
470 return -1;
473 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
474 if (!ADS_ERR_OK(status)) {
475 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
476 goto out;
479 if (!ads->config.realm) {
480 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
481 if (ads->config.realm == NULL) {
482 d_fprintf(stderr, _("Out of memory\n"));
483 goto out;
485 ads->ldap.port = 389;
488 ret = net_ads_cldap_netlogon(c, ads);
489 out:
490 TALLOC_FREE(tmp_ctx);
491 return ret;
495 #ifdef HAVE_JANSSON
497 static int net_ads_info_json(ADS_STRUCT *ads)
499 int ret = 0;
500 char addr[INET6_ADDRSTRLEN];
501 time_t pass_time;
502 struct json_object jsobj = json_new_object();
504 if (json_is_invalid(&jsobj)) {
505 d_fprintf(stderr, _("error setting up JSON value\n"));
507 goto failure;
510 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
512 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
514 ret = json_add_string (&jsobj, "LDAP server", addr);
515 if (ret != 0) {
516 goto failure;
519 ret = json_add_string (&jsobj, "LDAP server name",
520 ads->config.ldap_server_name);
521 if (ret != 0) {
522 goto failure;
525 ret = json_add_string (&jsobj, "Workgroup", ads->config.workgroup);
526 if (ret != 0) {
527 goto failure;
530 ret = json_add_string (&jsobj, "Realm", ads->config.realm);
531 if (ret != 0) {
532 goto failure;
535 ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
536 if (ret != 0) {
537 goto failure;
540 ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
541 if (ret != 0) {
542 goto failure;
545 ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
546 if (ret != 0) {
547 goto failure;
550 ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
551 if (ret != 0) {
552 goto failure;
555 ret = json_add_int (&jsobj, "Server time offset",
556 ads->auth.time_offset);
557 if (ret != 0) {
558 goto failure;
561 ret = json_add_int (&jsobj, "Last machine account password change",
562 pass_time);
563 if (ret != 0) {
564 goto failure;
567 ret = output_json(&jsobj);
568 failure:
569 json_free(&jsobj);
571 return ret;
574 #else /* [HAVE_JANSSON] */
576 static int net_ads_info_json(ADS_STRUCT *ads)
578 d_fprintf(stderr, _("JSON support not available\n"));
580 return -1;
583 #endif /* [HAVE_JANSSON] */
587 static int net_ads_info(struct net_context *c, int argc, const char **argv)
589 TALLOC_CTX *tmp_ctx = talloc_stackframe();
590 ADS_STRUCT *ads = NULL;
591 ADS_STATUS status;
592 char addr[INET6_ADDRSTRLEN];
593 time_t pass_time;
594 int ret = -1;
596 if (c->display_usage) {
597 d_printf("%s\n"
598 "net ads info\n"
599 " %s",
600 _("Usage:"),
601 _("Display information about an Active Directory "
602 "server.\n"));
603 TALLOC_FREE(tmp_ctx);
604 return -1;
607 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
608 if (!ADS_ERR_OK(status)) {
609 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
610 goto out;
613 if (!ads || !ads->config.realm) {
614 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
615 goto out;
618 /* Try to set the server's current time since we didn't do a full
619 TCP LDAP session initially */
621 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
622 d_fprintf( stderr, _("Failed to get server's current time!\n"));
625 if (c->opt_json) {
626 ret = net_ads_info_json(ads);
627 goto out;
630 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
632 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
634 d_printf(_("LDAP server: %s\n"), addr);
635 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
636 d_printf(_("Workgroup: %s\n"), ads->config.workgroup);
637 d_printf(_("Realm: %s\n"), ads->config.realm);
638 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
639 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
640 d_printf(_("Server time: %s\n"),
641 http_timestring(tmp_ctx, ads->config.current_time));
643 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
644 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
646 d_printf(_("Last machine account password change: %s\n"),
647 http_timestring(tmp_ctx, pass_time));
649 ret = 0;
650 out:
651 TALLOC_FREE(tmp_ctx);
652 return ret;
655 static ADS_STATUS ads_startup_int(struct net_context *c,
656 bool only_own_domain,
657 uint32_t auth_flags,
658 TALLOC_CTX *mem_ctx,
659 ADS_STRUCT **ads_ret)
661 ADS_STRUCT *ads = NULL;
662 ADS_STATUS status;
663 bool need_password = false;
664 bool second_time = false;
665 char *cp;
666 const char *realm = NULL;
667 bool tried_closest_dc = false;
668 enum credentials_use_kerberos krb5_state =
669 CRED_USE_KERBEROS_DISABLED;
671 /* lp_realm() should be handled by a command line param,
672 However, the join requires that realm be set in smb.conf
673 and compares our realm with the remote server's so this is
674 ok until someone needs more flexibility */
676 *ads_ret = NULL;
678 retry_connect:
679 if (only_own_domain) {
680 realm = lp_realm();
681 } else {
682 realm = assume_own_realm(c);
685 ads = ads_init(mem_ctx,
686 realm,
687 c->opt_target_workgroup,
688 c->opt_host,
689 ADS_SASL_PLAIN);
690 if (ads == NULL) {
691 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
694 if (!c->opt_user_name) {
695 c->opt_user_name = "administrator";
698 if (c->opt_user_specified) {
699 need_password = true;
702 retry:
703 if (!c->opt_password && need_password && !c->opt_machine_pass) {
704 c->opt_password = net_prompt_pass(c, c->opt_user_name);
705 if (!c->opt_password) {
706 TALLOC_FREE(ads);
707 return ADS_ERROR(LDAP_NO_MEMORY);
711 if (c->opt_password) {
712 use_in_memory_ccache();
713 ADS_TALLOC_CONST_FREE(ads->auth.password);
714 ads->auth.password = talloc_strdup(ads, c->opt_password);
715 if (ads->auth.password == NULL) {
716 TALLOC_FREE(ads);
717 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
721 ADS_TALLOC_CONST_FREE(ads->auth.user_name);
722 ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
723 if (ads->auth.user_name == NULL) {
724 TALLOC_FREE(ads);
725 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
728 ads->auth.flags |= auth_flags;
730 /* The ADS code will handle FIPS mode */
731 krb5_state = cli_credentials_get_kerberos_state(c->creds);
732 switch (krb5_state) {
733 case CRED_USE_KERBEROS_REQUIRED:
734 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
735 ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
736 break;
737 case CRED_USE_KERBEROS_DESIRED:
738 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
739 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
740 break;
741 case CRED_USE_KERBEROS_DISABLED:
742 ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
743 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
744 break;
748 * If the username is of the form "name@realm",
749 * extract the realm and convert to upper case.
750 * This is only used to establish the connection.
752 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
753 *cp++ = '\0';
754 ADS_TALLOC_CONST_FREE(ads->auth.realm);
755 ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
756 if (ads->auth.realm == NULL) {
757 TALLOC_FREE(ads);
758 return ADS_ERROR(LDAP_NO_MEMORY);
760 } else if (ads->auth.realm == NULL) {
761 const char *c_realm = cli_credentials_get_realm(c->creds);
763 if (c_realm != NULL) {
764 ads->auth.realm = talloc_strdup(ads, c_realm);
765 if (ads->auth.realm == NULL) {
766 TALLOC_FREE(ads);
767 return ADS_ERROR(LDAP_NO_MEMORY);
772 status = ads_connect(ads);
774 if (!ADS_ERR_OK(status)) {
776 if (NT_STATUS_EQUAL(ads_ntstatus(status),
777 NT_STATUS_NO_LOGON_SERVERS)) {
778 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
779 TALLOC_FREE(ads);
780 return status;
783 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
784 need_password = true;
785 second_time = true;
786 goto retry;
787 } else {
788 TALLOC_FREE(ads);
789 return status;
793 /* when contacting our own domain, make sure we use the closest DC.
794 * This is done by reconnecting to ADS because only the first call to
795 * ads_connect will give us our own sitename */
797 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
799 tried_closest_dc = true; /* avoid loop */
801 if (!ads_closest_dc(ads)) {
803 namecache_delete(ads->server.realm, 0x1C);
804 namecache_delete(ads->server.workgroup, 0x1C);
806 TALLOC_FREE(ads);
808 goto retry_connect;
812 *ads_ret = talloc_move(mem_ctx, &ads);
813 return status;
816 ADS_STATUS ads_startup(struct net_context *c,
817 bool only_own_domain,
818 TALLOC_CTX *mem_ctx,
819 ADS_STRUCT **ads)
821 return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
824 ADS_STATUS ads_startup_nobind(struct net_context *c,
825 bool only_own_domain,
826 TALLOC_CTX *mem_ctx,
827 ADS_STRUCT **ads)
829 return ads_startup_int(c,
830 only_own_domain,
831 ADS_AUTH_NO_BIND,
832 mem_ctx,
833 ads);
837 Check to see if connection can be made via ads.
838 ads_startup() stores the password in opt_password if it needs to so
839 that rpc or rap can use it without re-prompting.
841 static int net_ads_check_int(struct net_context *c,
842 const char *realm,
843 const char *workgroup,
844 const char *host)
846 TALLOC_CTX *tmp_ctx = talloc_stackframe();
847 ADS_STRUCT *ads;
848 ADS_STATUS status;
849 int ret = -1;
851 ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
852 if (ads == NULL) {
853 goto out;
856 ads->auth.flags |= ADS_AUTH_NO_BIND;
858 status = ads_connect(ads);
859 if ( !ADS_ERR_OK(status) ) {
860 goto out;
863 ret = 0;
864 out:
865 TALLOC_FREE(tmp_ctx);
866 return ret;
869 int net_ads_check_our_domain(struct net_context *c)
871 return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
874 int net_ads_check(struct net_context *c)
876 return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
880 determine the netbios workgroup name for a domain
882 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
884 TALLOC_CTX *tmp_ctx = talloc_stackframe();
885 ADS_STRUCT *ads = NULL;
886 ADS_STATUS status;
887 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
888 bool ok = false;
889 int ret = -1;
891 if (c->display_usage) {
892 d_printf ("%s\n"
893 "net ads workgroup\n"
894 " %s\n",
895 _("Usage:"),
896 _("Print the workgroup name"));
897 TALLOC_FREE(tmp_ctx);
898 return -1;
901 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
902 if (!ADS_ERR_OK(status)) {
903 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
904 goto out;
907 if (!ads->config.realm) {
908 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
909 if (ads->config.realm == NULL) {
910 d_fprintf(stderr, _("Out of memory\n"));
911 goto out;
913 ads->ldap.port = 389;
916 ok = ads_cldap_netlogon_5(tmp_ctx,
917 &ads->ldap.ss, ads->server.realm, &reply);
918 if (!ok) {
919 d_fprintf(stderr, _("CLDAP query failed!\n"));
920 goto out;
923 d_printf(_("Workgroup: %s\n"), reply.domain_name);
925 ret = 0;
926 out:
927 TALLOC_FREE(tmp_ctx);
929 return ret;
934 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
936 char **disp_fields = (char **) data_area;
938 if (!field) { /* must be end of record */
939 if (disp_fields[0]) {
940 if (!strchr_m(disp_fields[0], '$')) {
941 if (disp_fields[1])
942 d_printf("%-21.21s %s\n",
943 disp_fields[0], disp_fields[1]);
944 else
945 d_printf("%s\n", disp_fields[0]);
948 SAFE_FREE(disp_fields[0]);
949 SAFE_FREE(disp_fields[1]);
950 return true;
952 if (!values) /* must be new field, indicate string field */
953 return true;
954 if (strcasecmp_m(field, "sAMAccountName") == 0) {
955 disp_fields[0] = SMB_STRDUP((char *) values[0]);
957 if (strcasecmp_m(field, "description") == 0)
958 disp_fields[1] = SMB_STRDUP((char *) values[0]);
959 return true;
962 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
964 return net_user_usage(c, argc, argv);
967 static int ads_user_add(struct net_context *c, int argc, const char **argv)
969 TALLOC_CTX *tmp_ctx = talloc_stackframe();
970 ADS_STRUCT *ads = NULL;
971 ADS_STATUS status;
972 char *upn, *userdn;
973 LDAPMessage *res=NULL;
974 int rc = -1;
975 char *ou_str = NULL;
977 if (argc < 1 || c->display_usage) {
978 TALLOC_FREE(tmp_ctx);
979 return net_ads_user_usage(c, argc, argv);
982 status = ads_startup(c, false, tmp_ctx, &ads);
983 if (!ADS_ERR_OK(status)) {
984 goto done;
987 status = ads_find_user_acct(ads, &res, argv[0]);
988 if (!ADS_ERR_OK(status)) {
989 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
990 goto done;
993 if (ads_count_replies(ads, res)) {
994 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
995 argv[0]);
996 goto done;
999 if (c->opt_container) {
1000 ou_str = SMB_STRDUP(c->opt_container);
1001 } else {
1002 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1005 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
1006 if (!ADS_ERR_OK(status)) {
1007 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
1008 ads_errstr(status));
1009 goto done;
1012 /* if no password is to be set, we're done */
1013 if (argc == 1) {
1014 d_printf(_("User %s added\n"), argv[0]);
1015 rc = 0;
1016 goto done;
1019 /* try setting the password */
1020 upn = talloc_asprintf(tmp_ctx,
1021 "%s@%s",
1022 argv[0],
1023 ads->config.realm);
1024 if (upn == NULL) {
1025 goto done;
1028 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
1029 ads->auth.time_offset);
1030 if (ADS_ERR_OK(status)) {
1031 d_printf(_("User %s added\n"), argv[0]);
1032 rc = 0;
1033 goto done;
1035 TALLOC_FREE(upn);
1037 /* password didn't set, delete account */
1038 d_fprintf(stderr, _("Could not add user %s. "
1039 "Error setting password %s\n"),
1040 argv[0], ads_errstr(status));
1042 ads_msgfree(ads, res);
1043 res = NULL;
1045 status=ads_find_user_acct(ads, &res, argv[0]);
1046 if (ADS_ERR_OK(status)) {
1047 userdn = ads_get_dn(ads, tmp_ctx, res);
1048 ads_del_dn(ads, userdn);
1049 TALLOC_FREE(userdn);
1052 done:
1053 ads_msgfree(ads, res);
1054 SAFE_FREE(ou_str);
1055 TALLOC_FREE(tmp_ctx);
1056 return rc;
1059 static int ads_user_info(struct net_context *c, int argc, const char **argv)
1061 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1062 ADS_STRUCT *ads = NULL;
1063 ADS_STATUS status;
1064 LDAPMessage *res = NULL;
1065 int ret = -1;
1066 wbcErr wbc_status;
1067 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1068 char *searchstring = NULL;
1069 char **grouplist = NULL;
1070 char *primary_group = NULL;
1071 char *escaped_user = NULL;
1072 struct dom_sid primary_group_sid;
1073 uint32_t group_rid;
1074 enum wbcSidType type;
1076 if (argc < 1 || c->display_usage) {
1077 TALLOC_FREE(tmp_ctx);
1078 return net_ads_user_usage(c, argc, argv);
1081 escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1082 if (!escaped_user) {
1083 d_fprintf(stderr,
1084 _("ads_user_info: failed to escape user %s\n"),
1085 argv[0]);
1086 goto out;
1089 status = ads_startup(c, false, tmp_ctx, &ads);
1090 if (!ADS_ERR_OK(status)) {
1091 goto out;
1094 searchstring = talloc_asprintf(tmp_ctx,
1095 "(sAMAccountName=%s)",
1096 escaped_user);
1097 if (searchstring == NULL) {
1098 goto out;
1101 status = ads_search(ads, &res, searchstring, attrs);
1102 if (!ADS_ERR_OK(status)) {
1103 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1104 goto out;
1107 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1108 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1109 goto out;
1112 status = ads_domain_sid(ads, &primary_group_sid);
1113 if (!ADS_ERR_OK(status)) {
1114 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1115 goto out;
1118 sid_append_rid(&primary_group_sid, group_rid);
1120 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1121 NULL, /* don't look up domain */
1122 &primary_group,
1123 &type);
1124 if (!WBC_ERROR_IS_OK(wbc_status)) {
1125 d_fprintf(stderr, "wbcLookupSid: %s\n",
1126 wbcErrorString(wbc_status));
1127 goto out;
1130 d_printf("%s\n", primary_group);
1132 wbcFreeMemory(primary_group);
1134 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1135 (LDAPMessage *)res, "memberOf");
1137 if (grouplist) {
1138 int i;
1139 char **groupname;
1140 for (i=0;grouplist[i];i++) {
1141 groupname = ldap_explode_dn(grouplist[i], 1);
1142 d_printf("%s\n", groupname[0]);
1143 ldap_value_free(groupname);
1145 ldap_value_free(grouplist);
1148 ret = 0;
1149 out:
1150 TALLOC_FREE(escaped_user);
1151 TALLOC_FREE(searchstring);
1152 ads_msgfree(ads, res);
1153 TALLOC_FREE(tmp_ctx);
1154 return ret;
1157 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1159 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1160 ADS_STRUCT *ads = NULL;
1161 ADS_STATUS status;
1162 LDAPMessage *res = NULL;
1163 char *userdn = NULL;
1164 int ret = -1;
1166 if (argc < 1) {
1167 TALLOC_FREE(tmp_ctx);
1168 return net_ads_user_usage(c, argc, argv);
1171 status = ads_startup(c, false, tmp_ctx, &ads);
1172 if (!ADS_ERR_OK(status)) {
1173 goto out;
1176 status = ads_find_user_acct(ads, &res, argv[0]);
1177 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1178 d_printf(_("User %s does not exist.\n"), argv[0]);
1179 goto out;
1182 userdn = ads_get_dn(ads, tmp_ctx, res);
1183 if (userdn == NULL) {
1184 goto out;
1187 status = ads_del_dn(ads, userdn);
1188 if (!ADS_ERR_OK(status)) {
1189 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1190 ads_errstr(status));
1191 goto out;
1194 d_printf(_("User %s deleted\n"), argv[0]);
1196 ret = 0;
1197 out:
1198 ads_msgfree(ads, res);
1199 TALLOC_FREE(tmp_ctx);
1200 return ret;
1203 int net_ads_user(struct net_context *c, int argc, const char **argv)
1205 struct functable func[] = {
1207 "add",
1208 ads_user_add,
1209 NET_TRANSPORT_ADS,
1210 N_("Add an AD user"),
1211 N_("net ads user add\n"
1212 " Add an AD user")
1215 "info",
1216 ads_user_info,
1217 NET_TRANSPORT_ADS,
1218 N_("Display information about an AD user"),
1219 N_("net ads user info\n"
1220 " Display information about an AD user")
1223 "delete",
1224 ads_user_delete,
1225 NET_TRANSPORT_ADS,
1226 N_("Delete an AD user"),
1227 N_("net ads user delete\n"
1228 " Delete an AD user")
1230 {NULL, NULL, 0, NULL, NULL}
1232 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1233 ADS_STRUCT *ads = NULL;
1234 ADS_STATUS status;
1235 const char *shortattrs[] = {"sAMAccountName", NULL};
1236 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1237 char *disp_fields[2] = {NULL, NULL};
1238 int ret = -1;
1240 if (argc > 0) {
1241 TALLOC_FREE(tmp_ctx);
1242 return net_run_function(c, argc, argv, "net ads user", func);
1245 if (c->display_usage) {
1246 d_printf( "%s\n"
1247 "net ads user\n"
1248 " %s\n",
1249 _("Usage:"),
1250 _("List AD users"));
1251 net_display_usage_from_functable(func);
1252 TALLOC_FREE(tmp_ctx);
1253 return -1;
1256 status = ads_startup(c, false, tmp_ctx, &ads);
1257 if (!ADS_ERR_OK(status)) {
1258 goto out;
1261 if (c->opt_long_list_entries)
1262 d_printf(_("\nUser name Comment"
1263 "\n-----------------------------\n"));
1265 status = ads_do_search_all_fn(ads,
1266 ads->config.bind_path,
1267 LDAP_SCOPE_SUBTREE,
1268 "(objectCategory=user)",
1269 c->opt_long_list_entries ?
1270 longattrs : shortattrs,
1271 usergrp_display,
1272 disp_fields);
1273 if (!ADS_ERR_OK(status)) {
1274 goto out;
1277 ret = 0;
1278 out:
1279 TALLOC_FREE(tmp_ctx);
1280 return ret;
1283 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1285 return net_group_usage(c, argc, argv);
1288 static int ads_group_add(struct net_context *c, int argc, const char **argv)
1290 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1291 ADS_STRUCT *ads = NULL;
1292 ADS_STATUS status;
1293 LDAPMessage *res = NULL;
1294 int ret = -1;
1295 char *ou_str = NULL;
1297 if (argc < 1 || c->display_usage) {
1298 TALLOC_FREE(tmp_ctx);
1299 return net_ads_group_usage(c, argc, argv);
1302 status = ads_startup(c, false, tmp_ctx, &ads);
1303 if (!ADS_ERR_OK(status)) {
1304 goto out;
1307 status = ads_find_user_acct(ads, &res, argv[0]);
1308 if (!ADS_ERR_OK(status)) {
1309 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1310 goto out;
1313 if (ads_count_replies(ads, res)) {
1314 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1315 goto out;
1318 if (c->opt_container) {
1319 ou_str = SMB_STRDUP(c->opt_container);
1320 } else {
1321 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1324 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1325 if (!ADS_ERR_OK(status)) {
1326 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1327 ads_errstr(status));
1328 goto out;
1331 d_printf(_("Group %s added\n"), argv[0]);
1333 ret = 0;
1334 out:
1335 ads_msgfree(ads, res);
1336 SAFE_FREE(ou_str);
1337 TALLOC_FREE(tmp_ctx);
1338 return ret;
1341 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1343 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1344 ADS_STRUCT *ads = NULL;
1345 ADS_STATUS status;
1346 LDAPMessage *res = NULL;
1347 char *groupdn = NULL;
1348 int ret = -1;
1350 if (argc < 1 || c->display_usage) {
1351 TALLOC_FREE(tmp_ctx);
1352 return net_ads_group_usage(c, argc, argv);
1355 status = ads_startup(c, false, tmp_ctx, &ads);
1356 if (!ADS_ERR_OK(status)) {
1357 goto out;
1360 status = ads_find_user_acct(ads, &res, argv[0]);
1361 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1362 d_printf(_("Group %s does not exist.\n"), argv[0]);
1363 goto out;
1366 groupdn = ads_get_dn(ads, tmp_ctx, res);
1367 if (groupdn == NULL) {
1368 goto out;
1371 status = ads_del_dn(ads, groupdn);
1372 if (!ADS_ERR_OK(status)) {
1373 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1374 ads_errstr(status));
1375 goto out;
1377 d_printf(_("Group %s deleted\n"), argv[0]);
1379 ret = 0;
1380 out:
1381 ads_msgfree(ads, res);
1382 TALLOC_FREE(tmp_ctx);
1383 return ret;
1386 int net_ads_group(struct net_context *c, int argc, const char **argv)
1388 struct functable func[] = {
1390 "add",
1391 ads_group_add,
1392 NET_TRANSPORT_ADS,
1393 N_("Add an AD group"),
1394 N_("net ads group add\n"
1395 " Add an AD group")
1398 "delete",
1399 ads_group_delete,
1400 NET_TRANSPORT_ADS,
1401 N_("Delete an AD group"),
1402 N_("net ads group delete\n"
1403 " Delete an AD group")
1405 {NULL, NULL, 0, NULL, NULL}
1407 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1408 ADS_STRUCT *ads = NULL;
1409 ADS_STATUS status;
1410 const char *shortattrs[] = {"sAMAccountName", NULL};
1411 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1412 char *disp_fields[2] = {NULL, NULL};
1413 int ret = -1;
1415 if (argc >= 0) {
1416 TALLOC_FREE(tmp_ctx);
1417 return net_run_function(c, argc, argv, "net ads group", func);
1420 if (c->display_usage) {
1421 d_printf( "%s\n"
1422 "net ads group\n"
1423 " %s\n",
1424 _("Usage:"),
1425 _("List AD groups"));
1426 net_display_usage_from_functable(func);
1427 TALLOC_FREE(tmp_ctx);
1428 return -1;
1431 status = ads_startup(c, false, tmp_ctx, &ads);
1432 if (!ADS_ERR_OK(status)) {
1433 goto out;
1436 if (c->opt_long_list_entries)
1437 d_printf(_("\nGroup name Comment"
1438 "\n-----------------------------\n"));
1440 status = ads_do_search_all_fn(ads,
1441 ads->config.bind_path,
1442 LDAP_SCOPE_SUBTREE,
1443 "(objectCategory=group)",
1444 c->opt_long_list_entries ?
1445 longattrs : shortattrs,
1446 usergrp_display,
1447 disp_fields);
1448 if (!ADS_ERR_OK(status)) {
1449 goto out;
1452 ret = 0;
1453 out:
1454 TALLOC_FREE(tmp_ctx);
1455 return ret;
1458 static int net_ads_status(struct net_context *c, int argc, const char **argv)
1460 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1461 ADS_STRUCT *ads = NULL;
1462 ADS_STATUS status;
1463 LDAPMessage *res = NULL;
1464 int ret = -1;
1466 if (c->display_usage) {
1467 d_printf( "%s\n"
1468 "net ads status\n"
1469 " %s\n",
1470 _("Usage:"),
1471 _("Display machine account details"));
1472 TALLOC_FREE(tmp_ctx);
1473 return -1;
1476 net_warn_member_options();
1478 status = ads_startup(c, true, tmp_ctx, &ads);
1479 if (!ADS_ERR_OK(status)) {
1480 goto out;
1483 status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1484 if (!ADS_ERR_OK(status)) {
1485 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1486 ads_errstr(status));
1487 goto out;
1490 if (ads_count_replies(ads, res) == 0) {
1491 d_fprintf(stderr, _("No machine account for '%s' found\n"),
1492 lp_netbios_name());
1493 goto out;
1496 ads_dump(ads, res);
1498 ret = 0;
1499 out:
1500 ads_msgfree(ads, res);
1501 TALLOC_FREE(tmp_ctx);
1502 return ret;
1505 /*******************************************************************
1506 Leave an AD domain. Windows XP disables the machine account.
1507 We'll try the same. The old code would do an LDAP delete.
1508 That only worked using the machine creds because added the machine
1509 with full control to the computer object's ACL.
1510 *******************************************************************/
1512 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1514 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1515 struct libnet_UnjoinCtx *r = NULL;
1516 WERROR werr;
1517 int ret = -1;
1519 if (c->display_usage) {
1520 d_printf( "%s\n"
1521 "net ads leave [--keep-account]\n"
1522 " %s\n",
1523 _("Usage:"),
1524 _("Leave an AD domain"));
1525 TALLOC_FREE(tmp_ctx);
1526 return -1;
1529 if (!*lp_realm()) {
1530 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1531 TALLOC_FREE(tmp_ctx);
1532 return -1;
1535 if (!c->opt_kerberos) {
1536 use_in_memory_ccache();
1539 if (!c->msg_ctx) {
1540 d_fprintf(stderr, _("Could not initialise message context. "
1541 "Try running as root\n"));
1542 goto done;
1545 werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1546 if (!W_ERROR_IS_OK(werr)) {
1547 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1548 goto done;
1551 r->in.debug = true;
1552 r->in.use_kerberos = c->opt_kerberos;
1553 r->in.dc_name = c->opt_host;
1554 r->in.domain_name = lp_realm();
1555 r->in.admin_account = c->opt_user_name;
1556 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1557 r->in.modify_config = lp_config_backend_is_registry();
1559 /* Try to delete it, but if that fails, disable it. The
1560 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1561 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1562 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1563 if (c->opt_keep_account) {
1564 r->in.delete_machine_account = false;
1565 } else {
1566 r->in.delete_machine_account = true;
1569 r->in.msg_ctx = c->msg_ctx;
1571 werr = libnet_Unjoin(tmp_ctx, r);
1572 if (!W_ERROR_IS_OK(werr)) {
1573 d_printf(_("Failed to leave domain: %s\n"),
1574 r->out.error_string ? r->out.error_string :
1575 get_friendly_werror_msg(werr));
1576 goto done;
1579 if (r->out.deleted_machine_account) {
1580 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1581 r->in.machine_name, r->out.dns_domain_name);
1582 ret = 0;
1583 goto done;
1586 /* We couldn't delete it - see if the disable succeeded. */
1587 if (r->out.disabled_machine_account) {
1588 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1589 r->in.machine_name, r->out.dns_domain_name);
1590 ret = 0;
1591 goto done;
1594 /* Based on what we requested, we shouldn't get here, but if
1595 we did, it means the secrets were removed, and therefore
1596 we have left the domain */
1597 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1598 r->in.machine_name, r->out.dns_domain_name);
1600 ret = 0;
1601 done:
1602 TALLOC_FREE(tmp_ctx);
1603 return ret;
1606 static ADS_STATUS net_ads_join_ok(struct net_context *c)
1608 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1609 ADS_STRUCT *ads = NULL;
1610 ADS_STATUS status;
1611 fstring dc_name;
1612 struct sockaddr_storage dcip;
1614 if (!secrets_init()) {
1615 DEBUG(1,("Failed to initialise secrets database\n"));
1616 TALLOC_FREE(tmp_ctx);
1617 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1620 net_warn_member_options();
1622 net_use_krb_machine_account(c);
1624 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1626 status = ads_startup(c, true, tmp_ctx, &ads);
1627 if (!ADS_ERR_OK(status)) {
1628 goto out;
1631 status = ADS_ERROR_NT(NT_STATUS_OK);
1632 out:
1633 TALLOC_FREE(tmp_ctx);
1634 return status;
1638 check that an existing join is OK
1640 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1642 ADS_STATUS status;
1643 use_in_memory_ccache();
1645 if (c->display_usage) {
1646 d_printf( "%s\n"
1647 "net ads testjoin\n"
1648 " %s\n",
1649 _("Usage:"),
1650 _("Test if the existing join is ok"));
1651 return -1;
1654 net_warn_member_options();
1656 /* Display success or failure */
1657 status = net_ads_join_ok(c);
1658 if (!ADS_ERR_OK(status)) {
1659 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1660 get_friendly_nt_error_msg(ads_ntstatus(status)));
1661 return -1;
1664 printf(_("Join is OK\n"));
1665 return 0;
1668 /*******************************************************************
1669 Simple config checks before beginning the join
1670 ********************************************************************/
1672 static WERROR check_ads_config( void )
1674 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1675 d_printf(_("Host is not configured as a member server.\n"));
1676 return WERR_INVALID_DOMAIN_ROLE;
1679 if (strlen(lp_netbios_name()) > 15) {
1680 d_printf(_("Our netbios name can be at most 15 chars long, "
1681 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1682 (unsigned int)strlen(lp_netbios_name()));
1683 return WERR_INVALID_COMPUTERNAME;
1686 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1687 d_fprintf(stderr, _("realm must be set in %s for ADS "
1688 "join to succeed.\n"), get_dyn_CONFIGFILE());
1689 return WERR_INVALID_PARAMETER;
1692 return WERR_OK;
1695 /*******************************************************************
1696 ********************************************************************/
1698 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1700 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1701 "Valid options:\n"));
1702 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1703 " The default is in the form netbiosname.dnsdomain\n"));
1704 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1705 " The default UPN is in the form host/netbiosname@REALM.\n"));
1706 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1707 " The OU string read from top to bottom without RDNs\n"
1708 " and delimited by a '/'.\n"
1709 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1710 " NB: A backslash '\\' is used as escape at multiple\n"
1711 " levels and may need to be doubled or even\n"
1712 " quadrupled. It is not used as a separator.\n"));
1713 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1714 " the join. The default password is random.\n"));
1715 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1716 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1717 " NB: osName and osVer must be specified together for\n"
1718 " either to take effect. The operatingSystemService\n"
1719 " attribute is then also set along with the two\n"
1720 " other attributes.\n"));
1721 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1722 " during the join.\n"
1723 " NB: If not specified then by default the samba\n"
1724 " version string is used instead.\n"));
1725 return -1;
1729 int net_ads_join(struct net_context *c, int argc, const char **argv)
1731 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1732 struct libnet_JoinCtx *r = NULL;
1733 const char *domain = lp_realm();
1734 WERROR werr = WERR_NERR_SETUPNOTJOINED;
1735 bool createupn = false;
1736 const char *dnshostname = NULL;
1737 const char *machineupn = NULL;
1738 const char *machine_password = NULL;
1739 const char *create_in_ou = NULL;
1740 int i;
1741 const char *os_name = NULL;
1742 const char *os_version = NULL;
1743 const char *os_servicepack = NULL;
1744 bool modify_config = lp_config_backend_is_registry();
1745 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1746 int ret = -1;
1748 if (c->display_usage) {
1749 TALLOC_FREE(tmp_ctx);
1750 return net_ads_join_usage(c, argc, argv);
1753 net_warn_member_options();
1755 if (!modify_config) {
1756 werr = check_ads_config();
1757 if (!W_ERROR_IS_OK(werr)) {
1758 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1759 goto fail;
1763 if (!c->opt_kerberos) {
1764 use_in_memory_ccache();
1767 werr = libnet_init_JoinCtx(tmp_ctx, &r);
1768 if (!W_ERROR_IS_OK(werr)) {
1769 goto fail;
1772 /* process additional command line args */
1774 for ( i=0; i<argc; i++ ) {
1775 if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1776 dnshostname = get_string_param(argv[i]);
1778 else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1779 createupn = true;
1780 machineupn = get_string_param(argv[i]);
1782 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1783 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1784 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1785 werr = WERR_INVALID_PARAMETER;
1786 goto fail;
1789 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1790 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1791 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1792 werr = WERR_INVALID_PARAMETER;
1793 goto fail;
1796 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1797 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1798 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1799 werr = WERR_INVALID_PARAMETER;
1800 goto fail;
1803 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1804 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1805 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1806 werr = WERR_INVALID_PARAMETER;
1807 goto fail;
1810 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1811 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1812 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1813 werr = WERR_INVALID_PARAMETER;
1814 goto fail;
1816 } else {
1817 domain = argv[i];
1818 if (strchr(domain, '.') == NULL) {
1819 domain_name_type = JoinDomNameTypeUnknown;
1820 } else {
1821 domain_name_type = JoinDomNameTypeDNS;
1826 if (!*domain) {
1827 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1828 werr = WERR_INVALID_PARAMETER;
1829 goto fail;
1832 if (!c->msg_ctx) {
1833 d_fprintf(stderr, _("Could not initialise message context. "
1834 "Try running as root\n"));
1835 werr = WERR_ACCESS_DENIED;
1836 goto fail;
1839 /* Do the domain join here */
1841 r->in.domain_name = domain;
1842 r->in.domain_name_type = domain_name_type;
1843 r->in.create_upn = createupn;
1844 r->in.upn = machineupn;
1845 r->in.dnshostname = dnshostname;
1846 r->in.account_ou = create_in_ou;
1847 r->in.os_name = os_name;
1848 r->in.os_version = os_version;
1849 r->in.os_servicepack = os_servicepack;
1850 r->in.dc_name = c->opt_host;
1851 r->in.admin_account = c->opt_user_name;
1852 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1853 r->in.machine_password = machine_password;
1854 r->in.debug = true;
1855 r->in.use_kerberos = c->opt_kerberos;
1856 r->in.modify_config = modify_config;
1857 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1858 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1859 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1860 r->in.msg_ctx = c->msg_ctx;
1862 werr = libnet_Join(tmp_ctx, r);
1863 if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1864 strequal(domain, lp_realm())) {
1865 r->in.domain_name = lp_workgroup();
1866 r->in.domain_name_type = JoinDomNameTypeNBT;
1867 werr = libnet_Join(tmp_ctx, r);
1869 if (!W_ERROR_IS_OK(werr)) {
1870 goto fail;
1873 /* Check the short name of the domain */
1875 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1876 d_printf(_("The workgroup in %s does not match the short\n"
1877 "domain name obtained from the server.\n"
1878 "Using the name [%s] from the server.\n"
1879 "You should set \"workgroup = %s\" in %s.\n"),
1880 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1881 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1884 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1886 if (r->out.dns_domain_name) {
1887 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1888 r->out.dns_domain_name);
1889 } else {
1890 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1891 r->out.netbios_domain_name);
1894 /* print out informative error string in case there is one */
1895 if (r->out.error_string != NULL) {
1896 d_printf("%s\n", r->out.error_string);
1900 * We try doing the dns update (if it was compiled in
1901 * and if it was not disabled on the command line).
1902 * If the dns update fails, we still consider the join
1903 * operation as succeeded if we came this far.
1905 if (!c->opt_no_dns_updates) {
1906 net_ads_join_dns_updates(c, tmp_ctx, r);
1909 ret = 0;
1911 fail:
1912 if (ret != 0) {
1913 /* issue an overall failure message at the end. */
1914 d_printf(_("Failed to join domain: %s\n"),
1915 r && r->out.error_string ? r->out.error_string :
1916 get_friendly_werror_msg(werr));
1919 TALLOC_FREE(tmp_ctx);
1921 return ret;
1924 /*******************************************************************
1925 ********************************************************************/
1927 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1929 #if defined(HAVE_KRB5)
1930 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1931 ADS_STRUCT *ads = NULL;
1932 ADS_STATUS status;
1933 NTSTATUS ntstatus;
1934 const char *hostname = NULL;
1935 const char **addrs_list = NULL;
1936 struct sockaddr_storage *addrs = NULL;
1937 int num_addrs = 0;
1938 int count;
1939 int ret = -1;
1941 #ifdef DEVELOPER
1942 talloc_enable_leak_report();
1943 #endif
1945 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1946 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1947 "detection of addresses in a clustered "
1948 "setup.\n"));
1949 c->display_usage = true;
1952 if (c->display_usage) {
1953 d_printf( "%s\n"
1954 "net ads dns register [hostname [IP [IP...]]] "
1955 "[--force] [--dns-ttl TTL]\n"
1956 " %s\n",
1957 _("Usage:"),
1958 _("Register hostname with DNS\n"));
1959 TALLOC_FREE(tmp_ctx);
1960 return -1;
1963 if (argc >= 1) {
1964 hostname = argv[0];
1967 if (argc > 1) {
1968 num_addrs = argc - 1;
1969 addrs_list = &argv[1];
1970 } else if (lp_clustering()) {
1971 addrs_list = lp_cluster_addresses();
1972 num_addrs = str_list_length(addrs_list);
1975 if (num_addrs > 0) {
1976 addrs = talloc_zero_array(tmp_ctx,
1977 struct sockaddr_storage,
1978 num_addrs);
1979 if (addrs == NULL) {
1980 d_fprintf(stderr, _("Error allocating memory!\n"));
1981 goto out;
1985 for (count = 0; count < num_addrs; count++) {
1986 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1987 d_fprintf(stderr, "%s '%s'.\n",
1988 _("Cannot interpret address"),
1989 addrs_list[count]);
1990 goto out;
1994 status = ads_startup(c, true, tmp_ctx, &ads);
1995 if ( !ADS_ERR_OK(status) ) {
1996 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1997 goto out;
2000 ntstatus = net_update_dns_ext(c,
2001 tmp_ctx,
2002 ads,
2003 hostname,
2004 addrs,
2005 num_addrs,
2006 false);
2007 if (!NT_STATUS_IS_OK(ntstatus)) {
2008 d_fprintf( stderr, _("DNS update failed!\n") );
2009 goto out;
2012 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
2014 ret = 0;
2015 out:
2016 TALLOC_FREE(tmp_ctx);
2018 return ret;
2019 #else
2020 d_fprintf(stderr,
2021 _("DNS update support not enabled at compile time!\n"));
2022 return -1;
2023 #endif
2026 static int net_ads_dns_unregister(struct net_context *c,
2027 int argc,
2028 const char **argv)
2030 #if defined(HAVE_KRB5)
2031 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2032 ADS_STRUCT *ads = NULL;
2033 ADS_STATUS status;
2034 NTSTATUS ntstatus;
2035 const char *hostname = NULL;
2036 int ret = -1;
2038 #ifdef DEVELOPER
2039 talloc_enable_leak_report();
2040 #endif
2042 if (argc != 1) {
2043 c->display_usage = true;
2046 if (c->display_usage) {
2047 d_printf( "%s\n"
2048 "net ads dns unregister [hostname]\n"
2049 " %s\n",
2050 _("Usage:"),
2051 _("Remove all IP Address entries for a given\n"
2052 " hostname from the Active Directory server.\n"));
2053 TALLOC_FREE(tmp_ctx);
2054 return -1;
2057 /* Get the hostname for un-registering */
2058 hostname = argv[0];
2060 status = ads_startup(c, true, tmp_ctx, &ads);
2061 if ( !ADS_ERR_OK(status) ) {
2062 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2063 goto out;
2066 ntstatus = net_update_dns_ext(c,
2067 tmp_ctx,
2068 ads,
2069 hostname,
2070 NULL,
2072 true);
2073 if (!NT_STATUS_IS_OK(ntstatus)) {
2074 d_fprintf( stderr, _("DNS update failed!\n") );
2075 goto out;
2078 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2080 ret = 0;
2081 out:
2082 TALLOC_FREE(tmp_ctx);
2084 return ret;
2085 #else
2086 d_fprintf(stderr,
2087 _("DNS update support not enabled at compile time!\n"));
2088 return -1;
2089 #endif
2093 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2095 size_t num_names = 0;
2096 char **hostnames = NULL;
2097 size_t i = 0;
2098 struct samba_sockaddr *addrs = NULL;
2099 NTSTATUS status;
2101 if (argc != 1 || c->display_usage) {
2102 d_printf( "%s\n"
2103 " %s\n"
2104 " %s\n",
2105 _("Usage:"),
2106 _("net ads dns async <name>\n"),
2107 _(" Async look up hostname from the DNS server\n"
2108 " hostname\tName to look up\n"));
2109 return -1;
2112 status = ads_dns_lookup_a(talloc_tos(),
2113 argv[0],
2114 &num_names,
2115 &hostnames,
2116 &addrs);
2117 if (!NT_STATUS_IS_OK(status)) {
2118 d_printf("Looking up A record for %s got error %s\n",
2119 argv[0],
2120 nt_errstr(status));
2121 return -1;
2123 d_printf("Async A record lookup - got %u names for %s\n",
2124 (unsigned int)num_names,
2125 argv[0]);
2126 for (i = 0; i < num_names; i++) {
2127 char addr_buf[INET6_ADDRSTRLEN];
2128 print_sockaddr(addr_buf,
2129 sizeof(addr_buf),
2130 &addrs[i].u.ss);
2131 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2132 (unsigned int)i,
2133 hostnames[i],
2134 addr_buf);
2137 #if defined(HAVE_IPV6)
2138 status = ads_dns_lookup_aaaa(talloc_tos(),
2139 argv[0],
2140 &num_names,
2141 &hostnames,
2142 &addrs);
2143 if (!NT_STATUS_IS_OK(status)) {
2144 d_printf("Looking up AAAA record for %s got error %s\n",
2145 argv[0],
2146 nt_errstr(status));
2147 return -1;
2149 d_printf("Async AAAA record lookup - got %u names for %s\n",
2150 (unsigned int)num_names,
2151 argv[0]);
2152 for (i = 0; i < num_names; i++) {
2153 char addr_buf[INET6_ADDRSTRLEN];
2154 print_sockaddr(addr_buf,
2155 sizeof(addr_buf),
2156 &addrs[i].u.ss);
2157 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2158 (unsigned int)i,
2159 hostnames[i],
2160 addr_buf);
2162 #endif
2163 return 0;
2167 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2169 struct functable func[] = {
2171 "register",
2172 net_ads_dns_register,
2173 NET_TRANSPORT_ADS,
2174 N_("Add host dns entry to AD"),
2175 N_("net ads dns register\n"
2176 " Add host dns entry to AD")
2179 "unregister",
2180 net_ads_dns_unregister,
2181 NET_TRANSPORT_ADS,
2182 N_("Remove host dns entry from AD"),
2183 N_("net ads dns unregister\n"
2184 " Remove host dns entry from AD")
2187 "async",
2188 net_ads_dns_async,
2189 NET_TRANSPORT_ADS,
2190 N_("Look up host"),
2191 N_("net ads dns async\n"
2192 " Look up host using async DNS")
2194 {NULL, NULL, 0, NULL, NULL}
2197 return net_run_function(c, argc, argv, "net ads dns", func);
2200 /*******************************************************************
2201 ********************************************************************/
2203 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2205 d_printf(_(
2206 "\nnet ads printer search <printer>"
2207 "\n\tsearch for a printer in the directory\n"
2208 "\nnet ads printer info <printer> <server>"
2209 "\n\tlookup info in directory for printer on server"
2210 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2211 "\nnet ads printer publish <printername>"
2212 "\n\tpublish printer in directory"
2213 "\n\t(note: printer name is required)\n"
2214 "\nnet ads printer remove <printername>"
2215 "\n\tremove printer from directory"
2216 "\n\t(note: printer name is required)\n"));
2217 return -1;
2220 /*******************************************************************
2221 ********************************************************************/
2223 static int net_ads_printer_search(struct net_context *c,
2224 int argc,
2225 const char **argv)
2227 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2228 ADS_STRUCT *ads = NULL;
2229 ADS_STATUS status;
2230 LDAPMessage *res = NULL;
2231 int ret = -1;
2233 if (c->display_usage) {
2234 d_printf( "%s\n"
2235 "net ads printer search\n"
2236 " %s\n",
2237 _("Usage:"),
2238 _("List printers in the AD"));
2239 TALLOC_FREE(tmp_ctx);
2240 return -1;
2243 status = ads_startup(c, false, tmp_ctx, &ads);
2244 if (!ADS_ERR_OK(status)) {
2245 goto out;
2248 status = ads_find_printers(ads, &res);
2249 if (!ADS_ERR_OK(status)) {
2250 d_fprintf(stderr, _("ads_find_printer: %s\n"),
2251 ads_errstr(status));
2252 goto out;
2255 if (ads_count_replies(ads, res) == 0) {
2256 d_fprintf(stderr, _("No results found\n"));
2257 goto out;
2260 ads_dump(ads, res);
2262 ret = 0;
2263 out:
2264 ads_msgfree(ads, res);
2265 TALLOC_FREE(tmp_ctx);
2266 return ret;
2269 static int net_ads_printer_info(struct net_context *c,
2270 int argc,
2271 const char **argv)
2273 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2274 ADS_STRUCT *ads = NULL;
2275 ADS_STATUS status;
2276 const char *servername = NULL;
2277 const char *printername = NULL;
2278 LDAPMessage *res = NULL;
2279 int ret = -1;
2281 if (c->display_usage) {
2282 d_printf("%s\n%s",
2283 _("Usage:"),
2284 _("net ads printer info [printername [servername]]\n"
2285 " Display printer info from AD\n"
2286 " printername\tPrinter name or wildcard\n"
2287 " servername\tName of the print server\n"));
2288 TALLOC_FREE(tmp_ctx);
2289 return -1;
2292 status = ads_startup(c, false, tmp_ctx, &ads);
2293 if (!ADS_ERR_OK(status)) {
2294 goto out;
2297 if (argc > 0) {
2298 printername = argv[0];
2299 } else {
2300 printername = "*";
2303 if (argc > 1) {
2304 servername = argv[1];
2305 } else {
2306 servername = lp_netbios_name();
2309 status = ads_find_printer_on_server(ads, &res, printername, servername);
2310 if (!ADS_ERR_OK(status)) {
2311 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2312 servername, ads_errstr(status));
2313 goto out;
2316 if (ads_count_replies(ads, res) == 0) {
2317 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2318 goto out;
2321 ads_dump(ads, res);
2323 ret = 0;
2324 out:
2325 ads_msgfree(ads, res);
2326 TALLOC_FREE(tmp_ctx);
2327 return ret;
2330 static int net_ads_printer_publish(struct net_context *c,
2331 int argc,
2332 const char **argv)
2334 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2335 ADS_STRUCT *ads = NULL;
2336 ADS_STATUS status;
2337 const char *servername = NULL;
2338 const char *printername = NULL;
2339 struct cli_state *cli = NULL;
2340 struct rpc_pipe_client *pipe_hnd = NULL;
2341 struct sockaddr_storage server_ss = { 0 };
2342 NTSTATUS nt_status;
2343 ADS_MODLIST mods = NULL;
2344 char *prt_dn = NULL;
2345 char *srv_dn = NULL;
2346 char **srv_cn = NULL;
2347 char *srv_cn_escaped = NULL;
2348 char *printername_escaped = NULL;
2349 LDAPMessage *res = NULL;
2350 bool ok;
2351 int ret = -1;
2353 if (argc < 1 || c->display_usage) {
2354 d_printf("%s\n%s",
2355 _("Usage:"),
2356 _("net ads printer publish <printername> [servername]\n"
2357 " Publish printer in AD\n"
2358 " printername\tName of the printer\n"
2359 " servername\tName of the print server\n"));
2360 TALLOC_FREE(tmp_ctx);
2361 return -1;
2364 mods = ads_init_mods(tmp_ctx);
2365 if (mods == NULL) {
2366 d_fprintf(stderr, _("Out of memory\n"));
2367 goto out;
2370 status = ads_startup(c, true, tmp_ctx, &ads);
2371 if (!ADS_ERR_OK(status)) {
2372 goto out;
2375 printername = argv[0];
2377 if (argc == 2) {
2378 servername = argv[1];
2379 } else {
2380 servername = lp_netbios_name();
2383 /* Get printer data from SPOOLSS */
2385 ok = resolve_name(servername, &server_ss, 0x20, false);
2386 if (!ok) {
2387 d_fprintf(stderr, _("Could not find server %s\n"),
2388 servername);
2389 goto out;
2392 cli_credentials_set_kerberos_state(c->creds,
2393 CRED_USE_KERBEROS_REQUIRED,
2394 CRED_SPECIFIED);
2396 nt_status = cli_full_connection_creds(c,
2397 &cli,
2398 lp_netbios_name(),
2399 servername,
2400 &server_ss,
2402 "IPC$",
2403 "IPC",
2404 c->creds,
2405 CLI_FULL_CONNECTION_IPC);
2407 if (NT_STATUS_IS_ERR(nt_status)) {
2408 d_fprintf(stderr, _("Unable to open a connection to %s to "
2409 "obtain data for %s\n"),
2410 servername, printername);
2411 goto out;
2414 /* Publish on AD server */
2416 ads_find_machine_acct(ads, &res, servername);
2418 if (ads_count_replies(ads, res) == 0) {
2419 d_fprintf(stderr, _("Could not find machine account for server "
2420 "%s\n"),
2421 servername);
2422 goto out;
2425 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2426 srv_cn = ldap_explode_dn(srv_dn, 1);
2428 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2429 printername_escaped = escape_rdn_val_string_alloc(printername);
2430 if (!srv_cn_escaped || !printername_escaped) {
2431 SAFE_FREE(srv_cn_escaped);
2432 SAFE_FREE(printername_escaped);
2433 d_fprintf(stderr, _("Internal error, out of memory!"));
2434 goto out;
2437 prt_dn = talloc_asprintf(tmp_ctx,
2438 "cn=%s-%s,%s",
2439 srv_cn_escaped,
2440 printername_escaped,
2441 srv_dn);
2442 if (prt_dn == NULL) {
2443 SAFE_FREE(srv_cn_escaped);
2444 SAFE_FREE(printername_escaped);
2445 d_fprintf(stderr, _("Internal error, out of memory!"));
2446 goto out;
2449 SAFE_FREE(srv_cn_escaped);
2450 SAFE_FREE(printername_escaped);
2452 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2453 if (!NT_STATUS_IS_OK(nt_status)) {
2454 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2455 servername);
2456 goto out;
2459 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2460 tmp_ctx,
2461 &mods,
2462 printername))) {
2463 goto out;
2466 status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2467 if (!ADS_ERR_OK(status)) {
2468 d_fprintf(stderr, "ads_publish_printer: %s\n",
2469 ads_errstr(status));
2470 goto out;
2473 d_printf("published printer\n");
2475 ret = 0;
2476 out:
2477 talloc_destroy(tmp_ctx);
2479 return ret;
2482 static int net_ads_printer_remove(struct net_context *c,
2483 int argc,
2484 const char **argv)
2486 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2487 ADS_STRUCT *ads = NULL;
2488 ADS_STATUS status;
2489 const char *servername = NULL;
2490 char *prt_dn = NULL;
2491 LDAPMessage *res = NULL;
2492 int ret = -1;
2494 if (argc < 1 || c->display_usage) {
2495 d_printf("%s\n%s",
2496 _("Usage:"),
2497 _("net ads printer remove <printername> [servername]\n"
2498 " Remove a printer from the AD\n"
2499 " printername\tName of the printer\n"
2500 " servername\tName of the print server\n"));
2501 TALLOC_FREE(tmp_ctx);
2502 return -1;
2505 status = ads_startup(c, true, tmp_ctx, &ads);
2506 if (!ADS_ERR_OK(status)) {
2507 goto out;
2510 if (argc > 1) {
2511 servername = argv[1];
2512 } else {
2513 servername = lp_netbios_name();
2516 status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2517 if (!ADS_ERR_OK(status)) {
2518 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2519 ads_errstr(status));
2520 goto out;
2523 if (ads_count_replies(ads, res) == 0) {
2524 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2525 goto out;
2528 prt_dn = ads_get_dn(ads, tmp_ctx, res);
2529 if (prt_dn == NULL) {
2530 d_fprintf(stderr, _("Out of memory\n"));
2531 goto out;
2534 status = ads_del_dn(ads, prt_dn);
2535 if (!ADS_ERR_OK(status)) {
2536 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2537 goto out;
2540 ret = 0;
2541 out:
2542 ads_msgfree(ads, res);
2543 TALLOC_FREE(tmp_ctx);
2544 return ret;
2547 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2549 struct functable func[] = {
2551 "search",
2552 net_ads_printer_search,
2553 NET_TRANSPORT_ADS,
2554 N_("Search for a printer"),
2555 N_("net ads printer search\n"
2556 " Search for a printer")
2559 "info",
2560 net_ads_printer_info,
2561 NET_TRANSPORT_ADS,
2562 N_("Display printer information"),
2563 N_("net ads printer info\n"
2564 " Display printer information")
2567 "publish",
2568 net_ads_printer_publish,
2569 NET_TRANSPORT_ADS,
2570 N_("Publish a printer"),
2571 N_("net ads printer publish\n"
2572 " Publish a printer")
2575 "remove",
2576 net_ads_printer_remove,
2577 NET_TRANSPORT_ADS,
2578 N_("Delete a printer"),
2579 N_("net ads printer remove\n"
2580 " Delete a printer")
2582 {NULL, NULL, 0, NULL, NULL}
2585 return net_run_function(c, argc, argv, "net ads printer", func);
2589 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2591 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2592 ADS_STRUCT *ads = NULL;
2593 const char *auth_principal = cli_credentials_get_username(c->creds);
2594 const char *auth_password = cli_credentials_get_password(c->creds);
2595 const char *realm = NULL;
2596 char *new_password = NULL;
2597 char *chr = NULL;
2598 char *prompt = NULL;
2599 const char *user = NULL;
2600 char pwd[256] = {0};
2601 ADS_STATUS status;
2602 int ret = 0;
2604 if (c->display_usage) {
2605 d_printf("%s\n%s",
2606 _("Usage:"),
2607 _("net ads password <username>\n"
2608 " Change password for user\n"
2609 " username\tName of user to change password for\n"));
2610 TALLOC_FREE(tmp_ctx);
2611 return -1;
2614 if (auth_principal == NULL || auth_password == NULL) {
2615 d_fprintf(stderr, _("You must supply an administrator "
2616 "username/password\n"));
2617 TALLOC_FREE(tmp_ctx);
2618 return -1;
2621 if (argc < 1) {
2622 d_fprintf(stderr, _("ERROR: You must say which username to "
2623 "change password for\n"));
2624 TALLOC_FREE(tmp_ctx);
2625 return -1;
2628 if (strchr_m(argv[0], '@')) {
2629 user = talloc_strdup(tmp_ctx, argv[0]);
2630 } else {
2631 user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2633 if (user == NULL) {
2634 d_fprintf(stderr, _("Out of memory\n"));
2635 goto out;
2638 use_in_memory_ccache();
2639 chr = strchr_m(auth_principal, '@');
2640 if (chr) {
2641 realm = ++chr;
2642 } else {
2643 realm = lp_realm();
2646 /* use the realm so we can eventually change passwords for users
2647 in realms other than default */
2648 ads = ads_init(tmp_ctx,
2649 realm,
2650 c->opt_workgroup,
2651 c->opt_host,
2652 ADS_SASL_PLAIN);
2653 if (ads == NULL) {
2654 goto out;
2657 /* we don't actually need a full connect, but it's the easy way to
2658 fill in the KDC's address */
2659 ads_connect(ads);
2661 if (!ads->config.realm) {
2662 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2663 goto out;
2666 if (argv[1] != NULL) {
2667 new_password = talloc_strdup(tmp_ctx, argv[1]);
2668 } else {
2669 int rc;
2671 prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2672 if (prompt == NULL) {
2673 d_fprintf(stderr, _("Out of memory\n"));
2674 goto out;
2677 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2678 if (rc < 0) {
2679 goto out;
2681 new_password = talloc_strdup(tmp_ctx, pwd);
2682 memset(pwd, '\0', sizeof(pwd));
2685 if (new_password == NULL) {
2686 d_fprintf(stderr, _("Out of memory\n"));
2687 goto out;
2690 status = kerberos_set_password(ads->auth.kdc_server,
2691 auth_principal,
2692 auth_password,
2693 user,
2694 new_password,
2695 ads->auth.time_offset);
2696 memset(new_password, '\0', strlen(new_password));
2697 if (!ADS_ERR_OK(status)) {
2698 d_fprintf(stderr, _("Password change failed: %s\n"),
2699 ads_errstr(status));
2700 goto out;
2703 d_printf(_("Password change for %s completed.\n"), user);
2705 ret = 0;
2706 out:
2707 TALLOC_FREE(tmp_ctx);
2708 return ret;
2711 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2713 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2714 ADS_STRUCT *ads = NULL;
2715 char *host_principal = NULL;
2716 char *my_name = NULL;
2717 ADS_STATUS status;
2718 int ret = -1;
2720 if (c->display_usage) {
2721 d_printf( "%s\n"
2722 "net ads changetrustpw\n"
2723 " %s\n",
2724 _("Usage:"),
2725 _("Change the machine account's trust password"));
2726 TALLOC_FREE(tmp_ctx);
2727 return -1;
2730 if (!secrets_init()) {
2731 DEBUG(1,("Failed to initialise secrets database\n"));
2732 goto out;
2735 net_warn_member_options();
2737 net_use_krb_machine_account(c);
2739 use_in_memory_ccache();
2741 status = ads_startup(c, true, tmp_ctx, &ads);
2742 if (!ADS_ERR_OK(status)) {
2743 goto out;
2746 my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2747 if (my_name == NULL) {
2748 d_fprintf(stderr, _("Out of memory\n"));
2749 goto out;
2752 host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2753 if (host_principal == NULL) {
2754 d_fprintf(stderr, _("Out of memory\n"));
2755 goto out;
2758 d_printf(_("Changing password for principal: %s\n"), host_principal);
2760 status = ads_change_trust_account_password(ads, host_principal);
2761 if (!ADS_ERR_OK(status)) {
2762 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2763 goto out;
2766 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2768 if (USE_SYSTEM_KEYTAB) {
2769 d_printf(_("Attempting to update system keytab with new password.\n"));
2770 if (ads_keytab_create_default(ads)) {
2771 d_printf(_("Failed to update system keytab.\n"));
2775 ret = 0;
2776 out:
2777 TALLOC_FREE(tmp_ctx);
2779 return ret;
2783 help for net ads search
2785 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2787 d_printf(_(
2788 "\nnet ads search <expression> <attributes...>\n"
2789 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2790 "The expression is a standard LDAP search expression, and the\n"
2791 "attributes are a list of LDAP fields to show in the results.\n\n"
2792 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2794 net_common_flags_usage(c, argc, argv);
2795 return -1;
2800 general ADS search function. Useful in diagnosing problems in ADS
2802 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2804 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2805 ADS_STRUCT *ads = NULL;
2806 ADS_STATUS status;
2807 const char *ldap_exp = NULL;
2808 const char **attrs = NULL;
2809 LDAPMessage *res = NULL;
2810 int ret = -1;
2812 if (argc < 1 || c->display_usage) {
2813 TALLOC_FREE(tmp_ctx);
2814 return net_ads_search_usage(c, argc, argv);
2817 status = ads_startup(c, false, tmp_ctx, &ads);
2818 if (!ADS_ERR_OK(status)) {
2819 goto out;
2822 ldap_exp = argv[0];
2823 attrs = (argv + 1);
2825 status = ads_do_search_retry(ads,
2826 ads->config.bind_path,
2827 LDAP_SCOPE_SUBTREE,
2828 ldap_exp,
2829 attrs,
2830 &res);
2831 if (!ADS_ERR_OK(status)) {
2832 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2833 goto out;
2836 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2838 /* dump the results */
2839 ads_dump(ads, res);
2841 ret = 0;
2842 out:
2843 ads_msgfree(ads, res);
2844 TALLOC_FREE(tmp_ctx);
2845 return ret;
2850 help for net ads search
2852 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2854 d_printf(_(
2855 "\nnet ads dn <dn> <attributes...>\n"
2856 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2857 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2858 "to show in the results\n\n"
2859 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2860 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2862 net_common_flags_usage(c, argc, argv);
2863 return -1;
2868 general ADS search function. Useful in diagnosing problems in ADS
2870 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2872 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2873 ADS_STRUCT *ads = NULL;
2874 ADS_STATUS status;
2875 const char *dn = NULL;
2876 const char **attrs = NULL;
2877 LDAPMessage *res = NULL;
2878 int ret = -1;
2880 if (argc < 1 || c->display_usage) {
2881 TALLOC_FREE(tmp_ctx);
2882 return net_ads_dn_usage(c, argc, argv);
2885 status = ads_startup(c, false, tmp_ctx, &ads);
2886 if (!ADS_ERR_OK(status)) {
2887 goto out;
2890 dn = argv[0];
2891 attrs = (argv + 1);
2893 status = ads_do_search_all(ads,
2895 LDAP_SCOPE_BASE,
2896 "(objectclass=*)",
2897 attrs,
2898 &res);
2899 if (!ADS_ERR_OK(status)) {
2900 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2901 goto out;
2904 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2906 /* dump the results */
2907 ads_dump(ads, res);
2909 ret = 0;
2910 out:
2911 ads_msgfree(ads, res);
2912 TALLOC_FREE(tmp_ctx);
2913 return ret;
2917 help for net ads sid search
2919 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2921 d_printf(_(
2922 "\nnet ads sid <sid> <attributes...>\n"
2923 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2924 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2925 "to show in the results\n\n"
2926 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2928 net_common_flags_usage(c, argc, argv);
2929 return -1;
2934 general ADS search function. Useful in diagnosing problems in ADS
2936 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2938 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2939 ADS_STRUCT *ads = NULL;
2940 ADS_STATUS status;
2941 const char *sid_string = NULL;
2942 const char **attrs = NULL;
2943 LDAPMessage *res = NULL;
2944 struct dom_sid sid = { 0 };
2945 int ret = -1;
2947 if (argc < 1 || c->display_usage) {
2948 TALLOC_FREE(tmp_ctx);
2949 return net_ads_sid_usage(c, argc, argv);
2952 status = ads_startup(c, false, tmp_ctx, &ads);
2953 if (!ADS_ERR_OK(status)) {
2954 goto out;
2957 sid_string = argv[0];
2958 attrs = (argv + 1);
2960 if (!string_to_sid(&sid, sid_string)) {
2961 d_fprintf(stderr, _("could not convert sid\n"));
2962 goto out;
2965 status = ads_search_retry_sid(ads, &res, &sid, attrs);
2966 if (!ADS_ERR_OK(status)) {
2967 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2968 goto out;
2971 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2973 /* dump the results */
2974 ads_dump(ads, res);
2976 ret = 0;
2977 out:
2978 ads_msgfree(ads, res);
2979 TALLOC_FREE(tmp_ctx);
2980 return ret;
2983 static int net_ads_keytab_flush(struct net_context *c,
2984 int argc,
2985 const char **argv)
2987 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2988 ADS_STRUCT *ads = NULL;
2989 ADS_STATUS status;
2990 int ret = -1;
2992 if (c->display_usage) {
2993 d_printf( "%s\n"
2994 "net ads keytab flush\n"
2995 " %s\n",
2996 _("Usage:"),
2997 _("Delete the whole keytab"));
2998 TALLOC_FREE(tmp_ctx);
2999 return -1;
3002 if (!c->opt_user_specified && c->opt_password == NULL) {
3003 net_use_krb_machine_account(c);
3006 status = ads_startup(c, true, tmp_ctx, &ads);
3007 if (!ADS_ERR_OK(status)) {
3008 goto out;
3011 ret = ads_keytab_flush(ads);
3012 out:
3013 TALLOC_FREE(tmp_ctx);
3014 return ret;
3017 static int net_ads_keytab_add(struct net_context *c,
3018 int argc,
3019 const char **argv,
3020 bool update_ads)
3022 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3023 ADS_STRUCT *ads = NULL;
3024 ADS_STATUS status;
3025 int i;
3026 int ret = -1;
3028 if (c->display_usage) {
3029 d_printf("%s\n%s",
3030 _("Usage:"),
3031 _("net ads keytab add <principal> [principal ...]\n"
3032 " Add principals to local keytab\n"
3033 " principal\tKerberos principal to add to "
3034 "keytab\n"));
3035 TALLOC_FREE(tmp_ctx);
3036 return -1;
3039 net_warn_member_options();
3041 d_printf(_("Processing principals to add...\n"));
3043 if (!c->opt_user_specified && c->opt_password == NULL) {
3044 net_use_krb_machine_account(c);
3047 status = ads_startup(c, true, tmp_ctx, &ads);
3048 if (!ADS_ERR_OK(status)) {
3049 goto out;
3052 for (ret = 0, i = 0; i < argc; i++) {
3053 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3055 out:
3056 TALLOC_FREE(tmp_ctx);
3057 return ret;
3060 static int net_ads_keytab_add_default(struct net_context *c,
3061 int argc,
3062 const char **argv)
3064 return net_ads_keytab_add(c, argc, argv, false);
3067 static int net_ads_keytab_add_update_ads(struct net_context *c,
3068 int argc,
3069 const char **argv)
3071 return net_ads_keytab_add(c, argc, argv, true);
3074 static int net_ads_keytab_delete(struct net_context *c,
3075 int argc,
3076 const char **argv)
3078 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3079 ADS_STRUCT *ads = NULL;
3080 ADS_STATUS status;
3081 int i;
3082 int ret = -1;
3084 if (c->display_usage) {
3085 d_printf("%s\n%s",
3086 _("Usage:"),
3087 _("net ads keytab delete <principal> [principal ...]\n"
3088 " Remove entries for service principal, "
3089 " from the keytab file only."
3090 " Remove principals from local keytab\n"
3091 " principal\tKerberos principal to remove from "
3092 "keytab\n"));
3093 TALLOC_FREE(tmp_ctx);
3094 return -1;
3097 d_printf(_("Processing principals to delete...\n"));
3099 if (!c->opt_user_specified && c->opt_password == NULL) {
3100 net_use_krb_machine_account(c);
3103 status = ads_startup(c, true, tmp_ctx, &ads);
3104 if (!ADS_ERR_OK(status)) {
3105 goto out;
3108 for (ret = 0, i = 0; i < argc; i++) {
3109 ret |= ads_keytab_delete_entry(ads, argv[i]);
3111 out:
3112 TALLOC_FREE(tmp_ctx);
3113 return ret;
3116 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3118 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3119 ADS_STRUCT *ads = NULL;
3120 ADS_STATUS status;
3121 int ret = -1;
3123 if (c->display_usage) {
3124 d_printf( "%s\n"
3125 "net ads keytab create\n"
3126 " %s\n",
3127 _("Usage:"),
3128 _("Create new default keytab"));
3129 TALLOC_FREE(tmp_ctx);
3130 return -1;
3133 net_warn_member_options();
3135 if (!c->opt_user_specified && c->opt_password == NULL) {
3136 net_use_krb_machine_account(c);
3139 status = ads_startup(c, true, tmp_ctx, &ads);
3140 if (!ADS_ERR_OK(status)) {
3141 goto out;
3144 ret = ads_keytab_create_default(ads);
3145 out:
3146 TALLOC_FREE(tmp_ctx);
3147 return ret;
3150 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3152 const char *keytab = NULL;
3154 if (c->display_usage) {
3155 d_printf("%s\n%s",
3156 _("Usage:"),
3157 _("net ads keytab list [keytab]\n"
3158 " List a local keytab\n"
3159 " keytab\tKeytab to list\n"));
3160 return -1;
3163 if (argc >= 1) {
3164 keytab = argv[0];
3167 return ads_keytab_list(keytab);
3171 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3173 struct functable func[] = {
3175 "add",
3176 net_ads_keytab_add_default,
3177 NET_TRANSPORT_ADS,
3178 N_("Add a service principal"),
3179 N_("net ads keytab add\n"
3180 " Add a service principal, updates keytab file only.")
3183 "delete",
3184 net_ads_keytab_delete,
3185 NET_TRANSPORT_ADS,
3186 N_("Delete a service principal"),
3187 N_("net ads keytab delete\n"
3188 " Remove entries for service principal, from the keytab file only.")
3191 "add_update_ads",
3192 net_ads_keytab_add_update_ads,
3193 NET_TRANSPORT_ADS,
3194 N_("Add a service principal"),
3195 N_("net ads keytab add_update_ads\n"
3196 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3199 "create",
3200 net_ads_keytab_create,
3201 NET_TRANSPORT_ADS,
3202 N_("Create a fresh keytab"),
3203 N_("net ads keytab create\n"
3204 " Create a fresh keytab or update existing one.")
3207 "flush",
3208 net_ads_keytab_flush,
3209 NET_TRANSPORT_ADS,
3210 N_("Remove all keytab entries"),
3211 N_("net ads keytab flush\n"
3212 " Remove all keytab entries")
3215 "list",
3216 net_ads_keytab_list,
3217 NET_TRANSPORT_ADS,
3218 N_("List a keytab"),
3219 N_("net ads keytab list\n"
3220 " List a keytab")
3222 {NULL, NULL, 0, NULL, NULL}
3225 if (!USE_KERBEROS_KEYTAB) {
3226 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3227 "keytab method to use keytab functions.\n"));
3230 return net_run_function(c, argc, argv, "net ads keytab", func);
3233 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3235 int ret = -1;
3237 if (c->display_usage) {
3238 d_printf( "%s\n"
3239 "net ads kerberos renew\n"
3240 " %s\n",
3241 _("Usage:"),
3242 _("Renew TGT from existing credential cache"));
3243 return -1;
3246 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3247 if (ret) {
3248 d_printf(_("failed to renew kerberos ticket: %s\n"),
3249 error_message(ret));
3251 return ret;
3254 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3255 struct PAC_DATA_CTR **pac_data_ctr)
3257 NTSTATUS status;
3258 int ret = -1;
3259 const char *impersonate_princ_s = NULL;
3260 const char *local_service = NULL;
3261 int i;
3263 for (i=0; i<argc; i++) {
3264 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3265 impersonate_princ_s = get_string_param(argv[i]);
3266 if (impersonate_princ_s == NULL) {
3267 return -1;
3270 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3271 local_service = get_string_param(argv[i]);
3272 if (local_service == NULL) {
3273 return -1;
3278 if (local_service == NULL) {
3279 local_service = talloc_asprintf(c, "%s$@%s",
3280 lp_netbios_name(), lp_realm());
3281 if (local_service == NULL) {
3282 goto out;
3286 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3288 status = kerberos_return_pac(c,
3289 c->opt_user_name,
3290 c->opt_password,
3292 NULL,
3293 NULL,
3294 NULL,
3295 true,
3296 true,
3297 2592000, /* one month */
3298 impersonate_princ_s,
3299 local_service,
3300 NULL,
3301 NULL,
3302 pac_data_ctr);
3303 if (!NT_STATUS_IS_OK(status)) {
3304 d_printf(_("failed to query kerberos PAC: %s\n"),
3305 nt_errstr(status));
3306 goto out;
3309 ret = 0;
3310 out:
3311 return ret;
3314 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3316 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3317 int i, num_buffers;
3318 int ret = -1;
3319 enum PAC_TYPE type = 0;
3321 if (c->display_usage) {
3322 d_printf( "%s\n"
3323 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3324 " %s\n",
3325 _("Usage:"),
3326 _("Dump the Kerberos PAC"));
3327 return -1;
3330 for (i=0; i<argc; i++) {
3331 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3332 type = get_int_param(argv[i]);
3336 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3337 if (ret) {
3338 return ret;
3341 if (type == 0) {
3343 char *s = NULL;
3345 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3346 pac_data_ctr->pac_data);
3347 if (s != NULL) {
3348 d_printf(_("The Pac: %s\n"), s);
3349 talloc_free(s);
3352 return 0;
3355 num_buffers = pac_data_ctr->pac_data->num_buffers;
3357 for (i=0; i<num_buffers; i++) {
3359 char *s = NULL;
3361 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3362 continue;
3365 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3366 pac_data_ctr->pac_data->buffers[i].info);
3367 if (s != NULL) {
3368 d_printf(_("The Pac: %s\n"), s);
3369 talloc_free(s);
3371 break;
3374 return 0;
3377 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3379 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3380 char *filename = NULL;
3381 int ret = -1;
3382 int i;
3384 if (c->display_usage) {
3385 d_printf( "%s\n"
3386 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3387 " %s\n",
3388 _("Usage:"),
3389 _("Save the Kerberos PAC"));
3390 return -1;
3393 for (i=0; i<argc; i++) {
3394 if (strnequal(argv[i], "filename", strlen("filename"))) {
3395 filename = get_string_param(argv[i]);
3396 if (filename == NULL) {
3397 return -1;
3402 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3403 if (ret) {
3404 return ret;
3407 if (filename == NULL) {
3408 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3409 return -1;
3412 /* save the raw format */
3413 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3414 d_printf(_("failed to save PAC in %s\n"), filename);
3415 return -1;
3418 return 0;
3421 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3423 struct functable func[] = {
3425 "dump",
3426 net_ads_kerberos_pac_dump,
3427 NET_TRANSPORT_ADS,
3428 N_("Dump Kerberos PAC"),
3429 N_("net ads kerberos pac dump\n"
3430 " Dump a Kerberos PAC to stdout")
3433 "save",
3434 net_ads_kerberos_pac_save,
3435 NET_TRANSPORT_ADS,
3436 N_("Save Kerberos PAC"),
3437 N_("net ads kerberos pac save\n"
3438 " Save a Kerberos PAC in a file")
3441 {NULL, NULL, 0, NULL, NULL}
3444 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3447 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3449 int ret = -1;
3450 NTSTATUS status;
3452 if (c->display_usage) {
3453 d_printf( "%s\n"
3454 "net ads kerberos kinit\n"
3455 " %s\n",
3456 _("Usage:"),
3457 _("Get Ticket Granting Ticket (TGT) for the user"));
3458 return -1;
3461 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3463 ret = kerberos_kinit_password_ext(c->opt_user_name,
3464 c->opt_password,
3466 NULL,
3467 NULL,
3468 NULL,
3469 true,
3470 true,
3471 2592000, /* one month */
3472 NULL,
3473 NULL,
3474 NULL,
3475 &status);
3476 if (ret) {
3477 d_printf(_("failed to kinit password: %s\n"),
3478 nt_errstr(status));
3480 return ret;
3483 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3485 struct functable func[] = {
3487 "kinit",
3488 net_ads_kerberos_kinit,
3489 NET_TRANSPORT_ADS,
3490 N_("Retrieve Ticket Granting Ticket (TGT)"),
3491 N_("net ads kerberos kinit\n"
3492 " Receive Ticket Granting Ticket (TGT)")
3495 "renew",
3496 net_ads_kerberos_renew,
3497 NET_TRANSPORT_ADS,
3498 N_("Renew Ticket Granting Ticket from credential cache"),
3499 N_("net ads kerberos renew\n"
3500 " Renew Ticket Granting Ticket (TGT) from "
3501 "credential cache")
3504 "pac",
3505 net_ads_kerberos_pac,
3506 NET_TRANSPORT_ADS,
3507 N_("Dump Kerberos PAC"),
3508 N_("net ads kerberos pac\n"
3509 " Dump Kerberos PAC")
3511 {NULL, NULL, 0, NULL, NULL}
3514 return net_run_function(c, argc, argv, "net ads kerberos", func);
3517 static int net_ads_setspn_list(struct net_context *c,
3518 int argc,
3519 const char **argv)
3521 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3522 ADS_STRUCT *ads = NULL;
3523 ADS_STATUS status;
3524 bool ok = false;
3525 int ret = -1;
3527 if (c->display_usage) {
3528 d_printf("%s\n%s",
3529 _("Usage:"),
3530 _("net ads setspn list <machinename>\n"));
3531 TALLOC_FREE(tmp_ctx);
3532 return -1;
3535 status = ads_startup(c, true, tmp_ctx, &ads);
3536 if (!ADS_ERR_OK(status)) {
3537 goto out;
3540 if (argc) {
3541 ok = ads_setspn_list(ads, argv[0]);
3542 } else {
3543 ok = ads_setspn_list(ads, lp_netbios_name());
3546 ret = ok ? 0 : -1;
3547 out:
3548 TALLOC_FREE(tmp_ctx);
3549 return ret;
3552 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3554 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3555 ADS_STRUCT *ads = NULL;
3556 ADS_STATUS status;
3557 bool ok = false;
3558 int ret = -1;
3560 if (c->display_usage || argc < 1) {
3561 d_printf("%s\n%s",
3562 _("Usage:"),
3563 _("net ads setspn add <machinename> SPN\n"));
3564 TALLOC_FREE(tmp_ctx);
3565 return -1;
3568 status = ads_startup(c, true, tmp_ctx, &ads);
3569 if (!ADS_ERR_OK(status)) {
3570 goto out;
3573 if (argc > 1) {
3574 ok = ads_setspn_add(ads, argv[0], argv[1]);
3575 } else {
3576 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3579 ret = ok ? 0 : -1;
3580 out:
3581 TALLOC_FREE(tmp_ctx);
3582 return ret;
3585 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3587 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3588 ADS_STRUCT *ads = NULL;
3589 ADS_STATUS status;
3590 bool ok = false;
3591 int ret = -1;
3593 if (c->display_usage || argc < 1) {
3594 d_printf("%s\n%s",
3595 _("Usage:"),
3596 _("net ads setspn delete <machinename> SPN\n"));
3597 TALLOC_FREE(tmp_ctx);
3598 return -1;
3601 status = ads_startup(c, true, tmp_ctx, &ads);
3602 if (!ADS_ERR_OK(status)) {
3603 goto out;
3606 if (argc > 1) {
3607 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3608 } else {
3609 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3612 ret = ok ? 0 : -1;
3613 out:
3614 TALLOC_FREE(tmp_ctx);
3615 return ret;
3618 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3620 struct functable func[] = {
3622 "list",
3623 net_ads_setspn_list,
3624 NET_TRANSPORT_ADS,
3625 N_("List Service Principal Names (SPN)"),
3626 N_("net ads setspn list machine\n"
3627 " List Service Principal Names (SPN)")
3630 "add",
3631 net_ads_setspn_add,
3632 NET_TRANSPORT_ADS,
3633 N_("Add Service Principal Names (SPN)"),
3634 N_("net ads setspn add machine spn\n"
3635 " Add Service Principal Names (SPN)")
3638 "delete",
3639 net_ads_setspn_delete,
3640 NET_TRANSPORT_ADS,
3641 N_("Delete Service Principal Names (SPN)"),
3642 N_("net ads setspn delete machine spn\n"
3643 " Delete Service Principal Names (SPN)")
3645 {NULL, NULL, 0, NULL, NULL}
3648 return net_run_function(c, argc, argv, "net ads setspn", func);
3651 static int net_ads_enctype_lookup_account(struct net_context *c,
3652 ADS_STRUCT *ads,
3653 const char *account,
3654 LDAPMessage **res,
3655 const char **enctype_str)
3657 const char *filter;
3658 const char *attrs[] = {
3659 "msDS-SupportedEncryptionTypes",
3660 NULL
3662 int count;
3663 int ret = -1;
3664 ADS_STATUS status;
3666 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3667 account);
3668 if (filter == NULL) {
3669 goto done;
3672 status = ads_search(ads, res, filter, attrs);
3673 if (!ADS_ERR_OK(status)) {
3674 d_printf(_("no account found with filter: %s\n"), filter);
3675 goto done;
3678 count = ads_count_replies(ads, *res);
3679 switch (count) {
3680 case 1:
3681 break;
3682 case 0:
3683 d_printf(_("no account found with filter: %s\n"), filter);
3684 goto done;
3685 default:
3686 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3687 goto done;
3690 if (enctype_str) {
3691 *enctype_str = ads_pull_string(ads, c, *res,
3692 "msDS-SupportedEncryptionTypes");
3693 if (*enctype_str == NULL) {
3694 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3695 goto done;
3699 ret = 0;
3700 done:
3701 return ret;
3704 static void net_ads_enctype_dump_enctypes(const char *username,
3705 const char *enctype_str)
3707 int enctypes = atoi(enctype_str);
3709 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3710 username, enctypes, enctypes);
3712 printf("[%s] 0x%08x DES-CBC-CRC\n",
3713 enctypes & ENC_CRC32 ? "X" : " ",
3714 ENC_CRC32);
3715 printf("[%s] 0x%08x DES-CBC-MD5\n",
3716 enctypes & ENC_RSA_MD5 ? "X" : " ",
3717 ENC_RSA_MD5);
3718 printf("[%s] 0x%08x RC4-HMAC\n",
3719 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3720 ENC_RC4_HMAC_MD5);
3721 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3722 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3723 ENC_HMAC_SHA1_96_AES128);
3724 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3725 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3726 ENC_HMAC_SHA1_96_AES256);
3727 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3728 enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3729 ENC_HMAC_SHA1_96_AES256_SK);
3730 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3731 enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3732 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3735 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3737 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3738 ADS_STATUS status;
3739 ADS_STRUCT *ads = NULL;
3740 LDAPMessage *res = NULL;
3741 const char *str = NULL;
3742 int ret = -1;
3744 if (c->display_usage || (argc < 1)) {
3745 d_printf( "%s\n"
3746 "net ads enctypes list\n"
3747 " %s\n",
3748 _("Usage:"),
3749 _("List supported enctypes"));
3750 TALLOC_FREE(tmp_ctx);
3751 return -1;
3754 status = ads_startup(c, false, tmp_ctx, &ads);
3755 if (!ADS_ERR_OK(status)) {
3756 goto out;
3759 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3760 if (ret) {
3761 goto out;
3764 net_ads_enctype_dump_enctypes(argv[0], str);
3766 ret = 0;
3767 out:
3768 ads_msgfree(ads, res);
3769 TALLOC_FREE(tmp_ctx);
3770 return ret;
3773 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3775 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3776 int ret = -1;
3777 ADS_STATUS status;
3778 ADS_STRUCT *ads = NULL;
3779 LDAPMessage *res = NULL;
3780 const char *etype_list_str = NULL;
3781 const char *dn = NULL;
3782 ADS_MODLIST mods = NULL;
3783 uint32_t etype_list;
3784 const char *str = NULL;
3786 if (c->display_usage || argc < 1) {
3787 d_printf( "%s\n"
3788 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3789 " %s\n",
3790 _("Usage:"),
3791 _("Set supported enctypes"));
3792 TALLOC_FREE(tmp_ctx);
3793 return -1;
3796 status = ads_startup(c, false, tmp_ctx, &ads);
3797 if (!ADS_ERR_OK(status)) {
3798 goto done;
3801 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3802 if (ret) {
3803 goto done;
3806 dn = ads_get_dn(ads, tmp_ctx, res);
3807 if (dn == NULL) {
3808 goto done;
3811 etype_list = 0;
3812 etype_list |= ENC_RC4_HMAC_MD5;
3813 etype_list |= ENC_HMAC_SHA1_96_AES128;
3814 etype_list |= ENC_HMAC_SHA1_96_AES256;
3816 if (argv[1] != NULL) {
3817 sscanf(argv[1], "%i", &etype_list);
3820 etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3821 if (!etype_list_str) {
3822 goto done;
3825 mods = ads_init_mods(tmp_ctx);
3826 if (!mods) {
3827 goto done;
3830 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3831 etype_list_str);
3832 if (!ADS_ERR_OK(status)) {
3833 goto done;
3836 status = ads_gen_mod(ads, dn, mods);
3837 if (!ADS_ERR_OK(status)) {
3838 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3839 ads_errstr(status));
3840 goto done;
3843 ads_msgfree(ads, res);
3844 res = NULL;
3846 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3847 if (ret) {
3848 goto done;
3851 net_ads_enctype_dump_enctypes(argv[0], str);
3853 ret = 0;
3854 done:
3855 ads_msgfree(ads, res);
3856 TALLOC_FREE(tmp_ctx);
3857 return ret;
3860 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3862 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3863 int ret = -1;
3864 ADS_STATUS status;
3865 ADS_STRUCT *ads = NULL;
3866 LDAPMessage *res = NULL;
3867 const char *dn = NULL;
3868 ADS_MODLIST mods = NULL;
3870 if (c->display_usage || argc < 1) {
3871 d_printf( "%s\n"
3872 "net ads enctypes delete <sAMAccountName>\n"
3873 " %s\n",
3874 _("Usage:"),
3875 _("Delete supported enctypes"));
3876 TALLOC_FREE(tmp_ctx);
3877 return -1;
3880 status = ads_startup(c, false, tmp_ctx, &ads);
3881 if (!ADS_ERR_OK(status)) {
3882 goto done;
3885 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3886 if (ret) {
3887 goto done;
3890 dn = ads_get_dn(ads, tmp_ctx, res);
3891 if (dn == NULL) {
3892 goto done;
3895 mods = ads_init_mods(tmp_ctx);
3896 if (!mods) {
3897 goto done;
3900 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3901 if (!ADS_ERR_OK(status)) {
3902 goto done;
3905 status = ads_gen_mod(ads, dn, mods);
3906 if (!ADS_ERR_OK(status)) {
3907 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3908 ads_errstr(status));
3909 goto done;
3912 ret = 0;
3914 done:
3915 ads_msgfree(ads, res);
3916 TALLOC_FREE(tmp_ctx);
3917 return ret;
3920 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3922 struct functable func[] = {
3924 "list",
3925 net_ads_enctypes_list,
3926 NET_TRANSPORT_ADS,
3927 N_("List the supported encryption types"),
3928 N_("net ads enctypes list\n"
3929 " List the supported encryption types")
3932 "set",
3933 net_ads_enctypes_set,
3934 NET_TRANSPORT_ADS,
3935 N_("Set the supported encryption types"),
3936 N_("net ads enctypes set\n"
3937 " Set the supported encryption types")
3940 "delete",
3941 net_ads_enctypes_delete,
3942 NET_TRANSPORT_ADS,
3943 N_("Delete the supported encryption types"),
3944 N_("net ads enctypes delete\n"
3945 " Delete the supported encryption types")
3948 {NULL, NULL, 0, NULL, NULL}
3951 return net_run_function(c, argc, argv, "net ads enctypes", func);
3955 int net_ads(struct net_context *c, int argc, const char **argv)
3957 struct functable func[] = {
3959 "info",
3960 net_ads_info,
3961 NET_TRANSPORT_ADS,
3962 N_("Display details on remote ADS server"),
3963 N_("net ads info\n"
3964 " Display details on remote ADS server")
3967 "join",
3968 net_ads_join,
3969 NET_TRANSPORT_ADS,
3970 N_("Join the local machine to ADS realm"),
3971 N_("net ads join\n"
3972 " Join the local machine to ADS realm")
3975 "testjoin",
3976 net_ads_testjoin,
3977 NET_TRANSPORT_ADS,
3978 N_("Validate machine account"),
3979 N_("net ads testjoin\n"
3980 " Validate machine account")
3983 "leave",
3984 net_ads_leave,
3985 NET_TRANSPORT_ADS,
3986 N_("Remove the local machine from ADS"),
3987 N_("net ads leave\n"
3988 " Remove the local machine from ADS")
3991 "status",
3992 net_ads_status,
3993 NET_TRANSPORT_ADS,
3994 N_("Display machine account details"),
3995 N_("net ads status\n"
3996 " Display machine account details")
3999 "user",
4000 net_ads_user,
4001 NET_TRANSPORT_ADS,
4002 N_("List/modify users"),
4003 N_("net ads user\n"
4004 " List/modify users")
4007 "group",
4008 net_ads_group,
4009 NET_TRANSPORT_ADS,
4010 N_("List/modify groups"),
4011 N_("net ads group\n"
4012 " List/modify groups")
4015 "dns",
4016 net_ads_dns,
4017 NET_TRANSPORT_ADS,
4018 N_("Issue dynamic DNS update"),
4019 N_("net ads dns\n"
4020 " Issue dynamic DNS update")
4023 "password",
4024 net_ads_password,
4025 NET_TRANSPORT_ADS,
4026 N_("Change user passwords"),
4027 N_("net ads password\n"
4028 " Change user passwords")
4031 "changetrustpw",
4032 net_ads_changetrustpw,
4033 NET_TRANSPORT_ADS,
4034 N_("Change trust account password"),
4035 N_("net ads changetrustpw\n"
4036 " Change trust account password")
4039 "printer",
4040 net_ads_printer,
4041 NET_TRANSPORT_ADS,
4042 N_("List/modify printer entries"),
4043 N_("net ads printer\n"
4044 " List/modify printer entries")
4047 "search",
4048 net_ads_search,
4049 NET_TRANSPORT_ADS,
4050 N_("Issue LDAP search using filter"),
4051 N_("net ads search\n"
4052 " Issue LDAP search using filter")
4055 "dn",
4056 net_ads_dn,
4057 NET_TRANSPORT_ADS,
4058 N_("Issue LDAP search by DN"),
4059 N_("net ads dn\n"
4060 " Issue LDAP search by DN")
4063 "sid",
4064 net_ads_sid,
4065 NET_TRANSPORT_ADS,
4066 N_("Issue LDAP search by SID"),
4067 N_("net ads sid\n"
4068 " Issue LDAP search by SID")
4071 "workgroup",
4072 net_ads_workgroup,
4073 NET_TRANSPORT_ADS,
4074 N_("Display workgroup name"),
4075 N_("net ads workgroup\n"
4076 " Display the workgroup name")
4079 "lookup",
4080 net_ads_lookup,
4081 NET_TRANSPORT_ADS,
4082 N_("Perform CLDAP query on DC"),
4083 N_("net ads lookup\n"
4084 " Find the ADS DC using CLDAP lookups")
4087 "keytab",
4088 net_ads_keytab,
4089 NET_TRANSPORT_ADS,
4090 N_("Manage local keytab file"),
4091 N_("net ads keytab\n"
4092 " Manage local keytab file")
4095 "setspn",
4096 net_ads_setspn,
4097 NET_TRANSPORT_ADS,
4098 N_("Manage Service Principal Names (SPN)s"),
4099 N_("net ads spnset\n"
4100 " Manage Service Principal Names (SPN)s")
4103 "gpo",
4104 net_ads_gpo,
4105 NET_TRANSPORT_ADS,
4106 N_("Manage group policy objects"),
4107 N_("net ads gpo\n"
4108 " Manage group policy objects")
4111 "kerberos",
4112 net_ads_kerberos,
4113 NET_TRANSPORT_ADS,
4114 N_("Manage kerberos keytab"),
4115 N_("net ads kerberos\n"
4116 " Manage kerberos keytab")
4119 "enctypes",
4120 net_ads_enctypes,
4121 NET_TRANSPORT_ADS,
4122 N_("List/modify supported encryption types"),
4123 N_("net ads enctypes\n"
4124 " List/modify enctypes")
4126 {NULL, NULL, 0, NULL, NULL}
4129 return net_run_function(c, argc, argv, "net ads", func);
4132 #else
4134 static int net_ads_noads(void)
4136 d_fprintf(stderr, _("ADS support not compiled in\n"));
4137 return -1;
4140 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4142 return net_ads_noads();
4145 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4147 return net_ads_noads();
4150 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4152 return net_ads_noads();
4155 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4157 return net_ads_noads();
4160 int net_ads_join(struct net_context *c, int argc, const char **argv)
4162 return net_ads_noads();
4165 int net_ads_user(struct net_context *c, int argc, const char **argv)
4167 return net_ads_noads();
4170 int net_ads_group(struct net_context *c, int argc, const char **argv)
4172 return net_ads_noads();
4175 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4177 return net_ads_noads();
4180 /* this one shouldn't display a message */
4181 int net_ads_check(struct net_context *c)
4183 return -1;
4186 int net_ads_check_our_domain(struct net_context *c)
4188 return -1;
4191 int net_ads(struct net_context *c, int argc, const char **argv)
4193 return net_ads_noads();
4196 #endif /* HAVE_ADS */