s3:net: remove useless net_prompt_pass() wrapper
[Samba.git] / source3 / utils / net_ads.c
blobf368724215bdc58b92a55f7e814d01e83ed049c4
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_PLAIN);
690 if (ads == NULL) {
691 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
694 if (!c->opt_user_name) {
695 c->opt_user_name = "administrator";
698 if (c->opt_user_specified) {
699 need_password = true;
702 retry:
703 if (!c->opt_password && need_password && !c->opt_machine_pass) {
704 c->opt_password = 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 status = ads_startup(c, false, tmp_ctx, &ads);
981 if (!ADS_ERR_OK(status)) {
982 goto done;
985 status = ads_find_user_acct(ads, &res, argv[0]);
986 if (!ADS_ERR_OK(status)) {
987 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
988 goto done;
991 if (ads_count_replies(ads, res)) {
992 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
993 argv[0]);
994 goto done;
997 if (c->opt_container) {
998 ou_str = SMB_STRDUP(c->opt_container);
999 } else {
1000 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1003 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
1004 if (!ADS_ERR_OK(status)) {
1005 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
1006 ads_errstr(status));
1007 goto done;
1010 /* if no password is to be set, we're done */
1011 if (argc == 1) {
1012 d_printf(_("User %s added\n"), argv[0]);
1013 rc = 0;
1014 goto done;
1017 /* try setting the password */
1018 upn = talloc_asprintf(tmp_ctx,
1019 "%s@%s",
1020 argv[0],
1021 ads->config.realm);
1022 if (upn == NULL) {
1023 goto done;
1026 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1], 0);
1027 if (ADS_ERR_OK(status)) {
1028 d_printf(_("User %s added\n"), argv[0]);
1029 rc = 0;
1030 goto done;
1032 TALLOC_FREE(upn);
1034 /* password didn't set, delete account */
1035 d_fprintf(stderr, _("Could not add user %s. "
1036 "Error setting password %s\n"),
1037 argv[0], ads_errstr(status));
1039 ads_msgfree(ads, res);
1040 res = NULL;
1042 status=ads_find_user_acct(ads, &res, argv[0]);
1043 if (ADS_ERR_OK(status)) {
1044 userdn = ads_get_dn(ads, tmp_ctx, res);
1045 ads_del_dn(ads, userdn);
1046 TALLOC_FREE(userdn);
1049 done:
1050 ads_msgfree(ads, res);
1051 SAFE_FREE(ou_str);
1052 TALLOC_FREE(tmp_ctx);
1053 return rc;
1056 static int ads_user_info(struct net_context *c, int argc, const char **argv)
1058 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1059 ADS_STRUCT *ads = NULL;
1060 ADS_STATUS status;
1061 LDAPMessage *res = NULL;
1062 int ret = -1;
1063 wbcErr wbc_status;
1064 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1065 char *searchstring = NULL;
1066 char **grouplist = NULL;
1067 char *primary_group = NULL;
1068 char *escaped_user = NULL;
1069 struct dom_sid primary_group_sid;
1070 uint32_t group_rid;
1071 enum wbcSidType type;
1073 if (argc < 1 || c->display_usage) {
1074 TALLOC_FREE(tmp_ctx);
1075 return net_ads_user_usage(c, argc, argv);
1078 escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1079 if (!escaped_user) {
1080 d_fprintf(stderr,
1081 _("ads_user_info: failed to escape user %s\n"),
1082 argv[0]);
1083 goto out;
1086 status = ads_startup(c, false, tmp_ctx, &ads);
1087 if (!ADS_ERR_OK(status)) {
1088 goto out;
1091 searchstring = talloc_asprintf(tmp_ctx,
1092 "(sAMAccountName=%s)",
1093 escaped_user);
1094 if (searchstring == NULL) {
1095 goto out;
1098 status = ads_search(ads, &res, searchstring, attrs);
1099 if (!ADS_ERR_OK(status)) {
1100 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1101 goto out;
1104 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1105 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1106 goto out;
1109 status = ads_domain_sid(ads, &primary_group_sid);
1110 if (!ADS_ERR_OK(status)) {
1111 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1112 goto out;
1115 sid_append_rid(&primary_group_sid, group_rid);
1117 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1118 NULL, /* don't look up domain */
1119 &primary_group,
1120 &type);
1121 if (!WBC_ERROR_IS_OK(wbc_status)) {
1122 d_fprintf(stderr, "wbcLookupSid: %s\n",
1123 wbcErrorString(wbc_status));
1124 goto out;
1127 d_printf("%s\n", primary_group);
1129 wbcFreeMemory(primary_group);
1131 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1132 (LDAPMessage *)res, "memberOf");
1134 if (grouplist) {
1135 int i;
1136 char **groupname;
1137 for (i=0;grouplist[i];i++) {
1138 groupname = ldap_explode_dn(grouplist[i], 1);
1139 d_printf("%s\n", groupname[0]);
1140 ldap_value_free(groupname);
1142 ldap_value_free(grouplist);
1145 ret = 0;
1146 out:
1147 TALLOC_FREE(escaped_user);
1148 TALLOC_FREE(searchstring);
1149 ads_msgfree(ads, res);
1150 TALLOC_FREE(tmp_ctx);
1151 return ret;
1154 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1156 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1157 ADS_STRUCT *ads = NULL;
1158 ADS_STATUS status;
1159 LDAPMessage *res = NULL;
1160 char *userdn = NULL;
1161 int ret = -1;
1163 if (argc < 1) {
1164 TALLOC_FREE(tmp_ctx);
1165 return net_ads_user_usage(c, argc, argv);
1168 status = ads_startup(c, false, tmp_ctx, &ads);
1169 if (!ADS_ERR_OK(status)) {
1170 goto out;
1173 status = ads_find_user_acct(ads, &res, argv[0]);
1174 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1175 d_printf(_("User %s does not exist.\n"), argv[0]);
1176 goto out;
1179 userdn = ads_get_dn(ads, tmp_ctx, res);
1180 if (userdn == NULL) {
1181 goto out;
1184 status = ads_del_dn(ads, userdn);
1185 if (!ADS_ERR_OK(status)) {
1186 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1187 ads_errstr(status));
1188 goto out;
1191 d_printf(_("User %s deleted\n"), argv[0]);
1193 ret = 0;
1194 out:
1195 ads_msgfree(ads, res);
1196 TALLOC_FREE(tmp_ctx);
1197 return ret;
1200 int net_ads_user(struct net_context *c, int argc, const char **argv)
1202 struct functable func[] = {
1204 "add",
1205 ads_user_add,
1206 NET_TRANSPORT_ADS,
1207 N_("Add an AD user"),
1208 N_("net ads user add\n"
1209 " Add an AD user")
1212 "info",
1213 ads_user_info,
1214 NET_TRANSPORT_ADS,
1215 N_("Display information about an AD user"),
1216 N_("net ads user info\n"
1217 " Display information about an AD user")
1220 "delete",
1221 ads_user_delete,
1222 NET_TRANSPORT_ADS,
1223 N_("Delete an AD user"),
1224 N_("net ads user delete\n"
1225 " Delete an AD user")
1227 {NULL, NULL, 0, NULL, NULL}
1229 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1230 ADS_STRUCT *ads = NULL;
1231 ADS_STATUS status;
1232 const char *shortattrs[] = {"sAMAccountName", NULL};
1233 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1234 char *disp_fields[2] = {NULL, NULL};
1235 int ret = -1;
1237 if (argc > 0) {
1238 TALLOC_FREE(tmp_ctx);
1239 return net_run_function(c, argc, argv, "net ads user", func);
1242 if (c->display_usage) {
1243 d_printf( "%s\n"
1244 "net ads user\n"
1245 " %s\n",
1246 _("Usage:"),
1247 _("List AD users"));
1248 net_display_usage_from_functable(func);
1249 TALLOC_FREE(tmp_ctx);
1250 return -1;
1253 status = ads_startup(c, false, tmp_ctx, &ads);
1254 if (!ADS_ERR_OK(status)) {
1255 goto out;
1258 if (c->opt_long_list_entries)
1259 d_printf(_("\nUser name Comment"
1260 "\n-----------------------------\n"));
1262 status = ads_do_search_all_fn(ads,
1263 ads->config.bind_path,
1264 LDAP_SCOPE_SUBTREE,
1265 "(objectCategory=user)",
1266 c->opt_long_list_entries ?
1267 longattrs : shortattrs,
1268 usergrp_display,
1269 disp_fields);
1270 if (!ADS_ERR_OK(status)) {
1271 goto out;
1274 ret = 0;
1275 out:
1276 TALLOC_FREE(tmp_ctx);
1277 return ret;
1280 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1282 return net_group_usage(c, argc, argv);
1285 static int ads_group_add(struct net_context *c, int argc, const char **argv)
1287 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1288 ADS_STRUCT *ads = NULL;
1289 ADS_STATUS status;
1290 LDAPMessage *res = NULL;
1291 int ret = -1;
1292 char *ou_str = NULL;
1294 if (argc < 1 || c->display_usage) {
1295 TALLOC_FREE(tmp_ctx);
1296 return net_ads_group_usage(c, argc, argv);
1299 status = ads_startup(c, false, tmp_ctx, &ads);
1300 if (!ADS_ERR_OK(status)) {
1301 goto out;
1304 status = ads_find_user_acct(ads, &res, argv[0]);
1305 if (!ADS_ERR_OK(status)) {
1306 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1307 goto out;
1310 if (ads_count_replies(ads, res)) {
1311 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1312 goto out;
1315 if (c->opt_container) {
1316 ou_str = SMB_STRDUP(c->opt_container);
1317 } else {
1318 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1321 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1322 if (!ADS_ERR_OK(status)) {
1323 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1324 ads_errstr(status));
1325 goto out;
1328 d_printf(_("Group %s added\n"), argv[0]);
1330 ret = 0;
1331 out:
1332 ads_msgfree(ads, res);
1333 SAFE_FREE(ou_str);
1334 TALLOC_FREE(tmp_ctx);
1335 return ret;
1338 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1340 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1341 ADS_STRUCT *ads = NULL;
1342 ADS_STATUS status;
1343 LDAPMessage *res = NULL;
1344 char *groupdn = NULL;
1345 int ret = -1;
1347 if (argc < 1 || c->display_usage) {
1348 TALLOC_FREE(tmp_ctx);
1349 return net_ads_group_usage(c, argc, argv);
1352 status = ads_startup(c, false, tmp_ctx, &ads);
1353 if (!ADS_ERR_OK(status)) {
1354 goto out;
1357 status = ads_find_user_acct(ads, &res, argv[0]);
1358 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1359 d_printf(_("Group %s does not exist.\n"), argv[0]);
1360 goto out;
1363 groupdn = ads_get_dn(ads, tmp_ctx, res);
1364 if (groupdn == NULL) {
1365 goto out;
1368 status = ads_del_dn(ads, groupdn);
1369 if (!ADS_ERR_OK(status)) {
1370 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1371 ads_errstr(status));
1372 goto out;
1374 d_printf(_("Group %s deleted\n"), argv[0]);
1376 ret = 0;
1377 out:
1378 ads_msgfree(ads, res);
1379 TALLOC_FREE(tmp_ctx);
1380 return ret;
1383 int net_ads_group(struct net_context *c, int argc, const char **argv)
1385 struct functable func[] = {
1387 "add",
1388 ads_group_add,
1389 NET_TRANSPORT_ADS,
1390 N_("Add an AD group"),
1391 N_("net ads group add\n"
1392 " Add an AD group")
1395 "delete",
1396 ads_group_delete,
1397 NET_TRANSPORT_ADS,
1398 N_("Delete an AD group"),
1399 N_("net ads group delete\n"
1400 " Delete an AD group")
1402 {NULL, NULL, 0, NULL, NULL}
1404 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1405 ADS_STRUCT *ads = NULL;
1406 ADS_STATUS status;
1407 const char *shortattrs[] = {"sAMAccountName", NULL};
1408 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1409 char *disp_fields[2] = {NULL, NULL};
1410 int ret = -1;
1412 if (argc >= 0) {
1413 TALLOC_FREE(tmp_ctx);
1414 return net_run_function(c, argc, argv, "net ads group", func);
1417 if (c->display_usage) {
1418 d_printf( "%s\n"
1419 "net ads group\n"
1420 " %s\n",
1421 _("Usage:"),
1422 _("List AD groups"));
1423 net_display_usage_from_functable(func);
1424 TALLOC_FREE(tmp_ctx);
1425 return -1;
1428 status = ads_startup(c, false, tmp_ctx, &ads);
1429 if (!ADS_ERR_OK(status)) {
1430 goto out;
1433 if (c->opt_long_list_entries)
1434 d_printf(_("\nGroup name Comment"
1435 "\n-----------------------------\n"));
1437 status = ads_do_search_all_fn(ads,
1438 ads->config.bind_path,
1439 LDAP_SCOPE_SUBTREE,
1440 "(objectCategory=group)",
1441 c->opt_long_list_entries ?
1442 longattrs : shortattrs,
1443 usergrp_display,
1444 disp_fields);
1445 if (!ADS_ERR_OK(status)) {
1446 goto out;
1449 ret = 0;
1450 out:
1451 TALLOC_FREE(tmp_ctx);
1452 return ret;
1455 static int net_ads_status(struct net_context *c, int argc, const char **argv)
1457 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1458 ADS_STRUCT *ads = NULL;
1459 ADS_STATUS status;
1460 LDAPMessage *res = NULL;
1461 int ret = -1;
1463 if (c->display_usage) {
1464 d_printf( "%s\n"
1465 "net ads status\n"
1466 " %s\n",
1467 _("Usage:"),
1468 _("Display machine account details"));
1469 TALLOC_FREE(tmp_ctx);
1470 return -1;
1473 net_warn_member_options();
1475 status = ads_startup(c, true, tmp_ctx, &ads);
1476 if (!ADS_ERR_OK(status)) {
1477 goto out;
1480 status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1481 if (!ADS_ERR_OK(status)) {
1482 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1483 ads_errstr(status));
1484 goto out;
1487 if (ads_count_replies(ads, res) == 0) {
1488 d_fprintf(stderr, _("No machine account for '%s' found\n"),
1489 lp_netbios_name());
1490 goto out;
1493 ads_dump(ads, res);
1495 ret = 0;
1496 out:
1497 ads_msgfree(ads, res);
1498 TALLOC_FREE(tmp_ctx);
1499 return ret;
1502 /*******************************************************************
1503 Leave an AD domain. Windows XP disables the machine account.
1504 We'll try the same. The old code would do an LDAP delete.
1505 That only worked using the machine creds because added the machine
1506 with full control to the computer object's ACL.
1507 *******************************************************************/
1509 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1511 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1512 struct libnet_UnjoinCtx *r = NULL;
1513 WERROR werr;
1514 int ret = -1;
1516 if (c->display_usage) {
1517 d_printf( "%s\n"
1518 "net ads leave [--keep-account]\n"
1519 " %s\n",
1520 _("Usage:"),
1521 _("Leave an AD domain"));
1522 TALLOC_FREE(tmp_ctx);
1523 return -1;
1526 if (!*lp_realm()) {
1527 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1528 TALLOC_FREE(tmp_ctx);
1529 return -1;
1532 if (!c->opt_kerberos) {
1533 use_in_memory_ccache();
1536 if (!c->msg_ctx) {
1537 d_fprintf(stderr, _("Could not initialise message context. "
1538 "Try running as root\n"));
1539 goto done;
1542 werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1543 if (!W_ERROR_IS_OK(werr)) {
1544 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1545 goto done;
1548 r->in.debug = true;
1549 r->in.dc_name = c->opt_host;
1550 r->in.domain_name = lp_realm();
1551 r->in.admin_credentials = c->creds;
1552 r->in.modify_config = lp_config_backend_is_registry();
1554 /* Try to delete it, but if that fails, disable it. The
1555 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1556 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1557 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1558 if (c->opt_keep_account) {
1559 r->in.delete_machine_account = false;
1560 } else {
1561 r->in.delete_machine_account = true;
1564 r->in.msg_ctx = c->msg_ctx;
1566 werr = libnet_Unjoin(tmp_ctx, r);
1567 if (!W_ERROR_IS_OK(werr)) {
1568 d_printf(_("Failed to leave domain: %s\n"),
1569 r->out.error_string ? r->out.error_string :
1570 get_friendly_werror_msg(werr));
1571 goto done;
1574 if (r->out.deleted_machine_account) {
1575 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1576 r->in.machine_name, r->out.dns_domain_name);
1577 ret = 0;
1578 goto done;
1581 /* We couldn't delete it - see if the disable succeeded. */
1582 if (r->out.disabled_machine_account) {
1583 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1584 r->in.machine_name, r->out.dns_domain_name);
1585 ret = 0;
1586 goto done;
1589 /* Based on what we requested, we shouldn't get here, but if
1590 we did, it means the secrets were removed, and therefore
1591 we have left the domain */
1592 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1593 r->in.machine_name, r->out.dns_domain_name);
1595 ret = 0;
1596 done:
1597 TALLOC_FREE(tmp_ctx);
1598 return ret;
1601 static ADS_STATUS net_ads_join_ok(struct net_context *c)
1603 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1604 ADS_STRUCT *ads = NULL;
1605 ADS_STATUS status;
1606 fstring dc_name;
1607 struct sockaddr_storage dcip;
1609 if (!secrets_init()) {
1610 DEBUG(1,("Failed to initialise secrets database\n"));
1611 TALLOC_FREE(tmp_ctx);
1612 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1615 net_warn_member_options();
1617 net_use_krb_machine_account(c);
1619 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1621 status = ads_startup(c, true, tmp_ctx, &ads);
1622 if (!ADS_ERR_OK(status)) {
1623 goto out;
1626 status = ADS_ERROR_NT(NT_STATUS_OK);
1627 out:
1628 TALLOC_FREE(tmp_ctx);
1629 return status;
1633 check that an existing join is OK
1635 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1637 ADS_STATUS status;
1638 use_in_memory_ccache();
1640 if (c->display_usage) {
1641 d_printf( "%s\n"
1642 "net ads testjoin\n"
1643 " %s\n",
1644 _("Usage:"),
1645 _("Test if the existing join is ok"));
1646 return -1;
1649 net_warn_member_options();
1651 /* Display success or failure */
1652 status = net_ads_join_ok(c);
1653 if (!ADS_ERR_OK(status)) {
1654 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1655 get_friendly_nt_error_msg(ads_ntstatus(status)));
1656 return -1;
1659 printf(_("Join is OK\n"));
1660 return 0;
1663 /*******************************************************************
1664 Simple config checks before beginning the join
1665 ********************************************************************/
1667 static WERROR check_ads_config( void )
1669 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1670 d_printf(_("Host is not configured as a member server.\n"));
1671 return WERR_INVALID_DOMAIN_ROLE;
1674 if (strlen(lp_netbios_name()) > 15) {
1675 d_printf(_("Our netbios name can be at most 15 chars long, "
1676 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1677 (unsigned int)strlen(lp_netbios_name()));
1678 return WERR_INVALID_COMPUTERNAME;
1681 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1682 d_fprintf(stderr, _("realm must be set in %s for ADS "
1683 "join to succeed.\n"), get_dyn_CONFIGFILE());
1684 return WERR_INVALID_PARAMETER;
1687 return WERR_OK;
1690 /*******************************************************************
1691 ********************************************************************/
1693 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1695 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1696 "Valid options:\n"));
1697 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1698 " The default is in the form netbiosname.dnsdomain\n"));
1699 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1700 " The default UPN is in the form host/netbiosname@REALM.\n"));
1701 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1702 " The OU string read from top to bottom without RDNs\n"
1703 " and delimited by a '/'.\n"
1704 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1705 " NB: A backslash '\\' is used as escape at multiple\n"
1706 " levels and may need to be doubled or even\n"
1707 " quadrupled. It is not used as a separator.\n"));
1708 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1709 " the join. The default password is random.\n"));
1710 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1711 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1712 " NB: osName and osVer must be specified together for\n"
1713 " either to take effect. The operatingSystemService\n"
1714 " attribute is then also set along with the two\n"
1715 " other attributes.\n"));
1716 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1717 " during the join.\n"
1718 " NB: If not specified then by default the samba\n"
1719 " version string is used instead.\n"));
1720 return -1;
1724 int net_ads_join(struct net_context *c, int argc, const char **argv)
1726 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1727 struct libnet_JoinCtx *r = NULL;
1728 const char *domain = lp_realm();
1729 WERROR werr = WERR_NERR_SETUPNOTJOINED;
1730 bool createupn = false;
1731 const char *dnshostname = NULL;
1732 const char *machineupn = NULL;
1733 const char *machine_password = NULL;
1734 const char *create_in_ou = NULL;
1735 int i;
1736 const char *os_name = NULL;
1737 const char *os_version = NULL;
1738 const char *os_servicepack = NULL;
1739 bool modify_config = lp_config_backend_is_registry();
1740 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1741 int ret = -1;
1743 if (c->display_usage) {
1744 TALLOC_FREE(tmp_ctx);
1745 return net_ads_join_usage(c, argc, argv);
1748 net_warn_member_options();
1750 if (!modify_config) {
1751 werr = check_ads_config();
1752 if (!W_ERROR_IS_OK(werr)) {
1753 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1754 goto fail;
1758 if (!c->opt_kerberos) {
1759 use_in_memory_ccache();
1762 werr = libnet_init_JoinCtx(tmp_ctx, &r);
1763 if (!W_ERROR_IS_OK(werr)) {
1764 goto fail;
1767 /* process additional command line args */
1769 for ( i=0; i<argc; i++ ) {
1770 if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1771 dnshostname = get_string_param(argv[i]);
1773 else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1774 createupn = true;
1775 machineupn = get_string_param(argv[i]);
1777 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1778 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1779 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1780 werr = WERR_INVALID_PARAMETER;
1781 goto fail;
1784 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1785 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1786 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1787 werr = WERR_INVALID_PARAMETER;
1788 goto fail;
1791 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1792 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1793 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1794 werr = WERR_INVALID_PARAMETER;
1795 goto fail;
1798 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1799 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1800 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1801 werr = WERR_INVALID_PARAMETER;
1802 goto fail;
1805 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1806 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1807 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1808 werr = WERR_INVALID_PARAMETER;
1809 goto fail;
1811 } else {
1812 domain = argv[i];
1813 if (strchr(domain, '.') == NULL) {
1814 domain_name_type = JoinDomNameTypeUnknown;
1815 } else {
1816 domain_name_type = JoinDomNameTypeDNS;
1821 if (!*domain) {
1822 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1823 werr = WERR_INVALID_PARAMETER;
1824 goto fail;
1827 if (!c->msg_ctx) {
1828 d_fprintf(stderr, _("Could not initialise message context. "
1829 "Try running as root\n"));
1830 werr = WERR_ACCESS_DENIED;
1831 goto fail;
1834 /* Do the domain join here */
1836 r->in.domain_name = domain;
1837 r->in.domain_name_type = domain_name_type;
1838 r->in.create_upn = createupn;
1839 r->in.upn = machineupn;
1840 r->in.dnshostname = dnshostname;
1841 r->in.account_ou = create_in_ou;
1842 r->in.os_name = os_name;
1843 r->in.os_version = os_version;
1844 r->in.os_servicepack = os_servicepack;
1845 r->in.dc_name = c->opt_host;
1846 r->in.admin_credentials = c->creds;
1847 r->in.machine_password = machine_password;
1848 r->in.debug = true;
1849 r->in.modify_config = modify_config;
1850 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1851 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1852 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1853 r->in.msg_ctx = c->msg_ctx;
1855 werr = libnet_Join(tmp_ctx, r);
1856 if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1857 strequal(domain, lp_realm())) {
1858 r->in.domain_name = lp_workgroup();
1859 r->in.domain_name_type = JoinDomNameTypeNBT;
1860 werr = libnet_Join(tmp_ctx, r);
1862 if (!W_ERROR_IS_OK(werr)) {
1863 goto fail;
1866 /* Check the short name of the domain */
1868 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1869 d_printf(_("The workgroup in %s does not match the short\n"
1870 "domain name obtained from the server.\n"
1871 "Using the name [%s] from the server.\n"
1872 "You should set \"workgroup = %s\" in %s.\n"),
1873 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1874 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1877 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1879 if (r->out.dns_domain_name) {
1880 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1881 r->out.dns_domain_name);
1882 } else {
1883 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1884 r->out.netbios_domain_name);
1887 /* print out informative error string in case there is one */
1888 if (r->out.error_string != NULL) {
1889 d_printf("%s\n", r->out.error_string);
1893 * We try doing the dns update (if it was compiled in
1894 * and if it was not disabled on the command line).
1895 * If the dns update fails, we still consider the join
1896 * operation as succeeded if we came this far.
1898 if (!c->opt_no_dns_updates) {
1899 net_ads_join_dns_updates(c, tmp_ctx, r);
1902 ret = 0;
1904 fail:
1905 if (ret != 0) {
1906 /* issue an overall failure message at the end. */
1907 d_printf(_("Failed to join domain: %s\n"),
1908 r && r->out.error_string ? r->out.error_string :
1909 get_friendly_werror_msg(werr));
1912 TALLOC_FREE(tmp_ctx);
1914 return ret;
1917 /*******************************************************************
1918 ********************************************************************/
1920 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1922 #if defined(HAVE_KRB5)
1923 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1924 ADS_STRUCT *ads = NULL;
1925 ADS_STATUS status;
1926 NTSTATUS ntstatus;
1927 const char *hostname = NULL;
1928 const char **addrs_list = NULL;
1929 struct sockaddr_storage *addrs = NULL;
1930 int num_addrs = 0;
1931 int count;
1932 int ret = -1;
1934 #ifdef DEVELOPER
1935 talloc_enable_leak_report();
1936 #endif
1938 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1939 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1940 "detection of addresses in a clustered "
1941 "setup.\n"));
1942 c->display_usage = true;
1945 if (c->display_usage) {
1946 d_printf( "%s\n"
1947 "net ads dns register [hostname [IP [IP...]]] "
1948 "[--force] [--dns-ttl TTL]\n"
1949 " %s\n",
1950 _("Usage:"),
1951 _("Register hostname with DNS\n"));
1952 TALLOC_FREE(tmp_ctx);
1953 return -1;
1956 if (argc >= 1) {
1957 hostname = argv[0];
1960 if (argc > 1) {
1961 num_addrs = argc - 1;
1962 addrs_list = &argv[1];
1963 } else if (lp_clustering()) {
1964 addrs_list = lp_cluster_addresses();
1965 num_addrs = str_list_length(addrs_list);
1968 if (num_addrs > 0) {
1969 addrs = talloc_zero_array(tmp_ctx,
1970 struct sockaddr_storage,
1971 num_addrs);
1972 if (addrs == NULL) {
1973 d_fprintf(stderr, _("Error allocating memory!\n"));
1974 goto out;
1978 for (count = 0; count < num_addrs; count++) {
1979 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1980 d_fprintf(stderr, "%s '%s'.\n",
1981 _("Cannot interpret address"),
1982 addrs_list[count]);
1983 goto out;
1987 status = ads_startup(c, true, tmp_ctx, &ads);
1988 if ( !ADS_ERR_OK(status) ) {
1989 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1990 goto out;
1993 ntstatus = net_update_dns_ext(c,
1994 tmp_ctx,
1995 ads,
1996 c->creds,
1997 hostname,
1998 addrs,
1999 num_addrs,
2000 false);
2001 if (!NT_STATUS_IS_OK(ntstatus)) {
2002 d_fprintf( stderr, _("DNS update failed!\n") );
2003 goto out;
2006 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
2008 ret = 0;
2009 out:
2010 TALLOC_FREE(tmp_ctx);
2012 return ret;
2013 #else
2014 d_fprintf(stderr,
2015 _("DNS update support not enabled at compile time!\n"));
2016 return -1;
2017 #endif
2020 static int net_ads_dns_unregister(struct net_context *c,
2021 int argc,
2022 const char **argv)
2024 #if defined(HAVE_KRB5)
2025 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2026 ADS_STRUCT *ads = NULL;
2027 ADS_STATUS status;
2028 NTSTATUS ntstatus;
2029 const char *hostname = NULL;
2030 int ret = -1;
2032 #ifdef DEVELOPER
2033 talloc_enable_leak_report();
2034 #endif
2036 if (argc != 1) {
2037 c->display_usage = true;
2040 if (c->display_usage) {
2041 d_printf( "%s\n"
2042 "net ads dns unregister [hostname]\n"
2043 " %s\n",
2044 _("Usage:"),
2045 _("Remove all IP Address entries for a given\n"
2046 " hostname from the Active Directory server.\n"));
2047 TALLOC_FREE(tmp_ctx);
2048 return -1;
2051 /* Get the hostname for un-registering */
2052 hostname = argv[0];
2054 status = ads_startup(c, true, tmp_ctx, &ads);
2055 if ( !ADS_ERR_OK(status) ) {
2056 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2057 goto out;
2060 ntstatus = net_update_dns_ext(c,
2061 tmp_ctx,
2062 ads,
2063 c->creds,
2064 hostname,
2065 NULL,
2067 true);
2068 if (!NT_STATUS_IS_OK(ntstatus)) {
2069 d_fprintf( stderr, _("DNS update failed!\n") );
2070 goto out;
2073 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2075 ret = 0;
2076 out:
2077 TALLOC_FREE(tmp_ctx);
2079 return ret;
2080 #else
2081 d_fprintf(stderr,
2082 _("DNS update support not enabled at compile time!\n"));
2083 return -1;
2084 #endif
2088 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2090 size_t num_names = 0;
2091 char **hostnames = NULL;
2092 size_t i = 0;
2093 struct samba_sockaddr *addrs = NULL;
2094 NTSTATUS status;
2096 if (argc != 1 || c->display_usage) {
2097 d_printf( "%s\n"
2098 " %s\n"
2099 " %s\n",
2100 _("Usage:"),
2101 _("net ads dns async <name>\n"),
2102 _(" Async look up hostname from the DNS server\n"
2103 " hostname\tName to look up\n"));
2104 return -1;
2107 status = ads_dns_lookup_a(talloc_tos(),
2108 argv[0],
2109 &num_names,
2110 &hostnames,
2111 &addrs);
2112 if (!NT_STATUS_IS_OK(status)) {
2113 d_printf("Looking up A record for %s got error %s\n",
2114 argv[0],
2115 nt_errstr(status));
2116 return -1;
2118 d_printf("Async A record lookup - got %u names for %s\n",
2119 (unsigned int)num_names,
2120 argv[0]);
2121 for (i = 0; i < num_names; i++) {
2122 char addr_buf[INET6_ADDRSTRLEN];
2123 print_sockaddr(addr_buf,
2124 sizeof(addr_buf),
2125 &addrs[i].u.ss);
2126 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2127 (unsigned int)i,
2128 hostnames[i],
2129 addr_buf);
2132 #if defined(HAVE_IPV6)
2133 status = ads_dns_lookup_aaaa(talloc_tos(),
2134 argv[0],
2135 &num_names,
2136 &hostnames,
2137 &addrs);
2138 if (!NT_STATUS_IS_OK(status)) {
2139 d_printf("Looking up AAAA record for %s got error %s\n",
2140 argv[0],
2141 nt_errstr(status));
2142 return -1;
2144 d_printf("Async AAAA record lookup - got %u names for %s\n",
2145 (unsigned int)num_names,
2146 argv[0]);
2147 for (i = 0; i < num_names; i++) {
2148 char addr_buf[INET6_ADDRSTRLEN];
2149 print_sockaddr(addr_buf,
2150 sizeof(addr_buf),
2151 &addrs[i].u.ss);
2152 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2153 (unsigned int)i,
2154 hostnames[i],
2155 addr_buf);
2157 #endif
2158 return 0;
2162 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2164 struct functable func[] = {
2166 "register",
2167 net_ads_dns_register,
2168 NET_TRANSPORT_ADS,
2169 N_("Add host dns entry to AD"),
2170 N_("net ads dns register\n"
2171 " Add host dns entry to AD")
2174 "unregister",
2175 net_ads_dns_unregister,
2176 NET_TRANSPORT_ADS,
2177 N_("Remove host dns entry from AD"),
2178 N_("net ads dns unregister\n"
2179 " Remove host dns entry from AD")
2182 "async",
2183 net_ads_dns_async,
2184 NET_TRANSPORT_ADS,
2185 N_("Look up host"),
2186 N_("net ads dns async\n"
2187 " Look up host using async DNS")
2189 {NULL, NULL, 0, NULL, NULL}
2192 return net_run_function(c, argc, argv, "net ads dns", func);
2195 /*******************************************************************
2196 ********************************************************************/
2198 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2200 d_printf(_(
2201 "\nnet ads printer search <printer>"
2202 "\n\tsearch for a printer in the directory\n"
2203 "\nnet ads printer info <printer> <server>"
2204 "\n\tlookup info in directory for printer on server"
2205 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2206 "\nnet ads printer publish <printername>"
2207 "\n\tpublish printer in directory"
2208 "\n\t(note: printer name is required)\n"
2209 "\nnet ads printer remove <printername>"
2210 "\n\tremove printer from directory"
2211 "\n\t(note: printer name is required)\n"));
2212 return -1;
2215 /*******************************************************************
2216 ********************************************************************/
2218 static int net_ads_printer_search(struct net_context *c,
2219 int argc,
2220 const char **argv)
2222 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2223 ADS_STRUCT *ads = NULL;
2224 ADS_STATUS status;
2225 LDAPMessage *res = NULL;
2226 int ret = -1;
2228 if (c->display_usage) {
2229 d_printf( "%s\n"
2230 "net ads printer search\n"
2231 " %s\n",
2232 _("Usage:"),
2233 _("List printers in the AD"));
2234 TALLOC_FREE(tmp_ctx);
2235 return -1;
2238 status = ads_startup(c, false, tmp_ctx, &ads);
2239 if (!ADS_ERR_OK(status)) {
2240 goto out;
2243 status = ads_find_printers(ads, &res);
2244 if (!ADS_ERR_OK(status)) {
2245 d_fprintf(stderr, _("ads_find_printer: %s\n"),
2246 ads_errstr(status));
2247 goto out;
2250 if (ads_count_replies(ads, res) == 0) {
2251 d_fprintf(stderr, _("No results found\n"));
2252 goto out;
2255 ads_dump(ads, res);
2257 ret = 0;
2258 out:
2259 ads_msgfree(ads, res);
2260 TALLOC_FREE(tmp_ctx);
2261 return ret;
2264 static int net_ads_printer_info(struct net_context *c,
2265 int argc,
2266 const char **argv)
2268 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2269 ADS_STRUCT *ads = NULL;
2270 ADS_STATUS status;
2271 const char *servername = NULL;
2272 const char *printername = NULL;
2273 LDAPMessage *res = NULL;
2274 int ret = -1;
2276 if (c->display_usage) {
2277 d_printf("%s\n%s",
2278 _("Usage:"),
2279 _("net ads printer info [printername [servername]]\n"
2280 " Display printer info from AD\n"
2281 " printername\tPrinter name or wildcard\n"
2282 " servername\tName of the print server\n"));
2283 TALLOC_FREE(tmp_ctx);
2284 return -1;
2287 status = ads_startup(c, false, tmp_ctx, &ads);
2288 if (!ADS_ERR_OK(status)) {
2289 goto out;
2292 if (argc > 0) {
2293 printername = argv[0];
2294 } else {
2295 printername = "*";
2298 if (argc > 1) {
2299 servername = argv[1];
2300 } else {
2301 servername = lp_netbios_name();
2304 status = ads_find_printer_on_server(ads, &res, printername, servername);
2305 if (!ADS_ERR_OK(status)) {
2306 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2307 servername, ads_errstr(status));
2308 goto out;
2311 if (ads_count_replies(ads, res) == 0) {
2312 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2313 goto out;
2316 ads_dump(ads, res);
2318 ret = 0;
2319 out:
2320 ads_msgfree(ads, res);
2321 TALLOC_FREE(tmp_ctx);
2322 return ret;
2325 static int net_ads_printer_publish(struct net_context *c,
2326 int argc,
2327 const char **argv)
2329 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2330 ADS_STRUCT *ads = NULL;
2331 ADS_STATUS status;
2332 const char *servername = NULL;
2333 const char *printername = NULL;
2334 struct cli_state *cli = NULL;
2335 struct rpc_pipe_client *pipe_hnd = NULL;
2336 struct sockaddr_storage server_ss = { 0 };
2337 NTSTATUS nt_status;
2338 ADS_MODLIST mods = NULL;
2339 char *prt_dn = NULL;
2340 char *srv_dn = NULL;
2341 char **srv_cn = NULL;
2342 char *srv_cn_escaped = NULL;
2343 char *printername_escaped = NULL;
2344 LDAPMessage *res = NULL;
2345 bool ok;
2346 int ret = -1;
2348 if (argc < 1 || c->display_usage) {
2349 d_printf("%s\n%s",
2350 _("Usage:"),
2351 _("net ads printer publish <printername> [servername]\n"
2352 " Publish printer in AD\n"
2353 " printername\tName of the printer\n"
2354 " servername\tName of the print server\n"));
2355 TALLOC_FREE(tmp_ctx);
2356 return -1;
2359 mods = ads_init_mods(tmp_ctx);
2360 if (mods == NULL) {
2361 d_fprintf(stderr, _("Out of memory\n"));
2362 goto out;
2365 status = ads_startup(c, true, tmp_ctx, &ads);
2366 if (!ADS_ERR_OK(status)) {
2367 goto out;
2370 printername = argv[0];
2372 if (argc == 2) {
2373 servername = argv[1];
2374 } else {
2375 servername = lp_netbios_name();
2378 /* Get printer data from SPOOLSS */
2380 ok = resolve_name(servername, &server_ss, 0x20, false);
2381 if (!ok) {
2382 d_fprintf(stderr, _("Could not find server %s\n"),
2383 servername);
2384 goto out;
2387 cli_credentials_set_kerberos_state(c->creds,
2388 CRED_USE_KERBEROS_REQUIRED,
2389 CRED_SPECIFIED);
2391 nt_status = cli_full_connection_creds(c,
2392 &cli,
2393 lp_netbios_name(),
2394 servername,
2395 &server_ss,
2397 "IPC$",
2398 "IPC",
2399 c->creds,
2400 CLI_FULL_CONNECTION_IPC);
2402 if (NT_STATUS_IS_ERR(nt_status)) {
2403 d_fprintf(stderr, _("Unable to open a connection to %s to "
2404 "obtain data for %s\n"),
2405 servername, printername);
2406 goto out;
2409 /* Publish on AD server */
2411 ads_find_machine_acct(ads, &res, servername);
2413 if (ads_count_replies(ads, res) == 0) {
2414 d_fprintf(stderr, _("Could not find machine account for server "
2415 "%s\n"),
2416 servername);
2417 goto out;
2420 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2421 srv_cn = ldap_explode_dn(srv_dn, 1);
2423 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2424 printername_escaped = escape_rdn_val_string_alloc(printername);
2425 if (!srv_cn_escaped || !printername_escaped) {
2426 SAFE_FREE(srv_cn_escaped);
2427 SAFE_FREE(printername_escaped);
2428 d_fprintf(stderr, _("Internal error, out of memory!"));
2429 goto out;
2432 prt_dn = talloc_asprintf(tmp_ctx,
2433 "cn=%s-%s,%s",
2434 srv_cn_escaped,
2435 printername_escaped,
2436 srv_dn);
2437 if (prt_dn == NULL) {
2438 SAFE_FREE(srv_cn_escaped);
2439 SAFE_FREE(printername_escaped);
2440 d_fprintf(stderr, _("Internal error, out of memory!"));
2441 goto out;
2444 SAFE_FREE(srv_cn_escaped);
2445 SAFE_FREE(printername_escaped);
2447 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2448 if (!NT_STATUS_IS_OK(nt_status)) {
2449 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2450 servername);
2451 goto out;
2454 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2455 tmp_ctx,
2456 &mods,
2457 printername))) {
2458 goto out;
2461 status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2462 if (!ADS_ERR_OK(status)) {
2463 d_fprintf(stderr, "ads_publish_printer: %s\n",
2464 ads_errstr(status));
2465 goto out;
2468 d_printf("published printer\n");
2470 ret = 0;
2471 out:
2472 talloc_destroy(tmp_ctx);
2474 return ret;
2477 static int net_ads_printer_remove(struct net_context *c,
2478 int argc,
2479 const char **argv)
2481 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2482 ADS_STRUCT *ads = NULL;
2483 ADS_STATUS status;
2484 const char *servername = NULL;
2485 char *prt_dn = NULL;
2486 LDAPMessage *res = NULL;
2487 int ret = -1;
2489 if (argc < 1 || c->display_usage) {
2490 d_printf("%s\n%s",
2491 _("Usage:"),
2492 _("net ads printer remove <printername> [servername]\n"
2493 " Remove a printer from the AD\n"
2494 " printername\tName of the printer\n"
2495 " servername\tName of the print server\n"));
2496 TALLOC_FREE(tmp_ctx);
2497 return -1;
2500 status = ads_startup(c, true, tmp_ctx, &ads);
2501 if (!ADS_ERR_OK(status)) {
2502 goto out;
2505 if (argc > 1) {
2506 servername = argv[1];
2507 } else {
2508 servername = lp_netbios_name();
2511 status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2512 if (!ADS_ERR_OK(status)) {
2513 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2514 ads_errstr(status));
2515 goto out;
2518 if (ads_count_replies(ads, res) == 0) {
2519 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2520 goto out;
2523 prt_dn = ads_get_dn(ads, tmp_ctx, res);
2524 if (prt_dn == NULL) {
2525 d_fprintf(stderr, _("Out of memory\n"));
2526 goto out;
2529 status = ads_del_dn(ads, prt_dn);
2530 if (!ADS_ERR_OK(status)) {
2531 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2532 goto out;
2535 ret = 0;
2536 out:
2537 ads_msgfree(ads, res);
2538 TALLOC_FREE(tmp_ctx);
2539 return ret;
2542 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2544 struct functable func[] = {
2546 "search",
2547 net_ads_printer_search,
2548 NET_TRANSPORT_ADS,
2549 N_("Search for a printer"),
2550 N_("net ads printer search\n"
2551 " Search for a printer")
2554 "info",
2555 net_ads_printer_info,
2556 NET_TRANSPORT_ADS,
2557 N_("Display printer information"),
2558 N_("net ads printer info\n"
2559 " Display printer information")
2562 "publish",
2563 net_ads_printer_publish,
2564 NET_TRANSPORT_ADS,
2565 N_("Publish a printer"),
2566 N_("net ads printer publish\n"
2567 " Publish a printer")
2570 "remove",
2571 net_ads_printer_remove,
2572 NET_TRANSPORT_ADS,
2573 N_("Delete a printer"),
2574 N_("net ads printer remove\n"
2575 " Delete a printer")
2577 {NULL, NULL, 0, NULL, NULL}
2580 return net_run_function(c, argc, argv, "net ads printer", func);
2584 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2586 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2587 ADS_STRUCT *ads = NULL;
2588 const char *auth_principal = cli_credentials_get_username(c->creds);
2589 const char *auth_password = cli_credentials_get_password(c->creds);
2590 const char *realm = NULL;
2591 char *new_password = NULL;
2592 char *chr = NULL;
2593 char *prompt = NULL;
2594 const char *user = NULL;
2595 char pwd[256] = {0};
2596 ADS_STATUS status;
2597 int ret = 0;
2599 if (c->display_usage) {
2600 d_printf("%s\n%s",
2601 _("Usage:"),
2602 _("net ads password <username>\n"
2603 " Change password for user\n"
2604 " username\tName of user to change password for\n"));
2605 TALLOC_FREE(tmp_ctx);
2606 return -1;
2609 if (auth_principal == NULL || auth_password == NULL) {
2610 d_fprintf(stderr, _("You must supply an administrator "
2611 "username/password\n"));
2612 TALLOC_FREE(tmp_ctx);
2613 return -1;
2616 if (argc < 1) {
2617 d_fprintf(stderr, _("ERROR: You must say which username to "
2618 "change password for\n"));
2619 TALLOC_FREE(tmp_ctx);
2620 return -1;
2623 if (strchr_m(argv[0], '@')) {
2624 user = talloc_strdup(tmp_ctx, argv[0]);
2625 } else {
2626 user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2628 if (user == NULL) {
2629 d_fprintf(stderr, _("Out of memory\n"));
2630 goto out;
2633 use_in_memory_ccache();
2634 chr = strchr_m(auth_principal, '@');
2635 if (chr) {
2636 realm = ++chr;
2637 } else {
2638 realm = lp_realm();
2641 /* use the realm so we can eventually change passwords for users
2642 in realms other than default */
2643 ads = ads_init(tmp_ctx,
2644 realm,
2645 c->opt_workgroup,
2646 c->opt_host,
2647 ADS_SASL_PLAIN);
2648 if (ads == NULL) {
2649 goto out;
2652 /* we don't actually need a full connect, but it's the easy way to
2653 fill in the KDC's address */
2654 ads->auth.flags |= ADS_AUTH_GENERATE_KRB5_CONFIG;
2655 ads_connect_cldap_only(ads);
2657 if (!ads->config.realm) {
2658 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2659 goto out;
2662 if (argv[1] != NULL) {
2663 new_password = talloc_strdup(tmp_ctx, argv[1]);
2664 } else {
2665 int rc;
2667 prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2668 if (prompt == NULL) {
2669 d_fprintf(stderr, _("Out of memory\n"));
2670 goto out;
2673 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2674 if (rc < 0) {
2675 goto out;
2677 new_password = talloc_strdup(tmp_ctx, pwd);
2678 memset(pwd, '\0', sizeof(pwd));
2681 if (new_password == NULL) {
2682 d_fprintf(stderr, _("Out of memory\n"));
2683 goto out;
2686 status = kerberos_set_password(ads->auth.kdc_server,
2687 auth_principal,
2688 auth_password,
2689 user,
2690 new_password,
2692 memset(new_password, '\0', strlen(new_password));
2693 if (!ADS_ERR_OK(status)) {
2694 d_fprintf(stderr, _("Password change failed: %s\n"),
2695 ads_errstr(status));
2696 goto out;
2699 d_printf(_("Password change for %s completed.\n"), user);
2701 ret = 0;
2702 out:
2703 TALLOC_FREE(tmp_ctx);
2704 return ret;
2707 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2709 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2710 ADS_STRUCT *ads = NULL;
2711 char *host_principal = NULL;
2712 char *my_name = NULL;
2713 ADS_STATUS status;
2714 int ret = -1;
2716 if (c->display_usage) {
2717 d_printf( "%s\n"
2718 "net ads changetrustpw\n"
2719 " %s\n",
2720 _("Usage:"),
2721 _("Change the machine account's trust password"));
2722 TALLOC_FREE(tmp_ctx);
2723 return -1;
2726 if (!secrets_init()) {
2727 DEBUG(1,("Failed to initialise secrets database\n"));
2728 goto out;
2731 net_warn_member_options();
2733 net_use_krb_machine_account(c);
2735 use_in_memory_ccache();
2737 status = ads_startup(c, true, tmp_ctx, &ads);
2738 if (!ADS_ERR_OK(status)) {
2739 goto out;
2742 my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2743 if (my_name == NULL) {
2744 d_fprintf(stderr, _("Out of memory\n"));
2745 goto out;
2748 host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2749 if (host_principal == NULL) {
2750 d_fprintf(stderr, _("Out of memory\n"));
2751 goto out;
2754 d_printf(_("Changing password for principal: %s\n"), host_principal);
2756 status = ads_change_trust_account_password(ads, host_principal);
2757 if (!ADS_ERR_OK(status)) {
2758 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2759 goto out;
2762 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2764 if (USE_SYSTEM_KEYTAB) {
2765 d_printf(_("Attempting to update system keytab with new password.\n"));
2766 if (ads_keytab_create_default(ads)) {
2767 d_printf(_("Failed to update system keytab.\n"));
2771 ret = 0;
2772 out:
2773 TALLOC_FREE(tmp_ctx);
2775 return ret;
2779 help for net ads search
2781 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2783 d_printf(_(
2784 "\nnet ads search <expression> <attributes...>\n"
2785 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2786 "The expression is a standard LDAP search expression, and the\n"
2787 "attributes are a list of LDAP fields to show in the results.\n\n"
2788 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2790 net_common_flags_usage(c, argc, argv);
2791 return -1;
2796 general ADS search function. Useful in diagnosing problems in ADS
2798 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2800 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2801 ADS_STRUCT *ads = NULL;
2802 ADS_STATUS status;
2803 const char *ldap_exp = NULL;
2804 const char **attrs = NULL;
2805 LDAPMessage *res = NULL;
2806 int ret = -1;
2808 if (argc < 1 || c->display_usage) {
2809 TALLOC_FREE(tmp_ctx);
2810 return net_ads_search_usage(c, argc, argv);
2813 status = ads_startup(c, false, tmp_ctx, &ads);
2814 if (!ADS_ERR_OK(status)) {
2815 goto out;
2818 ldap_exp = argv[0];
2819 attrs = (argv + 1);
2821 status = ads_do_search_retry(ads,
2822 ads->config.bind_path,
2823 LDAP_SCOPE_SUBTREE,
2824 ldap_exp,
2825 attrs,
2826 &res);
2827 if (!ADS_ERR_OK(status)) {
2828 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2829 goto out;
2832 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2834 /* dump the results */
2835 ads_dump(ads, res);
2837 ret = 0;
2838 out:
2839 ads_msgfree(ads, res);
2840 TALLOC_FREE(tmp_ctx);
2841 return ret;
2846 help for net ads search
2848 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2850 d_printf(_(
2851 "\nnet ads dn <dn> <attributes...>\n"
2852 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2853 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2854 "to show in the results\n\n"
2855 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2856 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2858 net_common_flags_usage(c, argc, argv);
2859 return -1;
2864 general ADS search function. Useful in diagnosing problems in ADS
2866 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2868 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2869 ADS_STRUCT *ads = NULL;
2870 ADS_STATUS status;
2871 const char *dn = NULL;
2872 const char **attrs = NULL;
2873 LDAPMessage *res = NULL;
2874 int ret = -1;
2876 if (argc < 1 || c->display_usage) {
2877 TALLOC_FREE(tmp_ctx);
2878 return net_ads_dn_usage(c, argc, argv);
2881 status = ads_startup(c, false, tmp_ctx, &ads);
2882 if (!ADS_ERR_OK(status)) {
2883 goto out;
2886 dn = argv[0];
2887 attrs = (argv + 1);
2889 status = ads_do_search_all(ads,
2891 LDAP_SCOPE_BASE,
2892 "(objectclass=*)",
2893 attrs,
2894 &res);
2895 if (!ADS_ERR_OK(status)) {
2896 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2897 goto out;
2900 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2902 /* dump the results */
2903 ads_dump(ads, res);
2905 ret = 0;
2906 out:
2907 ads_msgfree(ads, res);
2908 TALLOC_FREE(tmp_ctx);
2909 return ret;
2913 help for net ads sid search
2915 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2917 d_printf(_(
2918 "\nnet ads sid <sid> <attributes...>\n"
2919 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2920 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2921 "to show in the results\n\n"
2922 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2924 net_common_flags_usage(c, argc, argv);
2925 return -1;
2930 general ADS search function. Useful in diagnosing problems in ADS
2932 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2934 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2935 ADS_STRUCT *ads = NULL;
2936 ADS_STATUS status;
2937 const char *sid_string = NULL;
2938 const char **attrs = NULL;
2939 LDAPMessage *res = NULL;
2940 struct dom_sid sid = { 0 };
2941 int ret = -1;
2943 if (argc < 1 || c->display_usage) {
2944 TALLOC_FREE(tmp_ctx);
2945 return net_ads_sid_usage(c, argc, argv);
2948 status = ads_startup(c, false, tmp_ctx, &ads);
2949 if (!ADS_ERR_OK(status)) {
2950 goto out;
2953 sid_string = argv[0];
2954 attrs = (argv + 1);
2956 if (!string_to_sid(&sid, sid_string)) {
2957 d_fprintf(stderr, _("could not convert sid\n"));
2958 goto out;
2961 status = ads_search_retry_sid(ads, &res, &sid, attrs);
2962 if (!ADS_ERR_OK(status)) {
2963 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2964 goto out;
2967 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2969 /* dump the results */
2970 ads_dump(ads, res);
2972 ret = 0;
2973 out:
2974 ads_msgfree(ads, res);
2975 TALLOC_FREE(tmp_ctx);
2976 return ret;
2979 static int net_ads_keytab_flush(struct net_context *c,
2980 int argc,
2981 const char **argv)
2983 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2984 ADS_STRUCT *ads = NULL;
2985 ADS_STATUS status;
2986 int ret = -1;
2988 if (c->display_usage) {
2989 d_printf( "%s\n"
2990 "net ads keytab flush\n"
2991 " %s\n",
2992 _("Usage:"),
2993 _("Delete the whole keytab"));
2994 TALLOC_FREE(tmp_ctx);
2995 return -1;
2998 if (!c->explicit_credentials) {
2999 net_use_krb_machine_account(c);
3002 status = ads_startup(c, true, tmp_ctx, &ads);
3003 if (!ADS_ERR_OK(status)) {
3004 goto out;
3007 ret = ads_keytab_flush(ads);
3008 out:
3009 TALLOC_FREE(tmp_ctx);
3010 return ret;
3013 static int net_ads_keytab_add(struct net_context *c,
3014 int argc,
3015 const char **argv,
3016 bool update_ads)
3018 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3019 ADS_STRUCT *ads = NULL;
3020 ADS_STATUS status;
3021 int i;
3022 int ret = -1;
3024 if (c->display_usage) {
3025 d_printf("%s\n%s",
3026 _("Usage:"),
3027 _("net ads keytab add <principal> [principal ...]\n"
3028 " Add principals to local keytab\n"
3029 " principal\tKerberos principal to add to "
3030 "keytab\n"));
3031 TALLOC_FREE(tmp_ctx);
3032 return -1;
3035 net_warn_member_options();
3037 d_printf(_("Processing principals to add...\n"));
3039 if (!c->explicit_credentials) {
3040 net_use_krb_machine_account(c);
3043 status = ads_startup(c, true, tmp_ctx, &ads);
3044 if (!ADS_ERR_OK(status)) {
3045 goto out;
3048 for (ret = 0, i = 0; i < argc; i++) {
3049 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3051 out:
3052 TALLOC_FREE(tmp_ctx);
3053 return ret;
3056 static int net_ads_keytab_add_default(struct net_context *c,
3057 int argc,
3058 const char **argv)
3060 return net_ads_keytab_add(c, argc, argv, false);
3063 static int net_ads_keytab_add_update_ads(struct net_context *c,
3064 int argc,
3065 const char **argv)
3067 return net_ads_keytab_add(c, argc, argv, true);
3070 static int net_ads_keytab_delete(struct net_context *c,
3071 int argc,
3072 const char **argv)
3074 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3075 ADS_STRUCT *ads = NULL;
3076 ADS_STATUS status;
3077 int i;
3078 int ret = -1;
3080 if (c->display_usage) {
3081 d_printf("%s\n%s",
3082 _("Usage:"),
3083 _("net ads keytab delete <principal> [principal ...]\n"
3084 " Remove entries for service principal, "
3085 " from the keytab file only."
3086 " Remove principals from local keytab\n"
3087 " principal\tKerberos principal to remove from "
3088 "keytab\n"));
3089 TALLOC_FREE(tmp_ctx);
3090 return -1;
3093 d_printf(_("Processing principals to delete...\n"));
3095 if (!c->explicit_credentials) {
3096 net_use_krb_machine_account(c);
3099 status = ads_startup(c, true, tmp_ctx, &ads);
3100 if (!ADS_ERR_OK(status)) {
3101 goto out;
3104 for (ret = 0, i = 0; i < argc; i++) {
3105 ret |= ads_keytab_delete_entry(ads, argv[i]);
3107 out:
3108 TALLOC_FREE(tmp_ctx);
3109 return ret;
3112 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3114 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3115 ADS_STRUCT *ads = NULL;
3116 ADS_STATUS status;
3117 int ret = -1;
3119 if (c->display_usage) {
3120 d_printf( "%s\n"
3121 "net ads keytab create\n"
3122 " %s\n",
3123 _("Usage:"),
3124 _("Create new default keytab"));
3125 TALLOC_FREE(tmp_ctx);
3126 return -1;
3129 net_warn_member_options();
3131 if (!c->explicit_credentials) {
3132 net_use_krb_machine_account(c);
3135 status = ads_startup(c, true, tmp_ctx, &ads);
3136 if (!ADS_ERR_OK(status)) {
3137 goto out;
3140 ret = ads_keytab_create_default(ads);
3141 out:
3142 TALLOC_FREE(tmp_ctx);
3143 return ret;
3146 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3148 const char *keytab = NULL;
3150 if (c->display_usage) {
3151 d_printf("%s\n%s",
3152 _("Usage:"),
3153 _("net ads keytab list [keytab]\n"
3154 " List a local keytab\n"
3155 " keytab\tKeytab to list\n"));
3156 return -1;
3159 if (argc >= 1) {
3160 keytab = argv[0];
3163 return ads_keytab_list(keytab);
3167 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3169 struct functable func[] = {
3171 "add",
3172 net_ads_keytab_add_default,
3173 NET_TRANSPORT_ADS,
3174 N_("Add a service principal"),
3175 N_("net ads keytab add\n"
3176 " Add a service principal, updates keytab file only.")
3179 "delete",
3180 net_ads_keytab_delete,
3181 NET_TRANSPORT_ADS,
3182 N_("Delete a service principal"),
3183 N_("net ads keytab delete\n"
3184 " Remove entries for service principal, from the keytab file only.")
3187 "add_update_ads",
3188 net_ads_keytab_add_update_ads,
3189 NET_TRANSPORT_ADS,
3190 N_("Add a service principal"),
3191 N_("net ads keytab add_update_ads\n"
3192 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3195 "create",
3196 net_ads_keytab_create,
3197 NET_TRANSPORT_ADS,
3198 N_("Create a fresh keytab"),
3199 N_("net ads keytab create\n"
3200 " Create a fresh keytab or update existing one.")
3203 "flush",
3204 net_ads_keytab_flush,
3205 NET_TRANSPORT_ADS,
3206 N_("Remove all keytab entries"),
3207 N_("net ads keytab flush\n"
3208 " Remove all keytab entries")
3211 "list",
3212 net_ads_keytab_list,
3213 NET_TRANSPORT_ADS,
3214 N_("List a keytab"),
3215 N_("net ads keytab list\n"
3216 " List a keytab")
3218 {NULL, NULL, 0, NULL, NULL}
3221 if (!USE_KERBEROS_KEYTAB) {
3222 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3223 "keytab method to use keytab functions.\n"));
3226 return net_run_function(c, argc, argv, "net ads keytab", func);
3229 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3231 int ret = -1;
3233 if (c->display_usage) {
3234 d_printf( "%s\n"
3235 "net ads kerberos renew\n"
3236 " %s\n",
3237 _("Usage:"),
3238 _("Renew TGT from existing credential cache"));
3239 return -1;
3242 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3243 if (ret) {
3244 d_printf(_("failed to renew kerberos ticket: %s\n"),
3245 error_message(ret));
3247 return ret;
3250 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3251 struct PAC_DATA_CTR **pac_data_ctr)
3253 NTSTATUS status;
3254 int ret = -1;
3255 const char *impersonate_princ_s = NULL;
3256 const char *local_service = NULL;
3257 const char *password = NULL;
3258 int i;
3260 for (i=0; i<argc; i++) {
3261 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3262 impersonate_princ_s = get_string_param(argv[i]);
3263 if (impersonate_princ_s == NULL) {
3264 return -1;
3267 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3268 local_service = get_string_param(argv[i]);
3269 if (local_service == NULL) {
3270 return -1;
3275 if (local_service == NULL) {
3276 local_service = talloc_asprintf(c, "%s$@%s",
3277 lp_netbios_name(), lp_realm());
3278 if (local_service == NULL) {
3279 goto out;
3283 password = cli_credentials_get_password(c->creds);
3285 status = kerberos_return_pac(c,
3286 c->opt_user_name,
3287 password,
3289 NULL,
3290 NULL,
3291 NULL,
3292 true,
3293 true,
3294 2592000, /* one month */
3295 impersonate_princ_s,
3296 local_service,
3297 NULL,
3298 NULL,
3299 pac_data_ctr);
3300 if (!NT_STATUS_IS_OK(status)) {
3301 d_printf(_("failed to query kerberos PAC: %s\n"),
3302 nt_errstr(status));
3303 goto out;
3306 ret = 0;
3307 out:
3308 return ret;
3311 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3313 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3314 int i, num_buffers;
3315 int ret = -1;
3316 enum PAC_TYPE type = 0;
3318 if (c->display_usage) {
3319 d_printf( "%s\n"
3320 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3321 " %s\n",
3322 _("Usage:"),
3323 _("Dump the Kerberos PAC"));
3324 return -1;
3327 for (i=0; i<argc; i++) {
3328 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3329 type = get_int_param(argv[i]);
3333 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3334 if (ret) {
3335 return ret;
3338 if (type == 0) {
3340 char *s = NULL;
3342 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3343 pac_data_ctr->pac_data);
3344 if (s != NULL) {
3345 d_printf(_("The Pac: %s\n"), s);
3346 talloc_free(s);
3349 return 0;
3352 num_buffers = pac_data_ctr->pac_data->num_buffers;
3354 for (i=0; i<num_buffers; i++) {
3356 char *s = NULL;
3358 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3359 continue;
3362 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3363 pac_data_ctr->pac_data->buffers[i].info);
3364 if (s != NULL) {
3365 d_printf(_("The Pac: %s\n"), s);
3366 talloc_free(s);
3368 break;
3371 return 0;
3374 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3376 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3377 char *filename = NULL;
3378 int ret = -1;
3379 int i;
3381 if (c->display_usage) {
3382 d_printf( "%s\n"
3383 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3384 " %s\n",
3385 _("Usage:"),
3386 _("Save the Kerberos PAC"));
3387 return -1;
3390 for (i=0; i<argc; i++) {
3391 if (strnequal(argv[i], "filename", strlen("filename"))) {
3392 filename = get_string_param(argv[i]);
3393 if (filename == NULL) {
3394 return -1;
3399 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3400 if (ret) {
3401 return ret;
3404 if (filename == NULL) {
3405 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3406 return -1;
3409 /* save the raw format */
3410 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3411 d_printf(_("failed to save PAC in %s\n"), filename);
3412 return -1;
3415 return 0;
3418 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3420 struct functable func[] = {
3422 "dump",
3423 net_ads_kerberos_pac_dump,
3424 NET_TRANSPORT_ADS,
3425 N_("Dump Kerberos PAC"),
3426 N_("net ads kerberos pac dump\n"
3427 " Dump a Kerberos PAC to stdout")
3430 "save",
3431 net_ads_kerberos_pac_save,
3432 NET_TRANSPORT_ADS,
3433 N_("Save Kerberos PAC"),
3434 N_("net ads kerberos pac save\n"
3435 " Save a Kerberos PAC in a file")
3438 {NULL, NULL, 0, NULL, NULL}
3441 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3444 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3446 int ret = -1;
3447 NTSTATUS status;
3448 const char *password = NULL;
3450 if (c->display_usage) {
3451 d_printf( "%s\n"
3452 "net ads kerberos kinit\n"
3453 " %s\n",
3454 _("Usage:"),
3455 _("Get Ticket Granting Ticket (TGT) for the user"));
3456 return -1;
3459 password = cli_credentials_get_password(c->creds);
3461 ret = kerberos_kinit_password_ext(c->opt_user_name,
3462 password,
3464 NULL,
3465 NULL,
3466 NULL,
3467 true,
3468 true,
3469 2592000, /* one month */
3470 NULL,
3471 NULL,
3472 NULL,
3473 &status);
3474 if (ret) {
3475 d_printf(_("failed to kinit password: %s\n"),
3476 nt_errstr(status));
3478 return ret;
3481 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3483 struct functable func[] = {
3485 "kinit",
3486 net_ads_kerberos_kinit,
3487 NET_TRANSPORT_ADS,
3488 N_("Retrieve Ticket Granting Ticket (TGT)"),
3489 N_("net ads kerberos kinit\n"
3490 " Receive Ticket Granting Ticket (TGT)")
3493 "renew",
3494 net_ads_kerberos_renew,
3495 NET_TRANSPORT_ADS,
3496 N_("Renew Ticket Granting Ticket from credential cache"),
3497 N_("net ads kerberos renew\n"
3498 " Renew Ticket Granting Ticket (TGT) from "
3499 "credential cache")
3502 "pac",
3503 net_ads_kerberos_pac,
3504 NET_TRANSPORT_ADS,
3505 N_("Dump Kerberos PAC"),
3506 N_("net ads kerberos pac\n"
3507 " Dump Kerberos PAC")
3509 {NULL, NULL, 0, NULL, NULL}
3512 return net_run_function(c, argc, argv, "net ads kerberos", func);
3515 static int net_ads_setspn_list(struct net_context *c,
3516 int argc,
3517 const char **argv)
3519 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3520 ADS_STRUCT *ads = NULL;
3521 ADS_STATUS status;
3522 bool ok = false;
3523 int ret = -1;
3525 if (c->display_usage) {
3526 d_printf("%s\n%s",
3527 _("Usage:"),
3528 _("net ads setspn list <machinename>\n"));
3529 TALLOC_FREE(tmp_ctx);
3530 return -1;
3533 status = ads_startup(c, true, tmp_ctx, &ads);
3534 if (!ADS_ERR_OK(status)) {
3535 goto out;
3538 if (argc) {
3539 ok = ads_setspn_list(ads, argv[0]);
3540 } else {
3541 ok = ads_setspn_list(ads, lp_netbios_name());
3544 ret = ok ? 0 : -1;
3545 out:
3546 TALLOC_FREE(tmp_ctx);
3547 return ret;
3550 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3552 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3553 ADS_STRUCT *ads = NULL;
3554 ADS_STATUS status;
3555 bool ok = false;
3556 int ret = -1;
3558 if (c->display_usage || argc < 1) {
3559 d_printf("%s\n%s",
3560 _("Usage:"),
3561 _("net ads setspn add <machinename> SPN\n"));
3562 TALLOC_FREE(tmp_ctx);
3563 return -1;
3566 status = ads_startup(c, true, tmp_ctx, &ads);
3567 if (!ADS_ERR_OK(status)) {
3568 goto out;
3571 if (argc > 1) {
3572 ok = ads_setspn_add(ads, argv[0], argv[1]);
3573 } else {
3574 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3577 ret = ok ? 0 : -1;
3578 out:
3579 TALLOC_FREE(tmp_ctx);
3580 return ret;
3583 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3585 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3586 ADS_STRUCT *ads = NULL;
3587 ADS_STATUS status;
3588 bool ok = false;
3589 int ret = -1;
3591 if (c->display_usage || argc < 1) {
3592 d_printf("%s\n%s",
3593 _("Usage:"),
3594 _("net ads setspn delete <machinename> SPN\n"));
3595 TALLOC_FREE(tmp_ctx);
3596 return -1;
3599 status = ads_startup(c, true, tmp_ctx, &ads);
3600 if (!ADS_ERR_OK(status)) {
3601 goto out;
3604 if (argc > 1) {
3605 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3606 } else {
3607 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3610 ret = ok ? 0 : -1;
3611 out:
3612 TALLOC_FREE(tmp_ctx);
3613 return ret;
3616 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3618 struct functable func[] = {
3620 "list",
3621 net_ads_setspn_list,
3622 NET_TRANSPORT_ADS,
3623 N_("List Service Principal Names (SPN)"),
3624 N_("net ads setspn list machine\n"
3625 " List Service Principal Names (SPN)")
3628 "add",
3629 net_ads_setspn_add,
3630 NET_TRANSPORT_ADS,
3631 N_("Add Service Principal Names (SPN)"),
3632 N_("net ads setspn add machine spn\n"
3633 " Add Service Principal Names (SPN)")
3636 "delete",
3637 net_ads_setspn_delete,
3638 NET_TRANSPORT_ADS,
3639 N_("Delete Service Principal Names (SPN)"),
3640 N_("net ads setspn delete machine spn\n"
3641 " Delete Service Principal Names (SPN)")
3643 {NULL, NULL, 0, NULL, NULL}
3646 return net_run_function(c, argc, argv, "net ads setspn", func);
3649 static int net_ads_enctype_lookup_account(struct net_context *c,
3650 ADS_STRUCT *ads,
3651 const char *account,
3652 LDAPMessage **res,
3653 const char **enctype_str)
3655 const char *filter;
3656 const char *attrs[] = {
3657 "msDS-SupportedEncryptionTypes",
3658 NULL
3660 int count;
3661 int ret = -1;
3662 ADS_STATUS status;
3664 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3665 account);
3666 if (filter == NULL) {
3667 goto done;
3670 status = ads_search(ads, res, filter, attrs);
3671 if (!ADS_ERR_OK(status)) {
3672 d_printf(_("no account found with filter: %s\n"), filter);
3673 goto done;
3676 count = ads_count_replies(ads, *res);
3677 switch (count) {
3678 case 1:
3679 break;
3680 case 0:
3681 d_printf(_("no account found with filter: %s\n"), filter);
3682 goto done;
3683 default:
3684 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3685 goto done;
3688 if (enctype_str) {
3689 *enctype_str = ads_pull_string(ads, c, *res,
3690 "msDS-SupportedEncryptionTypes");
3691 if (*enctype_str == NULL) {
3692 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3693 goto done;
3697 ret = 0;
3698 done:
3699 return ret;
3702 static void net_ads_enctype_dump_enctypes(const char *username,
3703 const char *enctype_str)
3705 int enctypes = atoi(enctype_str);
3707 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3708 username, enctypes, enctypes);
3710 printf("[%s] 0x%08x DES-CBC-CRC\n",
3711 enctypes & ENC_CRC32 ? "X" : " ",
3712 ENC_CRC32);
3713 printf("[%s] 0x%08x DES-CBC-MD5\n",
3714 enctypes & ENC_RSA_MD5 ? "X" : " ",
3715 ENC_RSA_MD5);
3716 printf("[%s] 0x%08x RC4-HMAC\n",
3717 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3718 ENC_RC4_HMAC_MD5);
3719 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3720 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3721 ENC_HMAC_SHA1_96_AES128);
3722 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3723 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3724 ENC_HMAC_SHA1_96_AES256);
3725 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3726 enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3727 ENC_HMAC_SHA1_96_AES256_SK);
3728 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3729 enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3730 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3733 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3735 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3736 ADS_STATUS status;
3737 ADS_STRUCT *ads = NULL;
3738 LDAPMessage *res = NULL;
3739 const char *str = NULL;
3740 int ret = -1;
3742 if (c->display_usage || (argc < 1)) {
3743 d_printf( "%s\n"
3744 "net ads enctypes list\n"
3745 " %s\n",
3746 _("Usage:"),
3747 _("List supported enctypes"));
3748 TALLOC_FREE(tmp_ctx);
3749 return -1;
3752 status = ads_startup(c, false, tmp_ctx, &ads);
3753 if (!ADS_ERR_OK(status)) {
3754 goto out;
3757 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3758 if (ret) {
3759 goto out;
3762 net_ads_enctype_dump_enctypes(argv[0], str);
3764 ret = 0;
3765 out:
3766 ads_msgfree(ads, res);
3767 TALLOC_FREE(tmp_ctx);
3768 return ret;
3771 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3773 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3774 int ret = -1;
3775 ADS_STATUS status;
3776 ADS_STRUCT *ads = NULL;
3777 LDAPMessage *res = NULL;
3778 const char *etype_list_str = NULL;
3779 const char *dn = NULL;
3780 ADS_MODLIST mods = NULL;
3781 uint32_t etype_list;
3782 const char *str = NULL;
3784 if (c->display_usage || argc < 1) {
3785 d_printf( "%s\n"
3786 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3787 " %s\n",
3788 _("Usage:"),
3789 _("Set supported enctypes"));
3790 TALLOC_FREE(tmp_ctx);
3791 return -1;
3794 status = ads_startup(c, false, tmp_ctx, &ads);
3795 if (!ADS_ERR_OK(status)) {
3796 goto done;
3799 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3800 if (ret) {
3801 goto done;
3804 dn = ads_get_dn(ads, tmp_ctx, res);
3805 if (dn == NULL) {
3806 goto done;
3809 etype_list = 0;
3810 etype_list |= ENC_RC4_HMAC_MD5;
3811 etype_list |= ENC_HMAC_SHA1_96_AES128;
3812 etype_list |= ENC_HMAC_SHA1_96_AES256;
3814 if (argv[1] != NULL) {
3815 sscanf(argv[1], "%i", &etype_list);
3818 etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3819 if (!etype_list_str) {
3820 goto done;
3823 mods = ads_init_mods(tmp_ctx);
3824 if (!mods) {
3825 goto done;
3828 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3829 etype_list_str);
3830 if (!ADS_ERR_OK(status)) {
3831 goto done;
3834 status = ads_gen_mod(ads, dn, mods);
3835 if (!ADS_ERR_OK(status)) {
3836 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3837 ads_errstr(status));
3838 goto done;
3841 ads_msgfree(ads, res);
3842 res = NULL;
3844 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3845 if (ret) {
3846 goto done;
3849 net_ads_enctype_dump_enctypes(argv[0], str);
3851 ret = 0;
3852 done:
3853 ads_msgfree(ads, res);
3854 TALLOC_FREE(tmp_ctx);
3855 return ret;
3858 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3860 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3861 int ret = -1;
3862 ADS_STATUS status;
3863 ADS_STRUCT *ads = NULL;
3864 LDAPMessage *res = NULL;
3865 const char *dn = NULL;
3866 ADS_MODLIST mods = NULL;
3868 if (c->display_usage || argc < 1) {
3869 d_printf( "%s\n"
3870 "net ads enctypes delete <sAMAccountName>\n"
3871 " %s\n",
3872 _("Usage:"),
3873 _("Delete supported enctypes"));
3874 TALLOC_FREE(tmp_ctx);
3875 return -1;
3878 status = ads_startup(c, false, tmp_ctx, &ads);
3879 if (!ADS_ERR_OK(status)) {
3880 goto done;
3883 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3884 if (ret) {
3885 goto done;
3888 dn = ads_get_dn(ads, tmp_ctx, res);
3889 if (dn == NULL) {
3890 goto done;
3893 mods = ads_init_mods(tmp_ctx);
3894 if (!mods) {
3895 goto done;
3898 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3899 if (!ADS_ERR_OK(status)) {
3900 goto done;
3903 status = ads_gen_mod(ads, dn, mods);
3904 if (!ADS_ERR_OK(status)) {
3905 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3906 ads_errstr(status));
3907 goto done;
3910 ret = 0;
3912 done:
3913 ads_msgfree(ads, res);
3914 TALLOC_FREE(tmp_ctx);
3915 return ret;
3918 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3920 struct functable func[] = {
3922 "list",
3923 net_ads_enctypes_list,
3924 NET_TRANSPORT_ADS,
3925 N_("List the supported encryption types"),
3926 N_("net ads enctypes list\n"
3927 " List the supported encryption types")
3930 "set",
3931 net_ads_enctypes_set,
3932 NET_TRANSPORT_ADS,
3933 N_("Set the supported encryption types"),
3934 N_("net ads enctypes set\n"
3935 " Set the supported encryption types")
3938 "delete",
3939 net_ads_enctypes_delete,
3940 NET_TRANSPORT_ADS,
3941 N_("Delete the supported encryption types"),
3942 N_("net ads enctypes delete\n"
3943 " Delete the supported encryption types")
3946 {NULL, NULL, 0, NULL, NULL}
3949 return net_run_function(c, argc, argv, "net ads enctypes", func);
3953 int net_ads(struct net_context *c, int argc, const char **argv)
3955 struct functable func[] = {
3957 "info",
3958 net_ads_info,
3959 NET_TRANSPORT_ADS,
3960 N_("Display details on remote ADS server"),
3961 N_("net ads info\n"
3962 " Display details on remote ADS server")
3965 "join",
3966 net_ads_join,
3967 NET_TRANSPORT_ADS,
3968 N_("Join the local machine to ADS realm"),
3969 N_("net ads join\n"
3970 " Join the local machine to ADS realm")
3973 "testjoin",
3974 net_ads_testjoin,
3975 NET_TRANSPORT_ADS,
3976 N_("Validate machine account"),
3977 N_("net ads testjoin\n"
3978 " Validate machine account")
3981 "leave",
3982 net_ads_leave,
3983 NET_TRANSPORT_ADS,
3984 N_("Remove the local machine from ADS"),
3985 N_("net ads leave\n"
3986 " Remove the local machine from ADS")
3989 "status",
3990 net_ads_status,
3991 NET_TRANSPORT_ADS,
3992 N_("Display machine account details"),
3993 N_("net ads status\n"
3994 " Display machine account details")
3997 "user",
3998 net_ads_user,
3999 NET_TRANSPORT_ADS,
4000 N_("List/modify users"),
4001 N_("net ads user\n"
4002 " List/modify users")
4005 "group",
4006 net_ads_group,
4007 NET_TRANSPORT_ADS,
4008 N_("List/modify groups"),
4009 N_("net ads group\n"
4010 " List/modify groups")
4013 "dns",
4014 net_ads_dns,
4015 NET_TRANSPORT_ADS,
4016 N_("Issue dynamic DNS update"),
4017 N_("net ads dns\n"
4018 " Issue dynamic DNS update")
4021 "password",
4022 net_ads_password,
4023 NET_TRANSPORT_ADS,
4024 N_("Change user passwords"),
4025 N_("net ads password\n"
4026 " Change user passwords")
4029 "changetrustpw",
4030 net_ads_changetrustpw,
4031 NET_TRANSPORT_ADS,
4032 N_("Change trust account password"),
4033 N_("net ads changetrustpw\n"
4034 " Change trust account password")
4037 "printer",
4038 net_ads_printer,
4039 NET_TRANSPORT_ADS,
4040 N_("List/modify printer entries"),
4041 N_("net ads printer\n"
4042 " List/modify printer entries")
4045 "search",
4046 net_ads_search,
4047 NET_TRANSPORT_ADS,
4048 N_("Issue LDAP search using filter"),
4049 N_("net ads search\n"
4050 " Issue LDAP search using filter")
4053 "dn",
4054 net_ads_dn,
4055 NET_TRANSPORT_ADS,
4056 N_("Issue LDAP search by DN"),
4057 N_("net ads dn\n"
4058 " Issue LDAP search by DN")
4061 "sid",
4062 net_ads_sid,
4063 NET_TRANSPORT_ADS,
4064 N_("Issue LDAP search by SID"),
4065 N_("net ads sid\n"
4066 " Issue LDAP search by SID")
4069 "workgroup",
4070 net_ads_workgroup,
4071 NET_TRANSPORT_ADS,
4072 N_("Display workgroup name"),
4073 N_("net ads workgroup\n"
4074 " Display the workgroup name")
4077 "lookup",
4078 net_ads_lookup,
4079 NET_TRANSPORT_ADS,
4080 N_("Perform CLDAP query on DC"),
4081 N_("net ads lookup\n"
4082 " Find the ADS DC using CLDAP lookups")
4085 "keytab",
4086 net_ads_keytab,
4087 NET_TRANSPORT_ADS,
4088 N_("Manage local keytab file"),
4089 N_("net ads keytab\n"
4090 " Manage local keytab file")
4093 "setspn",
4094 net_ads_setspn,
4095 NET_TRANSPORT_ADS,
4096 N_("Manage Service Principal Names (SPN)s"),
4097 N_("net ads spnset\n"
4098 " Manage Service Principal Names (SPN)s")
4101 "gpo",
4102 net_ads_gpo,
4103 NET_TRANSPORT_ADS,
4104 N_("Manage group policy objects"),
4105 N_("net ads gpo\n"
4106 " Manage group policy objects")
4109 "kerberos",
4110 net_ads_kerberos,
4111 NET_TRANSPORT_ADS,
4112 N_("Manage kerberos keytab"),
4113 N_("net ads kerberos\n"
4114 " Manage kerberos keytab")
4117 "enctypes",
4118 net_ads_enctypes,
4119 NET_TRANSPORT_ADS,
4120 N_("List/modify supported encryption types"),
4121 N_("net ads enctypes\n"
4122 " List/modify enctypes")
4124 {NULL, NULL, 0, NULL, NULL}
4127 return net_run_function(c, argc, argv, "net ads", func);
4130 #else
4132 static int net_ads_noads(void)
4134 d_fprintf(stderr, _("ADS support not compiled in\n"));
4135 return -1;
4138 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4140 return net_ads_noads();
4143 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4145 return net_ads_noads();
4148 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4150 return net_ads_noads();
4153 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4155 return net_ads_noads();
4158 int net_ads_join(struct net_context *c, int argc, const char **argv)
4160 return net_ads_noads();
4163 int net_ads_user(struct net_context *c, int argc, const char **argv)
4165 return net_ads_noads();
4168 int net_ads_group(struct net_context *c, int argc, const char **argv)
4170 return net_ads_noads();
4173 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4175 return net_ads_noads();
4178 /* this one shouldn't display a message */
4179 int net_ads_check(struct net_context *c)
4181 return -1;
4184 int net_ads_check_our_domain(struct net_context *c)
4186 return -1;
4189 int net_ads(struct net_context *c, int argc, const char **argv)
4191 return net_ads_noads();
4194 #endif /* HAVE_ADS */