s3:utils: Fix code spelling
[Samba.git] / source3 / utils / net_ads.c
blob4f3d754a095c54fb1e00cde15305f4c98a3c8d90
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"
46 #ifdef HAVE_JANSSON
47 #include <jansson.h>
48 #include "audit_logging.h" /* various JSON helpers */
49 #include "auth/common_auth.h"
50 #endif /* [HAVE_JANSSON] */
52 #ifdef HAVE_ADS
54 /* when we do not have sufficient input parameters to contact a remote domain
55 * we always fall back to our own realm - Guenther*/
57 static const char *assume_own_realm(struct net_context *c)
59 if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
60 return lp_realm();
63 return NULL;
66 #ifdef HAVE_JANSSON
69 * note: JSON output deliberately bypasses gettext so as to provide the same
70 * output irrespective of the locale.
73 static int output_json(const struct json_object *jsobj)
75 TALLOC_CTX *ctx = NULL;
76 char *json = NULL;
78 if (json_is_invalid(jsobj)) {
79 return -1;
82 ctx = talloc_new(NULL);
83 if (ctx == NULL) {
84 d_fprintf(stderr, _("Out of memory\n"));
85 return -1;
88 json = json_to_string(ctx, jsobj);
89 if (!json) {
90 d_fprintf(stderr, _("error encoding to JSON\n"));
91 return -1;
94 d_printf("%s\n", json);
95 TALLOC_FREE(ctx);
97 return 0;
100 static int net_ads_cldap_netlogon_json
101 (ADS_STRUCT *ads,
102 const char *addr,
103 const struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply)
105 struct json_object jsobj = json_new_object();
106 struct json_object flagsobj = json_new_object();
107 char response_type [32] = { '\0' };
108 int ret = 0;
110 if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
111 d_fprintf(stderr, _("error setting up JSON value\n"));
113 goto failure;
116 switch (reply->command) {
117 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
118 strncpy(response_type,
119 "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
120 sizeof(response_type));
121 break;
122 case LOGON_SAM_LOGON_RESPONSE_EX:
123 strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
124 sizeof(response_type));
125 break;
126 default:
127 snprintf(response_type, sizeof(response_type), "0x%x",
128 reply->command);
129 break;
132 ret = json_add_string(&jsobj, "Information for Domain Controller",
133 addr);
134 if (ret != 0) {
135 goto failure;
138 ret = json_add_string(&jsobj, "Response Type", response_type);
139 if (ret != 0) {
140 goto failure;
143 ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
144 if (ret != 0) {
145 goto failure;
148 ret = json_add_bool(&flagsobj, "Is a PDC",
149 reply->server_type & NBT_SERVER_PDC);
150 if (ret != 0) {
151 goto failure;
154 ret = json_add_bool(&flagsobj, "Is a GC of the forest",
155 reply->server_type & NBT_SERVER_GC);
156 if (ret != 0) {
157 goto failure;
160 ret = json_add_bool(&flagsobj, "Is an LDAP server",
161 reply->server_type & NBT_SERVER_LDAP);
162 if (ret != 0) {
163 goto failure;
166 ret = json_add_bool(&flagsobj, "Supports DS",
167 reply->server_type & NBT_SERVER_DS);
168 if (ret != 0) {
169 goto failure;
172 ret = json_add_bool(&flagsobj, "Is running a KDC",
173 reply->server_type & NBT_SERVER_KDC);
174 if (ret != 0) {
175 goto failure;
178 ret = json_add_bool(&flagsobj, "Is running time services",
179 reply->server_type & NBT_SERVER_TIMESERV);
180 if (ret != 0) {
181 goto failure;
184 ret = json_add_bool(&flagsobj, "Is the closest DC",
185 reply->server_type & NBT_SERVER_CLOSEST);
186 if (ret != 0) {
187 goto failure;
190 ret = json_add_bool(&flagsobj, "Is writable",
191 reply->server_type & NBT_SERVER_WRITABLE);
192 if (ret != 0) {
193 goto failure;
196 ret = json_add_bool(&flagsobj, "Has a hardware clock",
197 reply->server_type & NBT_SERVER_GOOD_TIMESERV);
198 if (ret != 0) {
199 goto failure;
202 ret = json_add_bool(&flagsobj,
203 "Is a non-domain NC serviced by LDAP server",
204 reply->server_type & NBT_SERVER_NDNC);
205 if (ret != 0) {
206 goto failure;
209 ret = json_add_bool
210 (&flagsobj, "Is NT6 DC that has some secrets",
211 reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
212 if (ret != 0) {
213 goto failure;
216 ret = json_add_bool
217 (&flagsobj, "Is NT6 DC that has all secrets",
218 reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
219 if (ret != 0) {
220 goto failure;
223 ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services",
224 reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
225 if (ret != 0) {
226 goto failure;
229 ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later",
230 reply->server_type & NBT_SERVER_DS_8);
231 if (ret != 0) {
232 goto failure;
235 ret = json_add_bool(&flagsobj, "Runs on Windows 2012R2 or later",
236 reply->server_type & NBT_SERVER_DS_9);
237 if (ret != 0) {
238 goto failure;
241 ret = json_add_bool(&flagsobj, "Runs on Windows 2016 or later",
242 reply->server_type & NBT_SERVER_DS_10);
243 if (ret != 0) {
244 goto failure;
247 ret = json_add_bool(&flagsobj, "Has a DNS name",
248 reply->server_type & NBT_SERVER_HAS_DNS_NAME);
249 if (ret != 0) {
250 goto failure;
253 ret = json_add_bool(&flagsobj, "Is a default NC",
254 reply->server_type & NBT_SERVER_IS_DEFAULT_NC);
255 if (ret != 0) {
256 goto failure;
259 ret = json_add_bool(&flagsobj, "Is the forest root",
260 reply->server_type & NBT_SERVER_FOREST_ROOT);
261 if (ret != 0) {
262 goto failure;
265 ret = json_add_string(&jsobj, "Forest", reply->forest);
266 if (ret != 0) {
267 goto failure;
270 ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
271 if (ret != 0) {
272 goto failure;
275 ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
276 if (ret != 0) {
277 goto failure;
281 ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
282 if (ret != 0) {
283 goto failure;
286 ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
287 if (ret != 0) {
288 goto failure;
291 if (*reply->user_name) {
292 ret = json_add_string(&jsobj, "User name", reply->user_name);
293 if (ret != 0) {
294 goto failure;
298 ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
299 if (ret != 0) {
300 goto failure;
303 ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
304 if (ret != 0) {
305 goto failure;
308 ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
309 if (ret != 0) {
310 goto failure;
313 ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
314 if (ret != 0) {
315 goto failure;
318 ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
319 if (ret != 0) {
320 goto failure;
323 ret = json_add_object(&jsobj, "Flags", &flagsobj);
324 if (ret != 0) {
325 goto failure;
328 ret = output_json(&jsobj);
329 json_free(&jsobj); /* frees flagsobj recursively */
331 return ret;
333 failure:
334 json_free(&flagsobj);
335 json_free(&jsobj);
337 return ret;
340 #else /* [HAVE_JANSSON] */
342 static int net_ads_cldap_netlogon_json
343 (ADS_STRUCT *ads,
344 const char *addr,
345 const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
347 d_fprintf(stderr, _("JSON support not available\n"));
349 return -1;
352 #endif /* [HAVE_JANSSON] */
355 do a cldap netlogon query
357 static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
359 char addr[INET6_ADDRSTRLEN];
360 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
362 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
364 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
365 d_fprintf(stderr, _("CLDAP query failed!\n"));
366 return -1;
369 if (c->opt_json) {
370 return net_ads_cldap_netlogon_json(ads, addr, &reply);
373 d_printf(_("Information for Domain Controller: %s\n\n"),
374 addr);
376 d_printf(_("Response Type: "));
377 switch (reply.command) {
378 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
379 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
380 break;
381 case LOGON_SAM_LOGON_RESPONSE_EX:
382 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
383 break;
384 default:
385 d_printf("0x%x\n", reply.command);
386 break;
389 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
391 d_printf(_("Flags:\n"
392 "\tIs a PDC: %s\n"
393 "\tIs a GC of the forest: %s\n"
394 "\tIs an LDAP server: %s\n"
395 "\tSupports DS: %s\n"
396 "\tIs running a KDC: %s\n"
397 "\tIs running time services: %s\n"
398 "\tIs the closest DC: %s\n"
399 "\tIs writable: %s\n"
400 "\tHas a hardware clock: %s\n"
401 "\tIs a non-domain NC serviced by LDAP server: %s\n"
402 "\tIs NT6 DC that has some secrets: %s\n"
403 "\tIs NT6 DC that has all secrets: %s\n"
404 "\tRuns Active Directory Web Services: %s\n"
405 "\tRuns on Windows 2012 or later: %s\n"
406 "\tRuns on Windows 2012R2 or later: %s\n"
407 "\tRuns on Windows 2016 or later: %s\n"
408 "\tHas a DNS name: %s\n"
409 "\tIs a default NC: %s\n"
410 "\tIs the forest root: %s\n"),
411 (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
412 (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
413 (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
414 (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
415 (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
416 (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
417 (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
418 (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
419 (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
420 (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
421 (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
422 (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
423 (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
424 (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"),
425 (reply.server_type & NBT_SERVER_DS_9) ? _("yes") : _("no"),
426 (reply.server_type & NBT_SERVER_DS_10) ? _("yes") : _("no"),
427 (reply.server_type & NBT_SERVER_HAS_DNS_NAME) ? _("yes") : _("no"),
428 (reply.server_type & NBT_SERVER_IS_DEFAULT_NC) ? _("yes") : _("no"),
429 (reply.server_type & NBT_SERVER_FOREST_ROOT) ? _("yes") : _("no"));
432 printf(_("Forest: %s\n"), reply.forest);
433 printf(_("Domain: %s\n"), reply.dns_domain);
434 printf(_("Domain Controller: %s\n"), reply.pdc_dns_name);
436 printf(_("Pre-Win2k Domain: %s\n"), reply.domain_name);
437 printf(_("Pre-Win2k Hostname: %s\n"), reply.pdc_name);
439 if (*reply.user_name) printf(_("User name: %s\n"), reply.user_name);
441 printf(_("Server Site Name: %s\n"), reply.server_site);
442 printf(_("Client Site Name: %s\n"), reply.client_site);
444 d_printf(_("NT Version: %d\n"), reply.nt_version);
445 d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
446 d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
448 return 0;
452 this implements the CLDAP based netlogon lookup requests
453 for finding the domain controller of a ADS domain
455 static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
457 TALLOC_CTX *tmp_ctx = talloc_stackframe();
458 ADS_STRUCT *ads = NULL;
459 ADS_STATUS status;
460 int ret = -1;
462 if (c->display_usage) {
463 d_printf("%s\n"
464 "net ads lookup\n"
465 " %s",
466 _("Usage:"),
467 _("Find the ADS DC using CLDAP lookup.\n"));
468 TALLOC_FREE(tmp_ctx);
469 return -1;
472 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
473 if (!ADS_ERR_OK(status)) {
474 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
475 goto out;
478 if (!ads->config.realm) {
479 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
480 if (ads->config.realm == NULL) {
481 d_fprintf(stderr, _("Out of memory\n"));
482 goto out;
484 ads->ldap.port = 389;
487 ret = net_ads_cldap_netlogon(c, ads);
488 out:
489 TALLOC_FREE(tmp_ctx);
490 return ret;
494 #ifdef HAVE_JANSSON
496 static int net_ads_info_json(ADS_STRUCT *ads)
498 int ret = 0;
499 char addr[INET6_ADDRSTRLEN];
500 time_t pass_time;
501 struct json_object jsobj = json_new_object();
503 if (json_is_invalid(&jsobj)) {
504 d_fprintf(stderr, _("error setting up JSON value\n"));
506 goto failure;
509 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
511 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
513 ret = json_add_string (&jsobj, "LDAP server", addr);
514 if (ret != 0) {
515 goto failure;
518 ret = json_add_string (&jsobj, "LDAP server name",
519 ads->config.ldap_server_name);
520 if (ret != 0) {
521 goto failure;
524 ret = json_add_string (&jsobj, "Realm", ads->config.realm);
525 if (ret != 0) {
526 goto failure;
529 ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
530 if (ret != 0) {
531 goto failure;
534 ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
535 if (ret != 0) {
536 goto failure;
539 ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
540 if (ret != 0) {
541 goto failure;
544 ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
545 if (ret != 0) {
546 goto failure;
549 ret = json_add_int (&jsobj, "Server time offset",
550 ads->auth.time_offset);
551 if (ret != 0) {
552 goto failure;
555 ret = json_add_int (&jsobj, "Last machine account password change",
556 pass_time);
557 if (ret != 0) {
558 goto failure;
561 ret = output_json(&jsobj);
562 failure:
563 json_free(&jsobj);
565 return ret;
568 #else /* [HAVE_JANSSON] */
570 static int net_ads_info_json(ADS_STRUCT *ads)
572 d_fprintf(stderr, _("JSON support not available\n"));
574 return -1;
577 #endif /* [HAVE_JANSSON] */
581 static int net_ads_info(struct net_context *c, int argc, const char **argv)
583 TALLOC_CTX *tmp_ctx = talloc_stackframe();
584 ADS_STRUCT *ads = NULL;
585 ADS_STATUS status;
586 char addr[INET6_ADDRSTRLEN];
587 time_t pass_time;
588 int ret = -1;
590 if (c->display_usage) {
591 d_printf("%s\n"
592 "net ads info\n"
593 " %s",
594 _("Usage:"),
595 _("Display information about an Active Directory "
596 "server.\n"));
597 TALLOC_FREE(tmp_ctx);
598 return -1;
601 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
602 if (!ADS_ERR_OK(status)) {
603 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
604 goto out;
607 if (!ads || !ads->config.realm) {
608 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
609 goto out;
612 /* Try to set the server's current time since we didn't do a full
613 TCP LDAP session initially */
615 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
616 d_fprintf( stderr, _("Failed to get server's current time!\n"));
619 if (c->opt_json) {
620 ret = net_ads_info_json(ads);
621 goto out;
624 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
626 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
628 d_printf(_("LDAP server: %s\n"), addr);
629 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
630 d_printf(_("Realm: %s\n"), ads->config.realm);
631 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
632 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
633 d_printf(_("Server time: %s\n"),
634 http_timestring(tmp_ctx, ads->config.current_time));
636 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
637 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
639 d_printf(_("Last machine account password change: %s\n"),
640 http_timestring(tmp_ctx, pass_time));
642 ret = 0;
643 out:
644 TALLOC_FREE(tmp_ctx);
645 return ret;
648 static ADS_STATUS ads_startup_int(struct net_context *c,
649 bool only_own_domain,
650 uint32_t auth_flags,
651 TALLOC_CTX *mem_ctx,
652 ADS_STRUCT **ads_ret)
654 ADS_STRUCT *ads = NULL;
655 ADS_STATUS status;
656 bool need_password = false;
657 bool second_time = false;
658 char *cp;
659 const char *realm = NULL;
660 bool tried_closest_dc = false;
661 enum credentials_use_kerberos krb5_state =
662 CRED_USE_KERBEROS_DISABLED;
664 /* lp_realm() should be handled by a command line param,
665 However, the join requires that realm be set in smb.conf
666 and compares our realm with the remote server's so this is
667 ok until someone needs more flexibility */
669 *ads_ret = NULL;
671 retry_connect:
672 if (only_own_domain) {
673 realm = lp_realm();
674 } else {
675 realm = assume_own_realm(c);
678 ads = ads_init(mem_ctx,
679 realm,
680 c->opt_target_workgroup,
681 c->opt_host,
682 ADS_SASL_PLAIN);
683 if (ads == NULL) {
684 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
687 if (!c->opt_user_name) {
688 c->opt_user_name = "administrator";
691 if (c->opt_user_specified) {
692 need_password = true;
695 retry:
696 if (!c->opt_password && need_password && !c->opt_machine_pass) {
697 c->opt_password = net_prompt_pass(c, c->opt_user_name);
698 if (!c->opt_password) {
699 TALLOC_FREE(ads);
700 return ADS_ERROR(LDAP_NO_MEMORY);
704 if (c->opt_password) {
705 use_in_memory_ccache();
706 ADS_TALLOC_CONST_FREE(ads->auth.password);
707 ads->auth.password = talloc_strdup(ads, c->opt_password);
708 if (ads->auth.password == NULL) {
709 TALLOC_FREE(ads);
710 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
714 ADS_TALLOC_CONST_FREE(ads->auth.user_name);
715 ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
716 if (ads->auth.user_name == NULL) {
717 TALLOC_FREE(ads);
718 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
721 ads->auth.flags |= auth_flags;
723 /* The ADS code will handle FIPS mode */
724 krb5_state = cli_credentials_get_kerberos_state(c->creds);
725 switch (krb5_state) {
726 case CRED_USE_KERBEROS_REQUIRED:
727 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
728 ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
729 break;
730 case CRED_USE_KERBEROS_DESIRED:
731 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
732 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
733 break;
734 case CRED_USE_KERBEROS_DISABLED:
735 ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
736 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
737 break;
741 * If the username is of the form "name@realm",
742 * extract the realm and convert to upper case.
743 * This is only used to establish the connection.
745 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
746 *cp++ = '\0';
747 ADS_TALLOC_CONST_FREE(ads->auth.realm);
748 ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
749 if (ads->auth.realm == NULL) {
750 TALLOC_FREE(ads);
751 return ADS_ERROR(LDAP_NO_MEMORY);
753 } else if (ads->auth.realm == NULL) {
754 const char *c_realm = cli_credentials_get_realm(c->creds);
756 if (c_realm != NULL) {
757 ads->auth.realm = talloc_strdup(ads, c_realm);
758 if (ads->auth.realm == NULL) {
759 TALLOC_FREE(ads);
760 return ADS_ERROR(LDAP_NO_MEMORY);
765 status = ads_connect(ads);
767 if (!ADS_ERR_OK(status)) {
769 if (NT_STATUS_EQUAL(ads_ntstatus(status),
770 NT_STATUS_NO_LOGON_SERVERS)) {
771 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
772 TALLOC_FREE(ads);
773 return status;
776 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
777 need_password = true;
778 second_time = true;
779 goto retry;
780 } else {
781 TALLOC_FREE(ads);
782 return status;
786 /* when contacting our own domain, make sure we use the closest DC.
787 * This is done by reconnecting to ADS because only the first call to
788 * ads_connect will give us our own sitename */
790 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
792 tried_closest_dc = true; /* avoid loop */
794 if (!ads_closest_dc(ads)) {
796 namecache_delete(ads->server.realm, 0x1C);
797 namecache_delete(ads->server.workgroup, 0x1C);
799 TALLOC_FREE(ads);
801 goto retry_connect;
805 *ads_ret = talloc_move(mem_ctx, &ads);
806 return status;
809 ADS_STATUS ads_startup(struct net_context *c,
810 bool only_own_domain,
811 TALLOC_CTX *mem_ctx,
812 ADS_STRUCT **ads)
814 return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
817 ADS_STATUS ads_startup_nobind(struct net_context *c,
818 bool only_own_domain,
819 TALLOC_CTX *mem_ctx,
820 ADS_STRUCT **ads)
822 return ads_startup_int(c,
823 only_own_domain,
824 ADS_AUTH_NO_BIND,
825 mem_ctx,
826 ads);
830 Check to see if connection can be made via ads.
831 ads_startup() stores the password in opt_password if it needs to so
832 that rpc or rap can use it without re-prompting.
834 static int net_ads_check_int(struct net_context *c,
835 const char *realm,
836 const char *workgroup,
837 const char *host)
839 TALLOC_CTX *tmp_ctx = talloc_stackframe();
840 ADS_STRUCT *ads;
841 ADS_STATUS status;
842 int ret = -1;
844 ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
845 if (ads == NULL) {
846 goto out;
849 ads->auth.flags |= ADS_AUTH_NO_BIND;
851 status = ads_connect(ads);
852 if ( !ADS_ERR_OK(status) ) {
853 goto out;
856 ret = 0;
857 out:
858 TALLOC_FREE(tmp_ctx);
859 return ret;
862 int net_ads_check_our_domain(struct net_context *c)
864 return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
867 int net_ads_check(struct net_context *c)
869 return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
873 determine the netbios workgroup name for a domain
875 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
877 TALLOC_CTX *tmp_ctx = talloc_stackframe();
878 ADS_STRUCT *ads = NULL;
879 ADS_STATUS status;
880 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
881 bool ok = false;
882 int ret = -1;
884 if (c->display_usage) {
885 d_printf ("%s\n"
886 "net ads workgroup\n"
887 " %s\n",
888 _("Usage:"),
889 _("Print the workgroup name"));
890 TALLOC_FREE(tmp_ctx);
891 return -1;
894 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
895 if (!ADS_ERR_OK(status)) {
896 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
897 goto out;
900 if (!ads->config.realm) {
901 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
902 if (ads->config.realm == NULL) {
903 d_fprintf(stderr, _("Out of memory\n"));
904 goto out;
906 ads->ldap.port = 389;
909 ok = ads_cldap_netlogon_5(tmp_ctx,
910 &ads->ldap.ss, ads->server.realm, &reply);
911 if (!ok) {
912 d_fprintf(stderr, _("CLDAP query failed!\n"));
913 goto out;
916 d_printf(_("Workgroup: %s\n"), reply.domain_name);
918 ret = 0;
919 out:
920 TALLOC_FREE(tmp_ctx);
922 return ret;
927 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
929 char **disp_fields = (char **) data_area;
931 if (!field) { /* must be end of record */
932 if (disp_fields[0]) {
933 if (!strchr_m(disp_fields[0], '$')) {
934 if (disp_fields[1])
935 d_printf("%-21.21s %s\n",
936 disp_fields[0], disp_fields[1]);
937 else
938 d_printf("%s\n", disp_fields[0]);
941 SAFE_FREE(disp_fields[0]);
942 SAFE_FREE(disp_fields[1]);
943 return true;
945 if (!values) /* must be new field, indicate string field */
946 return true;
947 if (strcasecmp_m(field, "sAMAccountName") == 0) {
948 disp_fields[0] = SMB_STRDUP((char *) values[0]);
950 if (strcasecmp_m(field, "description") == 0)
951 disp_fields[1] = SMB_STRDUP((char *) values[0]);
952 return true;
955 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
957 return net_user_usage(c, argc, argv);
960 static int ads_user_add(struct net_context *c, int argc, const char **argv)
962 TALLOC_CTX *tmp_ctx = talloc_stackframe();
963 ADS_STRUCT *ads = NULL;
964 ADS_STATUS status;
965 char *upn, *userdn;
966 LDAPMessage *res=NULL;
967 int rc = -1;
968 char *ou_str = NULL;
970 if (argc < 1 || c->display_usage) {
971 TALLOC_FREE(tmp_ctx);
972 return net_ads_user_usage(c, argc, argv);
975 status = ads_startup(c, false, tmp_ctx, &ads);
976 if (!ADS_ERR_OK(status)) {
977 goto done;
980 status = ads_find_user_acct(ads, &res, argv[0]);
981 if (!ADS_ERR_OK(status)) {
982 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
983 goto done;
986 if (ads_count_replies(ads, res)) {
987 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
988 argv[0]);
989 goto done;
992 if (c->opt_container) {
993 ou_str = SMB_STRDUP(c->opt_container);
994 } else {
995 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
998 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
999 if (!ADS_ERR_OK(status)) {
1000 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
1001 ads_errstr(status));
1002 goto done;
1005 /* if no password is to be set, we're done */
1006 if (argc == 1) {
1007 d_printf(_("User %s added\n"), argv[0]);
1008 rc = 0;
1009 goto done;
1012 /* try setting the password */
1013 upn = talloc_asprintf(tmp_ctx,
1014 "%s@%s",
1015 argv[0],
1016 ads->config.realm);
1017 if (upn == NULL) {
1018 goto done;
1021 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
1022 ads->auth.time_offset);
1023 if (ADS_ERR_OK(status)) {
1024 d_printf(_("User %s added\n"), argv[0]);
1025 rc = 0;
1026 goto done;
1028 TALLOC_FREE(upn);
1030 /* password didn't set, delete account */
1031 d_fprintf(stderr, _("Could not add user %s. "
1032 "Error setting password %s\n"),
1033 argv[0], ads_errstr(status));
1035 ads_msgfree(ads, res);
1036 res = NULL;
1038 status=ads_find_user_acct(ads, &res, argv[0]);
1039 if (ADS_ERR_OK(status)) {
1040 userdn = ads_get_dn(ads, tmp_ctx, res);
1041 ads_del_dn(ads, userdn);
1042 TALLOC_FREE(userdn);
1045 done:
1046 ads_msgfree(ads, res);
1047 SAFE_FREE(ou_str);
1048 TALLOC_FREE(tmp_ctx);
1049 return rc;
1052 static int ads_user_info(struct net_context *c, int argc, const char **argv)
1054 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1055 ADS_STRUCT *ads = NULL;
1056 ADS_STATUS status;
1057 LDAPMessage *res = NULL;
1058 int ret = -1;
1059 wbcErr wbc_status;
1060 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1061 char *searchstring = NULL;
1062 char **grouplist = NULL;
1063 char *primary_group = NULL;
1064 char *escaped_user = NULL;
1065 struct dom_sid primary_group_sid;
1066 uint32_t group_rid;
1067 enum wbcSidType type;
1069 if (argc < 1 || c->display_usage) {
1070 TALLOC_FREE(tmp_ctx);
1071 return net_ads_user_usage(c, argc, argv);
1074 escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1075 if (!escaped_user) {
1076 d_fprintf(stderr,
1077 _("ads_user_info: failed to escape user %s\n"),
1078 argv[0]);
1079 goto out;
1082 status = ads_startup(c, false, tmp_ctx, &ads);
1083 if (!ADS_ERR_OK(status)) {
1084 goto out;
1087 searchstring = talloc_asprintf(tmp_ctx,
1088 "(sAMAccountName=%s)",
1089 escaped_user);
1090 if (searchstring == NULL) {
1091 goto out;
1094 status = ads_search(ads, &res, searchstring, attrs);
1095 if (!ADS_ERR_OK(status)) {
1096 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1097 goto out;
1100 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1101 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1102 goto out;
1105 status = ads_domain_sid(ads, &primary_group_sid);
1106 if (!ADS_ERR_OK(status)) {
1107 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1108 goto out;
1111 sid_append_rid(&primary_group_sid, group_rid);
1113 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1114 NULL, /* don't look up domain */
1115 &primary_group,
1116 &type);
1117 if (!WBC_ERROR_IS_OK(wbc_status)) {
1118 d_fprintf(stderr, "wbcLookupSid: %s\n",
1119 wbcErrorString(wbc_status));
1120 goto out;
1123 d_printf("%s\n", primary_group);
1125 wbcFreeMemory(primary_group);
1127 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1128 (LDAPMessage *)res, "memberOf");
1130 if (grouplist) {
1131 int i;
1132 char **groupname;
1133 for (i=0;grouplist[i];i++) {
1134 groupname = ldap_explode_dn(grouplist[i], 1);
1135 d_printf("%s\n", groupname[0]);
1136 ldap_value_free(groupname);
1138 ldap_value_free(grouplist);
1141 ret = 0;
1142 out:
1143 ads_msgfree(ads, res);
1144 TALLOC_FREE(tmp_ctx);
1145 return ret;
1148 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1150 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1151 ADS_STRUCT *ads = NULL;
1152 ADS_STATUS status;
1153 LDAPMessage *res = NULL;
1154 char *userdn = NULL;
1155 int ret = -1;
1157 if (argc < 1) {
1158 TALLOC_FREE(tmp_ctx);
1159 return net_ads_user_usage(c, argc, argv);
1162 status = ads_startup(c, false, tmp_ctx, &ads);
1163 if (!ADS_ERR_OK(status)) {
1164 goto out;
1167 status = ads_find_user_acct(ads, &res, argv[0]);
1168 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1169 d_printf(_("User %s does not exist.\n"), argv[0]);
1170 goto out;
1173 userdn = ads_get_dn(ads, tmp_ctx, res);
1174 if (userdn == NULL) {
1175 goto out;
1178 status = ads_del_dn(ads, userdn);
1179 if (!ADS_ERR_OK(status)) {
1180 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1181 ads_errstr(status));
1182 goto out;
1185 d_printf(_("User %s deleted\n"), argv[0]);
1187 ret = 0;
1188 out:
1189 ads_msgfree(ads, res);
1190 TALLOC_FREE(tmp_ctx);
1191 return ret;
1194 int net_ads_user(struct net_context *c, int argc, const char **argv)
1196 struct functable func[] = {
1198 "add",
1199 ads_user_add,
1200 NET_TRANSPORT_ADS,
1201 N_("Add an AD user"),
1202 N_("net ads user add\n"
1203 " Add an AD user")
1206 "info",
1207 ads_user_info,
1208 NET_TRANSPORT_ADS,
1209 N_("Display information about an AD user"),
1210 N_("net ads user info\n"
1211 " Display information about an AD user")
1214 "delete",
1215 ads_user_delete,
1216 NET_TRANSPORT_ADS,
1217 N_("Delete an AD user"),
1218 N_("net ads user delete\n"
1219 " Delete an AD user")
1221 {NULL, NULL, 0, NULL, NULL}
1223 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1224 ADS_STRUCT *ads = NULL;
1225 ADS_STATUS status;
1226 const char *shortattrs[] = {"sAMAccountName", NULL};
1227 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1228 char *disp_fields[2] = {NULL, NULL};
1229 int ret = -1;
1231 if (argc > 0) {
1232 TALLOC_FREE(tmp_ctx);
1233 return net_run_function(c, argc, argv, "net ads user", func);
1236 if (c->display_usage) {
1237 d_printf( "%s\n"
1238 "net ads user\n"
1239 " %s\n",
1240 _("Usage:"),
1241 _("List AD users"));
1242 net_display_usage_from_functable(func);
1243 TALLOC_FREE(tmp_ctx);
1244 return -1;
1247 status = ads_startup(c, false, tmp_ctx, &ads);
1248 if (!ADS_ERR_OK(status)) {
1249 goto out;
1252 if (c->opt_long_list_entries)
1253 d_printf(_("\nUser name Comment"
1254 "\n-----------------------------\n"));
1256 status = ads_do_search_all_fn(ads,
1257 ads->config.bind_path,
1258 LDAP_SCOPE_SUBTREE,
1259 "(objectCategory=user)",
1260 c->opt_long_list_entries ?
1261 longattrs : shortattrs,
1262 usergrp_display,
1263 disp_fields);
1264 if (!ADS_ERR_OK(status)) {
1265 goto out;
1268 ret = 0;
1269 out:
1270 TALLOC_FREE(tmp_ctx);
1271 return ret;
1274 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1276 return net_group_usage(c, argc, argv);
1279 static int ads_group_add(struct net_context *c, int argc, const char **argv)
1281 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1282 ADS_STRUCT *ads = NULL;
1283 ADS_STATUS status;
1284 LDAPMessage *res = NULL;
1285 int ret = -1;
1286 char *ou_str = NULL;
1288 if (argc < 1 || c->display_usage) {
1289 TALLOC_FREE(tmp_ctx);
1290 return net_ads_group_usage(c, argc, argv);
1293 status = ads_startup(c, false, tmp_ctx, &ads);
1294 if (!ADS_ERR_OK(status)) {
1295 goto out;
1298 status = ads_find_user_acct(ads, &res, argv[0]);
1299 if (!ADS_ERR_OK(status)) {
1300 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1301 goto out;
1304 if (ads_count_replies(ads, res)) {
1305 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1306 goto out;
1309 if (c->opt_container) {
1310 ou_str = SMB_STRDUP(c->opt_container);
1311 } else {
1312 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1315 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1316 if (!ADS_ERR_OK(status)) {
1317 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1318 ads_errstr(status));
1319 goto out;
1322 d_printf(_("Group %s added\n"), argv[0]);
1324 ret = 0;
1325 out:
1326 ads_msgfree(ads, res);
1327 SAFE_FREE(ou_str);
1328 TALLOC_FREE(tmp_ctx);
1329 return ret;
1332 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1334 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1335 ADS_STRUCT *ads = NULL;
1336 ADS_STATUS status;
1337 LDAPMessage *res = NULL;
1338 char *groupdn = NULL;
1339 int ret = -1;
1341 if (argc < 1 || c->display_usage) {
1342 TALLOC_FREE(tmp_ctx);
1343 return net_ads_group_usage(c, argc, argv);
1346 status = ads_startup(c, false, tmp_ctx, &ads);
1347 if (!ADS_ERR_OK(status)) {
1348 goto out;
1351 status = ads_find_user_acct(ads, &res, argv[0]);
1352 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1353 d_printf(_("Group %s does not exist.\n"), argv[0]);
1354 goto out;
1357 groupdn = ads_get_dn(ads, tmp_ctx, res);
1358 if (groupdn == NULL) {
1359 goto out;
1362 status = ads_del_dn(ads, groupdn);
1363 if (!ADS_ERR_OK(status)) {
1364 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1365 ads_errstr(status));
1366 goto out;
1368 d_printf(_("Group %s deleted\n"), argv[0]);
1370 ret = 0;
1371 out:
1372 ads_msgfree(ads, res);
1373 TALLOC_FREE(tmp_ctx);
1374 return ret;
1377 int net_ads_group(struct net_context *c, int argc, const char **argv)
1379 struct functable func[] = {
1381 "add",
1382 ads_group_add,
1383 NET_TRANSPORT_ADS,
1384 N_("Add an AD group"),
1385 N_("net ads group add\n"
1386 " Add an AD group")
1389 "delete",
1390 ads_group_delete,
1391 NET_TRANSPORT_ADS,
1392 N_("Delete an AD group"),
1393 N_("net ads group delete\n"
1394 " Delete an AD group")
1396 {NULL, NULL, 0, NULL, NULL}
1398 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1399 ADS_STRUCT *ads = NULL;
1400 ADS_STATUS status;
1401 const char *shortattrs[] = {"sAMAccountName", NULL};
1402 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1403 char *disp_fields[2] = {NULL, NULL};
1404 int ret = -1;
1406 if (argc >= 0) {
1407 TALLOC_FREE(tmp_ctx);
1408 return net_run_function(c, argc, argv, "net ads group", func);
1411 if (c->display_usage) {
1412 d_printf( "%s\n"
1413 "net ads group\n"
1414 " %s\n",
1415 _("Usage:"),
1416 _("List AD groups"));
1417 net_display_usage_from_functable(func);
1418 TALLOC_FREE(tmp_ctx);
1419 return -1;
1422 status = ads_startup(c, false, tmp_ctx, &ads);
1423 if (!ADS_ERR_OK(status)) {
1424 goto out;
1427 if (c->opt_long_list_entries)
1428 d_printf(_("\nGroup name Comment"
1429 "\n-----------------------------\n"));
1431 status = ads_do_search_all_fn(ads,
1432 ads->config.bind_path,
1433 LDAP_SCOPE_SUBTREE,
1434 "(objectCategory=group)",
1435 c->opt_long_list_entries ?
1436 longattrs : shortattrs,
1437 usergrp_display,
1438 disp_fields);
1439 if (!ADS_ERR_OK(status)) {
1440 goto out;
1443 ret = 0;
1444 out:
1445 TALLOC_FREE(tmp_ctx);
1446 return ret;
1449 static int net_ads_status(struct net_context *c, int argc, const char **argv)
1451 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1452 ADS_STRUCT *ads = NULL;
1453 ADS_STATUS status;
1454 LDAPMessage *res = NULL;
1455 int ret = -1;
1457 if (c->display_usage) {
1458 d_printf( "%s\n"
1459 "net ads status\n"
1460 " %s\n",
1461 _("Usage:"),
1462 _("Display machine account details"));
1463 TALLOC_FREE(tmp_ctx);
1464 return -1;
1467 net_warn_member_options();
1469 status = ads_startup(c, true, tmp_ctx, &ads);
1470 if (!ADS_ERR_OK(status)) {
1471 goto out;
1474 status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1475 if (!ADS_ERR_OK(status)) {
1476 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1477 ads_errstr(status));
1478 goto out;
1481 if (ads_count_replies(ads, res) == 0) {
1482 d_fprintf(stderr, _("No machine account for '%s' found\n"),
1483 lp_netbios_name());
1484 goto out;
1487 ads_dump(ads, res);
1489 ret = 0;
1490 out:
1491 ads_msgfree(ads, res);
1492 TALLOC_FREE(tmp_ctx);
1493 return ret;
1496 /*******************************************************************
1497 Leave an AD domain. Windows XP disables the machine account.
1498 We'll try the same. The old code would do an LDAP delete.
1499 That only worked using the machine creds because added the machine
1500 with full control to the computer object's ACL.
1501 *******************************************************************/
1503 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1505 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1506 struct libnet_UnjoinCtx *r = NULL;
1507 WERROR werr;
1508 int ret = -1;
1510 if (c->display_usage) {
1511 d_printf( "%s\n"
1512 "net ads leave [--keep-account]\n"
1513 " %s\n",
1514 _("Usage:"),
1515 _("Leave an AD domain"));
1516 TALLOC_FREE(tmp_ctx);
1517 return -1;
1520 if (!*lp_realm()) {
1521 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1522 TALLOC_FREE(tmp_ctx);
1523 return -1;
1526 if (!c->opt_kerberos) {
1527 use_in_memory_ccache();
1530 if (!c->msg_ctx) {
1531 d_fprintf(stderr, _("Could not initialise message context. "
1532 "Try running as root\n"));
1533 goto done;
1536 werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1537 if (!W_ERROR_IS_OK(werr)) {
1538 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1539 goto done;
1542 r->in.debug = true;
1543 r->in.use_kerberos = c->opt_kerberos;
1544 r->in.dc_name = c->opt_host;
1545 r->in.domain_name = lp_realm();
1546 r->in.admin_account = c->opt_user_name;
1547 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1548 r->in.modify_config = lp_config_backend_is_registry();
1550 /* Try to delete it, but if that fails, disable it. The
1551 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1552 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1553 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1554 if (c->opt_keep_account) {
1555 r->in.delete_machine_account = false;
1556 } else {
1557 r->in.delete_machine_account = true;
1560 r->in.msg_ctx = c->msg_ctx;
1562 werr = libnet_Unjoin(tmp_ctx, r);
1563 if (!W_ERROR_IS_OK(werr)) {
1564 d_printf(_("Failed to leave domain: %s\n"),
1565 r->out.error_string ? r->out.error_string :
1566 get_friendly_werror_msg(werr));
1567 goto done;
1570 if (r->out.deleted_machine_account) {
1571 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1572 r->in.machine_name, r->out.dns_domain_name);
1573 ret = 0;
1574 goto done;
1577 /* We couldn't delete it - see if the disable succeeded. */
1578 if (r->out.disabled_machine_account) {
1579 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1580 r->in.machine_name, r->out.dns_domain_name);
1581 ret = 0;
1582 goto done;
1585 /* Based on what we requested, we shouldn't get here, but if
1586 we did, it means the secrets were removed, and therefore
1587 we have left the domain */
1588 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1589 r->in.machine_name, r->out.dns_domain_name);
1591 ret = 0;
1592 done:
1593 TALLOC_FREE(tmp_ctx);
1594 return ret;
1597 static ADS_STATUS net_ads_join_ok(struct net_context *c)
1599 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1600 ADS_STRUCT *ads = NULL;
1601 ADS_STATUS status;
1602 fstring dc_name;
1603 struct sockaddr_storage dcip;
1605 if (!secrets_init()) {
1606 DEBUG(1,("Failed to initialise secrets database\n"));
1607 TALLOC_FREE(tmp_ctx);
1608 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1611 net_warn_member_options();
1613 net_use_krb_machine_account(c);
1615 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1617 status = ads_startup(c, true, tmp_ctx, &ads);
1618 if (!ADS_ERR_OK(status)) {
1619 goto out;
1622 status = ADS_ERROR_NT(NT_STATUS_OK);
1623 out:
1624 TALLOC_FREE(tmp_ctx);
1625 return status;
1629 check that an existing join is OK
1631 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1633 ADS_STATUS status;
1634 use_in_memory_ccache();
1636 if (c->display_usage) {
1637 d_printf( "%s\n"
1638 "net ads testjoin\n"
1639 " %s\n",
1640 _("Usage:"),
1641 _("Test if the existing join is ok"));
1642 return -1;
1645 net_warn_member_options();
1647 /* Display success or failure */
1648 status = net_ads_join_ok(c);
1649 if (!ADS_ERR_OK(status)) {
1650 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1651 get_friendly_nt_error_msg(ads_ntstatus(status)));
1652 return -1;
1655 printf(_("Join is OK\n"));
1656 return 0;
1659 /*******************************************************************
1660 Simple config checks before beginning the join
1661 ********************************************************************/
1663 static WERROR check_ads_config( void )
1665 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1666 d_printf(_("Host is not configured as a member server.\n"));
1667 return WERR_INVALID_DOMAIN_ROLE;
1670 if (strlen(lp_netbios_name()) > 15) {
1671 d_printf(_("Our netbios name can be at most 15 chars long, "
1672 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1673 (unsigned int)strlen(lp_netbios_name()));
1674 return WERR_INVALID_COMPUTERNAME;
1677 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1678 d_fprintf(stderr, _("realm must be set in in %s for ADS "
1679 "join to succeed.\n"), get_dyn_CONFIGFILE());
1680 return WERR_INVALID_PARAMETER;
1683 return WERR_OK;
1686 /*******************************************************************
1687 ********************************************************************/
1689 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1691 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1692 "Valid options:\n"));
1693 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1694 " The default is in the form netbiosname.dnsdomain\n"));
1695 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1696 " The default UPN is in the form host/netbiosname@REALM.\n"));
1697 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1698 " The OU string read from top to bottom without RDNs\n"
1699 " and delimited by a '/'.\n"
1700 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1701 " NB: A backslash '\\' is used as escape at multiple\n"
1702 " levels and may need to be doubled or even\n"
1703 " quadrupled. It is not used as a separator.\n"));
1704 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1705 " the join. The default password is random.\n"));
1706 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1707 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1708 " NB: osName and osVer must be specified together for\n"
1709 " either to take effect. The operatingSystemService\n"
1710 " attribute is then also set along with the two\n"
1711 " other attributes.\n"));
1712 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1713 " during the join.\n"
1714 " NB: If not specified then by default the samba\n"
1715 " version string is used instead.\n"));
1716 return -1;
1720 int net_ads_join(struct net_context *c, int argc, const char **argv)
1722 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1723 struct libnet_JoinCtx *r = NULL;
1724 const char *domain = lp_realm();
1725 WERROR werr = WERR_NERR_SETUPNOTJOINED;
1726 bool createupn = false;
1727 const char *dnshostname = NULL;
1728 const char *machineupn = NULL;
1729 const char *machine_password = NULL;
1730 const char *create_in_ou = NULL;
1731 int i;
1732 const char *os_name = NULL;
1733 const char *os_version = NULL;
1734 const char *os_servicepack = NULL;
1735 bool modify_config = lp_config_backend_is_registry();
1736 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1737 int ret = -1;
1739 if (c->display_usage) {
1740 TALLOC_FREE(tmp_ctx);
1741 return net_ads_join_usage(c, argc, argv);
1744 net_warn_member_options();
1746 if (!modify_config) {
1747 werr = check_ads_config();
1748 if (!W_ERROR_IS_OK(werr)) {
1749 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1750 goto fail;
1754 if (!c->opt_kerberos) {
1755 use_in_memory_ccache();
1758 werr = libnet_init_JoinCtx(tmp_ctx, &r);
1759 if (!W_ERROR_IS_OK(werr)) {
1760 goto fail;
1763 /* process additional command line args */
1765 for ( i=0; i<argc; i++ ) {
1766 if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1767 dnshostname = get_string_param(argv[i]);
1769 else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1770 createupn = true;
1771 machineupn = get_string_param(argv[i]);
1773 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1774 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1775 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1776 werr = WERR_INVALID_PARAMETER;
1777 goto fail;
1780 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1781 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1782 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1783 werr = WERR_INVALID_PARAMETER;
1784 goto fail;
1787 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1788 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1789 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1790 werr = WERR_INVALID_PARAMETER;
1791 goto fail;
1794 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1795 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1796 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1797 werr = WERR_INVALID_PARAMETER;
1798 goto fail;
1801 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1802 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1803 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1804 werr = WERR_INVALID_PARAMETER;
1805 goto fail;
1807 } else {
1808 domain = argv[i];
1809 if (strchr(domain, '.') == NULL) {
1810 domain_name_type = JoinDomNameTypeUnknown;
1811 } else {
1812 domain_name_type = JoinDomNameTypeDNS;
1817 if (!*domain) {
1818 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1819 werr = WERR_INVALID_PARAMETER;
1820 goto fail;
1823 if (!c->msg_ctx) {
1824 d_fprintf(stderr, _("Could not initialise message context. "
1825 "Try running as root\n"));
1826 werr = WERR_ACCESS_DENIED;
1827 goto fail;
1830 /* Do the domain join here */
1832 r->in.domain_name = domain;
1833 r->in.domain_name_type = domain_name_type;
1834 r->in.create_upn = createupn;
1835 r->in.upn = machineupn;
1836 r->in.dnshostname = dnshostname;
1837 r->in.account_ou = create_in_ou;
1838 r->in.os_name = os_name;
1839 r->in.os_version = os_version;
1840 r->in.os_servicepack = os_servicepack;
1841 r->in.dc_name = c->opt_host;
1842 r->in.admin_account = c->opt_user_name;
1843 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1844 r->in.machine_password = machine_password;
1845 r->in.debug = true;
1846 r->in.use_kerberos = c->opt_kerberos;
1847 r->in.modify_config = modify_config;
1848 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1849 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1850 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1851 r->in.msg_ctx = c->msg_ctx;
1853 werr = libnet_Join(tmp_ctx, r);
1854 if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1855 strequal(domain, lp_realm())) {
1856 r->in.domain_name = lp_workgroup();
1857 r->in.domain_name_type = JoinDomNameTypeNBT;
1858 werr = libnet_Join(tmp_ctx, r);
1860 if (!W_ERROR_IS_OK(werr)) {
1861 goto fail;
1864 /* Check the short name of the domain */
1866 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1867 d_printf(_("The workgroup in %s does not match the short\n"
1868 "domain name obtained from the server.\n"
1869 "Using the name [%s] from the server.\n"
1870 "You should set \"workgroup = %s\" in %s.\n"),
1871 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1872 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1875 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1877 if (r->out.dns_domain_name) {
1878 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1879 r->out.dns_domain_name);
1880 } else {
1881 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1882 r->out.netbios_domain_name);
1885 /* print out informative error string in case there is one */
1886 if (r->out.error_string != NULL) {
1887 d_printf("%s\n", r->out.error_string);
1891 * We try doing the dns update (if it was compiled in
1892 * and if it was not disabled on the command line).
1893 * If the dns update fails, we still consider the join
1894 * operation as succeeded if we came this far.
1896 if (!c->opt_no_dns_updates) {
1897 net_ads_join_dns_updates(c, tmp_ctx, r);
1900 ret = 0;
1902 fail:
1903 if (ret != 0) {
1904 /* issue an overall failure message at the end. */
1905 d_printf(_("Failed to join domain: %s\n"),
1906 r && r->out.error_string ? r->out.error_string :
1907 get_friendly_werror_msg(werr));
1910 TALLOC_FREE(tmp_ctx);
1912 return ret;
1915 /*******************************************************************
1916 ********************************************************************/
1918 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1920 #if defined(HAVE_KRB5)
1921 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1922 ADS_STRUCT *ads = NULL;
1923 ADS_STATUS status;
1924 NTSTATUS ntstatus;
1925 const char *hostname = NULL;
1926 const char **addrs_list = NULL;
1927 struct sockaddr_storage *addrs = NULL;
1928 int num_addrs = 0;
1929 int count;
1930 int ret = -1;
1932 #ifdef DEVELOPER
1933 talloc_enable_leak_report();
1934 #endif
1936 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1937 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1938 "detection of addresses in a clustered "
1939 "setup.\n"));
1940 c->display_usage = true;
1943 if (c->display_usage) {
1944 d_printf( "%s\n"
1945 "net ads dns register [hostname [IP [IP...]]] "
1946 "[--force] [--dns-ttl TTL]\n"
1947 " %s\n",
1948 _("Usage:"),
1949 _("Register hostname with DNS\n"));
1950 TALLOC_FREE(tmp_ctx);
1951 return -1;
1954 if (argc >= 1) {
1955 hostname = argv[0];
1958 if (argc > 1) {
1959 num_addrs = argc - 1;
1960 addrs_list = &argv[1];
1961 } else if (lp_clustering()) {
1962 addrs_list = lp_cluster_addresses();
1963 num_addrs = str_list_length(addrs_list);
1966 if (num_addrs > 0) {
1967 addrs = talloc_zero_array(tmp_ctx,
1968 struct sockaddr_storage,
1969 num_addrs);
1970 if (addrs == NULL) {
1971 d_fprintf(stderr, _("Error allocating memory!\n"));
1972 goto out;
1976 for (count = 0; count < num_addrs; count++) {
1977 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1978 d_fprintf(stderr, "%s '%s'.\n",
1979 _("Cannot interpret address"),
1980 addrs_list[count]);
1981 goto out;
1985 status = ads_startup(c, true, tmp_ctx, &ads);
1986 if ( !ADS_ERR_OK(status) ) {
1987 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1988 goto out;
1991 ntstatus = net_update_dns_ext(c,
1992 tmp_ctx,
1993 ads,
1994 hostname,
1995 addrs,
1996 num_addrs,
1997 false);
1998 if (!NT_STATUS_IS_OK(ntstatus)) {
1999 d_fprintf( stderr, _("DNS update failed!\n") );
2000 goto out;
2003 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
2005 ret = 0;
2006 out:
2007 TALLOC_FREE(tmp_ctx);
2009 return ret;
2010 #else
2011 d_fprintf(stderr,
2012 _("DNS update support not enabled at compile time!\n"));
2013 return -1;
2014 #endif
2017 static int net_ads_dns_unregister(struct net_context *c,
2018 int argc,
2019 const char **argv)
2021 #if defined(HAVE_KRB5)
2022 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2023 ADS_STRUCT *ads = NULL;
2024 ADS_STATUS status;
2025 NTSTATUS ntstatus;
2026 const char *hostname = NULL;
2027 int ret = -1;
2029 #ifdef DEVELOPER
2030 talloc_enable_leak_report();
2031 #endif
2033 if (argc != 1) {
2034 c->display_usage = true;
2037 if (c->display_usage) {
2038 d_printf( "%s\n"
2039 "net ads dns unregister [hostname]\n"
2040 " %s\n",
2041 _("Usage:"),
2042 _("Remove all IP Address entries for a given\n"
2043 " hostname from the Active Directory server.\n"));
2044 TALLOC_FREE(tmp_ctx);
2045 return -1;
2048 /* Get the hostname for un-registering */
2049 hostname = argv[0];
2051 status = ads_startup(c, true, tmp_ctx, &ads);
2052 if ( !ADS_ERR_OK(status) ) {
2053 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2054 goto out;
2057 ntstatus = net_update_dns_ext(c,
2058 tmp_ctx,
2059 ads,
2060 hostname,
2061 NULL,
2063 true);
2064 if (!NT_STATUS_IS_OK(ntstatus)) {
2065 d_fprintf( stderr, _("DNS update failed!\n") );
2066 goto out;
2069 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2071 ret = 0;
2072 out:
2073 TALLOC_FREE(tmp_ctx);
2075 return ret;
2076 #else
2077 d_fprintf(stderr,
2078 _("DNS update support not enabled at compile time!\n"));
2079 return -1;
2080 #endif
2084 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2086 size_t num_names = 0;
2087 char **hostnames = NULL;
2088 size_t i = 0;
2089 struct samba_sockaddr *addrs = NULL;
2090 NTSTATUS status;
2092 if (argc != 1 || c->display_usage) {
2093 d_printf( "%s\n"
2094 " %s\n"
2095 " %s\n",
2096 _("Usage:"),
2097 _("net ads dns async <name>\n"),
2098 _(" Async look up hostname from the DNS server\n"
2099 " hostname\tName to look up\n"));
2100 return -1;
2103 status = ads_dns_lookup_a(talloc_tos(),
2104 argv[0],
2105 &num_names,
2106 &hostnames,
2107 &addrs);
2108 if (!NT_STATUS_IS_OK(status)) {
2109 d_printf("Looking up A record for %s got error %s\n",
2110 argv[0],
2111 nt_errstr(status));
2112 return -1;
2114 d_printf("Async A record lookup - got %u names for %s\n",
2115 (unsigned int)num_names,
2116 argv[0]);
2117 for (i = 0; i < num_names; i++) {
2118 char addr_buf[INET6_ADDRSTRLEN];
2119 print_sockaddr(addr_buf,
2120 sizeof(addr_buf),
2121 &addrs[i].u.ss);
2122 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2123 (unsigned int)i,
2124 hostnames[i],
2125 addr_buf);
2128 #if defined(HAVE_IPV6)
2129 status = ads_dns_lookup_aaaa(talloc_tos(),
2130 argv[0],
2131 &num_names,
2132 &hostnames,
2133 &addrs);
2134 if (!NT_STATUS_IS_OK(status)) {
2135 d_printf("Looking up AAAA record for %s got error %s\n",
2136 argv[0],
2137 nt_errstr(status));
2138 return -1;
2140 d_printf("Async AAAA record lookup - got %u names for %s\n",
2141 (unsigned int)num_names,
2142 argv[0]);
2143 for (i = 0; i < num_names; i++) {
2144 char addr_buf[INET6_ADDRSTRLEN];
2145 print_sockaddr(addr_buf,
2146 sizeof(addr_buf),
2147 &addrs[i].u.ss);
2148 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2149 (unsigned int)i,
2150 hostnames[i],
2151 addr_buf);
2153 #endif
2154 return 0;
2158 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2160 struct functable func[] = {
2162 "register",
2163 net_ads_dns_register,
2164 NET_TRANSPORT_ADS,
2165 N_("Add host dns entry to AD"),
2166 N_("net ads dns register\n"
2167 " Add host dns entry to AD")
2170 "unregister",
2171 net_ads_dns_unregister,
2172 NET_TRANSPORT_ADS,
2173 N_("Remove host dns entry from AD"),
2174 N_("net ads dns unregister\n"
2175 " Remove host dns entry from AD")
2178 "async",
2179 net_ads_dns_async,
2180 NET_TRANSPORT_ADS,
2181 N_("Look up host"),
2182 N_("net ads dns async\n"
2183 " Look up host using async DNS")
2185 {NULL, NULL, 0, NULL, NULL}
2188 return net_run_function(c, argc, argv, "net ads dns", func);
2191 /*******************************************************************
2192 ********************************************************************/
2194 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2196 d_printf(_(
2197 "\nnet ads printer search <printer>"
2198 "\n\tsearch for a printer in the directory\n"
2199 "\nnet ads printer info <printer> <server>"
2200 "\n\tlookup info in directory for printer on server"
2201 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2202 "\nnet ads printer publish <printername>"
2203 "\n\tpublish printer in directory"
2204 "\n\t(note: printer name is required)\n"
2205 "\nnet ads printer remove <printername>"
2206 "\n\tremove printer from directory"
2207 "\n\t(note: printer name is required)\n"));
2208 return -1;
2211 /*******************************************************************
2212 ********************************************************************/
2214 static int net_ads_printer_search(struct net_context *c,
2215 int argc,
2216 const char **argv)
2218 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2219 ADS_STRUCT *ads = NULL;
2220 ADS_STATUS status;
2221 LDAPMessage *res = NULL;
2222 int ret = -1;
2224 if (c->display_usage) {
2225 d_printf( "%s\n"
2226 "net ads printer search\n"
2227 " %s\n",
2228 _("Usage:"),
2229 _("List printers in the AD"));
2230 TALLOC_FREE(tmp_ctx);
2231 return -1;
2234 status = ads_startup(c, false, tmp_ctx, &ads);
2235 if (!ADS_ERR_OK(status)) {
2236 goto out;
2239 status = ads_find_printers(ads, &res);
2240 if (!ADS_ERR_OK(status)) {
2241 d_fprintf(stderr, _("ads_find_printer: %s\n"),
2242 ads_errstr(status));
2243 goto out;
2246 if (ads_count_replies(ads, res) == 0) {
2247 d_fprintf(stderr, _("No results found\n"));
2248 goto out;
2251 ads_dump(ads, res);
2253 ret = 0;
2254 out:
2255 ads_msgfree(ads, res);
2256 TALLOC_FREE(tmp_ctx);
2257 return ret;
2260 static int net_ads_printer_info(struct net_context *c,
2261 int argc,
2262 const char **argv)
2264 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2265 ADS_STRUCT *ads = NULL;
2266 ADS_STATUS status;
2267 const char *servername = NULL;
2268 const char *printername = NULL;
2269 LDAPMessage *res = NULL;
2270 int ret = -1;
2272 if (c->display_usage) {
2273 d_printf("%s\n%s",
2274 _("Usage:"),
2275 _("net ads printer info [printername [servername]]\n"
2276 " Display printer info from AD\n"
2277 " printername\tPrinter name or wildcard\n"
2278 " servername\tName of the print server\n"));
2279 TALLOC_FREE(tmp_ctx);
2280 return -1;
2283 status = ads_startup(c, false, tmp_ctx, &ads);
2284 if (!ADS_ERR_OK(status)) {
2285 goto out;
2288 if (argc > 0) {
2289 printername = argv[0];
2290 } else {
2291 printername = "*";
2294 if (argc > 1) {
2295 servername = argv[1];
2296 } else {
2297 servername = lp_netbios_name();
2300 status = ads_find_printer_on_server(ads, &res, printername, servername);
2301 if (!ADS_ERR_OK(status)) {
2302 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2303 servername, ads_errstr(status));
2304 goto out;
2307 if (ads_count_replies(ads, res) == 0) {
2308 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2309 goto out;
2312 ads_dump(ads, res);
2314 ret = 0;
2315 out:
2316 ads_msgfree(ads, res);
2317 TALLOC_FREE(tmp_ctx);
2318 return ret;
2321 static int net_ads_printer_publish(struct net_context *c,
2322 int argc,
2323 const char **argv)
2325 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2326 ADS_STRUCT *ads = NULL;
2327 ADS_STATUS status;
2328 const char *servername = NULL;
2329 const char *printername = NULL;
2330 struct cli_state *cli = NULL;
2331 struct rpc_pipe_client *pipe_hnd = NULL;
2332 struct sockaddr_storage server_ss = { 0 };
2333 NTSTATUS nt_status;
2334 ADS_MODLIST mods = NULL;
2335 char *prt_dn = NULL;
2336 char *srv_dn = NULL;
2337 char **srv_cn = NULL;
2338 char *srv_cn_escaped = NULL;
2339 char *printername_escaped = NULL;
2340 LDAPMessage *res = NULL;
2341 bool ok;
2342 int ret = -1;
2344 if (argc < 1 || c->display_usage) {
2345 d_printf("%s\n%s",
2346 _("Usage:"),
2347 _("net ads printer publish <printername> [servername]\n"
2348 " Publish printer in AD\n"
2349 " printername\tName of the printer\n"
2350 " servername\tName of the print server\n"));
2351 TALLOC_FREE(tmp_ctx);
2352 return -1;
2355 mods = ads_init_mods(tmp_ctx);
2356 if (mods == NULL) {
2357 d_fprintf(stderr, _("Out of memory\n"));
2358 goto out;
2361 status = ads_startup(c, true, tmp_ctx, &ads);
2362 if (!ADS_ERR_OK(status)) {
2363 goto out;
2366 printername = argv[0];
2368 if (argc == 2) {
2369 servername = argv[1];
2370 } else {
2371 servername = lp_netbios_name();
2374 /* Get printer data from SPOOLSS */
2376 ok = resolve_name(servername, &server_ss, 0x20, false);
2377 if (!ok) {
2378 d_fprintf(stderr, _("Could not find server %s\n"),
2379 servername);
2380 goto out;
2383 cli_credentials_set_kerberos_state(c->creds,
2384 CRED_USE_KERBEROS_REQUIRED,
2385 CRED_SPECIFIED);
2387 nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2388 &server_ss, 0,
2389 "IPC$", "IPC",
2390 c->creds,
2391 CLI_FULL_CONNECTION_IPC);
2393 if (NT_STATUS_IS_ERR(nt_status)) {
2394 d_fprintf(stderr, _("Unable to open a connection to %s to "
2395 "obtain data for %s\n"),
2396 servername, printername);
2397 goto out;
2400 /* Publish on AD server */
2402 ads_find_machine_acct(ads, &res, servername);
2404 if (ads_count_replies(ads, res) == 0) {
2405 d_fprintf(stderr, _("Could not find machine account for server "
2406 "%s\n"),
2407 servername);
2408 goto out;
2411 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2412 srv_cn = ldap_explode_dn(srv_dn, 1);
2414 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2415 printername_escaped = escape_rdn_val_string_alloc(printername);
2416 if (!srv_cn_escaped || !printername_escaped) {
2417 SAFE_FREE(srv_cn_escaped);
2418 SAFE_FREE(printername_escaped);
2419 d_fprintf(stderr, _("Internal error, out of memory!"));
2420 goto out;
2423 prt_dn = talloc_asprintf(tmp_ctx,
2424 "cn=%s-%s,%s",
2425 srv_cn_escaped,
2426 printername_escaped,
2427 srv_dn);
2428 if (prt_dn == NULL) {
2429 SAFE_FREE(srv_cn_escaped);
2430 SAFE_FREE(printername_escaped);
2431 d_fprintf(stderr, _("Internal error, out of memory!"));
2432 goto out;
2435 SAFE_FREE(srv_cn_escaped);
2436 SAFE_FREE(printername_escaped);
2438 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2439 if (!NT_STATUS_IS_OK(nt_status)) {
2440 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2441 servername);
2442 goto out;
2445 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2446 tmp_ctx,
2447 &mods,
2448 printername))) {
2449 goto out;
2452 status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2453 if (!ADS_ERR_OK(status)) {
2454 d_fprintf(stderr, "ads_publish_printer: %s\n",
2455 ads_errstr(status));
2456 goto out;
2459 d_printf("published printer\n");
2461 ret = 0;
2462 out:
2463 talloc_destroy(tmp_ctx);
2465 return ret;
2468 static int net_ads_printer_remove(struct net_context *c,
2469 int argc,
2470 const char **argv)
2472 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2473 ADS_STRUCT *ads = NULL;
2474 ADS_STATUS status;
2475 const char *servername = NULL;
2476 char *prt_dn = NULL;
2477 LDAPMessage *res = NULL;
2478 int ret = -1;
2480 if (argc < 1 || c->display_usage) {
2481 d_printf("%s\n%s",
2482 _("Usage:"),
2483 _("net ads printer remove <printername> [servername]\n"
2484 " Remove a printer from the AD\n"
2485 " printername\tName of the printer\n"
2486 " servername\tName of the print server\n"));
2487 TALLOC_FREE(tmp_ctx);
2488 return -1;
2491 status = ads_startup(c, true, tmp_ctx, &ads);
2492 if (!ADS_ERR_OK(status)) {
2493 goto out;
2496 if (argc > 1) {
2497 servername = argv[1];
2498 } else {
2499 servername = lp_netbios_name();
2502 status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2503 if (!ADS_ERR_OK(status)) {
2504 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2505 ads_errstr(status));
2506 goto out;
2509 if (ads_count_replies(ads, res) == 0) {
2510 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2511 goto out;
2514 prt_dn = ads_get_dn(ads, tmp_ctx, res);
2515 if (prt_dn == NULL) {
2516 d_fprintf(stderr, _("Out of memory\n"));
2517 goto out;
2520 status = ads_del_dn(ads, prt_dn);
2521 if (!ADS_ERR_OK(status)) {
2522 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2523 goto out;
2526 ret = 0;
2527 out:
2528 ads_msgfree(ads, res);
2529 TALLOC_FREE(tmp_ctx);
2530 return ret;
2533 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2535 struct functable func[] = {
2537 "search",
2538 net_ads_printer_search,
2539 NET_TRANSPORT_ADS,
2540 N_("Search for a printer"),
2541 N_("net ads printer search\n"
2542 " Search for a printer")
2545 "info",
2546 net_ads_printer_info,
2547 NET_TRANSPORT_ADS,
2548 N_("Display printer information"),
2549 N_("net ads printer info\n"
2550 " Display printer information")
2553 "publish",
2554 net_ads_printer_publish,
2555 NET_TRANSPORT_ADS,
2556 N_("Publish a printer"),
2557 N_("net ads printer publish\n"
2558 " Publish a printer")
2561 "remove",
2562 net_ads_printer_remove,
2563 NET_TRANSPORT_ADS,
2564 N_("Delete a printer"),
2565 N_("net ads printer remove\n"
2566 " Delete a printer")
2568 {NULL, NULL, 0, NULL, NULL}
2571 return net_run_function(c, argc, argv, "net ads printer", func);
2575 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2577 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2578 ADS_STRUCT *ads = NULL;
2579 const char *auth_principal = cli_credentials_get_username(c->creds);
2580 const char *auth_password = cli_credentials_get_password(c->creds);
2581 const char *realm = NULL;
2582 char *new_password = NULL;
2583 char *chr = NULL;
2584 char *prompt = NULL;
2585 const char *user = NULL;
2586 char pwd[256] = {0};
2587 ADS_STATUS status;
2588 int ret = 0;
2590 if (c->display_usage) {
2591 d_printf("%s\n%s",
2592 _("Usage:"),
2593 _("net ads password <username>\n"
2594 " Change password for user\n"
2595 " username\tName of user to change password for\n"));
2596 TALLOC_FREE(tmp_ctx);
2597 return -1;
2600 if (auth_principal == NULL || auth_password == NULL) {
2601 d_fprintf(stderr, _("You must supply an administrator "
2602 "username/password\n"));
2603 TALLOC_FREE(tmp_ctx);
2604 return -1;
2607 if (argc < 1) {
2608 d_fprintf(stderr, _("ERROR: You must say which username to "
2609 "change password for\n"));
2610 TALLOC_FREE(tmp_ctx);
2611 return -1;
2614 if (strchr_m(argv[0], '@')) {
2615 user = talloc_strdup(tmp_ctx, argv[0]);
2616 } else {
2617 user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2619 if (user == NULL) {
2620 d_fprintf(stderr, _("Out of memory\n"));
2621 goto out;
2624 use_in_memory_ccache();
2625 chr = strchr_m(auth_principal, '@');
2626 if (chr) {
2627 realm = ++chr;
2628 } else {
2629 realm = lp_realm();
2632 /* use the realm so we can eventually change passwords for users
2633 in realms other than default */
2634 ads = ads_init(tmp_ctx,
2635 realm,
2636 c->opt_workgroup,
2637 c->opt_host,
2638 ADS_SASL_PLAIN);
2639 if (ads == NULL) {
2640 goto out;
2643 /* we don't actually need a full connect, but it's the easy way to
2644 fill in the KDC's address */
2645 ads_connect(ads);
2647 if (!ads->config.realm) {
2648 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2649 goto out;
2652 if (argv[1] != NULL) {
2653 new_password = talloc_strdup(tmp_ctx, argv[1]);
2654 } else {
2655 int rc;
2657 prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2658 if (prompt == NULL) {
2659 d_fprintf(stderr, _("Out of memory\n"));
2660 goto out;
2663 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2664 if (rc < 0) {
2665 goto out;
2667 new_password = talloc_strdup(tmp_ctx, pwd);
2668 memset(pwd, '\0', sizeof(pwd));
2671 if (new_password == NULL) {
2672 d_fprintf(stderr, _("Out of memory\n"));
2673 goto out;
2676 status = kerberos_set_password(ads->auth.kdc_server,
2677 auth_principal,
2678 auth_password,
2679 user,
2680 new_password,
2681 ads->auth.time_offset);
2682 memset(new_password, '\0', strlen(new_password));
2683 if (!ADS_ERR_OK(status)) {
2684 d_fprintf(stderr, _("Password change failed: %s\n"),
2685 ads_errstr(status));
2686 goto out;
2689 d_printf(_("Password change for %s completed.\n"), user);
2691 ret = 0;
2692 out:
2693 TALLOC_FREE(tmp_ctx);
2694 return ret;
2697 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2699 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2700 ADS_STRUCT *ads = NULL;
2701 char *host_principal = NULL;
2702 char *my_name = NULL;
2703 ADS_STATUS status;
2704 int ret = -1;
2706 if (c->display_usage) {
2707 d_printf( "%s\n"
2708 "net ads changetrustpw\n"
2709 " %s\n",
2710 _("Usage:"),
2711 _("Change the machine account's trust password"));
2712 TALLOC_FREE(tmp_ctx);
2713 return -1;
2716 if (!secrets_init()) {
2717 DEBUG(1,("Failed to initialise secrets database\n"));
2718 goto out;
2721 net_warn_member_options();
2723 net_use_krb_machine_account(c);
2725 use_in_memory_ccache();
2727 status = ads_startup(c, true, tmp_ctx, &ads);
2728 if (!ADS_ERR_OK(status)) {
2729 goto out;
2732 my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2733 if (my_name == NULL) {
2734 d_fprintf(stderr, _("Out of memory\n"));
2735 goto out;
2738 host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2739 if (host_principal == NULL) {
2740 d_fprintf(stderr, _("Out of memory\n"));
2741 goto out;
2744 d_printf(_("Changing password for principal: %s\n"), host_principal);
2746 status = ads_change_trust_account_password(ads, host_principal);
2747 if (!ADS_ERR_OK(status)) {
2748 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2749 goto out;
2752 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2754 if (USE_SYSTEM_KEYTAB) {
2755 d_printf(_("Attempting to update system keytab with new password.\n"));
2756 if (ads_keytab_create_default(ads)) {
2757 d_printf(_("Failed to update system keytab.\n"));
2761 ret = 0;
2762 out:
2763 TALLOC_FREE(tmp_ctx);
2765 return ret;
2769 help for net ads search
2771 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2773 d_printf(_(
2774 "\nnet ads search <expression> <attributes...>\n"
2775 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2776 "The expression is a standard LDAP search expression, and the\n"
2777 "attributes are a list of LDAP fields to show in the results.\n\n"
2778 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2780 net_common_flags_usage(c, argc, argv);
2781 return -1;
2786 general ADS search function. Useful in diagnosing problems in ADS
2788 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2790 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2791 ADS_STRUCT *ads = NULL;
2792 ADS_STATUS status;
2793 const char *ldap_exp = NULL;
2794 const char **attrs = NULL;
2795 LDAPMessage *res = NULL;
2796 int ret = -1;
2798 if (argc < 1 || c->display_usage) {
2799 TALLOC_FREE(tmp_ctx);
2800 return net_ads_search_usage(c, argc, argv);
2803 status = ads_startup(c, false, tmp_ctx, &ads);
2804 if (!ADS_ERR_OK(status)) {
2805 goto out;
2808 ldap_exp = argv[0];
2809 attrs = (argv + 1);
2811 status = ads_do_search_retry(ads,
2812 ads->config.bind_path,
2813 LDAP_SCOPE_SUBTREE,
2814 ldap_exp,
2815 attrs,
2816 &res);
2817 if (!ADS_ERR_OK(status)) {
2818 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2819 goto out;
2822 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2824 /* dump the results */
2825 ads_dump(ads, res);
2827 ret = 0;
2828 out:
2829 ads_msgfree(ads, res);
2830 TALLOC_FREE(tmp_ctx);
2831 return ret;
2836 help for net ads search
2838 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2840 d_printf(_(
2841 "\nnet ads dn <dn> <attributes...>\n"
2842 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2843 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2844 "to show in the results\n\n"
2845 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2846 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2848 net_common_flags_usage(c, argc, argv);
2849 return -1;
2854 general ADS search function. Useful in diagnosing problems in ADS
2856 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2858 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2859 ADS_STRUCT *ads = NULL;
2860 ADS_STATUS status;
2861 const char *dn = NULL;
2862 const char **attrs = NULL;
2863 LDAPMessage *res = NULL;
2864 int ret = -1;
2866 if (argc < 1 || c->display_usage) {
2867 TALLOC_FREE(tmp_ctx);
2868 return net_ads_dn_usage(c, argc, argv);
2871 status = ads_startup(c, false, tmp_ctx, &ads);
2872 if (!ADS_ERR_OK(status)) {
2873 goto out;
2876 dn = argv[0];
2877 attrs = (argv + 1);
2879 status = ads_do_search_all(ads,
2881 LDAP_SCOPE_BASE,
2882 "(objectclass=*)",
2883 attrs,
2884 &res);
2885 if (!ADS_ERR_OK(status)) {
2886 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2887 goto out;
2890 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2892 /* dump the results */
2893 ads_dump(ads, res);
2895 ret = 0;
2896 out:
2897 ads_msgfree(ads, res);
2898 TALLOC_FREE(tmp_ctx);
2899 return ret;
2903 help for net ads sid search
2905 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2907 d_printf(_(
2908 "\nnet ads sid <sid> <attributes...>\n"
2909 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2910 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2911 "to show in the results\n\n"
2912 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2914 net_common_flags_usage(c, argc, argv);
2915 return -1;
2920 general ADS search function. Useful in diagnosing problems in ADS
2922 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2924 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2925 ADS_STRUCT *ads = NULL;
2926 ADS_STATUS status;
2927 const char *sid_string = NULL;
2928 const char **attrs = NULL;
2929 LDAPMessage *res = NULL;
2930 struct dom_sid sid = { 0 };
2931 int ret = -1;
2933 if (argc < 1 || c->display_usage) {
2934 TALLOC_FREE(tmp_ctx);
2935 return net_ads_sid_usage(c, argc, argv);
2938 status = ads_startup(c, false, tmp_ctx, &ads);
2939 if (!ADS_ERR_OK(status)) {
2940 goto out;
2943 sid_string = argv[0];
2944 attrs = (argv + 1);
2946 if (!string_to_sid(&sid, sid_string)) {
2947 d_fprintf(stderr, _("could not convert sid\n"));
2948 goto out;
2951 status = ads_search_retry_sid(ads, &res, &sid, attrs);
2952 if (!ADS_ERR_OK(status)) {
2953 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2954 goto out;
2957 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2959 /* dump the results */
2960 ads_dump(ads, res);
2962 ret = 0;
2963 out:
2964 ads_msgfree(ads, res);
2965 TALLOC_FREE(tmp_ctx);
2966 return ret;
2969 static int net_ads_keytab_flush(struct net_context *c,
2970 int argc,
2971 const char **argv)
2973 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2974 ADS_STRUCT *ads = NULL;
2975 ADS_STATUS status;
2976 int ret = -1;
2978 if (c->display_usage) {
2979 d_printf( "%s\n"
2980 "net ads keytab flush\n"
2981 " %s\n",
2982 _("Usage:"),
2983 _("Delete the whole keytab"));
2984 TALLOC_FREE(tmp_ctx);
2985 return -1;
2988 if (!c->opt_user_specified && c->opt_password == NULL) {
2989 net_use_krb_machine_account(c);
2992 status = ads_startup(c, true, tmp_ctx, &ads);
2993 if (!ADS_ERR_OK(status)) {
2994 goto out;
2997 ret = ads_keytab_flush(ads);
2998 out:
2999 TALLOC_FREE(tmp_ctx);
3000 return ret;
3003 static int net_ads_keytab_add(struct net_context *c,
3004 int argc,
3005 const char **argv,
3006 bool update_ads)
3008 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3009 ADS_STRUCT *ads = NULL;
3010 ADS_STATUS status;
3011 int i;
3012 int ret = -1;
3014 if (c->display_usage) {
3015 d_printf("%s\n%s",
3016 _("Usage:"),
3017 _("net ads keytab add <principal> [principal ...]\n"
3018 " Add principals to local keytab\n"
3019 " principal\tKerberos principal to add to "
3020 "keytab\n"));
3021 TALLOC_FREE(tmp_ctx);
3022 return -1;
3025 net_warn_member_options();
3027 d_printf(_("Processing principals to add...\n"));
3029 if (!c->opt_user_specified && c->opt_password == NULL) {
3030 net_use_krb_machine_account(c);
3033 status = ads_startup(c, true, tmp_ctx, &ads);
3034 if (!ADS_ERR_OK(status)) {
3035 goto out;
3038 for (ret = 0, i = 0; i < argc; i++) {
3039 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3041 out:
3042 TALLOC_FREE(tmp_ctx);
3043 return ret;
3046 static int net_ads_keytab_add_default(struct net_context *c,
3047 int argc,
3048 const char **argv)
3050 return net_ads_keytab_add(c, argc, argv, false);
3053 static int net_ads_keytab_add_update_ads(struct net_context *c,
3054 int argc,
3055 const char **argv)
3057 return net_ads_keytab_add(c, argc, argv, true);
3060 static int net_ads_keytab_delete(struct net_context *c,
3061 int argc,
3062 const char **argv)
3064 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3065 ADS_STRUCT *ads = NULL;
3066 ADS_STATUS status;
3067 int i;
3068 int ret = -1;
3070 if (c->display_usage) {
3071 d_printf("%s\n%s",
3072 _("Usage:"),
3073 _("net ads keytab delete <principal> [principal ...]\n"
3074 " Remove entries for service principal, "
3075 " from the keytab file only."
3076 " Remove principals from local keytab\n"
3077 " principal\tKerberos principal to remove from "
3078 "keytab\n"));
3079 TALLOC_FREE(tmp_ctx);
3080 return -1;
3083 d_printf(_("Processing principals to delete...\n"));
3085 if (!c->opt_user_specified && c->opt_password == NULL) {
3086 net_use_krb_machine_account(c);
3089 status = ads_startup(c, true, tmp_ctx, &ads);
3090 if (!ADS_ERR_OK(status)) {
3091 goto out;
3094 for (ret = 0, i = 0; i < argc; i++) {
3095 ret |= ads_keytab_delete_entry(ads, argv[i]);
3097 out:
3098 TALLOC_FREE(tmp_ctx);
3099 return ret;
3102 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3104 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3105 ADS_STRUCT *ads = NULL;
3106 ADS_STATUS status;
3107 int ret = -1;
3109 if (c->display_usage) {
3110 d_printf( "%s\n"
3111 "net ads keytab create\n"
3112 " %s\n",
3113 _("Usage:"),
3114 _("Create new default keytab"));
3115 TALLOC_FREE(tmp_ctx);
3116 return -1;
3119 net_warn_member_options();
3121 if (!c->opt_user_specified && c->opt_password == NULL) {
3122 net_use_krb_machine_account(c);
3125 status = ads_startup(c, true, tmp_ctx, &ads);
3126 if (!ADS_ERR_OK(status)) {
3127 goto out;
3130 ret = ads_keytab_create_default(ads);
3131 out:
3132 TALLOC_FREE(tmp_ctx);
3133 return ret;
3136 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3138 const char *keytab = NULL;
3140 if (c->display_usage) {
3141 d_printf("%s\n%s",
3142 _("Usage:"),
3143 _("net ads keytab list [keytab]\n"
3144 " List a local keytab\n"
3145 " keytab\tKeytab to list\n"));
3146 return -1;
3149 if (argc >= 1) {
3150 keytab = argv[0];
3153 return ads_keytab_list(keytab);
3157 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3159 struct functable func[] = {
3161 "add",
3162 net_ads_keytab_add_default,
3163 NET_TRANSPORT_ADS,
3164 N_("Add a service principal"),
3165 N_("net ads keytab add\n"
3166 " Add a service principal, updates keytab file only.")
3169 "delete",
3170 net_ads_keytab_delete,
3171 NET_TRANSPORT_ADS,
3172 N_("Delete a service principal"),
3173 N_("net ads keytab delete\n"
3174 " Remove entries for service principal, from the keytab file only.")
3177 "add_update_ads",
3178 net_ads_keytab_add_update_ads,
3179 NET_TRANSPORT_ADS,
3180 N_("Add a service principal"),
3181 N_("net ads keytab add_update_ads\n"
3182 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3185 "create",
3186 net_ads_keytab_create,
3187 NET_TRANSPORT_ADS,
3188 N_("Create a fresh keytab"),
3189 N_("net ads keytab create\n"
3190 " Create a fresh keytab or update existing one.")
3193 "flush",
3194 net_ads_keytab_flush,
3195 NET_TRANSPORT_ADS,
3196 N_("Remove all keytab entries"),
3197 N_("net ads keytab flush\n"
3198 " Remove all keytab entries")
3201 "list",
3202 net_ads_keytab_list,
3203 NET_TRANSPORT_ADS,
3204 N_("List a keytab"),
3205 N_("net ads keytab list\n"
3206 " List a keytab")
3208 {NULL, NULL, 0, NULL, NULL}
3211 if (!USE_KERBEROS_KEYTAB) {
3212 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3213 "keytab method to use keytab functions.\n"));
3216 return net_run_function(c, argc, argv, "net ads keytab", func);
3219 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3221 int ret = -1;
3223 if (c->display_usage) {
3224 d_printf( "%s\n"
3225 "net ads kerberos renew\n"
3226 " %s\n",
3227 _("Usage:"),
3228 _("Renew TGT from existing credential cache"));
3229 return -1;
3232 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3233 if (ret) {
3234 d_printf(_("failed to renew kerberos ticket: %s\n"),
3235 error_message(ret));
3237 return ret;
3240 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3241 struct PAC_DATA_CTR **pac_data_ctr)
3243 NTSTATUS status;
3244 int ret = -1;
3245 const char *impersonate_princ_s = NULL;
3246 const char *local_service = NULL;
3247 int i;
3249 for (i=0; i<argc; i++) {
3250 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3251 impersonate_princ_s = get_string_param(argv[i]);
3252 if (impersonate_princ_s == NULL) {
3253 return -1;
3256 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3257 local_service = get_string_param(argv[i]);
3258 if (local_service == NULL) {
3259 return -1;
3264 if (local_service == NULL) {
3265 local_service = talloc_asprintf(c, "%s$@%s",
3266 lp_netbios_name(), lp_realm());
3267 if (local_service == NULL) {
3268 goto out;
3272 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3274 status = kerberos_return_pac(c,
3275 c->opt_user_name,
3276 c->opt_password,
3278 NULL,
3279 NULL,
3280 NULL,
3281 true,
3282 true,
3283 2592000, /* one month */
3284 impersonate_princ_s,
3285 local_service,
3286 NULL,
3287 NULL,
3288 pac_data_ctr);
3289 if (!NT_STATUS_IS_OK(status)) {
3290 d_printf(_("failed to query kerberos PAC: %s\n"),
3291 nt_errstr(status));
3292 goto out;
3295 ret = 0;
3296 out:
3297 return ret;
3300 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3302 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3303 int i, num_buffers;
3304 int ret = -1;
3305 enum PAC_TYPE type = 0;
3307 if (c->display_usage) {
3308 d_printf( "%s\n"
3309 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3310 " %s\n",
3311 _("Usage:"),
3312 _("Dump the Kerberos PAC"));
3313 return -1;
3316 for (i=0; i<argc; i++) {
3317 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3318 type = get_int_param(argv[i]);
3322 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3323 if (ret) {
3324 return ret;
3327 if (type == 0) {
3329 char *s = NULL;
3331 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3332 pac_data_ctr->pac_data);
3333 if (s != NULL) {
3334 d_printf(_("The Pac: %s\n"), s);
3335 talloc_free(s);
3338 return 0;
3341 num_buffers = pac_data_ctr->pac_data->num_buffers;
3343 for (i=0; i<num_buffers; i++) {
3345 char *s = NULL;
3347 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3348 continue;
3351 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3352 pac_data_ctr->pac_data->buffers[i].info);
3353 if (s != NULL) {
3354 d_printf(_("The Pac: %s\n"), s);
3355 talloc_free(s);
3357 break;
3360 return 0;
3363 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3365 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3366 char *filename = NULL;
3367 int ret = -1;
3368 int i;
3370 if (c->display_usage) {
3371 d_printf( "%s\n"
3372 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3373 " %s\n",
3374 _("Usage:"),
3375 _("Save the Kerberos PAC"));
3376 return -1;
3379 for (i=0; i<argc; i++) {
3380 if (strnequal(argv[i], "filename", strlen("filename"))) {
3381 filename = get_string_param(argv[i]);
3382 if (filename == NULL) {
3383 return -1;
3388 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3389 if (ret) {
3390 return ret;
3393 if (filename == NULL) {
3394 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3395 return -1;
3398 /* save the raw format */
3399 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3400 d_printf(_("failed to save PAC in %s\n"), filename);
3401 return -1;
3404 return 0;
3407 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3409 struct functable func[] = {
3411 "dump",
3412 net_ads_kerberos_pac_dump,
3413 NET_TRANSPORT_ADS,
3414 N_("Dump Kerberos PAC"),
3415 N_("net ads kerberos pac dump\n"
3416 " Dump a Kerberos PAC to stdout")
3419 "save",
3420 net_ads_kerberos_pac_save,
3421 NET_TRANSPORT_ADS,
3422 N_("Save Kerberos PAC"),
3423 N_("net ads kerberos pac save\n"
3424 " Save a Kerberos PAC in a file")
3427 {NULL, NULL, 0, NULL, NULL}
3430 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3433 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3435 int ret = -1;
3436 NTSTATUS status;
3438 if (c->display_usage) {
3439 d_printf( "%s\n"
3440 "net ads kerberos kinit\n"
3441 " %s\n",
3442 _("Usage:"),
3443 _("Get Ticket Granting Ticket (TGT) for the user"));
3444 return -1;
3447 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3449 ret = kerberos_kinit_password_ext(c->opt_user_name,
3450 c->opt_password,
3452 NULL,
3453 NULL,
3454 NULL,
3455 true,
3456 true,
3457 2592000, /* one month */
3458 NULL,
3459 NULL,
3460 NULL,
3461 &status);
3462 if (ret) {
3463 d_printf(_("failed to kinit password: %s\n"),
3464 nt_errstr(status));
3466 return ret;
3469 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3471 struct functable func[] = {
3473 "kinit",
3474 net_ads_kerberos_kinit,
3475 NET_TRANSPORT_ADS,
3476 N_("Retrieve Ticket Granting Ticket (TGT)"),
3477 N_("net ads kerberos kinit\n"
3478 " Receive Ticket Granting Ticket (TGT)")
3481 "renew",
3482 net_ads_kerberos_renew,
3483 NET_TRANSPORT_ADS,
3484 N_("Renew Ticket Granting Ticket from credential cache"),
3485 N_("net ads kerberos renew\n"
3486 " Renew Ticket Granting Ticket (TGT) from "
3487 "credential cache")
3490 "pac",
3491 net_ads_kerberos_pac,
3492 NET_TRANSPORT_ADS,
3493 N_("Dump Kerberos PAC"),
3494 N_("net ads kerberos pac\n"
3495 " Dump Kerberos PAC")
3497 {NULL, NULL, 0, NULL, NULL}
3500 return net_run_function(c, argc, argv, "net ads kerberos", func);
3503 static int net_ads_setspn_list(struct net_context *c,
3504 int argc,
3505 const char **argv)
3507 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3508 ADS_STRUCT *ads = NULL;
3509 ADS_STATUS status;
3510 bool ok = false;
3511 int ret = -1;
3513 if (c->display_usage) {
3514 d_printf("%s\n%s",
3515 _("Usage:"),
3516 _("net ads setspn list <machinename>\n"));
3517 TALLOC_FREE(tmp_ctx);
3518 return -1;
3521 status = ads_startup(c, true, tmp_ctx, &ads);
3522 if (!ADS_ERR_OK(status)) {
3523 goto out;
3526 if (argc) {
3527 ok = ads_setspn_list(ads, argv[0]);
3528 } else {
3529 ok = ads_setspn_list(ads, lp_netbios_name());
3532 ret = ok ? 0 : -1;
3533 out:
3534 TALLOC_FREE(tmp_ctx);
3535 return ret;
3538 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3540 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3541 ADS_STRUCT *ads = NULL;
3542 ADS_STATUS status;
3543 bool ok = false;
3544 int ret = -1;
3546 if (c->display_usage || argc < 1) {
3547 d_printf("%s\n%s",
3548 _("Usage:"),
3549 _("net ads setspn add <machinename> SPN\n"));
3550 TALLOC_FREE(tmp_ctx);
3551 return -1;
3554 status = ads_startup(c, true, tmp_ctx, &ads);
3555 if (!ADS_ERR_OK(status)) {
3556 goto out;
3559 if (argc > 1) {
3560 ok = ads_setspn_add(ads, argv[0], argv[1]);
3561 } else {
3562 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3565 ret = ok ? 0 : -1;
3566 out:
3567 TALLOC_FREE(tmp_ctx);
3568 return ret;
3571 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3573 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3574 ADS_STRUCT *ads = NULL;
3575 ADS_STATUS status;
3576 bool ok = false;
3577 int ret = -1;
3579 if (c->display_usage || argc < 1) {
3580 d_printf("%s\n%s",
3581 _("Usage:"),
3582 _("net ads setspn delete <machinename> SPN\n"));
3583 TALLOC_FREE(tmp_ctx);
3584 return -1;
3587 status = ads_startup(c, true, tmp_ctx, &ads);
3588 if (!ADS_ERR_OK(status)) {
3589 goto out;
3592 if (argc > 1) {
3593 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3594 } else {
3595 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3598 ret = ok ? 0 : -1;
3599 out:
3600 TALLOC_FREE(tmp_ctx);
3601 return ret;
3604 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3606 struct functable func[] = {
3608 "list",
3609 net_ads_setspn_list,
3610 NET_TRANSPORT_ADS,
3611 N_("List Service Principal Names (SPN)"),
3612 N_("net ads setspn list machine\n"
3613 " List Service Principal Names (SPN)")
3616 "add",
3617 net_ads_setspn_add,
3618 NET_TRANSPORT_ADS,
3619 N_("Add Service Principal Names (SPN)"),
3620 N_("net ads setspn add machine spn\n"
3621 " Add Service Principal Names (SPN)")
3624 "delete",
3625 net_ads_setspn_delete,
3626 NET_TRANSPORT_ADS,
3627 N_("Delete Service Principal Names (SPN)"),
3628 N_("net ads setspn delete machine spn\n"
3629 " Delete Service Principal Names (SPN)")
3631 {NULL, NULL, 0, NULL, NULL}
3634 return net_run_function(c, argc, argv, "net ads setspn", func);
3637 static int net_ads_enctype_lookup_account(struct net_context *c,
3638 ADS_STRUCT *ads,
3639 const char *account,
3640 LDAPMessage **res,
3641 const char **enctype_str)
3643 const char *filter;
3644 const char *attrs[] = {
3645 "msDS-SupportedEncryptionTypes",
3646 NULL
3648 int count;
3649 int ret = -1;
3650 ADS_STATUS status;
3652 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3653 account);
3654 if (filter == NULL) {
3655 goto done;
3658 status = ads_search(ads, res, filter, attrs);
3659 if (!ADS_ERR_OK(status)) {
3660 d_printf(_("no account found with filter: %s\n"), filter);
3661 goto done;
3664 count = ads_count_replies(ads, *res);
3665 switch (count) {
3666 case 1:
3667 break;
3668 case 0:
3669 d_printf(_("no account found with filter: %s\n"), filter);
3670 goto done;
3671 default:
3672 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3673 goto done;
3676 if (enctype_str) {
3677 *enctype_str = ads_pull_string(ads, c, *res,
3678 "msDS-SupportedEncryptionTypes");
3679 if (*enctype_str == NULL) {
3680 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3681 goto done;
3685 ret = 0;
3686 done:
3687 return ret;
3690 static void net_ads_enctype_dump_enctypes(const char *username,
3691 const char *enctype_str)
3693 int enctypes = atoi(enctype_str);
3695 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3696 username, enctypes, enctypes);
3698 printf("[%s] 0x%08x DES-CBC-CRC\n",
3699 enctypes & ENC_CRC32 ? "X" : " ",
3700 ENC_CRC32);
3701 printf("[%s] 0x%08x DES-CBC-MD5\n",
3702 enctypes & ENC_RSA_MD5 ? "X" : " ",
3703 ENC_RSA_MD5);
3704 printf("[%s] 0x%08x RC4-HMAC\n",
3705 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3706 ENC_RC4_HMAC_MD5);
3707 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3708 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3709 ENC_HMAC_SHA1_96_AES128);
3710 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3711 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3712 ENC_HMAC_SHA1_96_AES256);
3713 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3714 enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3715 ENC_HMAC_SHA1_96_AES256_SK);
3716 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3717 enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3718 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3721 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3723 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3724 ADS_STATUS status;
3725 ADS_STRUCT *ads = NULL;
3726 LDAPMessage *res = NULL;
3727 const char *str = NULL;
3728 int ret = -1;
3730 if (c->display_usage || (argc < 1)) {
3731 d_printf( "%s\n"
3732 "net ads enctypes list\n"
3733 " %s\n",
3734 _("Usage:"),
3735 _("List supported enctypes"));
3736 TALLOC_FREE(tmp_ctx);
3737 return -1;
3740 status = ads_startup(c, false, tmp_ctx, &ads);
3741 if (!ADS_ERR_OK(status)) {
3742 goto out;
3745 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3746 if (ret) {
3747 goto out;
3750 net_ads_enctype_dump_enctypes(argv[0], str);
3752 ret = 0;
3753 out:
3754 ads_msgfree(ads, res);
3755 TALLOC_FREE(tmp_ctx);
3756 return ret;
3759 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3761 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3762 int ret = -1;
3763 ADS_STATUS status;
3764 ADS_STRUCT *ads = NULL;
3765 LDAPMessage *res = NULL;
3766 const char *etype_list_str = NULL;
3767 const char *dn = NULL;
3768 ADS_MODLIST mods = NULL;
3769 uint32_t etype_list;
3770 const char *str = NULL;
3772 if (c->display_usage || argc < 1) {
3773 d_printf( "%s\n"
3774 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3775 " %s\n",
3776 _("Usage:"),
3777 _("Set supported enctypes"));
3778 TALLOC_FREE(tmp_ctx);
3779 return -1;
3782 status = ads_startup(c, false, tmp_ctx, &ads);
3783 if (!ADS_ERR_OK(status)) {
3784 goto done;
3787 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3788 if (ret) {
3789 goto done;
3792 dn = ads_get_dn(ads, tmp_ctx, res);
3793 if (dn == NULL) {
3794 goto done;
3797 etype_list = 0;
3798 etype_list |= ENC_RC4_HMAC_MD5;
3799 etype_list |= ENC_HMAC_SHA1_96_AES128;
3800 etype_list |= ENC_HMAC_SHA1_96_AES256;
3802 if (argv[1] != NULL) {
3803 sscanf(argv[1], "%i", &etype_list);
3806 etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3807 if (!etype_list_str) {
3808 goto done;
3811 mods = ads_init_mods(tmp_ctx);
3812 if (!mods) {
3813 goto done;
3816 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3817 etype_list_str);
3818 if (!ADS_ERR_OK(status)) {
3819 goto done;
3822 status = ads_gen_mod(ads, dn, mods);
3823 if (!ADS_ERR_OK(status)) {
3824 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3825 ads_errstr(status));
3826 goto done;
3829 ads_msgfree(ads, res);
3830 res = NULL;
3832 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3833 if (ret) {
3834 goto done;
3837 net_ads_enctype_dump_enctypes(argv[0], str);
3839 ret = 0;
3840 done:
3841 ads_msgfree(ads, res);
3842 TALLOC_FREE(tmp_ctx);
3843 return ret;
3846 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3848 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3849 int ret = -1;
3850 ADS_STATUS status;
3851 ADS_STRUCT *ads = NULL;
3852 LDAPMessage *res = NULL;
3853 const char *dn = NULL;
3854 ADS_MODLIST mods = NULL;
3856 if (c->display_usage || argc < 1) {
3857 d_printf( "%s\n"
3858 "net ads enctypes delete <sAMAccountName>\n"
3859 " %s\n",
3860 _("Usage:"),
3861 _("Delete supported enctypes"));
3862 TALLOC_FREE(tmp_ctx);
3863 return -1;
3866 status = ads_startup(c, false, tmp_ctx, &ads);
3867 if (!ADS_ERR_OK(status)) {
3868 goto done;
3871 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3872 if (ret) {
3873 goto done;
3876 dn = ads_get_dn(ads, tmp_ctx, res);
3877 if (dn == NULL) {
3878 goto done;
3881 mods = ads_init_mods(tmp_ctx);
3882 if (!mods) {
3883 goto done;
3886 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3887 if (!ADS_ERR_OK(status)) {
3888 goto done;
3891 status = ads_gen_mod(ads, dn, mods);
3892 if (!ADS_ERR_OK(status)) {
3893 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3894 ads_errstr(status));
3895 goto done;
3898 ret = 0;
3900 done:
3901 ads_msgfree(ads, res);
3902 TALLOC_FREE(tmp_ctx);
3903 return ret;
3906 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3908 struct functable func[] = {
3910 "list",
3911 net_ads_enctypes_list,
3912 NET_TRANSPORT_ADS,
3913 N_("List the supported encryption types"),
3914 N_("net ads enctypes list\n"
3915 " List the supported encryption types")
3918 "set",
3919 net_ads_enctypes_set,
3920 NET_TRANSPORT_ADS,
3921 N_("Set the supported encryption types"),
3922 N_("net ads enctypes set\n"
3923 " Set the supported encryption types")
3926 "delete",
3927 net_ads_enctypes_delete,
3928 NET_TRANSPORT_ADS,
3929 N_("Delete the supported encryption types"),
3930 N_("net ads enctypes delete\n"
3931 " Delete the supported encryption types")
3934 {NULL, NULL, 0, NULL, NULL}
3937 return net_run_function(c, argc, argv, "net ads enctypes", func);
3941 int net_ads(struct net_context *c, int argc, const char **argv)
3943 struct functable func[] = {
3945 "info",
3946 net_ads_info,
3947 NET_TRANSPORT_ADS,
3948 N_("Display details on remote ADS server"),
3949 N_("net ads info\n"
3950 " Display details on remote ADS server")
3953 "join",
3954 net_ads_join,
3955 NET_TRANSPORT_ADS,
3956 N_("Join the local machine to ADS realm"),
3957 N_("net ads join\n"
3958 " Join the local machine to ADS realm")
3961 "testjoin",
3962 net_ads_testjoin,
3963 NET_TRANSPORT_ADS,
3964 N_("Validate machine account"),
3965 N_("net ads testjoin\n"
3966 " Validate machine account")
3969 "leave",
3970 net_ads_leave,
3971 NET_TRANSPORT_ADS,
3972 N_("Remove the local machine from ADS"),
3973 N_("net ads leave\n"
3974 " Remove the local machine from ADS")
3977 "status",
3978 net_ads_status,
3979 NET_TRANSPORT_ADS,
3980 N_("Display machine account details"),
3981 N_("net ads status\n"
3982 " Display machine account details")
3985 "user",
3986 net_ads_user,
3987 NET_TRANSPORT_ADS,
3988 N_("List/modify users"),
3989 N_("net ads user\n"
3990 " List/modify users")
3993 "group",
3994 net_ads_group,
3995 NET_TRANSPORT_ADS,
3996 N_("List/modify groups"),
3997 N_("net ads group\n"
3998 " List/modify groups")
4001 "dns",
4002 net_ads_dns,
4003 NET_TRANSPORT_ADS,
4004 N_("Issue dynamic DNS update"),
4005 N_("net ads dns\n"
4006 " Issue dynamic DNS update")
4009 "password",
4010 net_ads_password,
4011 NET_TRANSPORT_ADS,
4012 N_("Change user passwords"),
4013 N_("net ads password\n"
4014 " Change user passwords")
4017 "changetrustpw",
4018 net_ads_changetrustpw,
4019 NET_TRANSPORT_ADS,
4020 N_("Change trust account password"),
4021 N_("net ads changetrustpw\n"
4022 " Change trust account password")
4025 "printer",
4026 net_ads_printer,
4027 NET_TRANSPORT_ADS,
4028 N_("List/modify printer entries"),
4029 N_("net ads printer\n"
4030 " List/modify printer entries")
4033 "search",
4034 net_ads_search,
4035 NET_TRANSPORT_ADS,
4036 N_("Issue LDAP search using filter"),
4037 N_("net ads search\n"
4038 " Issue LDAP search using filter")
4041 "dn",
4042 net_ads_dn,
4043 NET_TRANSPORT_ADS,
4044 N_("Issue LDAP search by DN"),
4045 N_("net ads dn\n"
4046 " Issue LDAP search by DN")
4049 "sid",
4050 net_ads_sid,
4051 NET_TRANSPORT_ADS,
4052 N_("Issue LDAP search by SID"),
4053 N_("net ads sid\n"
4054 " Issue LDAP search by SID")
4057 "workgroup",
4058 net_ads_workgroup,
4059 NET_TRANSPORT_ADS,
4060 N_("Display workgroup name"),
4061 N_("net ads workgroup\n"
4062 " Display the workgroup name")
4065 "lookup",
4066 net_ads_lookup,
4067 NET_TRANSPORT_ADS,
4068 N_("Perform CLDAP query on DC"),
4069 N_("net ads lookup\n"
4070 " Find the ADS DC using CLDAP lookups")
4073 "keytab",
4074 net_ads_keytab,
4075 NET_TRANSPORT_ADS,
4076 N_("Manage local keytab file"),
4077 N_("net ads keytab\n"
4078 " Manage local keytab file")
4081 "setspn",
4082 net_ads_setspn,
4083 NET_TRANSPORT_ADS,
4084 N_("Manage Service Principal Names (SPN)s"),
4085 N_("net ads spnset\n"
4086 " Manage Service Principal Names (SPN)s")
4089 "gpo",
4090 net_ads_gpo,
4091 NET_TRANSPORT_ADS,
4092 N_("Manage group policy objects"),
4093 N_("net ads gpo\n"
4094 " Manage group policy objects")
4097 "kerberos",
4098 net_ads_kerberos,
4099 NET_TRANSPORT_ADS,
4100 N_("Manage kerberos keytab"),
4101 N_("net ads kerberos\n"
4102 " Manage kerberos keytab")
4105 "enctypes",
4106 net_ads_enctypes,
4107 NET_TRANSPORT_ADS,
4108 N_("List/modify supported encryption types"),
4109 N_("net ads enctypes\n"
4110 " List/modify enctypes")
4112 {NULL, NULL, 0, NULL, NULL}
4115 return net_run_function(c, argc, argv, "net ads", func);
4118 #else
4120 static int net_ads_noads(void)
4122 d_fprintf(stderr, _("ADS support not compiled in\n"));
4123 return -1;
4126 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4128 return net_ads_noads();
4131 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4133 return net_ads_noads();
4136 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4138 return net_ads_noads();
4141 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4143 return net_ads_noads();
4146 int net_ads_join(struct net_context *c, int argc, const char **argv)
4148 return net_ads_noads();
4151 int net_ads_user(struct net_context *c, int argc, const char **argv)
4153 return net_ads_noads();
4156 int net_ads_group(struct net_context *c, int argc, const char **argv)
4158 return net_ads_noads();
4161 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4163 return net_ads_noads();
4166 /* this one shouldn't display a message */
4167 int net_ads_check(struct net_context *c)
4169 return -1;
4172 int net_ads_check_our_domain(struct net_context *c)
4174 return -1;
4177 int net_ads(struct net_context *c, int argc, const char **argv)
4179 return net_ads_noads();
4182 #endif /* HAVE_ADS */