s3:libads: remove unused kdc_host and time_offset arguments to kerberos_set_password()
[Samba.git] / source3 / utils / net_ads.c
blob1144a31de7aab41c70c824641358e55572122949
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->config.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->config.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_SEAL);
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 = cli_credentials_get_password(c->creds);
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 status = ads_connect_cldap_only(ads);
857 if (!ADS_ERR_OK(status)) {
858 goto out;
861 ret = 0;
862 out:
863 TALLOC_FREE(tmp_ctx);
864 return ret;
867 int net_ads_check_our_domain(struct net_context *c)
869 return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
872 int net_ads_check(struct net_context *c)
874 return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
878 determine the netbios workgroup name for a domain
880 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
882 TALLOC_CTX *tmp_ctx = talloc_stackframe();
883 ADS_STRUCT *ads = NULL;
884 ADS_STATUS status;
885 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
886 bool ok = false;
887 int ret = -1;
889 if (c->display_usage) {
890 d_printf ("%s\n"
891 "net ads workgroup\n"
892 " %s\n",
893 _("Usage:"),
894 _("Print the workgroup name"));
895 TALLOC_FREE(tmp_ctx);
896 return -1;
899 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
900 if (!ADS_ERR_OK(status)) {
901 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
902 goto out;
905 if (!ads->config.realm) {
906 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
907 if (ads->config.realm == NULL) {
908 d_fprintf(stderr, _("Out of memory\n"));
909 goto out;
911 ads->ldap.port = 389;
914 ok = ads_cldap_netlogon_5(tmp_ctx,
915 &ads->ldap.ss, ads->server.realm, &reply);
916 if (!ok) {
917 d_fprintf(stderr, _("CLDAP query failed!\n"));
918 goto out;
921 d_printf(_("Workgroup: %s\n"), reply.domain_name);
923 ret = 0;
924 out:
925 TALLOC_FREE(tmp_ctx);
927 return ret;
932 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
934 char **disp_fields = (char **) data_area;
936 if (!field) { /* must be end of record */
937 if (disp_fields[0]) {
938 if (!strchr_m(disp_fields[0], '$')) {
939 if (disp_fields[1])
940 d_printf("%-21.21s %s\n",
941 disp_fields[0], disp_fields[1]);
942 else
943 d_printf("%s\n", disp_fields[0]);
946 SAFE_FREE(disp_fields[0]);
947 SAFE_FREE(disp_fields[1]);
948 return true;
950 if (!values) /* must be new field, indicate string field */
951 return true;
952 if (strcasecmp_m(field, "sAMAccountName") == 0) {
953 disp_fields[0] = SMB_STRDUP((char *) values[0]);
955 if (strcasecmp_m(field, "description") == 0)
956 disp_fields[1] = SMB_STRDUP((char *) values[0]);
957 return true;
960 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
962 return net_user_usage(c, argc, argv);
965 static int ads_user_add(struct net_context *c, int argc, const char **argv)
967 TALLOC_CTX *tmp_ctx = talloc_stackframe();
968 ADS_STRUCT *ads = NULL;
969 ADS_STATUS status;
970 char *upn, *userdn;
971 LDAPMessage *res=NULL;
972 int rc = -1;
973 char *ou_str = NULL;
975 if (argc < 1 || c->display_usage) {
976 TALLOC_FREE(tmp_ctx);
977 return net_ads_user_usage(c, argc, argv);
980 if (argc > 1) {
982 * We rely on ads_krb5_set_password() to
983 * set the password below.
985 * We could pass the password to
986 * ads_add_user_acct()
987 * and set the unicodePwd attribute there...
989 cli_credentials_set_kerberos_state(c->creds,
990 CRED_USE_KERBEROS_REQUIRED,
991 CRED_SPECIFIED);
994 status = ads_startup(c, false, tmp_ctx, &ads);
995 if (!ADS_ERR_OK(status)) {
996 goto done;
999 status = ads_find_user_acct(ads, &res, argv[0]);
1000 if (!ADS_ERR_OK(status)) {
1001 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
1002 goto done;
1005 if (ads_count_replies(ads, res)) {
1006 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
1007 argv[0]);
1008 goto done;
1011 if (c->opt_container) {
1012 ou_str = SMB_STRDUP(c->opt_container);
1013 } else {
1014 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1017 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
1018 if (!ADS_ERR_OK(status)) {
1019 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
1020 ads_errstr(status));
1021 goto done;
1024 /* if no password is to be set, we're done */
1025 if (argc == 1) {
1026 d_printf(_("User %s added\n"), argv[0]);
1027 rc = 0;
1028 goto done;
1031 /* try setting the password */
1032 upn = talloc_asprintf(tmp_ctx,
1033 "%s@%s",
1034 argv[0],
1035 ads->config.realm);
1036 if (upn == NULL) {
1037 goto done;
1040 status = ads_krb5_set_password(upn, argv[1]);
1041 if (ADS_ERR_OK(status)) {
1042 d_printf(_("User %s added\n"), argv[0]);
1043 rc = 0;
1044 goto done;
1046 TALLOC_FREE(upn);
1048 /* password didn't set, delete account */
1049 d_fprintf(stderr, _("Could not add user %s. "
1050 "Error setting password %s\n"),
1051 argv[0], ads_errstr(status));
1053 ads_msgfree(ads, res);
1054 res = NULL;
1056 status=ads_find_user_acct(ads, &res, argv[0]);
1057 if (ADS_ERR_OK(status)) {
1058 userdn = ads_get_dn(ads, tmp_ctx, res);
1059 ads_del_dn(ads, userdn);
1060 TALLOC_FREE(userdn);
1063 done:
1064 ads_msgfree(ads, res);
1065 SAFE_FREE(ou_str);
1066 TALLOC_FREE(tmp_ctx);
1067 return rc;
1070 static int ads_user_info(struct net_context *c, int argc, const char **argv)
1072 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1073 ADS_STRUCT *ads = NULL;
1074 ADS_STATUS status;
1075 LDAPMessage *res = NULL;
1076 int ret = -1;
1077 wbcErr wbc_status;
1078 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1079 char *searchstring = NULL;
1080 char **grouplist = NULL;
1081 char *primary_group = NULL;
1082 char *escaped_user = NULL;
1083 struct dom_sid primary_group_sid;
1084 uint32_t group_rid;
1085 enum wbcSidType type;
1087 if (argc < 1 || c->display_usage) {
1088 TALLOC_FREE(tmp_ctx);
1089 return net_ads_user_usage(c, argc, argv);
1092 escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1093 if (!escaped_user) {
1094 d_fprintf(stderr,
1095 _("ads_user_info: failed to escape user %s\n"),
1096 argv[0]);
1097 goto out;
1100 status = ads_startup(c, false, tmp_ctx, &ads);
1101 if (!ADS_ERR_OK(status)) {
1102 goto out;
1105 searchstring = talloc_asprintf(tmp_ctx,
1106 "(sAMAccountName=%s)",
1107 escaped_user);
1108 if (searchstring == NULL) {
1109 goto out;
1112 status = ads_search(ads, &res, searchstring, attrs);
1113 if (!ADS_ERR_OK(status)) {
1114 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1115 goto out;
1118 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1119 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1120 goto out;
1123 status = ads_domain_sid(ads, &primary_group_sid);
1124 if (!ADS_ERR_OK(status)) {
1125 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1126 goto out;
1129 sid_append_rid(&primary_group_sid, group_rid);
1131 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1132 NULL, /* don't look up domain */
1133 &primary_group,
1134 &type);
1135 if (!WBC_ERROR_IS_OK(wbc_status)) {
1136 d_fprintf(stderr, "wbcLookupSid: %s\n",
1137 wbcErrorString(wbc_status));
1138 goto out;
1141 d_printf("%s\n", primary_group);
1143 wbcFreeMemory(primary_group);
1145 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1146 (LDAPMessage *)res, "memberOf");
1148 if (grouplist) {
1149 int i;
1150 char **groupname;
1151 for (i=0;grouplist[i];i++) {
1152 groupname = ldap_explode_dn(grouplist[i], 1);
1153 d_printf("%s\n", groupname[0]);
1154 ldap_value_free(groupname);
1156 ldap_value_free(grouplist);
1159 ret = 0;
1160 out:
1161 TALLOC_FREE(escaped_user);
1162 TALLOC_FREE(searchstring);
1163 ads_msgfree(ads, res);
1164 TALLOC_FREE(tmp_ctx);
1165 return ret;
1168 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1170 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1171 ADS_STRUCT *ads = NULL;
1172 ADS_STATUS status;
1173 LDAPMessage *res = NULL;
1174 char *userdn = NULL;
1175 int ret = -1;
1177 if (argc < 1) {
1178 TALLOC_FREE(tmp_ctx);
1179 return net_ads_user_usage(c, argc, argv);
1182 status = ads_startup(c, false, tmp_ctx, &ads);
1183 if (!ADS_ERR_OK(status)) {
1184 goto out;
1187 status = ads_find_user_acct(ads, &res, argv[0]);
1188 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1189 d_printf(_("User %s does not exist.\n"), argv[0]);
1190 goto out;
1193 userdn = ads_get_dn(ads, tmp_ctx, res);
1194 if (userdn == NULL) {
1195 goto out;
1198 status = ads_del_dn(ads, userdn);
1199 if (!ADS_ERR_OK(status)) {
1200 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1201 ads_errstr(status));
1202 goto out;
1205 d_printf(_("User %s deleted\n"), argv[0]);
1207 ret = 0;
1208 out:
1209 ads_msgfree(ads, res);
1210 TALLOC_FREE(tmp_ctx);
1211 return ret;
1214 int net_ads_user(struct net_context *c, int argc, const char **argv)
1216 struct functable func[] = {
1218 "add",
1219 ads_user_add,
1220 NET_TRANSPORT_ADS,
1221 N_("Add an AD user"),
1222 N_("net ads user add\n"
1223 " Add an AD user")
1226 "info",
1227 ads_user_info,
1228 NET_TRANSPORT_ADS,
1229 N_("Display information about an AD user"),
1230 N_("net ads user info\n"
1231 " Display information about an AD user")
1234 "delete",
1235 ads_user_delete,
1236 NET_TRANSPORT_ADS,
1237 N_("Delete an AD user"),
1238 N_("net ads user delete\n"
1239 " Delete an AD user")
1241 {NULL, NULL, 0, NULL, NULL}
1243 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1244 ADS_STRUCT *ads = NULL;
1245 ADS_STATUS status;
1246 const char *shortattrs[] = {"sAMAccountName", NULL};
1247 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1248 char *disp_fields[2] = {NULL, NULL};
1249 int ret = -1;
1251 if (argc > 0) {
1252 TALLOC_FREE(tmp_ctx);
1253 return net_run_function(c, argc, argv, "net ads user", func);
1256 if (c->display_usage) {
1257 d_printf( "%s\n"
1258 "net ads user\n"
1259 " %s\n",
1260 _("Usage:"),
1261 _("List AD users"));
1262 net_display_usage_from_functable(func);
1263 TALLOC_FREE(tmp_ctx);
1264 return -1;
1267 status = ads_startup(c, false, tmp_ctx, &ads);
1268 if (!ADS_ERR_OK(status)) {
1269 goto out;
1272 if (c->opt_long_list_entries)
1273 d_printf(_("\nUser name Comment"
1274 "\n-----------------------------\n"));
1276 status = ads_do_search_all_fn(ads,
1277 ads->config.bind_path,
1278 LDAP_SCOPE_SUBTREE,
1279 "(objectCategory=user)",
1280 c->opt_long_list_entries ?
1281 longattrs : shortattrs,
1282 usergrp_display,
1283 disp_fields);
1284 if (!ADS_ERR_OK(status)) {
1285 goto out;
1288 ret = 0;
1289 out:
1290 TALLOC_FREE(tmp_ctx);
1291 return ret;
1294 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1296 return net_group_usage(c, argc, argv);
1299 static int ads_group_add(struct net_context *c, int argc, const char **argv)
1301 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1302 ADS_STRUCT *ads = NULL;
1303 ADS_STATUS status;
1304 LDAPMessage *res = NULL;
1305 int ret = -1;
1306 char *ou_str = NULL;
1308 if (argc < 1 || c->display_usage) {
1309 TALLOC_FREE(tmp_ctx);
1310 return net_ads_group_usage(c, argc, argv);
1313 status = ads_startup(c, false, tmp_ctx, &ads);
1314 if (!ADS_ERR_OK(status)) {
1315 goto out;
1318 status = ads_find_user_acct(ads, &res, argv[0]);
1319 if (!ADS_ERR_OK(status)) {
1320 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1321 goto out;
1324 if (ads_count_replies(ads, res)) {
1325 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1326 goto out;
1329 if (c->opt_container) {
1330 ou_str = SMB_STRDUP(c->opt_container);
1331 } else {
1332 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1335 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1336 if (!ADS_ERR_OK(status)) {
1337 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1338 ads_errstr(status));
1339 goto out;
1342 d_printf(_("Group %s added\n"), argv[0]);
1344 ret = 0;
1345 out:
1346 ads_msgfree(ads, res);
1347 SAFE_FREE(ou_str);
1348 TALLOC_FREE(tmp_ctx);
1349 return ret;
1352 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1354 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1355 ADS_STRUCT *ads = NULL;
1356 ADS_STATUS status;
1357 LDAPMessage *res = NULL;
1358 char *groupdn = NULL;
1359 int ret = -1;
1361 if (argc < 1 || c->display_usage) {
1362 TALLOC_FREE(tmp_ctx);
1363 return net_ads_group_usage(c, argc, argv);
1366 status = ads_startup(c, false, tmp_ctx, &ads);
1367 if (!ADS_ERR_OK(status)) {
1368 goto out;
1371 status = ads_find_user_acct(ads, &res, argv[0]);
1372 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1373 d_printf(_("Group %s does not exist.\n"), argv[0]);
1374 goto out;
1377 groupdn = ads_get_dn(ads, tmp_ctx, res);
1378 if (groupdn == NULL) {
1379 goto out;
1382 status = ads_del_dn(ads, groupdn);
1383 if (!ADS_ERR_OK(status)) {
1384 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1385 ads_errstr(status));
1386 goto out;
1388 d_printf(_("Group %s deleted\n"), argv[0]);
1390 ret = 0;
1391 out:
1392 ads_msgfree(ads, res);
1393 TALLOC_FREE(tmp_ctx);
1394 return ret;
1397 int net_ads_group(struct net_context *c, int argc, const char **argv)
1399 struct functable func[] = {
1401 "add",
1402 ads_group_add,
1403 NET_TRANSPORT_ADS,
1404 N_("Add an AD group"),
1405 N_("net ads group add\n"
1406 " Add an AD group")
1409 "delete",
1410 ads_group_delete,
1411 NET_TRANSPORT_ADS,
1412 N_("Delete an AD group"),
1413 N_("net ads group delete\n"
1414 " Delete an AD group")
1416 {NULL, NULL, 0, NULL, NULL}
1418 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1419 ADS_STRUCT *ads = NULL;
1420 ADS_STATUS status;
1421 const char *shortattrs[] = {"sAMAccountName", NULL};
1422 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1423 char *disp_fields[2] = {NULL, NULL};
1424 int ret = -1;
1426 if (argc >= 0) {
1427 TALLOC_FREE(tmp_ctx);
1428 return net_run_function(c, argc, argv, "net ads group", func);
1431 if (c->display_usage) {
1432 d_printf( "%s\n"
1433 "net ads group\n"
1434 " %s\n",
1435 _("Usage:"),
1436 _("List AD groups"));
1437 net_display_usage_from_functable(func);
1438 TALLOC_FREE(tmp_ctx);
1439 return -1;
1442 status = ads_startup(c, false, tmp_ctx, &ads);
1443 if (!ADS_ERR_OK(status)) {
1444 goto out;
1447 if (c->opt_long_list_entries)
1448 d_printf(_("\nGroup name Comment"
1449 "\n-----------------------------\n"));
1451 status = ads_do_search_all_fn(ads,
1452 ads->config.bind_path,
1453 LDAP_SCOPE_SUBTREE,
1454 "(objectCategory=group)",
1455 c->opt_long_list_entries ?
1456 longattrs : shortattrs,
1457 usergrp_display,
1458 disp_fields);
1459 if (!ADS_ERR_OK(status)) {
1460 goto out;
1463 ret = 0;
1464 out:
1465 TALLOC_FREE(tmp_ctx);
1466 return ret;
1469 static int net_ads_status(struct net_context *c, int argc, const char **argv)
1471 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1472 ADS_STRUCT *ads = NULL;
1473 ADS_STATUS status;
1474 LDAPMessage *res = NULL;
1475 int ret = -1;
1477 if (c->display_usage) {
1478 d_printf( "%s\n"
1479 "net ads status\n"
1480 " %s\n",
1481 _("Usage:"),
1482 _("Display machine account details"));
1483 TALLOC_FREE(tmp_ctx);
1484 return -1;
1487 net_warn_member_options();
1489 status = ads_startup(c, true, tmp_ctx, &ads);
1490 if (!ADS_ERR_OK(status)) {
1491 goto out;
1494 status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1495 if (!ADS_ERR_OK(status)) {
1496 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1497 ads_errstr(status));
1498 goto out;
1501 if (ads_count_replies(ads, res) == 0) {
1502 d_fprintf(stderr, _("No machine account for '%s' found\n"),
1503 lp_netbios_name());
1504 goto out;
1507 ads_dump(ads, res);
1509 ret = 0;
1510 out:
1511 ads_msgfree(ads, res);
1512 TALLOC_FREE(tmp_ctx);
1513 return ret;
1516 /*******************************************************************
1517 Leave an AD domain. Windows XP disables the machine account.
1518 We'll try the same. The old code would do an LDAP delete.
1519 That only worked using the machine creds because added the machine
1520 with full control to the computer object's ACL.
1521 *******************************************************************/
1523 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1525 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1526 struct libnet_UnjoinCtx *r = NULL;
1527 WERROR werr;
1528 int ret = -1;
1530 if (c->display_usage) {
1531 d_printf( "%s\n"
1532 "net ads leave [--keep-account]\n"
1533 " %s\n",
1534 _("Usage:"),
1535 _("Leave an AD domain"));
1536 TALLOC_FREE(tmp_ctx);
1537 return -1;
1540 if (!*lp_realm()) {
1541 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1542 TALLOC_FREE(tmp_ctx);
1543 return -1;
1546 if (!c->opt_kerberos) {
1547 use_in_memory_ccache();
1550 if (!c->msg_ctx) {
1551 d_fprintf(stderr, _("Could not initialise message context. "
1552 "Try running as root\n"));
1553 goto done;
1556 werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1557 if (!W_ERROR_IS_OK(werr)) {
1558 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1559 goto done;
1562 r->in.debug = true;
1563 r->in.dc_name = c->opt_host;
1564 r->in.domain_name = lp_realm();
1565 r->in.admin_credentials = c->creds;
1566 r->in.modify_config = lp_config_backend_is_registry();
1568 /* Try to delete it, but if that fails, disable it. The
1569 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1570 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1571 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1572 if (c->opt_keep_account) {
1573 r->in.delete_machine_account = false;
1574 } else {
1575 r->in.delete_machine_account = true;
1578 r->in.msg_ctx = c->msg_ctx;
1580 werr = libnet_Unjoin(tmp_ctx, r);
1581 if (!W_ERROR_IS_OK(werr)) {
1582 d_printf(_("Failed to leave domain: %s\n"),
1583 r->out.error_string ? r->out.error_string :
1584 get_friendly_werror_msg(werr));
1585 goto done;
1588 if (r->out.deleted_machine_account) {
1589 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1590 r->in.machine_name, r->out.dns_domain_name);
1591 ret = 0;
1592 goto done;
1595 /* We couldn't delete it - see if the disable succeeded. */
1596 if (r->out.disabled_machine_account) {
1597 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1598 r->in.machine_name, r->out.dns_domain_name);
1599 ret = 0;
1600 goto done;
1603 /* Based on what we requested, we shouldn't get here, but if
1604 we did, it means the secrets were removed, and therefore
1605 we have left the domain */
1606 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1607 r->in.machine_name, r->out.dns_domain_name);
1609 ret = 0;
1610 done:
1611 TALLOC_FREE(tmp_ctx);
1612 return ret;
1615 static ADS_STATUS net_ads_join_ok(struct net_context *c)
1617 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1618 ADS_STRUCT *ads = NULL;
1619 ADS_STATUS status;
1620 fstring dc_name;
1621 struct sockaddr_storage dcip;
1623 if (!secrets_init()) {
1624 DEBUG(1,("Failed to initialise secrets database\n"));
1625 TALLOC_FREE(tmp_ctx);
1626 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1629 net_warn_member_options();
1631 net_use_krb_machine_account(c);
1633 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1635 status = ads_startup(c, true, tmp_ctx, &ads);
1636 if (!ADS_ERR_OK(status)) {
1637 goto out;
1640 status = ADS_ERROR_NT(NT_STATUS_OK);
1641 out:
1642 TALLOC_FREE(tmp_ctx);
1643 return status;
1647 check that an existing join is OK
1649 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1651 ADS_STATUS status;
1652 use_in_memory_ccache();
1654 if (c->display_usage) {
1655 d_printf( "%s\n"
1656 "net ads testjoin\n"
1657 " %s\n",
1658 _("Usage:"),
1659 _("Test if the existing join is ok"));
1660 return -1;
1663 net_warn_member_options();
1665 /* Display success or failure */
1666 status = net_ads_join_ok(c);
1667 if (!ADS_ERR_OK(status)) {
1668 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1669 get_friendly_nt_error_msg(ads_ntstatus(status)));
1670 return -1;
1673 printf(_("Join is OK\n"));
1674 return 0;
1677 /*******************************************************************
1678 Simple config checks before beginning the join
1679 ********************************************************************/
1681 static WERROR check_ads_config( void )
1683 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1684 d_printf(_("Host is not configured as a member server.\n"));
1685 return WERR_INVALID_DOMAIN_ROLE;
1688 if (strlen(lp_netbios_name()) > 15) {
1689 d_printf(_("Our netbios name can be at most 15 chars long, "
1690 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1691 (unsigned int)strlen(lp_netbios_name()));
1692 return WERR_INVALID_COMPUTERNAME;
1695 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1696 d_fprintf(stderr, _("realm must be set in %s for ADS "
1697 "join to succeed.\n"), get_dyn_CONFIGFILE());
1698 return WERR_INVALID_PARAMETER;
1701 return WERR_OK;
1704 /*******************************************************************
1705 ********************************************************************/
1707 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1709 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1710 "Valid options:\n"));
1711 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1712 " The default is in the form netbiosname.dnsdomain\n"));
1713 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1714 " The default UPN is in the form host/netbiosname@REALM.\n"));
1715 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1716 " The OU string read from top to bottom without RDNs\n"
1717 " and delimited by a '/'.\n"
1718 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1719 " NB: A backslash '\\' is used as escape at multiple\n"
1720 " levels and may need to be doubled or even\n"
1721 " quadrupled. It is not used as a separator.\n"));
1722 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1723 " the join. The default password is random.\n"));
1724 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1725 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1726 " NB: osName and osVer must be specified together for\n"
1727 " either to take effect. The operatingSystemService\n"
1728 " attribute is then also set along with the two\n"
1729 " other attributes.\n"));
1730 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1731 " during the join.\n"
1732 " NB: If not specified then by default the samba\n"
1733 " version string is used instead.\n"));
1734 return -1;
1738 int net_ads_join(struct net_context *c, int argc, const char **argv)
1740 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1741 struct libnet_JoinCtx *r = NULL;
1742 const char *domain = lp_realm();
1743 WERROR werr = WERR_NERR_SETUPNOTJOINED;
1744 bool createupn = false;
1745 const char *dnshostname = NULL;
1746 const char *machineupn = NULL;
1747 const char *machine_password = NULL;
1748 const char *create_in_ou = NULL;
1749 int i;
1750 const char *os_name = NULL;
1751 const char *os_version = NULL;
1752 const char *os_servicepack = NULL;
1753 bool modify_config = lp_config_backend_is_registry();
1754 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1755 int ret = -1;
1757 if (c->display_usage) {
1758 TALLOC_FREE(tmp_ctx);
1759 return net_ads_join_usage(c, argc, argv);
1762 net_warn_member_options();
1764 if (!modify_config) {
1765 werr = check_ads_config();
1766 if (!W_ERROR_IS_OK(werr)) {
1767 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1768 goto fail;
1772 if (!c->opt_kerberos) {
1773 use_in_memory_ccache();
1776 werr = libnet_init_JoinCtx(tmp_ctx, &r);
1777 if (!W_ERROR_IS_OK(werr)) {
1778 goto fail;
1781 /* process additional command line args */
1783 for ( i=0; i<argc; i++ ) {
1784 if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1785 dnshostname = get_string_param(argv[i]);
1787 else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1788 createupn = true;
1789 machineupn = get_string_param(argv[i]);
1791 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1792 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1793 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1794 werr = WERR_INVALID_PARAMETER;
1795 goto fail;
1798 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1799 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1800 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1801 werr = WERR_INVALID_PARAMETER;
1802 goto fail;
1805 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1806 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1807 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1808 werr = WERR_INVALID_PARAMETER;
1809 goto fail;
1812 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1813 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1814 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1815 werr = WERR_INVALID_PARAMETER;
1816 goto fail;
1819 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1820 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1821 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1822 werr = WERR_INVALID_PARAMETER;
1823 goto fail;
1825 } else {
1826 domain = argv[i];
1827 if (strchr(domain, '.') == NULL) {
1828 domain_name_type = JoinDomNameTypeUnknown;
1829 } else {
1830 domain_name_type = JoinDomNameTypeDNS;
1835 if (!*domain) {
1836 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1837 werr = WERR_INVALID_PARAMETER;
1838 goto fail;
1841 if (!c->msg_ctx) {
1842 d_fprintf(stderr, _("Could not initialise message context. "
1843 "Try running as root\n"));
1844 werr = WERR_ACCESS_DENIED;
1845 goto fail;
1848 /* Do the domain join here */
1850 r->in.domain_name = domain;
1851 r->in.domain_name_type = domain_name_type;
1852 r->in.create_upn = createupn;
1853 r->in.upn = machineupn;
1854 r->in.dnshostname = dnshostname;
1855 r->in.account_ou = create_in_ou;
1856 r->in.os_name = os_name;
1857 r->in.os_version = os_version;
1858 r->in.os_servicepack = os_servicepack;
1859 r->in.dc_name = c->opt_host;
1860 r->in.admin_credentials = c->creds;
1861 r->in.machine_password = machine_password;
1862 r->in.debug = true;
1863 r->in.modify_config = modify_config;
1864 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1865 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1866 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1867 r->in.msg_ctx = c->msg_ctx;
1869 werr = libnet_Join(tmp_ctx, r);
1870 if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1871 strequal(domain, lp_realm())) {
1872 r->in.domain_name = lp_workgroup();
1873 r->in.domain_name_type = JoinDomNameTypeNBT;
1874 werr = libnet_Join(tmp_ctx, r);
1876 if (!W_ERROR_IS_OK(werr)) {
1877 goto fail;
1880 /* Check the short name of the domain */
1882 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1883 d_printf(_("The workgroup in %s does not match the short\n"
1884 "domain name obtained from the server.\n"
1885 "Using the name [%s] from the server.\n"
1886 "You should set \"workgroup = %s\" in %s.\n"),
1887 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1888 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1891 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1893 if (r->out.dns_domain_name) {
1894 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1895 r->out.dns_domain_name);
1896 } else {
1897 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1898 r->out.netbios_domain_name);
1901 /* print out informative error string in case there is one */
1902 if (r->out.error_string != NULL) {
1903 d_printf("%s\n", r->out.error_string);
1907 * We try doing the dns update (if it was compiled in
1908 * and if it was not disabled on the command line).
1909 * If the dns update fails, we still consider the join
1910 * operation as succeeded if we came this far.
1912 if (!c->opt_no_dns_updates) {
1913 net_ads_join_dns_updates(c, tmp_ctx, r);
1916 ret = 0;
1918 fail:
1919 if (ret != 0) {
1920 /* issue an overall failure message at the end. */
1921 d_printf(_("Failed to join domain: %s\n"),
1922 r && r->out.error_string ? r->out.error_string :
1923 get_friendly_werror_msg(werr));
1926 TALLOC_FREE(tmp_ctx);
1928 return ret;
1931 /*******************************************************************
1932 ********************************************************************/
1934 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1936 #if defined(HAVE_KRB5)
1937 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1938 ADS_STRUCT *ads = NULL;
1939 ADS_STATUS status;
1940 NTSTATUS ntstatus;
1941 const char *hostname = NULL;
1942 const char **addrs_list = NULL;
1943 struct sockaddr_storage *addrs = NULL;
1944 int num_addrs = 0;
1945 int count;
1946 int ret = -1;
1948 #ifdef DEVELOPER
1949 talloc_enable_leak_report();
1950 #endif
1952 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1953 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1954 "detection of addresses in a clustered "
1955 "setup.\n"));
1956 c->display_usage = true;
1959 if (c->display_usage) {
1960 d_printf( "%s\n"
1961 "net ads dns register [hostname [IP [IP...]]] "
1962 "[--force] [--dns-ttl TTL]\n"
1963 " %s\n",
1964 _("Usage:"),
1965 _("Register hostname with DNS\n"));
1966 TALLOC_FREE(tmp_ctx);
1967 return -1;
1970 if (argc >= 1) {
1971 hostname = argv[0];
1974 if (argc > 1) {
1975 num_addrs = argc - 1;
1976 addrs_list = &argv[1];
1977 } else if (lp_clustering()) {
1978 addrs_list = lp_cluster_addresses();
1979 num_addrs = str_list_length(addrs_list);
1982 if (num_addrs > 0) {
1983 addrs = talloc_zero_array(tmp_ctx,
1984 struct sockaddr_storage,
1985 num_addrs);
1986 if (addrs == NULL) {
1987 d_fprintf(stderr, _("Error allocating memory!\n"));
1988 goto out;
1992 for (count = 0; count < num_addrs; count++) {
1993 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1994 d_fprintf(stderr, "%s '%s'.\n",
1995 _("Cannot interpret address"),
1996 addrs_list[count]);
1997 goto out;
2001 status = ads_startup(c, true, tmp_ctx, &ads);
2002 if ( !ADS_ERR_OK(status) ) {
2003 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2004 goto out;
2007 ntstatus = net_update_dns_ext(c,
2008 tmp_ctx,
2009 ads,
2010 c->creds,
2011 hostname,
2012 addrs,
2013 num_addrs,
2014 false);
2015 if (!NT_STATUS_IS_OK(ntstatus)) {
2016 d_fprintf( stderr, _("DNS update failed!\n") );
2017 goto out;
2020 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
2022 ret = 0;
2023 out:
2024 TALLOC_FREE(tmp_ctx);
2026 return ret;
2027 #else
2028 d_fprintf(stderr,
2029 _("DNS update support not enabled at compile time!\n"));
2030 return -1;
2031 #endif
2034 static int net_ads_dns_unregister(struct net_context *c,
2035 int argc,
2036 const char **argv)
2038 #if defined(HAVE_KRB5)
2039 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2040 ADS_STRUCT *ads = NULL;
2041 ADS_STATUS status;
2042 NTSTATUS ntstatus;
2043 const char *hostname = NULL;
2044 int ret = -1;
2046 #ifdef DEVELOPER
2047 talloc_enable_leak_report();
2048 #endif
2050 if (argc != 1) {
2051 c->display_usage = true;
2054 if (c->display_usage) {
2055 d_printf( "%s\n"
2056 "net ads dns unregister [hostname]\n"
2057 " %s\n",
2058 _("Usage:"),
2059 _("Remove all IP Address entries for a given\n"
2060 " hostname from the Active Directory server.\n"));
2061 TALLOC_FREE(tmp_ctx);
2062 return -1;
2065 /* Get the hostname for un-registering */
2066 hostname = argv[0];
2068 status = ads_startup(c, true, tmp_ctx, &ads);
2069 if ( !ADS_ERR_OK(status) ) {
2070 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2071 goto out;
2074 ntstatus = net_update_dns_ext(c,
2075 tmp_ctx,
2076 ads,
2077 c->creds,
2078 hostname,
2079 NULL,
2081 true);
2082 if (!NT_STATUS_IS_OK(ntstatus)) {
2083 d_fprintf( stderr, _("DNS update failed!\n") );
2084 goto out;
2087 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2089 ret = 0;
2090 out:
2091 TALLOC_FREE(tmp_ctx);
2093 return ret;
2094 #else
2095 d_fprintf(stderr,
2096 _("DNS update support not enabled at compile time!\n"));
2097 return -1;
2098 #endif
2102 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2104 size_t num_names = 0;
2105 char **hostnames = NULL;
2106 size_t i = 0;
2107 struct samba_sockaddr *addrs = NULL;
2108 NTSTATUS status;
2110 if (argc != 1 || c->display_usage) {
2111 d_printf( "%s\n"
2112 " %s\n"
2113 " %s\n",
2114 _("Usage:"),
2115 _("net ads dns async <name>\n"),
2116 _(" Async look up hostname from the DNS server\n"
2117 " hostname\tName to look up\n"));
2118 return -1;
2121 status = ads_dns_lookup_a(talloc_tos(),
2122 argv[0],
2123 &num_names,
2124 &hostnames,
2125 &addrs);
2126 if (!NT_STATUS_IS_OK(status)) {
2127 d_printf("Looking up A record for %s got error %s\n",
2128 argv[0],
2129 nt_errstr(status));
2130 return -1;
2132 d_printf("Async A record lookup - got %u names for %s\n",
2133 (unsigned int)num_names,
2134 argv[0]);
2135 for (i = 0; i < num_names; i++) {
2136 char addr_buf[INET6_ADDRSTRLEN];
2137 print_sockaddr(addr_buf,
2138 sizeof(addr_buf),
2139 &addrs[i].u.ss);
2140 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2141 (unsigned int)i,
2142 hostnames[i],
2143 addr_buf);
2146 #if defined(HAVE_IPV6)
2147 status = ads_dns_lookup_aaaa(talloc_tos(),
2148 argv[0],
2149 &num_names,
2150 &hostnames,
2151 &addrs);
2152 if (!NT_STATUS_IS_OK(status)) {
2153 d_printf("Looking up AAAA record for %s got error %s\n",
2154 argv[0],
2155 nt_errstr(status));
2156 return -1;
2158 d_printf("Async AAAA record lookup - got %u names for %s\n",
2159 (unsigned int)num_names,
2160 argv[0]);
2161 for (i = 0; i < num_names; i++) {
2162 char addr_buf[INET6_ADDRSTRLEN];
2163 print_sockaddr(addr_buf,
2164 sizeof(addr_buf),
2165 &addrs[i].u.ss);
2166 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2167 (unsigned int)i,
2168 hostnames[i],
2169 addr_buf);
2171 #endif
2172 return 0;
2176 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2178 struct functable func[] = {
2180 "register",
2181 net_ads_dns_register,
2182 NET_TRANSPORT_ADS,
2183 N_("Add host dns entry to AD"),
2184 N_("net ads dns register\n"
2185 " Add host dns entry to AD")
2188 "unregister",
2189 net_ads_dns_unregister,
2190 NET_TRANSPORT_ADS,
2191 N_("Remove host dns entry from AD"),
2192 N_("net ads dns unregister\n"
2193 " Remove host dns entry from AD")
2196 "async",
2197 net_ads_dns_async,
2198 NET_TRANSPORT_ADS,
2199 N_("Look up host"),
2200 N_("net ads dns async\n"
2201 " Look up host using async DNS")
2203 {NULL, NULL, 0, NULL, NULL}
2206 return net_run_function(c, argc, argv, "net ads dns", func);
2209 /*******************************************************************
2210 ********************************************************************/
2212 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2214 d_printf(_(
2215 "\nnet ads printer search <printer>"
2216 "\n\tsearch for a printer in the directory\n"
2217 "\nnet ads printer info <printer> <server>"
2218 "\n\tlookup info in directory for printer on server"
2219 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2220 "\nnet ads printer publish <printername>"
2221 "\n\tpublish printer in directory"
2222 "\n\t(note: printer name is required)\n"
2223 "\nnet ads printer remove <printername>"
2224 "\n\tremove printer from directory"
2225 "\n\t(note: printer name is required)\n"));
2226 return -1;
2229 /*******************************************************************
2230 ********************************************************************/
2232 static int net_ads_printer_search(struct net_context *c,
2233 int argc,
2234 const char **argv)
2236 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2237 ADS_STRUCT *ads = NULL;
2238 ADS_STATUS status;
2239 LDAPMessage *res = NULL;
2240 int ret = -1;
2242 if (c->display_usage) {
2243 d_printf( "%s\n"
2244 "net ads printer search\n"
2245 " %s\n",
2246 _("Usage:"),
2247 _("List printers in the AD"));
2248 TALLOC_FREE(tmp_ctx);
2249 return -1;
2252 status = ads_startup(c, false, tmp_ctx, &ads);
2253 if (!ADS_ERR_OK(status)) {
2254 goto out;
2257 status = ads_find_printers(ads, &res);
2258 if (!ADS_ERR_OK(status)) {
2259 d_fprintf(stderr, _("ads_find_printer: %s\n"),
2260 ads_errstr(status));
2261 goto out;
2264 if (ads_count_replies(ads, res) == 0) {
2265 d_fprintf(stderr, _("No results found\n"));
2266 goto out;
2269 ads_dump(ads, res);
2271 ret = 0;
2272 out:
2273 ads_msgfree(ads, res);
2274 TALLOC_FREE(tmp_ctx);
2275 return ret;
2278 static int net_ads_printer_info(struct net_context *c,
2279 int argc,
2280 const char **argv)
2282 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2283 ADS_STRUCT *ads = NULL;
2284 ADS_STATUS status;
2285 const char *servername = NULL;
2286 const char *printername = NULL;
2287 LDAPMessage *res = NULL;
2288 int ret = -1;
2290 if (c->display_usage) {
2291 d_printf("%s\n%s",
2292 _("Usage:"),
2293 _("net ads printer info [printername [servername]]\n"
2294 " Display printer info from AD\n"
2295 " printername\tPrinter name or wildcard\n"
2296 " servername\tName of the print server\n"));
2297 TALLOC_FREE(tmp_ctx);
2298 return -1;
2301 status = ads_startup(c, false, tmp_ctx, &ads);
2302 if (!ADS_ERR_OK(status)) {
2303 goto out;
2306 if (argc > 0) {
2307 printername = argv[0];
2308 } else {
2309 printername = "*";
2312 if (argc > 1) {
2313 servername = argv[1];
2314 } else {
2315 servername = lp_netbios_name();
2318 status = ads_find_printer_on_server(ads, &res, printername, servername);
2319 if (!ADS_ERR_OK(status)) {
2320 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2321 servername, ads_errstr(status));
2322 goto out;
2325 if (ads_count_replies(ads, res) == 0) {
2326 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2327 goto out;
2330 ads_dump(ads, res);
2332 ret = 0;
2333 out:
2334 ads_msgfree(ads, res);
2335 TALLOC_FREE(tmp_ctx);
2336 return ret;
2339 static int net_ads_printer_publish(struct net_context *c,
2340 int argc,
2341 const char **argv)
2343 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2344 ADS_STRUCT *ads = NULL;
2345 ADS_STATUS status;
2346 const char *servername = NULL;
2347 const char *printername = NULL;
2348 struct cli_state *cli = NULL;
2349 struct rpc_pipe_client *pipe_hnd = NULL;
2350 struct sockaddr_storage server_ss = { 0 };
2351 NTSTATUS nt_status;
2352 ADS_MODLIST mods = NULL;
2353 char *prt_dn = NULL;
2354 char *srv_dn = NULL;
2355 char **srv_cn = NULL;
2356 char *srv_cn_escaped = NULL;
2357 char *printername_escaped = NULL;
2358 LDAPMessage *res = NULL;
2359 bool ok;
2360 int ret = -1;
2362 if (argc < 1 || c->display_usage) {
2363 d_printf("%s\n%s",
2364 _("Usage:"),
2365 _("net ads printer publish <printername> [servername]\n"
2366 " Publish printer in AD\n"
2367 " printername\tName of the printer\n"
2368 " servername\tName of the print server\n"));
2369 TALLOC_FREE(tmp_ctx);
2370 return -1;
2373 mods = ads_init_mods(tmp_ctx);
2374 if (mods == NULL) {
2375 d_fprintf(stderr, _("Out of memory\n"));
2376 goto out;
2379 status = ads_startup(c, true, tmp_ctx, &ads);
2380 if (!ADS_ERR_OK(status)) {
2381 goto out;
2384 printername = argv[0];
2386 if (argc == 2) {
2387 servername = argv[1];
2388 } else {
2389 servername = lp_netbios_name();
2392 /* Get printer data from SPOOLSS */
2394 ok = resolve_name(servername, &server_ss, 0x20, false);
2395 if (!ok) {
2396 d_fprintf(stderr, _("Could not find server %s\n"),
2397 servername);
2398 goto out;
2401 cli_credentials_set_kerberos_state(c->creds,
2402 CRED_USE_KERBEROS_REQUIRED,
2403 CRED_SPECIFIED);
2405 nt_status = cli_full_connection_creds(c,
2406 &cli,
2407 lp_netbios_name(),
2408 servername,
2409 &server_ss,
2411 "IPC$",
2412 "IPC",
2413 c->creds,
2414 CLI_FULL_CONNECTION_IPC);
2416 if (NT_STATUS_IS_ERR(nt_status)) {
2417 d_fprintf(stderr, _("Unable to open a connection to %s to "
2418 "obtain data for %s\n"),
2419 servername, printername);
2420 goto out;
2423 /* Publish on AD server */
2425 ads_find_machine_acct(ads, &res, servername);
2427 if (ads_count_replies(ads, res) == 0) {
2428 d_fprintf(stderr, _("Could not find machine account for server "
2429 "%s\n"),
2430 servername);
2431 goto out;
2434 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2435 srv_cn = ldap_explode_dn(srv_dn, 1);
2437 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2438 printername_escaped = escape_rdn_val_string_alloc(printername);
2439 if (!srv_cn_escaped || !printername_escaped) {
2440 SAFE_FREE(srv_cn_escaped);
2441 SAFE_FREE(printername_escaped);
2442 d_fprintf(stderr, _("Internal error, out of memory!"));
2443 goto out;
2446 prt_dn = talloc_asprintf(tmp_ctx,
2447 "cn=%s-%s,%s",
2448 srv_cn_escaped,
2449 printername_escaped,
2450 srv_dn);
2451 if (prt_dn == NULL) {
2452 SAFE_FREE(srv_cn_escaped);
2453 SAFE_FREE(printername_escaped);
2454 d_fprintf(stderr, _("Internal error, out of memory!"));
2455 goto out;
2458 SAFE_FREE(srv_cn_escaped);
2459 SAFE_FREE(printername_escaped);
2461 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2462 if (!NT_STATUS_IS_OK(nt_status)) {
2463 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2464 servername);
2465 goto out;
2468 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2469 tmp_ctx,
2470 &mods,
2471 printername))) {
2472 goto out;
2475 status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2476 if (!ADS_ERR_OK(status)) {
2477 d_fprintf(stderr, "ads_publish_printer: %s\n",
2478 ads_errstr(status));
2479 goto out;
2482 d_printf("published printer\n");
2484 ret = 0;
2485 out:
2486 talloc_destroy(tmp_ctx);
2488 return ret;
2491 static int net_ads_printer_remove(struct net_context *c,
2492 int argc,
2493 const char **argv)
2495 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2496 ADS_STRUCT *ads = NULL;
2497 ADS_STATUS status;
2498 const char *servername = NULL;
2499 char *prt_dn = NULL;
2500 LDAPMessage *res = NULL;
2501 int ret = -1;
2503 if (argc < 1 || c->display_usage) {
2504 d_printf("%s\n%s",
2505 _("Usage:"),
2506 _("net ads printer remove <printername> [servername]\n"
2507 " Remove a printer from the AD\n"
2508 " printername\tName of the printer\n"
2509 " servername\tName of the print server\n"));
2510 TALLOC_FREE(tmp_ctx);
2511 return -1;
2514 status = ads_startup(c, true, tmp_ctx, &ads);
2515 if (!ADS_ERR_OK(status)) {
2516 goto out;
2519 if (argc > 1) {
2520 servername = argv[1];
2521 } else {
2522 servername = lp_netbios_name();
2525 status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2526 if (!ADS_ERR_OK(status)) {
2527 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2528 ads_errstr(status));
2529 goto out;
2532 if (ads_count_replies(ads, res) == 0) {
2533 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2534 goto out;
2537 prt_dn = ads_get_dn(ads, tmp_ctx, res);
2538 if (prt_dn == NULL) {
2539 d_fprintf(stderr, _("Out of memory\n"));
2540 goto out;
2543 status = ads_del_dn(ads, prt_dn);
2544 if (!ADS_ERR_OK(status)) {
2545 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2546 goto out;
2549 ret = 0;
2550 out:
2551 ads_msgfree(ads, res);
2552 TALLOC_FREE(tmp_ctx);
2553 return ret;
2556 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2558 struct functable func[] = {
2560 "search",
2561 net_ads_printer_search,
2562 NET_TRANSPORT_ADS,
2563 N_("Search for a printer"),
2564 N_("net ads printer search\n"
2565 " Search for a printer")
2568 "info",
2569 net_ads_printer_info,
2570 NET_TRANSPORT_ADS,
2571 N_("Display printer information"),
2572 N_("net ads printer info\n"
2573 " Display printer information")
2576 "publish",
2577 net_ads_printer_publish,
2578 NET_TRANSPORT_ADS,
2579 N_("Publish a printer"),
2580 N_("net ads printer publish\n"
2581 " Publish a printer")
2584 "remove",
2585 net_ads_printer_remove,
2586 NET_TRANSPORT_ADS,
2587 N_("Delete a printer"),
2588 N_("net ads printer remove\n"
2589 " Delete a printer")
2591 {NULL, NULL, 0, NULL, NULL}
2594 return net_run_function(c, argc, argv, "net ads printer", func);
2598 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2600 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2601 ADS_STRUCT *ads = NULL;
2602 const char *auth_principal = cli_credentials_get_username(c->creds);
2603 const char *auth_password = cli_credentials_get_password(c->creds);
2604 const char *realm = NULL;
2605 char *new_password = NULL;
2606 char *chr = NULL;
2607 char *prompt = NULL;
2608 const char *user = NULL;
2609 char pwd[256] = {0};
2610 ADS_STATUS status;
2611 int ret = 0;
2613 if (c->display_usage) {
2614 d_printf("%s\n%s",
2615 _("Usage:"),
2616 _("net ads password <username>\n"
2617 " Change password for user\n"
2618 " username\tName of user to change password for\n"));
2619 TALLOC_FREE(tmp_ctx);
2620 return -1;
2623 if (auth_principal == NULL || auth_password == NULL) {
2624 d_fprintf(stderr, _("You must supply an administrator "
2625 "username/password\n"));
2626 TALLOC_FREE(tmp_ctx);
2627 return -1;
2630 if (argc < 1) {
2631 d_fprintf(stderr, _("ERROR: You must say which username to "
2632 "change password for\n"));
2633 TALLOC_FREE(tmp_ctx);
2634 return -1;
2637 if (strchr_m(argv[0], '@')) {
2638 user = talloc_strdup(tmp_ctx, argv[0]);
2639 } else {
2640 user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2642 if (user == NULL) {
2643 d_fprintf(stderr, _("Out of memory\n"));
2644 goto out;
2647 use_in_memory_ccache();
2648 chr = strchr_m(auth_principal, '@');
2649 if (chr) {
2650 realm = ++chr;
2651 } else {
2652 realm = lp_realm();
2655 /* use the realm so we can eventually change passwords for users
2656 in realms other than default */
2657 ads = ads_init(tmp_ctx,
2658 realm,
2659 c->opt_workgroup,
2660 c->opt_host,
2661 ADS_SASL_PLAIN);
2662 if (ads == NULL) {
2663 goto out;
2666 /* we don't actually need a full connect, but it's the easy way to
2667 fill in the KDC's address */
2668 ads->auth.flags |= ADS_AUTH_GENERATE_KRB5_CONFIG;
2669 ads_connect_cldap_only(ads);
2671 if (!ads->config.realm) {
2672 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2673 goto out;
2676 if (argv[1] != NULL) {
2677 new_password = talloc_strdup(tmp_ctx, argv[1]);
2678 } else {
2679 int rc;
2681 prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2682 if (prompt == NULL) {
2683 d_fprintf(stderr, _("Out of memory\n"));
2684 goto out;
2687 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2688 if (rc < 0) {
2689 goto out;
2691 new_password = talloc_strdup(tmp_ctx, pwd);
2692 memset(pwd, '\0', sizeof(pwd));
2695 if (new_password == NULL) {
2696 d_fprintf(stderr, _("Out of memory\n"));
2697 goto out;
2700 status = kerberos_set_password(auth_principal,
2701 auth_password,
2702 user,
2703 new_password);
2704 memset(new_password, '\0', strlen(new_password));
2705 if (!ADS_ERR_OK(status)) {
2706 d_fprintf(stderr, _("Password change failed: %s\n"),
2707 ads_errstr(status));
2708 goto out;
2711 d_printf(_("Password change for %s completed.\n"), user);
2713 ret = 0;
2714 out:
2715 TALLOC_FREE(tmp_ctx);
2716 return ret;
2719 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2721 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2722 ADS_STRUCT *ads = NULL;
2723 char *host_principal = NULL;
2724 char *my_name = NULL;
2725 ADS_STATUS status;
2726 int ret = -1;
2728 if (c->display_usage) {
2729 d_printf( "%s\n"
2730 "net ads changetrustpw\n"
2731 " %s\n",
2732 _("Usage:"),
2733 _("Change the machine account's trust password"));
2734 TALLOC_FREE(tmp_ctx);
2735 return -1;
2738 if (!secrets_init()) {
2739 DEBUG(1,("Failed to initialise secrets database\n"));
2740 goto out;
2743 net_warn_member_options();
2745 net_use_krb_machine_account(c);
2747 use_in_memory_ccache();
2749 status = ads_startup(c, true, tmp_ctx, &ads);
2750 if (!ADS_ERR_OK(status)) {
2751 goto out;
2754 my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2755 if (my_name == NULL) {
2756 d_fprintf(stderr, _("Out of memory\n"));
2757 goto out;
2760 host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2761 if (host_principal == NULL) {
2762 d_fprintf(stderr, _("Out of memory\n"));
2763 goto out;
2766 d_printf(_("Changing password for principal: %s\n"), host_principal);
2768 status = ads_change_trust_account_password(ads, host_principal);
2769 if (!ADS_ERR_OK(status)) {
2770 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2771 goto out;
2774 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2776 if (USE_SYSTEM_KEYTAB) {
2777 d_printf(_("Attempting to update system keytab with new password.\n"));
2778 if (ads_keytab_create_default(ads)) {
2779 d_printf(_("Failed to update system keytab.\n"));
2783 ret = 0;
2784 out:
2785 TALLOC_FREE(tmp_ctx);
2787 return ret;
2791 help for net ads search
2793 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2795 d_printf(_(
2796 "\nnet ads search <expression> <attributes...>\n"
2797 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2798 "The expression is a standard LDAP search expression, and the\n"
2799 "attributes are a list of LDAP fields to show in the results.\n\n"
2800 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2802 net_common_flags_usage(c, argc, argv);
2803 return -1;
2808 general ADS search function. Useful in diagnosing problems in ADS
2810 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2812 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2813 ADS_STRUCT *ads = NULL;
2814 ADS_STATUS status;
2815 const char *ldap_exp = NULL;
2816 const char **attrs = NULL;
2817 LDAPMessage *res = NULL;
2818 int ret = -1;
2820 if (argc < 1 || c->display_usage) {
2821 TALLOC_FREE(tmp_ctx);
2822 return net_ads_search_usage(c, argc, argv);
2825 status = ads_startup(c, false, tmp_ctx, &ads);
2826 if (!ADS_ERR_OK(status)) {
2827 goto out;
2830 ldap_exp = argv[0];
2831 attrs = (argv + 1);
2833 status = ads_do_search_retry(ads,
2834 ads->config.bind_path,
2835 LDAP_SCOPE_SUBTREE,
2836 ldap_exp,
2837 attrs,
2838 &res);
2839 if (!ADS_ERR_OK(status)) {
2840 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2841 goto out;
2844 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2846 /* dump the results */
2847 ads_dump(ads, res);
2849 ret = 0;
2850 out:
2851 ads_msgfree(ads, res);
2852 TALLOC_FREE(tmp_ctx);
2853 return ret;
2858 help for net ads search
2860 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2862 d_printf(_(
2863 "\nnet ads dn <dn> <attributes...>\n"
2864 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2865 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2866 "to show in the results\n\n"
2867 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2868 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2870 net_common_flags_usage(c, argc, argv);
2871 return -1;
2876 general ADS search function. Useful in diagnosing problems in ADS
2878 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2880 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2881 ADS_STRUCT *ads = NULL;
2882 ADS_STATUS status;
2883 const char *dn = NULL;
2884 const char **attrs = NULL;
2885 LDAPMessage *res = NULL;
2886 int ret = -1;
2888 if (argc < 1 || c->display_usage) {
2889 TALLOC_FREE(tmp_ctx);
2890 return net_ads_dn_usage(c, argc, argv);
2893 status = ads_startup(c, false, tmp_ctx, &ads);
2894 if (!ADS_ERR_OK(status)) {
2895 goto out;
2898 dn = argv[0];
2899 attrs = (argv + 1);
2901 status = ads_do_search_all(ads,
2903 LDAP_SCOPE_BASE,
2904 "(objectclass=*)",
2905 attrs,
2906 &res);
2907 if (!ADS_ERR_OK(status)) {
2908 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2909 goto out;
2912 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2914 /* dump the results */
2915 ads_dump(ads, res);
2917 ret = 0;
2918 out:
2919 ads_msgfree(ads, res);
2920 TALLOC_FREE(tmp_ctx);
2921 return ret;
2925 help for net ads sid search
2927 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2929 d_printf(_(
2930 "\nnet ads sid <sid> <attributes...>\n"
2931 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2932 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2933 "to show in the results\n\n"
2934 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2936 net_common_flags_usage(c, argc, argv);
2937 return -1;
2942 general ADS search function. Useful in diagnosing problems in ADS
2944 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2946 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2947 ADS_STRUCT *ads = NULL;
2948 ADS_STATUS status;
2949 const char *sid_string = NULL;
2950 const char **attrs = NULL;
2951 LDAPMessage *res = NULL;
2952 struct dom_sid sid = { 0 };
2953 int ret = -1;
2955 if (argc < 1 || c->display_usage) {
2956 TALLOC_FREE(tmp_ctx);
2957 return net_ads_sid_usage(c, argc, argv);
2960 status = ads_startup(c, false, tmp_ctx, &ads);
2961 if (!ADS_ERR_OK(status)) {
2962 goto out;
2965 sid_string = argv[0];
2966 attrs = (argv + 1);
2968 if (!string_to_sid(&sid, sid_string)) {
2969 d_fprintf(stderr, _("could not convert sid\n"));
2970 goto out;
2973 status = ads_search_retry_sid(ads, &res, &sid, attrs);
2974 if (!ADS_ERR_OK(status)) {
2975 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2976 goto out;
2979 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2981 /* dump the results */
2982 ads_dump(ads, res);
2984 ret = 0;
2985 out:
2986 ads_msgfree(ads, res);
2987 TALLOC_FREE(tmp_ctx);
2988 return ret;
2991 static int net_ads_keytab_flush(struct net_context *c,
2992 int argc,
2993 const char **argv)
2995 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2996 ADS_STRUCT *ads = NULL;
2997 ADS_STATUS status;
2998 int ret = -1;
3000 if (c->display_usage) {
3001 d_printf( "%s\n"
3002 "net ads keytab flush\n"
3003 " %s\n",
3004 _("Usage:"),
3005 _("Delete the whole keytab"));
3006 TALLOC_FREE(tmp_ctx);
3007 return -1;
3010 if (!c->explicit_credentials) {
3011 net_use_krb_machine_account(c);
3014 status = ads_startup(c, true, tmp_ctx, &ads);
3015 if (!ADS_ERR_OK(status)) {
3016 goto out;
3019 ret = ads_keytab_flush(ads);
3020 out:
3021 TALLOC_FREE(tmp_ctx);
3022 return ret;
3025 static int net_ads_keytab_add(struct net_context *c,
3026 int argc,
3027 const char **argv,
3028 bool update_ads)
3030 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3031 ADS_STRUCT *ads = NULL;
3032 ADS_STATUS status;
3033 int i;
3034 int ret = -1;
3036 if (c->display_usage) {
3037 d_printf("%s\n%s",
3038 _("Usage:"),
3039 _("net ads keytab add <principal> [principal ...]\n"
3040 " Add principals to local keytab\n"
3041 " principal\tKerberos principal to add to "
3042 "keytab\n"));
3043 TALLOC_FREE(tmp_ctx);
3044 return -1;
3047 net_warn_member_options();
3049 d_printf(_("Processing principals to add...\n"));
3051 if (!c->explicit_credentials) {
3052 net_use_krb_machine_account(c);
3055 status = ads_startup(c, true, tmp_ctx, &ads);
3056 if (!ADS_ERR_OK(status)) {
3057 goto out;
3060 for (ret = 0, i = 0; i < argc; i++) {
3061 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3063 out:
3064 TALLOC_FREE(tmp_ctx);
3065 return ret;
3068 static int net_ads_keytab_add_default(struct net_context *c,
3069 int argc,
3070 const char **argv)
3072 return net_ads_keytab_add(c, argc, argv, false);
3075 static int net_ads_keytab_add_update_ads(struct net_context *c,
3076 int argc,
3077 const char **argv)
3079 return net_ads_keytab_add(c, argc, argv, true);
3082 static int net_ads_keytab_delete(struct net_context *c,
3083 int argc,
3084 const char **argv)
3086 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3087 ADS_STRUCT *ads = NULL;
3088 ADS_STATUS status;
3089 int i;
3090 int ret = -1;
3092 if (c->display_usage) {
3093 d_printf("%s\n%s",
3094 _("Usage:"),
3095 _("net ads keytab delete <principal> [principal ...]\n"
3096 " Remove entries for service principal, "
3097 " from the keytab file only."
3098 " Remove principals from local keytab\n"
3099 " principal\tKerberos principal to remove from "
3100 "keytab\n"));
3101 TALLOC_FREE(tmp_ctx);
3102 return -1;
3105 d_printf(_("Processing principals to delete...\n"));
3107 if (!c->explicit_credentials) {
3108 net_use_krb_machine_account(c);
3111 status = ads_startup(c, true, tmp_ctx, &ads);
3112 if (!ADS_ERR_OK(status)) {
3113 goto out;
3116 for (ret = 0, i = 0; i < argc; i++) {
3117 ret |= ads_keytab_delete_entry(ads, argv[i]);
3119 out:
3120 TALLOC_FREE(tmp_ctx);
3121 return ret;
3124 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3126 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3127 ADS_STRUCT *ads = NULL;
3128 ADS_STATUS status;
3129 int ret = -1;
3131 if (c->display_usage) {
3132 d_printf( "%s\n"
3133 "net ads keytab create\n"
3134 " %s\n",
3135 _("Usage:"),
3136 _("Create new default keytab"));
3137 TALLOC_FREE(tmp_ctx);
3138 return -1;
3141 net_warn_member_options();
3143 if (!c->explicit_credentials) {
3144 net_use_krb_machine_account(c);
3147 status = ads_startup(c, true, tmp_ctx, &ads);
3148 if (!ADS_ERR_OK(status)) {
3149 goto out;
3152 ret = ads_keytab_create_default(ads);
3153 out:
3154 TALLOC_FREE(tmp_ctx);
3155 return ret;
3158 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3160 const char *keytab = NULL;
3162 if (c->display_usage) {
3163 d_printf("%s\n%s",
3164 _("Usage:"),
3165 _("net ads keytab list [keytab]\n"
3166 " List a local keytab\n"
3167 " keytab\tKeytab to list\n"));
3168 return -1;
3171 if (argc >= 1) {
3172 keytab = argv[0];
3175 return ads_keytab_list(keytab);
3179 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3181 struct functable func[] = {
3183 "add",
3184 net_ads_keytab_add_default,
3185 NET_TRANSPORT_ADS,
3186 N_("Add a service principal"),
3187 N_("net ads keytab add\n"
3188 " Add a service principal, updates keytab file only.")
3191 "delete",
3192 net_ads_keytab_delete,
3193 NET_TRANSPORT_ADS,
3194 N_("Delete a service principal"),
3195 N_("net ads keytab delete\n"
3196 " Remove entries for service principal, from the keytab file only.")
3199 "add_update_ads",
3200 net_ads_keytab_add_update_ads,
3201 NET_TRANSPORT_ADS,
3202 N_("Add a service principal"),
3203 N_("net ads keytab add_update_ads\n"
3204 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3207 "create",
3208 net_ads_keytab_create,
3209 NET_TRANSPORT_ADS,
3210 N_("Create a fresh keytab"),
3211 N_("net ads keytab create\n"
3212 " Create a fresh keytab or update existing one.")
3215 "flush",
3216 net_ads_keytab_flush,
3217 NET_TRANSPORT_ADS,
3218 N_("Remove all keytab entries"),
3219 N_("net ads keytab flush\n"
3220 " Remove all keytab entries")
3223 "list",
3224 net_ads_keytab_list,
3225 NET_TRANSPORT_ADS,
3226 N_("List a keytab"),
3227 N_("net ads keytab list\n"
3228 " List a keytab")
3230 {NULL, NULL, 0, NULL, NULL}
3233 if (!USE_KERBEROS_KEYTAB) {
3234 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3235 "keytab method to use keytab functions.\n"));
3238 return net_run_function(c, argc, argv, "net ads keytab", func);
3241 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3243 int ret = -1;
3245 if (c->display_usage) {
3246 d_printf( "%s\n"
3247 "net ads kerberos renew\n"
3248 " %s\n",
3249 _("Usage:"),
3250 _("Renew TGT from existing credential cache"));
3251 return -1;
3254 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3255 if (ret) {
3256 d_printf(_("failed to renew kerberos ticket: %s\n"),
3257 error_message(ret));
3259 return ret;
3262 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3263 struct PAC_DATA_CTR **pac_data_ctr)
3265 NTSTATUS status;
3266 int ret = -1;
3267 const char *impersonate_princ_s = NULL;
3268 const char *local_service = NULL;
3269 const char *principal = NULL;
3270 const char *password = NULL;
3271 int i;
3273 for (i=0; i<argc; i++) {
3274 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3275 impersonate_princ_s = get_string_param(argv[i]);
3276 if (impersonate_princ_s == NULL) {
3277 return -1;
3280 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3281 local_service = get_string_param(argv[i]);
3282 if (local_service == NULL) {
3283 return -1;
3288 if (local_service == NULL) {
3289 local_service = talloc_asprintf(c, "%s$@%s",
3290 lp_netbios_name(), lp_realm());
3291 if (local_service == NULL) {
3292 goto out;
3296 principal = cli_credentials_get_principal(c->creds, c);
3297 if (principal == NULL) {
3298 d_printf("cli_credentials_get_principal() failed\n");
3299 goto out;
3301 password = cli_credentials_get_password(c->creds);
3303 status = kerberos_return_pac(c,
3304 principal,
3305 password,
3307 NULL,
3308 NULL,
3309 NULL,
3310 true,
3311 true,
3312 2592000, /* one month */
3313 impersonate_princ_s,
3314 local_service,
3315 NULL,
3316 NULL,
3317 pac_data_ctr);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 d_printf(_("failed to query kerberos PAC: %s\n"),
3320 nt_errstr(status));
3321 goto out;
3324 ret = 0;
3325 out:
3326 return ret;
3329 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3331 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3332 int i, num_buffers;
3333 int ret = -1;
3334 enum PAC_TYPE type = 0;
3336 if (c->display_usage) {
3337 d_printf( "%s\n"
3338 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3339 " %s\n",
3340 _("Usage:"),
3341 _("Dump the Kerberos PAC"));
3342 return -1;
3345 for (i=0; i<argc; i++) {
3346 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3347 type = get_int_param(argv[i]);
3351 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3352 if (ret) {
3353 return ret;
3356 if (type == 0) {
3358 char *s = NULL;
3360 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3361 pac_data_ctr->pac_data);
3362 if (s != NULL) {
3363 d_printf(_("The Pac: %s\n"), s);
3364 talloc_free(s);
3367 return 0;
3370 num_buffers = pac_data_ctr->pac_data->num_buffers;
3372 for (i=0; i<num_buffers; i++) {
3374 char *s = NULL;
3376 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3377 continue;
3380 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3381 pac_data_ctr->pac_data->buffers[i].info);
3382 if (s != NULL) {
3383 d_printf(_("The Pac: %s\n"), s);
3384 talloc_free(s);
3386 break;
3389 return 0;
3392 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3394 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3395 char *filename = NULL;
3396 int ret = -1;
3397 int i;
3399 if (c->display_usage) {
3400 d_printf( "%s\n"
3401 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3402 " %s\n",
3403 _("Usage:"),
3404 _("Save the Kerberos PAC"));
3405 return -1;
3408 for (i=0; i<argc; i++) {
3409 if (strnequal(argv[i], "filename", strlen("filename"))) {
3410 filename = get_string_param(argv[i]);
3411 if (filename == NULL) {
3412 return -1;
3417 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3418 if (ret) {
3419 return ret;
3422 if (filename == NULL) {
3423 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3424 return -1;
3427 /* save the raw format */
3428 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3429 d_printf(_("failed to save PAC in %s\n"), filename);
3430 return -1;
3433 return 0;
3436 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3438 struct functable func[] = {
3440 "dump",
3441 net_ads_kerberos_pac_dump,
3442 NET_TRANSPORT_ADS,
3443 N_("Dump Kerberos PAC"),
3444 N_("net ads kerberos pac dump\n"
3445 " Dump a Kerberos PAC to stdout")
3448 "save",
3449 net_ads_kerberos_pac_save,
3450 NET_TRANSPORT_ADS,
3451 N_("Save Kerberos PAC"),
3452 N_("net ads kerberos pac save\n"
3453 " Save a Kerberos PAC in a file")
3456 {NULL, NULL, 0, NULL, NULL}
3459 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3462 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3464 int ret = -1;
3465 NTSTATUS status;
3466 const char *principal = NULL;
3467 const char *password = NULL;
3469 if (c->display_usage) {
3470 d_printf( "%s\n"
3471 "net ads kerberos kinit\n"
3472 " %s\n",
3473 _("Usage:"),
3474 _("Get Ticket Granting Ticket (TGT) for the user"));
3475 return -1;
3478 principal = cli_credentials_get_principal(c->creds, c);
3479 if (principal == NULL) {
3480 d_printf("cli_credentials_get_principal() failed\n");
3481 return -1;
3483 password = cli_credentials_get_password(c->creds);
3485 ret = kerberos_kinit_password_ext(principal,
3486 password,
3488 NULL,
3489 NULL,
3490 NULL,
3491 true,
3492 true,
3493 2592000, /* one month */
3494 NULL,
3495 NULL,
3496 NULL,
3497 &status);
3498 if (ret) {
3499 d_printf(_("failed to kinit password: %s\n"),
3500 nt_errstr(status));
3502 return ret;
3505 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3507 struct functable func[] = {
3509 "kinit",
3510 net_ads_kerberos_kinit,
3511 NET_TRANSPORT_ADS,
3512 N_("Retrieve Ticket Granting Ticket (TGT)"),
3513 N_("net ads kerberos kinit\n"
3514 " Receive Ticket Granting Ticket (TGT)")
3517 "renew",
3518 net_ads_kerberos_renew,
3519 NET_TRANSPORT_ADS,
3520 N_("Renew Ticket Granting Ticket from credential cache"),
3521 N_("net ads kerberos renew\n"
3522 " Renew Ticket Granting Ticket (TGT) from "
3523 "credential cache")
3526 "pac",
3527 net_ads_kerberos_pac,
3528 NET_TRANSPORT_ADS,
3529 N_("Dump Kerberos PAC"),
3530 N_("net ads kerberos pac\n"
3531 " Dump Kerberos PAC")
3533 {NULL, NULL, 0, NULL, NULL}
3536 return net_run_function(c, argc, argv, "net ads kerberos", func);
3539 static int net_ads_setspn_list(struct net_context *c,
3540 int argc,
3541 const char **argv)
3543 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3544 ADS_STRUCT *ads = NULL;
3545 ADS_STATUS status;
3546 bool ok = false;
3547 int ret = -1;
3549 if (c->display_usage) {
3550 d_printf("%s\n%s",
3551 _("Usage:"),
3552 _("net ads setspn list <machinename>\n"));
3553 TALLOC_FREE(tmp_ctx);
3554 return -1;
3557 status = ads_startup(c, true, tmp_ctx, &ads);
3558 if (!ADS_ERR_OK(status)) {
3559 goto out;
3562 if (argc) {
3563 ok = ads_setspn_list(ads, argv[0]);
3564 } else {
3565 ok = ads_setspn_list(ads, lp_netbios_name());
3568 ret = ok ? 0 : -1;
3569 out:
3570 TALLOC_FREE(tmp_ctx);
3571 return ret;
3574 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3576 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3577 ADS_STRUCT *ads = NULL;
3578 ADS_STATUS status;
3579 bool ok = false;
3580 int ret = -1;
3582 if (c->display_usage || argc < 1) {
3583 d_printf("%s\n%s",
3584 _("Usage:"),
3585 _("net ads setspn add <machinename> SPN\n"));
3586 TALLOC_FREE(tmp_ctx);
3587 return -1;
3590 status = ads_startup(c, true, tmp_ctx, &ads);
3591 if (!ADS_ERR_OK(status)) {
3592 goto out;
3595 if (argc > 1) {
3596 ok = ads_setspn_add(ads, argv[0], argv[1]);
3597 } else {
3598 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3601 ret = ok ? 0 : -1;
3602 out:
3603 TALLOC_FREE(tmp_ctx);
3604 return ret;
3607 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3609 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3610 ADS_STRUCT *ads = NULL;
3611 ADS_STATUS status;
3612 bool ok = false;
3613 int ret = -1;
3615 if (c->display_usage || argc < 1) {
3616 d_printf("%s\n%s",
3617 _("Usage:"),
3618 _("net ads setspn delete <machinename> SPN\n"));
3619 TALLOC_FREE(tmp_ctx);
3620 return -1;
3623 status = ads_startup(c, true, tmp_ctx, &ads);
3624 if (!ADS_ERR_OK(status)) {
3625 goto out;
3628 if (argc > 1) {
3629 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3630 } else {
3631 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3634 ret = ok ? 0 : -1;
3635 out:
3636 TALLOC_FREE(tmp_ctx);
3637 return ret;
3640 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3642 struct functable func[] = {
3644 "list",
3645 net_ads_setspn_list,
3646 NET_TRANSPORT_ADS,
3647 N_("List Service Principal Names (SPN)"),
3648 N_("net ads setspn list machine\n"
3649 " List Service Principal Names (SPN)")
3652 "add",
3653 net_ads_setspn_add,
3654 NET_TRANSPORT_ADS,
3655 N_("Add Service Principal Names (SPN)"),
3656 N_("net ads setspn add machine spn\n"
3657 " Add Service Principal Names (SPN)")
3660 "delete",
3661 net_ads_setspn_delete,
3662 NET_TRANSPORT_ADS,
3663 N_("Delete Service Principal Names (SPN)"),
3664 N_("net ads setspn delete machine spn\n"
3665 " Delete Service Principal Names (SPN)")
3667 {NULL, NULL, 0, NULL, NULL}
3670 return net_run_function(c, argc, argv, "net ads setspn", func);
3673 static int net_ads_enctype_lookup_account(struct net_context *c,
3674 ADS_STRUCT *ads,
3675 const char *account,
3676 LDAPMessage **res,
3677 const char **enctype_str)
3679 const char *filter;
3680 const char *attrs[] = {
3681 "msDS-SupportedEncryptionTypes",
3682 NULL
3684 int count;
3685 int ret = -1;
3686 ADS_STATUS status;
3688 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3689 account);
3690 if (filter == NULL) {
3691 goto done;
3694 status = ads_search(ads, res, filter, attrs);
3695 if (!ADS_ERR_OK(status)) {
3696 d_printf(_("no account found with filter: %s\n"), filter);
3697 goto done;
3700 count = ads_count_replies(ads, *res);
3701 switch (count) {
3702 case 1:
3703 break;
3704 case 0:
3705 d_printf(_("no account found with filter: %s\n"), filter);
3706 goto done;
3707 default:
3708 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3709 goto done;
3712 if (enctype_str) {
3713 *enctype_str = ads_pull_string(ads, c, *res,
3714 "msDS-SupportedEncryptionTypes");
3715 if (*enctype_str == NULL) {
3716 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3717 goto done;
3721 ret = 0;
3722 done:
3723 return ret;
3726 static void net_ads_enctype_dump_enctypes(const char *username,
3727 const char *enctype_str)
3729 int enctypes = atoi(enctype_str);
3731 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3732 username, enctypes, enctypes);
3734 printf("[%s] 0x%08x DES-CBC-CRC\n",
3735 enctypes & ENC_CRC32 ? "X" : " ",
3736 ENC_CRC32);
3737 printf("[%s] 0x%08x DES-CBC-MD5\n",
3738 enctypes & ENC_RSA_MD5 ? "X" : " ",
3739 ENC_RSA_MD5);
3740 printf("[%s] 0x%08x RC4-HMAC\n",
3741 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3742 ENC_RC4_HMAC_MD5);
3743 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3744 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3745 ENC_HMAC_SHA1_96_AES128);
3746 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3747 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3748 ENC_HMAC_SHA1_96_AES256);
3749 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3750 enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3751 ENC_HMAC_SHA1_96_AES256_SK);
3752 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3753 enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3754 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3757 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3759 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3760 ADS_STATUS status;
3761 ADS_STRUCT *ads = NULL;
3762 LDAPMessage *res = NULL;
3763 const char *str = NULL;
3764 int ret = -1;
3766 if (c->display_usage || (argc < 1)) {
3767 d_printf( "%s\n"
3768 "net ads enctypes list\n"
3769 " %s\n",
3770 _("Usage:"),
3771 _("List supported enctypes"));
3772 TALLOC_FREE(tmp_ctx);
3773 return -1;
3776 status = ads_startup(c, false, tmp_ctx, &ads);
3777 if (!ADS_ERR_OK(status)) {
3778 goto out;
3781 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3782 if (ret) {
3783 goto out;
3786 net_ads_enctype_dump_enctypes(argv[0], str);
3788 ret = 0;
3789 out:
3790 ads_msgfree(ads, res);
3791 TALLOC_FREE(tmp_ctx);
3792 return ret;
3795 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3797 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3798 int ret = -1;
3799 ADS_STATUS status;
3800 ADS_STRUCT *ads = NULL;
3801 LDAPMessage *res = NULL;
3802 const char *etype_list_str = NULL;
3803 const char *dn = NULL;
3804 ADS_MODLIST mods = NULL;
3805 uint32_t etype_list;
3806 const char *str = NULL;
3808 if (c->display_usage || argc < 1) {
3809 d_printf( "%s\n"
3810 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3811 " %s\n",
3812 _("Usage:"),
3813 _("Set supported enctypes"));
3814 TALLOC_FREE(tmp_ctx);
3815 return -1;
3818 status = ads_startup(c, false, tmp_ctx, &ads);
3819 if (!ADS_ERR_OK(status)) {
3820 goto done;
3823 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3824 if (ret) {
3825 goto done;
3828 dn = ads_get_dn(ads, tmp_ctx, res);
3829 if (dn == NULL) {
3830 goto done;
3833 etype_list = 0;
3834 etype_list |= ENC_RC4_HMAC_MD5;
3835 etype_list |= ENC_HMAC_SHA1_96_AES128;
3836 etype_list |= ENC_HMAC_SHA1_96_AES256;
3838 if (argv[1] != NULL) {
3839 sscanf(argv[1], "%i", &etype_list);
3842 etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3843 if (!etype_list_str) {
3844 goto done;
3847 mods = ads_init_mods(tmp_ctx);
3848 if (!mods) {
3849 goto done;
3852 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3853 etype_list_str);
3854 if (!ADS_ERR_OK(status)) {
3855 goto done;
3858 status = ads_gen_mod(ads, dn, mods);
3859 if (!ADS_ERR_OK(status)) {
3860 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3861 ads_errstr(status));
3862 goto done;
3865 ads_msgfree(ads, res);
3866 res = NULL;
3868 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3869 if (ret) {
3870 goto done;
3873 net_ads_enctype_dump_enctypes(argv[0], str);
3875 ret = 0;
3876 done:
3877 ads_msgfree(ads, res);
3878 TALLOC_FREE(tmp_ctx);
3879 return ret;
3882 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3884 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3885 int ret = -1;
3886 ADS_STATUS status;
3887 ADS_STRUCT *ads = NULL;
3888 LDAPMessage *res = NULL;
3889 const char *dn = NULL;
3890 ADS_MODLIST mods = NULL;
3892 if (c->display_usage || argc < 1) {
3893 d_printf( "%s\n"
3894 "net ads enctypes delete <sAMAccountName>\n"
3895 " %s\n",
3896 _("Usage:"),
3897 _("Delete supported enctypes"));
3898 TALLOC_FREE(tmp_ctx);
3899 return -1;
3902 status = ads_startup(c, false, tmp_ctx, &ads);
3903 if (!ADS_ERR_OK(status)) {
3904 goto done;
3907 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3908 if (ret) {
3909 goto done;
3912 dn = ads_get_dn(ads, tmp_ctx, res);
3913 if (dn == NULL) {
3914 goto done;
3917 mods = ads_init_mods(tmp_ctx);
3918 if (!mods) {
3919 goto done;
3922 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3923 if (!ADS_ERR_OK(status)) {
3924 goto done;
3927 status = ads_gen_mod(ads, dn, mods);
3928 if (!ADS_ERR_OK(status)) {
3929 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3930 ads_errstr(status));
3931 goto done;
3934 ret = 0;
3936 done:
3937 ads_msgfree(ads, res);
3938 TALLOC_FREE(tmp_ctx);
3939 return ret;
3942 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3944 struct functable func[] = {
3946 "list",
3947 net_ads_enctypes_list,
3948 NET_TRANSPORT_ADS,
3949 N_("List the supported encryption types"),
3950 N_("net ads enctypes list\n"
3951 " List the supported encryption types")
3954 "set",
3955 net_ads_enctypes_set,
3956 NET_TRANSPORT_ADS,
3957 N_("Set the supported encryption types"),
3958 N_("net ads enctypes set\n"
3959 " Set the supported encryption types")
3962 "delete",
3963 net_ads_enctypes_delete,
3964 NET_TRANSPORT_ADS,
3965 N_("Delete the supported encryption types"),
3966 N_("net ads enctypes delete\n"
3967 " Delete the supported encryption types")
3970 {NULL, NULL, 0, NULL, NULL}
3973 return net_run_function(c, argc, argv, "net ads enctypes", func);
3977 int net_ads(struct net_context *c, int argc, const char **argv)
3979 struct functable func[] = {
3981 "info",
3982 net_ads_info,
3983 NET_TRANSPORT_ADS,
3984 N_("Display details on remote ADS server"),
3985 N_("net ads info\n"
3986 " Display details on remote ADS server")
3989 "join",
3990 net_ads_join,
3991 NET_TRANSPORT_ADS,
3992 N_("Join the local machine to ADS realm"),
3993 N_("net ads join\n"
3994 " Join the local machine to ADS realm")
3997 "testjoin",
3998 net_ads_testjoin,
3999 NET_TRANSPORT_ADS,
4000 N_("Validate machine account"),
4001 N_("net ads testjoin\n"
4002 " Validate machine account")
4005 "leave",
4006 net_ads_leave,
4007 NET_TRANSPORT_ADS,
4008 N_("Remove the local machine from ADS"),
4009 N_("net ads leave\n"
4010 " Remove the local machine from ADS")
4013 "status",
4014 net_ads_status,
4015 NET_TRANSPORT_ADS,
4016 N_("Display machine account details"),
4017 N_("net ads status\n"
4018 " Display machine account details")
4021 "user",
4022 net_ads_user,
4023 NET_TRANSPORT_ADS,
4024 N_("List/modify users"),
4025 N_("net ads user\n"
4026 " List/modify users")
4029 "group",
4030 net_ads_group,
4031 NET_TRANSPORT_ADS,
4032 N_("List/modify groups"),
4033 N_("net ads group\n"
4034 " List/modify groups")
4037 "dns",
4038 net_ads_dns,
4039 NET_TRANSPORT_ADS,
4040 N_("Issue dynamic DNS update"),
4041 N_("net ads dns\n"
4042 " Issue dynamic DNS update")
4045 "password",
4046 net_ads_password,
4047 NET_TRANSPORT_ADS,
4048 N_("Change user passwords"),
4049 N_("net ads password\n"
4050 " Change user passwords")
4053 "changetrustpw",
4054 net_ads_changetrustpw,
4055 NET_TRANSPORT_ADS,
4056 N_("Change trust account password"),
4057 N_("net ads changetrustpw\n"
4058 " Change trust account password")
4061 "printer",
4062 net_ads_printer,
4063 NET_TRANSPORT_ADS,
4064 N_("List/modify printer entries"),
4065 N_("net ads printer\n"
4066 " List/modify printer entries")
4069 "search",
4070 net_ads_search,
4071 NET_TRANSPORT_ADS,
4072 N_("Issue LDAP search using filter"),
4073 N_("net ads search\n"
4074 " Issue LDAP search using filter")
4077 "dn",
4078 net_ads_dn,
4079 NET_TRANSPORT_ADS,
4080 N_("Issue LDAP search by DN"),
4081 N_("net ads dn\n"
4082 " Issue LDAP search by DN")
4085 "sid",
4086 net_ads_sid,
4087 NET_TRANSPORT_ADS,
4088 N_("Issue LDAP search by SID"),
4089 N_("net ads sid\n"
4090 " Issue LDAP search by SID")
4093 "workgroup",
4094 net_ads_workgroup,
4095 NET_TRANSPORT_ADS,
4096 N_("Display workgroup name"),
4097 N_("net ads workgroup\n"
4098 " Display the workgroup name")
4101 "lookup",
4102 net_ads_lookup,
4103 NET_TRANSPORT_ADS,
4104 N_("Perform CLDAP query on DC"),
4105 N_("net ads lookup\n"
4106 " Find the ADS DC using CLDAP lookups")
4109 "keytab",
4110 net_ads_keytab,
4111 NET_TRANSPORT_ADS,
4112 N_("Manage local keytab file"),
4113 N_("net ads keytab\n"
4114 " Manage local keytab file")
4117 "setspn",
4118 net_ads_setspn,
4119 NET_TRANSPORT_ADS,
4120 N_("Manage Service Principal Names (SPN)s"),
4121 N_("net ads spnset\n"
4122 " Manage Service Principal Names (SPN)s")
4125 "gpo",
4126 net_ads_gpo,
4127 NET_TRANSPORT_ADS,
4128 N_("Manage group policy objects"),
4129 N_("net ads gpo\n"
4130 " Manage group policy objects")
4133 "kerberos",
4134 net_ads_kerberos,
4135 NET_TRANSPORT_ADS,
4136 N_("Manage kerberos keytab"),
4137 N_("net ads kerberos\n"
4138 " Manage kerberos keytab")
4141 "enctypes",
4142 net_ads_enctypes,
4143 NET_TRANSPORT_ADS,
4144 N_("List/modify supported encryption types"),
4145 N_("net ads enctypes\n"
4146 " List/modify enctypes")
4148 {NULL, NULL, 0, NULL, NULL}
4151 return net_run_function(c, argc, argv, "net ads", func);
4154 #else
4156 static int net_ads_noads(void)
4158 d_fprintf(stderr, _("ADS support not compiled in\n"));
4159 return -1;
4162 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4164 return net_ads_noads();
4167 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4169 return net_ads_noads();
4172 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4174 return net_ads_noads();
4177 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4179 return net_ads_noads();
4182 int net_ads_join(struct net_context *c, int argc, const char **argv)
4184 return net_ads_noads();
4187 int net_ads_user(struct net_context *c, int argc, const char **argv)
4189 return net_ads_noads();
4192 int net_ads_group(struct net_context *c, int argc, const char **argv)
4194 return net_ads_noads();
4197 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4199 return net_ads_noads();
4202 /* this one shouldn't display a message */
4203 int net_ads_check(struct net_context *c)
4205 return -1;
4208 int net_ads_check_our_domain(struct net_context *c)
4210 return -1;
4213 int net_ads(struct net_context *c, int argc, const char **argv)
4215 return net_ads_noads();
4218 #endif /* HAVE_ADS */