2 Samba Unix/Linux SMB client library
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/>.
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"
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"
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"
48 #include "audit_logging.h" /* various JSON helpers */
49 #include "auth/common_auth.h"
50 #endif /* [HAVE_JANSSON] */
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)) {
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;
78 if (json_is_invalid(jsobj)) {
82 ctx = talloc_new(NULL);
84 d_fprintf(stderr, _("Out of memory\n"));
88 json = json_to_string(ctx, jsobj);
90 d_fprintf(stderr, _("error encoding to JSON\n"));
94 d_printf("%s\n", json);
100 static int net_ads_cldap_netlogon_json
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' };
110 if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
111 d_fprintf(stderr, _("error setting up JSON value\n"));
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));
122 case LOGON_SAM_LOGON_RESPONSE_EX:
123 strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
124 sizeof(response_type));
127 snprintf(response_type, sizeof(response_type), "0x%x",
132 ret = json_add_string(&jsobj, "Information for Domain Controller",
138 ret = json_add_string(&jsobj, "Response Type", response_type);
143 ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
148 ret = json_add_bool(&flagsobj, "Is a PDC",
149 reply->server_type & NBT_SERVER_PDC);
154 ret = json_add_bool(&flagsobj, "Is a GC of the forest",
155 reply->server_type & NBT_SERVER_GC);
160 ret = json_add_bool(&flagsobj, "Is an LDAP server",
161 reply->server_type & NBT_SERVER_LDAP);
166 ret = json_add_bool(&flagsobj, "Supports DS",
167 reply->server_type & NBT_SERVER_DS);
172 ret = json_add_bool(&flagsobj, "Is running a KDC",
173 reply->server_type & NBT_SERVER_KDC);
178 ret = json_add_bool(&flagsobj, "Is running time services",
179 reply->server_type & NBT_SERVER_TIMESERV);
184 ret = json_add_bool(&flagsobj, "Is the closest DC",
185 reply->server_type & NBT_SERVER_CLOSEST);
190 ret = json_add_bool(&flagsobj, "Is writable",
191 reply->server_type & NBT_SERVER_WRITABLE);
196 ret = json_add_bool(&flagsobj, "Has a hardware clock",
197 reply->server_type & NBT_SERVER_GOOD_TIMESERV);
202 ret = json_add_bool(&flagsobj,
203 "Is a non-domain NC serviced by LDAP server",
204 reply->server_type & NBT_SERVER_NDNC);
210 (&flagsobj, "Is NT6 DC that has some secrets",
211 reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
217 (&flagsobj, "Is NT6 DC that has all secrets",
218 reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
223 ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services",
224 reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
229 ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later",
230 reply->server_type & NBT_SERVER_DS_8);
235 ret = json_add_bool(&flagsobj, "Runs on Windows 2012R2 or later",
236 reply->server_type & NBT_SERVER_DS_9);
241 ret = json_add_bool(&flagsobj, "Runs on Windows 2016 or later",
242 reply->server_type & NBT_SERVER_DS_10);
247 ret = json_add_bool(&flagsobj, "Has a DNS name",
248 reply->server_type & NBT_SERVER_HAS_DNS_NAME);
253 ret = json_add_bool(&flagsobj, "Is a default NC",
254 reply->server_type & NBT_SERVER_IS_DEFAULT_NC);
259 ret = json_add_bool(&flagsobj, "Is the forest root",
260 reply->server_type & NBT_SERVER_FOREST_ROOT);
265 ret = json_add_string(&jsobj, "Forest", reply->forest);
270 ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
275 ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
281 ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
286 ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
291 if (*reply->user_name) {
292 ret = json_add_string(&jsobj, "User name", reply->user_name);
298 ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
303 ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
308 ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
313 ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
318 ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
323 ret = json_add_object(&jsobj, "Flags", &flagsobj);
328 ret = output_json(&jsobj);
329 json_free(&jsobj); /* frees flagsobj recursively */
334 json_free(&flagsobj);
340 #else /* [HAVE_JANSSON] */
342 static int net_ads_cldap_netlogon_json
345 const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
347 d_fprintf(stderr, _("JSON support not available\n"));
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"));
370 return net_ads_cldap_netlogon_json(ads, addr, &reply);
373 d_printf(_("Information for Domain Controller: %s\n\n"),
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");
381 case LOGON_SAM_LOGON_RESPONSE_EX:
382 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
385 d_printf("0x%x\n", reply.command);
389 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
391 d_printf(_("Flags:\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);
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;
462 if (c->display_usage) {
467 _("Find the ADS DC using CLDAP lookup.\n"));
468 TALLOC_FREE(tmp_ctx);
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"));
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"));
484 ads->ldap.port = 389;
487 ret = net_ads_cldap_netlogon(c, ads);
489 TALLOC_FREE(tmp_ctx);
496 static int net_ads_info_json(ADS_STRUCT *ads)
499 char addr[INET6_ADDRSTRLEN];
501 struct json_object jsobj = json_new_object();
503 if (json_is_invalid(&jsobj)) {
504 d_fprintf(stderr, _("error setting up JSON value\n"));
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);
518 ret = json_add_string (&jsobj, "LDAP server name",
519 ads->config.ldap_server_name);
524 ret = json_add_string (&jsobj, "Workgroup", ads->config.workgroup);
529 ret = json_add_string (&jsobj, "Realm", ads->config.realm);
534 ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
539 ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
544 ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
549 ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
554 ret = json_add_int (&jsobj, "Server time offset",
555 ads->auth.time_offset);
560 ret = json_add_int (&jsobj, "Last machine account password change",
566 ret = output_json(&jsobj);
573 #else /* [HAVE_JANSSON] */
575 static int net_ads_info_json(ADS_STRUCT *ads)
577 d_fprintf(stderr, _("JSON support not available\n"));
582 #endif /* [HAVE_JANSSON] */
586 static int net_ads_info(struct net_context *c, int argc, const char **argv)
588 TALLOC_CTX *tmp_ctx = talloc_stackframe();
589 ADS_STRUCT *ads = NULL;
591 char addr[INET6_ADDRSTRLEN];
595 if (c->display_usage) {
600 _("Display information about an Active Directory "
602 TALLOC_FREE(tmp_ctx);
606 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
607 if (!ADS_ERR_OK(status)) {
608 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
612 if (!ads || !ads->config.realm) {
613 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
617 /* Try to set the server's current time since we didn't do a full
618 TCP LDAP session initially */
620 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
621 d_fprintf( stderr, _("Failed to get server's current time!\n"));
625 ret = net_ads_info_json(ads);
629 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
631 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
633 d_printf(_("LDAP server: %s\n"), addr);
634 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
635 d_printf(_("Workgroup: %s\n"), ads->config.workgroup);
636 d_printf(_("Realm: %s\n"), ads->config.realm);
637 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
638 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
639 d_printf(_("Server time: %s\n"),
640 http_timestring(tmp_ctx, ads->config.current_time));
642 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
643 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
645 d_printf(_("Last machine account password change: %s\n"),
646 http_timestring(tmp_ctx, pass_time));
650 TALLOC_FREE(tmp_ctx);
654 static ADS_STATUS ads_startup_int(struct net_context *c,
655 bool only_own_domain,
658 ADS_STRUCT **ads_ret)
660 ADS_STRUCT *ads = NULL;
662 bool need_password = false;
663 bool second_time = false;
665 const char *realm = NULL;
666 bool tried_closest_dc = false;
667 enum credentials_use_kerberos krb5_state =
668 CRED_USE_KERBEROS_DISABLED;
670 /* lp_realm() should be handled by a command line param,
671 However, the join requires that realm be set in smb.conf
672 and compares our realm with the remote server's so this is
673 ok until someone needs more flexibility */
678 if (only_own_domain) {
681 realm = assume_own_realm(c);
684 ads = ads_init(mem_ctx,
686 c->opt_target_workgroup,
690 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
693 if (!c->opt_user_name) {
694 c->opt_user_name = "administrator";
697 if (c->opt_user_specified) {
698 need_password = true;
702 if (!c->opt_password && need_password && !c->opt_machine_pass) {
703 c->opt_password = net_prompt_pass(c, c->opt_user_name);
704 if (!c->opt_password) {
706 return ADS_ERROR(LDAP_NO_MEMORY);
710 if (c->opt_password) {
711 use_in_memory_ccache();
712 ADS_TALLOC_CONST_FREE(ads->auth.password);
713 ads->auth.password = talloc_strdup(ads, c->opt_password);
714 if (ads->auth.password == NULL) {
716 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
720 ADS_TALLOC_CONST_FREE(ads->auth.user_name);
721 ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
722 if (ads->auth.user_name == NULL) {
724 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
727 ads->auth.flags |= auth_flags;
729 /* The ADS code will handle FIPS mode */
730 krb5_state = cli_credentials_get_kerberos_state(c->creds);
731 switch (krb5_state) {
732 case CRED_USE_KERBEROS_REQUIRED:
733 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
734 ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
736 case CRED_USE_KERBEROS_DESIRED:
737 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
738 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
740 case CRED_USE_KERBEROS_DISABLED:
741 ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
742 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
747 * If the username is of the form "name@realm",
748 * extract the realm and convert to upper case.
749 * This is only used to establish the connection.
751 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
753 ADS_TALLOC_CONST_FREE(ads->auth.realm);
754 ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
755 if (ads->auth.realm == NULL) {
757 return ADS_ERROR(LDAP_NO_MEMORY);
759 } else if (ads->auth.realm == NULL) {
760 const char *c_realm = cli_credentials_get_realm(c->creds);
762 if (c_realm != NULL) {
763 ads->auth.realm = talloc_strdup(ads, c_realm);
764 if (ads->auth.realm == NULL) {
766 return ADS_ERROR(LDAP_NO_MEMORY);
771 status = ads_connect(ads);
773 if (!ADS_ERR_OK(status)) {
775 if (NT_STATUS_EQUAL(ads_ntstatus(status),
776 NT_STATUS_NO_LOGON_SERVERS)) {
777 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
782 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
783 need_password = true;
792 /* when contacting our own domain, make sure we use the closest DC.
793 * This is done by reconnecting to ADS because only the first call to
794 * ads_connect will give us our own sitename */
796 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
798 tried_closest_dc = true; /* avoid loop */
800 if (!ads_closest_dc(ads)) {
802 namecache_delete(ads->server.realm, 0x1C);
803 namecache_delete(ads->server.workgroup, 0x1C);
811 *ads_ret = talloc_move(mem_ctx, &ads);
815 ADS_STATUS ads_startup(struct net_context *c,
816 bool only_own_domain,
820 return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
823 ADS_STATUS ads_startup_nobind(struct net_context *c,
824 bool only_own_domain,
828 return ads_startup_int(c,
836 Check to see if connection can be made via ads.
837 ads_startup() stores the password in opt_password if it needs to so
838 that rpc or rap can use it without re-prompting.
840 static int net_ads_check_int(struct net_context *c,
842 const char *workgroup,
845 TALLOC_CTX *tmp_ctx = talloc_stackframe();
850 ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
855 ads->auth.flags |= ADS_AUTH_NO_BIND;
857 status = ads_connect(ads);
858 if ( !ADS_ERR_OK(status) ) {
864 TALLOC_FREE(tmp_ctx);
868 int net_ads_check_our_domain(struct net_context *c)
870 return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
873 int net_ads_check(struct net_context *c)
875 return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
879 determine the netbios workgroup name for a domain
881 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
883 TALLOC_CTX *tmp_ctx = talloc_stackframe();
884 ADS_STRUCT *ads = NULL;
886 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
890 if (c->display_usage) {
892 "net ads workgroup\n"
895 _("Print the workgroup name"));
896 TALLOC_FREE(tmp_ctx);
900 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
901 if (!ADS_ERR_OK(status)) {
902 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
906 if (!ads->config.realm) {
907 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
908 if (ads->config.realm == NULL) {
909 d_fprintf(stderr, _("Out of memory\n"));
912 ads->ldap.port = 389;
915 ok = ads_cldap_netlogon_5(tmp_ctx,
916 &ads->ldap.ss, ads->server.realm, &reply);
918 d_fprintf(stderr, _("CLDAP query failed!\n"));
922 d_printf(_("Workgroup: %s\n"), reply.domain_name);
926 TALLOC_FREE(tmp_ctx);
933 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
935 char **disp_fields = (char **) data_area;
937 if (!field) { /* must be end of record */
938 if (disp_fields[0]) {
939 if (!strchr_m(disp_fields[0], '$')) {
941 d_printf("%-21.21s %s\n",
942 disp_fields[0], disp_fields[1]);
944 d_printf("%s\n", disp_fields[0]);
947 SAFE_FREE(disp_fields[0]);
948 SAFE_FREE(disp_fields[1]);
951 if (!values) /* must be new field, indicate string field */
953 if (strcasecmp_m(field, "sAMAccountName") == 0) {
954 disp_fields[0] = SMB_STRDUP((char *) values[0]);
956 if (strcasecmp_m(field, "description") == 0)
957 disp_fields[1] = SMB_STRDUP((char *) values[0]);
961 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
963 return net_user_usage(c, argc, argv);
966 static int ads_user_add(struct net_context *c, int argc, const char **argv)
968 TALLOC_CTX *tmp_ctx = talloc_stackframe();
969 ADS_STRUCT *ads = NULL;
972 LDAPMessage *res=NULL;
976 if (argc < 1 || c->display_usage) {
977 TALLOC_FREE(tmp_ctx);
978 return net_ads_user_usage(c, argc, argv);
981 status = ads_startup(c, false, tmp_ctx, &ads);
982 if (!ADS_ERR_OK(status)) {
986 status = ads_find_user_acct(ads, &res, argv[0]);
987 if (!ADS_ERR_OK(status)) {
988 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
992 if (ads_count_replies(ads, res)) {
993 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
998 if (c->opt_container) {
999 ou_str = SMB_STRDUP(c->opt_container);
1001 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1004 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
1005 if (!ADS_ERR_OK(status)) {
1006 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
1007 ads_errstr(status));
1011 /* if no password is to be set, we're done */
1013 d_printf(_("User %s added\n"), argv[0]);
1018 /* try setting the password */
1019 upn = talloc_asprintf(tmp_ctx,
1027 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
1028 ads->auth.time_offset);
1029 if (ADS_ERR_OK(status)) {
1030 d_printf(_("User %s added\n"), argv[0]);
1036 /* password didn't set, delete account */
1037 d_fprintf(stderr, _("Could not add user %s. "
1038 "Error setting password %s\n"),
1039 argv[0], ads_errstr(status));
1041 ads_msgfree(ads, res);
1044 status=ads_find_user_acct(ads, &res, argv[0]);
1045 if (ADS_ERR_OK(status)) {
1046 userdn = ads_get_dn(ads, tmp_ctx, res);
1047 ads_del_dn(ads, userdn);
1048 TALLOC_FREE(userdn);
1052 ads_msgfree(ads, res);
1054 TALLOC_FREE(tmp_ctx);
1058 static int ads_user_info(struct net_context *c, int argc, const char **argv)
1060 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1061 ADS_STRUCT *ads = NULL;
1063 LDAPMessage *res = NULL;
1066 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1067 char *searchstring = NULL;
1068 char **grouplist = NULL;
1069 char *primary_group = NULL;
1070 char *escaped_user = NULL;
1071 struct dom_sid primary_group_sid;
1073 enum wbcSidType type;
1075 if (argc < 1 || c->display_usage) {
1076 TALLOC_FREE(tmp_ctx);
1077 return net_ads_user_usage(c, argc, argv);
1080 escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1081 if (!escaped_user) {
1083 _("ads_user_info: failed to escape user %s\n"),
1088 status = ads_startup(c, false, tmp_ctx, &ads);
1089 if (!ADS_ERR_OK(status)) {
1093 searchstring = talloc_asprintf(tmp_ctx,
1094 "(sAMAccountName=%s)",
1096 if (searchstring == NULL) {
1100 status = ads_search(ads, &res, searchstring, attrs);
1101 if (!ADS_ERR_OK(status)) {
1102 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1106 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1107 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1111 status = ads_domain_sid(ads, &primary_group_sid);
1112 if (!ADS_ERR_OK(status)) {
1113 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1117 sid_append_rid(&primary_group_sid, group_rid);
1119 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1120 NULL, /* don't look up domain */
1123 if (!WBC_ERROR_IS_OK(wbc_status)) {
1124 d_fprintf(stderr, "wbcLookupSid: %s\n",
1125 wbcErrorString(wbc_status));
1129 d_printf("%s\n", primary_group);
1131 wbcFreeMemory(primary_group);
1133 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1134 (LDAPMessage *)res, "memberOf");
1139 for (i=0;grouplist[i];i++) {
1140 groupname = ldap_explode_dn(grouplist[i], 1);
1141 d_printf("%s\n", groupname[0]);
1142 ldap_value_free(groupname);
1144 ldap_value_free(grouplist);
1149 TALLOC_FREE(escaped_user);
1150 TALLOC_FREE(searchstring);
1151 ads_msgfree(ads, res);
1152 TALLOC_FREE(tmp_ctx);
1156 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1158 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1159 ADS_STRUCT *ads = NULL;
1161 LDAPMessage *res = NULL;
1162 char *userdn = NULL;
1166 TALLOC_FREE(tmp_ctx);
1167 return net_ads_user_usage(c, argc, argv);
1170 status = ads_startup(c, false, tmp_ctx, &ads);
1171 if (!ADS_ERR_OK(status)) {
1175 status = ads_find_user_acct(ads, &res, argv[0]);
1176 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1177 d_printf(_("User %s does not exist.\n"), argv[0]);
1181 userdn = ads_get_dn(ads, tmp_ctx, res);
1182 if (userdn == NULL) {
1186 status = ads_del_dn(ads, userdn);
1187 if (!ADS_ERR_OK(status)) {
1188 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1189 ads_errstr(status));
1193 d_printf(_("User %s deleted\n"), argv[0]);
1197 ads_msgfree(ads, res);
1198 TALLOC_FREE(tmp_ctx);
1202 int net_ads_user(struct net_context *c, int argc, const char **argv)
1204 struct functable func[] = {
1209 N_("Add an AD user"),
1210 N_("net ads user add\n"
1217 N_("Display information about an AD user"),
1218 N_("net ads user info\n"
1219 " Display information about an AD user")
1225 N_("Delete an AD user"),
1226 N_("net ads user delete\n"
1227 " Delete an AD user")
1229 {NULL, NULL, 0, NULL, NULL}
1231 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1232 ADS_STRUCT *ads = NULL;
1234 const char *shortattrs[] = {"sAMAccountName", NULL};
1235 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1236 char *disp_fields[2] = {NULL, NULL};
1240 TALLOC_FREE(tmp_ctx);
1241 return net_run_function(c, argc, argv, "net ads user", func);
1244 if (c->display_usage) {
1249 _("List AD users"));
1250 net_display_usage_from_functable(func);
1251 TALLOC_FREE(tmp_ctx);
1255 status = ads_startup(c, false, tmp_ctx, &ads);
1256 if (!ADS_ERR_OK(status)) {
1260 if (c->opt_long_list_entries)
1261 d_printf(_("\nUser name Comment"
1262 "\n-----------------------------\n"));
1264 status = ads_do_search_all_fn(ads,
1265 ads->config.bind_path,
1267 "(objectCategory=user)",
1268 c->opt_long_list_entries ?
1269 longattrs : shortattrs,
1272 if (!ADS_ERR_OK(status)) {
1278 TALLOC_FREE(tmp_ctx);
1282 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1284 return net_group_usage(c, argc, argv);
1287 static int ads_group_add(struct net_context *c, int argc, const char **argv)
1289 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1290 ADS_STRUCT *ads = NULL;
1292 LDAPMessage *res = NULL;
1294 char *ou_str = NULL;
1296 if (argc < 1 || c->display_usage) {
1297 TALLOC_FREE(tmp_ctx);
1298 return net_ads_group_usage(c, argc, argv);
1301 status = ads_startup(c, false, tmp_ctx, &ads);
1302 if (!ADS_ERR_OK(status)) {
1306 status = ads_find_user_acct(ads, &res, argv[0]);
1307 if (!ADS_ERR_OK(status)) {
1308 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1312 if (ads_count_replies(ads, res)) {
1313 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1317 if (c->opt_container) {
1318 ou_str = SMB_STRDUP(c->opt_container);
1320 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1323 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1324 if (!ADS_ERR_OK(status)) {
1325 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1326 ads_errstr(status));
1330 d_printf(_("Group %s added\n"), argv[0]);
1334 ads_msgfree(ads, res);
1336 TALLOC_FREE(tmp_ctx);
1340 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1342 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1343 ADS_STRUCT *ads = NULL;
1345 LDAPMessage *res = NULL;
1346 char *groupdn = NULL;
1349 if (argc < 1 || c->display_usage) {
1350 TALLOC_FREE(tmp_ctx);
1351 return net_ads_group_usage(c, argc, argv);
1354 status = ads_startup(c, false, tmp_ctx, &ads);
1355 if (!ADS_ERR_OK(status)) {
1359 status = ads_find_user_acct(ads, &res, argv[0]);
1360 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1361 d_printf(_("Group %s does not exist.\n"), argv[0]);
1365 groupdn = ads_get_dn(ads, tmp_ctx, res);
1366 if (groupdn == NULL) {
1370 status = ads_del_dn(ads, groupdn);
1371 if (!ADS_ERR_OK(status)) {
1372 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1373 ads_errstr(status));
1376 d_printf(_("Group %s deleted\n"), argv[0]);
1380 ads_msgfree(ads, res);
1381 TALLOC_FREE(tmp_ctx);
1385 int net_ads_group(struct net_context *c, int argc, const char **argv)
1387 struct functable func[] = {
1392 N_("Add an AD group"),
1393 N_("net ads group add\n"
1400 N_("Delete an AD group"),
1401 N_("net ads group delete\n"
1402 " Delete an AD group")
1404 {NULL, NULL, 0, NULL, NULL}
1406 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1407 ADS_STRUCT *ads = NULL;
1409 const char *shortattrs[] = {"sAMAccountName", NULL};
1410 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1411 char *disp_fields[2] = {NULL, NULL};
1415 TALLOC_FREE(tmp_ctx);
1416 return net_run_function(c, argc, argv, "net ads group", func);
1419 if (c->display_usage) {
1424 _("List AD groups"));
1425 net_display_usage_from_functable(func);
1426 TALLOC_FREE(tmp_ctx);
1430 status = ads_startup(c, false, tmp_ctx, &ads);
1431 if (!ADS_ERR_OK(status)) {
1435 if (c->opt_long_list_entries)
1436 d_printf(_("\nGroup name Comment"
1437 "\n-----------------------------\n"));
1439 status = ads_do_search_all_fn(ads,
1440 ads->config.bind_path,
1442 "(objectCategory=group)",
1443 c->opt_long_list_entries ?
1444 longattrs : shortattrs,
1447 if (!ADS_ERR_OK(status)) {
1453 TALLOC_FREE(tmp_ctx);
1457 static int net_ads_status(struct net_context *c, int argc, const char **argv)
1459 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1460 ADS_STRUCT *ads = NULL;
1462 LDAPMessage *res = NULL;
1465 if (c->display_usage) {
1470 _("Display machine account details"));
1471 TALLOC_FREE(tmp_ctx);
1475 net_warn_member_options();
1477 status = ads_startup(c, true, tmp_ctx, &ads);
1478 if (!ADS_ERR_OK(status)) {
1482 status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1483 if (!ADS_ERR_OK(status)) {
1484 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1485 ads_errstr(status));
1489 if (ads_count_replies(ads, res) == 0) {
1490 d_fprintf(stderr, _("No machine account for '%s' found\n"),
1499 ads_msgfree(ads, res);
1500 TALLOC_FREE(tmp_ctx);
1504 /*******************************************************************
1505 Leave an AD domain. Windows XP disables the machine account.
1506 We'll try the same. The old code would do an LDAP delete.
1507 That only worked using the machine creds because added the machine
1508 with full control to the computer object's ACL.
1509 *******************************************************************/
1511 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1513 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1514 struct libnet_UnjoinCtx *r = NULL;
1518 if (c->display_usage) {
1520 "net ads leave [--keep-account]\n"
1523 _("Leave an AD domain"));
1524 TALLOC_FREE(tmp_ctx);
1529 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1530 TALLOC_FREE(tmp_ctx);
1534 if (!c->opt_kerberos) {
1535 use_in_memory_ccache();
1539 d_fprintf(stderr, _("Could not initialise message context. "
1540 "Try running as root\n"));
1544 werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1545 if (!W_ERROR_IS_OK(werr)) {
1546 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1551 r->in.use_kerberos = c->opt_kerberos;
1552 r->in.dc_name = c->opt_host;
1553 r->in.domain_name = lp_realm();
1554 r->in.admin_account = c->opt_user_name;
1555 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1556 r->in.modify_config = lp_config_backend_is_registry();
1558 /* Try to delete it, but if that fails, disable it. The
1559 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1560 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1561 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1562 if (c->opt_keep_account) {
1563 r->in.delete_machine_account = false;
1565 r->in.delete_machine_account = true;
1568 r->in.msg_ctx = c->msg_ctx;
1570 werr = libnet_Unjoin(tmp_ctx, r);
1571 if (!W_ERROR_IS_OK(werr)) {
1572 d_printf(_("Failed to leave domain: %s\n"),
1573 r->out.error_string ? r->out.error_string :
1574 get_friendly_werror_msg(werr));
1578 if (r->out.deleted_machine_account) {
1579 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1580 r->in.machine_name, r->out.dns_domain_name);
1585 /* We couldn't delete it - see if the disable succeeded. */
1586 if (r->out.disabled_machine_account) {
1587 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1588 r->in.machine_name, r->out.dns_domain_name);
1593 /* Based on what we requested, we shouldn't get here, but if
1594 we did, it means the secrets were removed, and therefore
1595 we have left the domain */
1596 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1597 r->in.machine_name, r->out.dns_domain_name);
1601 TALLOC_FREE(tmp_ctx);
1605 static ADS_STATUS net_ads_join_ok(struct net_context *c)
1607 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1608 ADS_STRUCT *ads = NULL;
1611 struct sockaddr_storage dcip;
1613 if (!secrets_init()) {
1614 DEBUG(1,("Failed to initialise secrets database\n"));
1615 TALLOC_FREE(tmp_ctx);
1616 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1619 net_warn_member_options();
1621 net_use_krb_machine_account(c);
1623 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1625 status = ads_startup(c, true, tmp_ctx, &ads);
1626 if (!ADS_ERR_OK(status)) {
1630 status = ADS_ERROR_NT(NT_STATUS_OK);
1632 TALLOC_FREE(tmp_ctx);
1637 check that an existing join is OK
1639 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1642 use_in_memory_ccache();
1644 if (c->display_usage) {
1646 "net ads testjoin\n"
1649 _("Test if the existing join is ok"));
1653 net_warn_member_options();
1655 /* Display success or failure */
1656 status = net_ads_join_ok(c);
1657 if (!ADS_ERR_OK(status)) {
1658 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1659 get_friendly_nt_error_msg(ads_ntstatus(status)));
1663 printf(_("Join is OK\n"));
1667 /*******************************************************************
1668 Simple config checks before beginning the join
1669 ********************************************************************/
1671 static WERROR check_ads_config( void )
1673 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1674 d_printf(_("Host is not configured as a member server.\n"));
1675 return WERR_INVALID_DOMAIN_ROLE;
1678 if (strlen(lp_netbios_name()) > 15) {
1679 d_printf(_("Our netbios name can be at most 15 chars long, "
1680 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1681 (unsigned int)strlen(lp_netbios_name()));
1682 return WERR_INVALID_COMPUTERNAME;
1685 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1686 d_fprintf(stderr, _("realm must be set in %s for ADS "
1687 "join to succeed.\n"), get_dyn_CONFIGFILE());
1688 return WERR_INVALID_PARAMETER;
1694 /*******************************************************************
1695 ********************************************************************/
1697 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1699 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1700 "Valid options:\n"));
1701 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1702 " The default is in the form netbiosname.dnsdomain\n"));
1703 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1704 " The default UPN is in the form host/netbiosname@REALM.\n"));
1705 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1706 " The OU string read from top to bottom without RDNs\n"
1707 " and delimited by a '/'.\n"
1708 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1709 " NB: A backslash '\\' is used as escape at multiple\n"
1710 " levels and may need to be doubled or even\n"
1711 " quadrupled. It is not used as a separator.\n"));
1712 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1713 " the join. The default password is random.\n"));
1714 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1715 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1716 " NB: osName and osVer must be specified together for\n"
1717 " either to take effect. The operatingSystemService\n"
1718 " attribute is then also set along with the two\n"
1719 " other attributes.\n"));
1720 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1721 " during the join.\n"
1722 " NB: If not specified then by default the samba\n"
1723 " version string is used instead.\n"));
1728 int net_ads_join(struct net_context *c, int argc, const char **argv)
1730 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1731 struct libnet_JoinCtx *r = NULL;
1732 const char *domain = lp_realm();
1733 WERROR werr = WERR_NERR_SETUPNOTJOINED;
1734 bool createupn = false;
1735 const char *dnshostname = NULL;
1736 const char *machineupn = NULL;
1737 const char *machine_password = NULL;
1738 const char *create_in_ou = NULL;
1740 const char *os_name = NULL;
1741 const char *os_version = NULL;
1742 const char *os_servicepack = NULL;
1743 bool modify_config = lp_config_backend_is_registry();
1744 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1747 if (c->display_usage) {
1748 TALLOC_FREE(tmp_ctx);
1749 return net_ads_join_usage(c, argc, argv);
1752 net_warn_member_options();
1754 if (!modify_config) {
1755 werr = check_ads_config();
1756 if (!W_ERROR_IS_OK(werr)) {
1757 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1762 if (!c->opt_kerberos) {
1763 use_in_memory_ccache();
1766 werr = libnet_init_JoinCtx(tmp_ctx, &r);
1767 if (!W_ERROR_IS_OK(werr)) {
1771 /* process additional command line args */
1773 for ( i=0; i<argc; i++ ) {
1774 if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1775 dnshostname = get_string_param(argv[i]);
1777 else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1779 machineupn = get_string_param(argv[i]);
1781 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1782 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1783 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1784 werr = WERR_INVALID_PARAMETER;
1788 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1789 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1790 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1791 werr = WERR_INVALID_PARAMETER;
1795 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1796 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1797 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1798 werr = WERR_INVALID_PARAMETER;
1802 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1803 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1804 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1805 werr = WERR_INVALID_PARAMETER;
1809 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1810 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1811 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1812 werr = WERR_INVALID_PARAMETER;
1817 if (strchr(domain, '.') == NULL) {
1818 domain_name_type = JoinDomNameTypeUnknown;
1820 domain_name_type = JoinDomNameTypeDNS;
1826 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1827 werr = WERR_INVALID_PARAMETER;
1832 d_fprintf(stderr, _("Could not initialise message context. "
1833 "Try running as root\n"));
1834 werr = WERR_ACCESS_DENIED;
1838 /* Do the domain join here */
1840 r->in.domain_name = domain;
1841 r->in.domain_name_type = domain_name_type;
1842 r->in.create_upn = createupn;
1843 r->in.upn = machineupn;
1844 r->in.dnshostname = dnshostname;
1845 r->in.account_ou = create_in_ou;
1846 r->in.os_name = os_name;
1847 r->in.os_version = os_version;
1848 r->in.os_servicepack = os_servicepack;
1849 r->in.dc_name = c->opt_host;
1850 r->in.admin_account = c->opt_user_name;
1851 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1852 r->in.machine_password = machine_password;
1854 r->in.use_kerberos = c->opt_kerberos;
1855 r->in.modify_config = modify_config;
1856 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1857 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1858 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1859 r->in.msg_ctx = c->msg_ctx;
1861 werr = libnet_Join(tmp_ctx, r);
1862 if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1863 strequal(domain, lp_realm())) {
1864 r->in.domain_name = lp_workgroup();
1865 r->in.domain_name_type = JoinDomNameTypeNBT;
1866 werr = libnet_Join(tmp_ctx, r);
1868 if (!W_ERROR_IS_OK(werr)) {
1872 /* Check the short name of the domain */
1874 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1875 d_printf(_("The workgroup in %s does not match the short\n"
1876 "domain name obtained from the server.\n"
1877 "Using the name [%s] from the server.\n"
1878 "You should set \"workgroup = %s\" in %s.\n"),
1879 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1880 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1883 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1885 if (r->out.dns_domain_name) {
1886 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1887 r->out.dns_domain_name);
1889 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1890 r->out.netbios_domain_name);
1893 /* print out informative error string in case there is one */
1894 if (r->out.error_string != NULL) {
1895 d_printf("%s\n", r->out.error_string);
1899 * We try doing the dns update (if it was compiled in
1900 * and if it was not disabled on the command line).
1901 * If the dns update fails, we still consider the join
1902 * operation as succeeded if we came this far.
1904 if (!c->opt_no_dns_updates) {
1905 net_ads_join_dns_updates(c, tmp_ctx, r);
1912 /* issue an overall failure message at the end. */
1913 d_printf(_("Failed to join domain: %s\n"),
1914 r && r->out.error_string ? r->out.error_string :
1915 get_friendly_werror_msg(werr));
1918 TALLOC_FREE(tmp_ctx);
1923 /*******************************************************************
1924 ********************************************************************/
1926 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1928 #if defined(HAVE_KRB5)
1929 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1930 ADS_STRUCT *ads = NULL;
1933 const char *hostname = NULL;
1934 const char **addrs_list = NULL;
1935 struct sockaddr_storage *addrs = NULL;
1941 talloc_enable_leak_report();
1944 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1945 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1946 "detection of addresses in a clustered "
1948 c->display_usage = true;
1951 if (c->display_usage) {
1953 "net ads dns register [hostname [IP [IP...]]] "
1954 "[--force] [--dns-ttl TTL]\n"
1957 _("Register hostname with DNS\n"));
1958 TALLOC_FREE(tmp_ctx);
1967 num_addrs = argc - 1;
1968 addrs_list = &argv[1];
1969 } else if (lp_clustering()) {
1970 addrs_list = lp_cluster_addresses();
1971 num_addrs = str_list_length(addrs_list);
1974 if (num_addrs > 0) {
1975 addrs = talloc_zero_array(tmp_ctx,
1976 struct sockaddr_storage,
1978 if (addrs == NULL) {
1979 d_fprintf(stderr, _("Error allocating memory!\n"));
1984 for (count = 0; count < num_addrs; count++) {
1985 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1986 d_fprintf(stderr, "%s '%s'.\n",
1987 _("Cannot interpret address"),
1993 status = ads_startup(c, true, tmp_ctx, &ads);
1994 if ( !ADS_ERR_OK(status) ) {
1995 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1999 ntstatus = net_update_dns_ext(c,
2006 if (!NT_STATUS_IS_OK(ntstatus)) {
2007 d_fprintf( stderr, _("DNS update failed!\n") );
2011 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
2015 TALLOC_FREE(tmp_ctx);
2020 _("DNS update support not enabled at compile time!\n"));
2025 static int net_ads_dns_unregister(struct net_context *c,
2029 #if defined(HAVE_KRB5)
2030 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2031 ADS_STRUCT *ads = NULL;
2034 const char *hostname = NULL;
2038 talloc_enable_leak_report();
2042 c->display_usage = true;
2045 if (c->display_usage) {
2047 "net ads dns unregister [hostname]\n"
2050 _("Remove all IP Address entries for a given\n"
2051 " hostname from the Active Directory server.\n"));
2052 TALLOC_FREE(tmp_ctx);
2056 /* Get the hostname for un-registering */
2059 status = ads_startup(c, true, tmp_ctx, &ads);
2060 if ( !ADS_ERR_OK(status) ) {
2061 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2065 ntstatus = net_update_dns_ext(c,
2072 if (!NT_STATUS_IS_OK(ntstatus)) {
2073 d_fprintf( stderr, _("DNS update failed!\n") );
2077 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2081 TALLOC_FREE(tmp_ctx);
2086 _("DNS update support not enabled at compile time!\n"));
2092 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2094 size_t num_names = 0;
2095 char **hostnames = NULL;
2097 struct samba_sockaddr *addrs = NULL;
2100 if (argc != 1 || c->display_usage) {
2105 _("net ads dns async <name>\n"),
2106 _(" Async look up hostname from the DNS server\n"
2107 " hostname\tName to look up\n"));
2111 status = ads_dns_lookup_a(talloc_tos(),
2116 if (!NT_STATUS_IS_OK(status)) {
2117 d_printf("Looking up A record for %s got error %s\n",
2122 d_printf("Async A record lookup - got %u names for %s\n",
2123 (unsigned int)num_names,
2125 for (i = 0; i < num_names; i++) {
2126 char addr_buf[INET6_ADDRSTRLEN];
2127 print_sockaddr(addr_buf,
2130 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2136 #if defined(HAVE_IPV6)
2137 status = ads_dns_lookup_aaaa(talloc_tos(),
2142 if (!NT_STATUS_IS_OK(status)) {
2143 d_printf("Looking up AAAA record for %s got error %s\n",
2148 d_printf("Async AAAA record lookup - got %u names for %s\n",
2149 (unsigned int)num_names,
2151 for (i = 0; i < num_names; i++) {
2152 char addr_buf[INET6_ADDRSTRLEN];
2153 print_sockaddr(addr_buf,
2156 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2166 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2168 struct functable func[] = {
2171 net_ads_dns_register,
2173 N_("Add host dns entry to AD"),
2174 N_("net ads dns register\n"
2175 " Add host dns entry to AD")
2179 net_ads_dns_unregister,
2181 N_("Remove host dns entry from AD"),
2182 N_("net ads dns unregister\n"
2183 " Remove host dns entry from AD")
2190 N_("net ads dns async\n"
2191 " Look up host using async DNS")
2193 {NULL, NULL, 0, NULL, NULL}
2196 return net_run_function(c, argc, argv, "net ads dns", func);
2199 /*******************************************************************
2200 ********************************************************************/
2202 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2205 "\nnet ads printer search <printer>"
2206 "\n\tsearch for a printer in the directory\n"
2207 "\nnet ads printer info <printer> <server>"
2208 "\n\tlookup info in directory for printer on server"
2209 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2210 "\nnet ads printer publish <printername>"
2211 "\n\tpublish printer in directory"
2212 "\n\t(note: printer name is required)\n"
2213 "\nnet ads printer remove <printername>"
2214 "\n\tremove printer from directory"
2215 "\n\t(note: printer name is required)\n"));
2219 /*******************************************************************
2220 ********************************************************************/
2222 static int net_ads_printer_search(struct net_context *c,
2226 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2227 ADS_STRUCT *ads = NULL;
2229 LDAPMessage *res = NULL;
2232 if (c->display_usage) {
2234 "net ads printer search\n"
2237 _("List printers in the AD"));
2238 TALLOC_FREE(tmp_ctx);
2242 status = ads_startup(c, false, tmp_ctx, &ads);
2243 if (!ADS_ERR_OK(status)) {
2247 status = ads_find_printers(ads, &res);
2248 if (!ADS_ERR_OK(status)) {
2249 d_fprintf(stderr, _("ads_find_printer: %s\n"),
2250 ads_errstr(status));
2254 if (ads_count_replies(ads, res) == 0) {
2255 d_fprintf(stderr, _("No results found\n"));
2263 ads_msgfree(ads, res);
2264 TALLOC_FREE(tmp_ctx);
2268 static int net_ads_printer_info(struct net_context *c,
2272 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2273 ADS_STRUCT *ads = NULL;
2275 const char *servername = NULL;
2276 const char *printername = NULL;
2277 LDAPMessage *res = NULL;
2280 if (c->display_usage) {
2283 _("net ads printer info [printername [servername]]\n"
2284 " Display printer info from AD\n"
2285 " printername\tPrinter name or wildcard\n"
2286 " servername\tName of the print server\n"));
2287 TALLOC_FREE(tmp_ctx);
2291 status = ads_startup(c, false, tmp_ctx, &ads);
2292 if (!ADS_ERR_OK(status)) {
2297 printername = argv[0];
2303 servername = argv[1];
2305 servername = lp_netbios_name();
2308 status = ads_find_printer_on_server(ads, &res, printername, servername);
2309 if (!ADS_ERR_OK(status)) {
2310 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2311 servername, ads_errstr(status));
2315 if (ads_count_replies(ads, res) == 0) {
2316 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2324 ads_msgfree(ads, res);
2325 TALLOC_FREE(tmp_ctx);
2329 static int net_ads_printer_publish(struct net_context *c,
2333 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2334 ADS_STRUCT *ads = NULL;
2336 const char *servername = NULL;
2337 const char *printername = NULL;
2338 struct cli_state *cli = NULL;
2339 struct rpc_pipe_client *pipe_hnd = NULL;
2340 struct sockaddr_storage server_ss = { 0 };
2342 ADS_MODLIST mods = NULL;
2343 char *prt_dn = NULL;
2344 char *srv_dn = NULL;
2345 char **srv_cn = NULL;
2346 char *srv_cn_escaped = NULL;
2347 char *printername_escaped = NULL;
2348 LDAPMessage *res = NULL;
2352 if (argc < 1 || c->display_usage) {
2355 _("net ads printer publish <printername> [servername]\n"
2356 " Publish printer in AD\n"
2357 " printername\tName of the printer\n"
2358 " servername\tName of the print server\n"));
2359 TALLOC_FREE(tmp_ctx);
2363 mods = ads_init_mods(tmp_ctx);
2365 d_fprintf(stderr, _("Out of memory\n"));
2369 status = ads_startup(c, true, tmp_ctx, &ads);
2370 if (!ADS_ERR_OK(status)) {
2374 printername = argv[0];
2377 servername = argv[1];
2379 servername = lp_netbios_name();
2382 /* Get printer data from SPOOLSS */
2384 ok = resolve_name(servername, &server_ss, 0x20, false);
2386 d_fprintf(stderr, _("Could not find server %s\n"),
2391 cli_credentials_set_kerberos_state(c->creds,
2392 CRED_USE_KERBEROS_REQUIRED,
2395 nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2399 CLI_FULL_CONNECTION_IPC);
2401 if (NT_STATUS_IS_ERR(nt_status)) {
2402 d_fprintf(stderr, _("Unable to open a connection to %s to "
2403 "obtain data for %s\n"),
2404 servername, printername);
2408 /* Publish on AD server */
2410 ads_find_machine_acct(ads, &res, servername);
2412 if (ads_count_replies(ads, res) == 0) {
2413 d_fprintf(stderr, _("Could not find machine account for server "
2419 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2420 srv_cn = ldap_explode_dn(srv_dn, 1);
2422 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2423 printername_escaped = escape_rdn_val_string_alloc(printername);
2424 if (!srv_cn_escaped || !printername_escaped) {
2425 SAFE_FREE(srv_cn_escaped);
2426 SAFE_FREE(printername_escaped);
2427 d_fprintf(stderr, _("Internal error, out of memory!"));
2431 prt_dn = talloc_asprintf(tmp_ctx,
2434 printername_escaped,
2436 if (prt_dn == NULL) {
2437 SAFE_FREE(srv_cn_escaped);
2438 SAFE_FREE(printername_escaped);
2439 d_fprintf(stderr, _("Internal error, out of memory!"));
2443 SAFE_FREE(srv_cn_escaped);
2444 SAFE_FREE(printername_escaped);
2446 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2447 if (!NT_STATUS_IS_OK(nt_status)) {
2448 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2453 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2460 status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2461 if (!ADS_ERR_OK(status)) {
2462 d_fprintf(stderr, "ads_publish_printer: %s\n",
2463 ads_errstr(status));
2467 d_printf("published printer\n");
2471 talloc_destroy(tmp_ctx);
2476 static int net_ads_printer_remove(struct net_context *c,
2480 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2481 ADS_STRUCT *ads = NULL;
2483 const char *servername = NULL;
2484 char *prt_dn = NULL;
2485 LDAPMessage *res = NULL;
2488 if (argc < 1 || c->display_usage) {
2491 _("net ads printer remove <printername> [servername]\n"
2492 " Remove a printer from the AD\n"
2493 " printername\tName of the printer\n"
2494 " servername\tName of the print server\n"));
2495 TALLOC_FREE(tmp_ctx);
2499 status = ads_startup(c, true, tmp_ctx, &ads);
2500 if (!ADS_ERR_OK(status)) {
2505 servername = argv[1];
2507 servername = lp_netbios_name();
2510 status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2511 if (!ADS_ERR_OK(status)) {
2512 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2513 ads_errstr(status));
2517 if (ads_count_replies(ads, res) == 0) {
2518 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2522 prt_dn = ads_get_dn(ads, tmp_ctx, res);
2523 if (prt_dn == NULL) {
2524 d_fprintf(stderr, _("Out of memory\n"));
2528 status = ads_del_dn(ads, prt_dn);
2529 if (!ADS_ERR_OK(status)) {
2530 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2536 ads_msgfree(ads, res);
2537 TALLOC_FREE(tmp_ctx);
2541 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2543 struct functable func[] = {
2546 net_ads_printer_search,
2548 N_("Search for a printer"),
2549 N_("net ads printer search\n"
2550 " Search for a printer")
2554 net_ads_printer_info,
2556 N_("Display printer information"),
2557 N_("net ads printer info\n"
2558 " Display printer information")
2562 net_ads_printer_publish,
2564 N_("Publish a printer"),
2565 N_("net ads printer publish\n"
2566 " Publish a printer")
2570 net_ads_printer_remove,
2572 N_("Delete a printer"),
2573 N_("net ads printer remove\n"
2574 " Delete a printer")
2576 {NULL, NULL, 0, NULL, NULL}
2579 return net_run_function(c, argc, argv, "net ads printer", func);
2583 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2585 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2586 ADS_STRUCT *ads = NULL;
2587 const char *auth_principal = cli_credentials_get_username(c->creds);
2588 const char *auth_password = cli_credentials_get_password(c->creds);
2589 const char *realm = NULL;
2590 char *new_password = NULL;
2592 char *prompt = NULL;
2593 const char *user = NULL;
2594 char pwd[256] = {0};
2598 if (c->display_usage) {
2601 _("net ads password <username>\n"
2602 " Change password for user\n"
2603 " username\tName of user to change password for\n"));
2604 TALLOC_FREE(tmp_ctx);
2608 if (auth_principal == NULL || auth_password == NULL) {
2609 d_fprintf(stderr, _("You must supply an administrator "
2610 "username/password\n"));
2611 TALLOC_FREE(tmp_ctx);
2616 d_fprintf(stderr, _("ERROR: You must say which username to "
2617 "change password for\n"));
2618 TALLOC_FREE(tmp_ctx);
2622 if (strchr_m(argv[0], '@')) {
2623 user = talloc_strdup(tmp_ctx, argv[0]);
2625 user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2628 d_fprintf(stderr, _("Out of memory\n"));
2632 use_in_memory_ccache();
2633 chr = strchr_m(auth_principal, '@');
2640 /* use the realm so we can eventually change passwords for users
2641 in realms other than default */
2642 ads = ads_init(tmp_ctx,
2651 /* we don't actually need a full connect, but it's the easy way to
2652 fill in the KDC's address */
2655 if (!ads->config.realm) {
2656 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2660 if (argv[1] != NULL) {
2661 new_password = talloc_strdup(tmp_ctx, argv[1]);
2665 prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2666 if (prompt == NULL) {
2667 d_fprintf(stderr, _("Out of memory\n"));
2671 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2675 new_password = talloc_strdup(tmp_ctx, pwd);
2676 memset(pwd, '\0', sizeof(pwd));
2679 if (new_password == NULL) {
2680 d_fprintf(stderr, _("Out of memory\n"));
2684 status = kerberos_set_password(ads->auth.kdc_server,
2689 ads->auth.time_offset);
2690 memset(new_password, '\0', strlen(new_password));
2691 if (!ADS_ERR_OK(status)) {
2692 d_fprintf(stderr, _("Password change failed: %s\n"),
2693 ads_errstr(status));
2697 d_printf(_("Password change for %s completed.\n"), user);
2701 TALLOC_FREE(tmp_ctx);
2705 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2707 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2708 ADS_STRUCT *ads = NULL;
2709 char *host_principal = NULL;
2710 char *my_name = NULL;
2714 if (c->display_usage) {
2716 "net ads changetrustpw\n"
2719 _("Change the machine account's trust password"));
2720 TALLOC_FREE(tmp_ctx);
2724 if (!secrets_init()) {
2725 DEBUG(1,("Failed to initialise secrets database\n"));
2729 net_warn_member_options();
2731 net_use_krb_machine_account(c);
2733 use_in_memory_ccache();
2735 status = ads_startup(c, true, tmp_ctx, &ads);
2736 if (!ADS_ERR_OK(status)) {
2740 my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2741 if (my_name == NULL) {
2742 d_fprintf(stderr, _("Out of memory\n"));
2746 host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2747 if (host_principal == NULL) {
2748 d_fprintf(stderr, _("Out of memory\n"));
2752 d_printf(_("Changing password for principal: %s\n"), host_principal);
2754 status = ads_change_trust_account_password(ads, host_principal);
2755 if (!ADS_ERR_OK(status)) {
2756 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2760 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2762 if (USE_SYSTEM_KEYTAB) {
2763 d_printf(_("Attempting to update system keytab with new password.\n"));
2764 if (ads_keytab_create_default(ads)) {
2765 d_printf(_("Failed to update system keytab.\n"));
2771 TALLOC_FREE(tmp_ctx);
2777 help for net ads search
2779 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2782 "\nnet ads search <expression> <attributes...>\n"
2783 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2784 "The expression is a standard LDAP search expression, and the\n"
2785 "attributes are a list of LDAP fields to show in the results.\n\n"
2786 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2788 net_common_flags_usage(c, argc, argv);
2794 general ADS search function. Useful in diagnosing problems in ADS
2796 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2798 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2799 ADS_STRUCT *ads = NULL;
2801 const char *ldap_exp = NULL;
2802 const char **attrs = NULL;
2803 LDAPMessage *res = NULL;
2806 if (argc < 1 || c->display_usage) {
2807 TALLOC_FREE(tmp_ctx);
2808 return net_ads_search_usage(c, argc, argv);
2811 status = ads_startup(c, false, tmp_ctx, &ads);
2812 if (!ADS_ERR_OK(status)) {
2819 status = ads_do_search_retry(ads,
2820 ads->config.bind_path,
2825 if (!ADS_ERR_OK(status)) {
2826 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2830 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2832 /* dump the results */
2837 ads_msgfree(ads, res);
2838 TALLOC_FREE(tmp_ctx);
2844 help for net ads search
2846 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2849 "\nnet ads dn <dn> <attributes...>\n"
2850 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2851 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2852 "to show in the results\n\n"
2853 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2854 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2856 net_common_flags_usage(c, argc, argv);
2862 general ADS search function. Useful in diagnosing problems in ADS
2864 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2866 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2867 ADS_STRUCT *ads = NULL;
2869 const char *dn = NULL;
2870 const char **attrs = NULL;
2871 LDAPMessage *res = NULL;
2874 if (argc < 1 || c->display_usage) {
2875 TALLOC_FREE(tmp_ctx);
2876 return net_ads_dn_usage(c, argc, argv);
2879 status = ads_startup(c, false, tmp_ctx, &ads);
2880 if (!ADS_ERR_OK(status)) {
2887 status = ads_do_search_all(ads,
2893 if (!ADS_ERR_OK(status)) {
2894 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2898 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2900 /* dump the results */
2905 ads_msgfree(ads, res);
2906 TALLOC_FREE(tmp_ctx);
2911 help for net ads sid search
2913 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2916 "\nnet ads sid <sid> <attributes...>\n"
2917 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2918 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2919 "to show in the results\n\n"
2920 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2922 net_common_flags_usage(c, argc, argv);
2928 general ADS search function. Useful in diagnosing problems in ADS
2930 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2932 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2933 ADS_STRUCT *ads = NULL;
2935 const char *sid_string = NULL;
2936 const char **attrs = NULL;
2937 LDAPMessage *res = NULL;
2938 struct dom_sid sid = { 0 };
2941 if (argc < 1 || c->display_usage) {
2942 TALLOC_FREE(tmp_ctx);
2943 return net_ads_sid_usage(c, argc, argv);
2946 status = ads_startup(c, false, tmp_ctx, &ads);
2947 if (!ADS_ERR_OK(status)) {
2951 sid_string = argv[0];
2954 if (!string_to_sid(&sid, sid_string)) {
2955 d_fprintf(stderr, _("could not convert sid\n"));
2959 status = ads_search_retry_sid(ads, &res, &sid, attrs);
2960 if (!ADS_ERR_OK(status)) {
2961 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2965 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2967 /* dump the results */
2972 ads_msgfree(ads, res);
2973 TALLOC_FREE(tmp_ctx);
2977 static int net_ads_keytab_flush(struct net_context *c,
2981 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2982 ADS_STRUCT *ads = NULL;
2986 if (c->display_usage) {
2988 "net ads keytab flush\n"
2991 _("Delete the whole keytab"));
2992 TALLOC_FREE(tmp_ctx);
2996 if (!c->opt_user_specified && c->opt_password == NULL) {
2997 net_use_krb_machine_account(c);
3000 status = ads_startup(c, true, tmp_ctx, &ads);
3001 if (!ADS_ERR_OK(status)) {
3005 ret = ads_keytab_flush(ads);
3007 TALLOC_FREE(tmp_ctx);
3011 static int net_ads_keytab_add(struct net_context *c,
3016 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3017 ADS_STRUCT *ads = NULL;
3022 if (c->display_usage) {
3025 _("net ads keytab add <principal> [principal ...]\n"
3026 " Add principals to local keytab\n"
3027 " principal\tKerberos principal to add to "
3029 TALLOC_FREE(tmp_ctx);
3033 net_warn_member_options();
3035 d_printf(_("Processing principals to add...\n"));
3037 if (!c->opt_user_specified && c->opt_password == NULL) {
3038 net_use_krb_machine_account(c);
3041 status = ads_startup(c, true, tmp_ctx, &ads);
3042 if (!ADS_ERR_OK(status)) {
3046 for (ret = 0, i = 0; i < argc; i++) {
3047 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3050 TALLOC_FREE(tmp_ctx);
3054 static int net_ads_keytab_add_default(struct net_context *c,
3058 return net_ads_keytab_add(c, argc, argv, false);
3061 static int net_ads_keytab_add_update_ads(struct net_context *c,
3065 return net_ads_keytab_add(c, argc, argv, true);
3068 static int net_ads_keytab_delete(struct net_context *c,
3072 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3073 ADS_STRUCT *ads = NULL;
3078 if (c->display_usage) {
3081 _("net ads keytab delete <principal> [principal ...]\n"
3082 " Remove entries for service principal, "
3083 " from the keytab file only."
3084 " Remove principals from local keytab\n"
3085 " principal\tKerberos principal to remove from "
3087 TALLOC_FREE(tmp_ctx);
3091 d_printf(_("Processing principals to delete...\n"));
3093 if (!c->opt_user_specified && c->opt_password == NULL) {
3094 net_use_krb_machine_account(c);
3097 status = ads_startup(c, true, tmp_ctx, &ads);
3098 if (!ADS_ERR_OK(status)) {
3102 for (ret = 0, i = 0; i < argc; i++) {
3103 ret |= ads_keytab_delete_entry(ads, argv[i]);
3106 TALLOC_FREE(tmp_ctx);
3110 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3112 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3113 ADS_STRUCT *ads = NULL;
3117 if (c->display_usage) {
3119 "net ads keytab create\n"
3122 _("Create new default keytab"));
3123 TALLOC_FREE(tmp_ctx);
3127 net_warn_member_options();
3129 if (!c->opt_user_specified && c->opt_password == NULL) {
3130 net_use_krb_machine_account(c);
3133 status = ads_startup(c, true, tmp_ctx, &ads);
3134 if (!ADS_ERR_OK(status)) {
3138 ret = ads_keytab_create_default(ads);
3140 TALLOC_FREE(tmp_ctx);
3144 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3146 const char *keytab = NULL;
3148 if (c->display_usage) {
3151 _("net ads keytab list [keytab]\n"
3152 " List a local keytab\n"
3153 " keytab\tKeytab to list\n"));
3161 return ads_keytab_list(keytab);
3165 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3167 struct functable func[] = {
3170 net_ads_keytab_add_default,
3172 N_("Add a service principal"),
3173 N_("net ads keytab add\n"
3174 " Add a service principal, updates keytab file only.")
3178 net_ads_keytab_delete,
3180 N_("Delete a service principal"),
3181 N_("net ads keytab delete\n"
3182 " Remove entries for service principal, from the keytab file only.")
3186 net_ads_keytab_add_update_ads,
3188 N_("Add a service principal"),
3189 N_("net ads keytab add_update_ads\n"
3190 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3194 net_ads_keytab_create,
3196 N_("Create a fresh keytab"),
3197 N_("net ads keytab create\n"
3198 " Create a fresh keytab or update existing one.")
3202 net_ads_keytab_flush,
3204 N_("Remove all keytab entries"),
3205 N_("net ads keytab flush\n"
3206 " Remove all keytab entries")
3210 net_ads_keytab_list,
3212 N_("List a keytab"),
3213 N_("net ads keytab list\n"
3216 {NULL, NULL, 0, NULL, NULL}
3219 if (!USE_KERBEROS_KEYTAB) {
3220 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3221 "keytab method to use keytab functions.\n"));
3224 return net_run_function(c, argc, argv, "net ads keytab", func);
3227 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3231 if (c->display_usage) {
3233 "net ads kerberos renew\n"
3236 _("Renew TGT from existing credential cache"));
3240 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3242 d_printf(_("failed to renew kerberos ticket: %s\n"),
3243 error_message(ret));
3248 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3249 struct PAC_DATA_CTR **pac_data_ctr)
3253 const char *impersonate_princ_s = NULL;
3254 const char *local_service = NULL;
3257 for (i=0; i<argc; i++) {
3258 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3259 impersonate_princ_s = get_string_param(argv[i]);
3260 if (impersonate_princ_s == NULL) {
3264 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3265 local_service = get_string_param(argv[i]);
3266 if (local_service == NULL) {
3272 if (local_service == NULL) {
3273 local_service = talloc_asprintf(c, "%s$@%s",
3274 lp_netbios_name(), lp_realm());
3275 if (local_service == NULL) {
3280 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3282 status = kerberos_return_pac(c,
3291 2592000, /* one month */
3292 impersonate_princ_s,
3297 if (!NT_STATUS_IS_OK(status)) {
3298 d_printf(_("failed to query kerberos PAC: %s\n"),
3308 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3310 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3313 enum PAC_TYPE type = 0;
3315 if (c->display_usage) {
3317 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3320 _("Dump the Kerberos PAC"));
3324 for (i=0; i<argc; i++) {
3325 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3326 type = get_int_param(argv[i]);
3330 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3339 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3340 pac_data_ctr->pac_data);
3342 d_printf(_("The Pac: %s\n"), s);
3349 num_buffers = pac_data_ctr->pac_data->num_buffers;
3351 for (i=0; i<num_buffers; i++) {
3355 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3359 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3360 pac_data_ctr->pac_data->buffers[i].info);
3362 d_printf(_("The Pac: %s\n"), s);
3371 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3373 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3374 char *filename = NULL;
3378 if (c->display_usage) {
3380 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3383 _("Save the Kerberos PAC"));
3387 for (i=0; i<argc; i++) {
3388 if (strnequal(argv[i], "filename", strlen("filename"))) {
3389 filename = get_string_param(argv[i]);
3390 if (filename == NULL) {
3396 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3401 if (filename == NULL) {
3402 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3406 /* save the raw format */
3407 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3408 d_printf(_("failed to save PAC in %s\n"), filename);
3415 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3417 struct functable func[] = {
3420 net_ads_kerberos_pac_dump,
3422 N_("Dump Kerberos PAC"),
3423 N_("net ads kerberos pac dump\n"
3424 " Dump a Kerberos PAC to stdout")
3428 net_ads_kerberos_pac_save,
3430 N_("Save Kerberos PAC"),
3431 N_("net ads kerberos pac save\n"
3432 " Save a Kerberos PAC in a file")
3435 {NULL, NULL, 0, NULL, NULL}
3438 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3441 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3446 if (c->display_usage) {
3448 "net ads kerberos kinit\n"
3451 _("Get Ticket Granting Ticket (TGT) for the user"));
3455 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3457 ret = kerberos_kinit_password_ext(c->opt_user_name,
3465 2592000, /* one month */
3471 d_printf(_("failed to kinit password: %s\n"),
3477 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3479 struct functable func[] = {
3482 net_ads_kerberos_kinit,
3484 N_("Retrieve Ticket Granting Ticket (TGT)"),
3485 N_("net ads kerberos kinit\n"
3486 " Receive Ticket Granting Ticket (TGT)")
3490 net_ads_kerberos_renew,
3492 N_("Renew Ticket Granting Ticket from credential cache"),
3493 N_("net ads kerberos renew\n"
3494 " Renew Ticket Granting Ticket (TGT) from "
3499 net_ads_kerberos_pac,
3501 N_("Dump Kerberos PAC"),
3502 N_("net ads kerberos pac\n"
3503 " Dump Kerberos PAC")
3505 {NULL, NULL, 0, NULL, NULL}
3508 return net_run_function(c, argc, argv, "net ads kerberos", func);
3511 static int net_ads_setspn_list(struct net_context *c,
3515 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3516 ADS_STRUCT *ads = NULL;
3521 if (c->display_usage) {
3524 _("net ads setspn list <machinename>\n"));
3525 TALLOC_FREE(tmp_ctx);
3529 status = ads_startup(c, true, tmp_ctx, &ads);
3530 if (!ADS_ERR_OK(status)) {
3535 ok = ads_setspn_list(ads, argv[0]);
3537 ok = ads_setspn_list(ads, lp_netbios_name());
3542 TALLOC_FREE(tmp_ctx);
3546 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3548 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3549 ADS_STRUCT *ads = NULL;
3554 if (c->display_usage || argc < 1) {
3557 _("net ads setspn add <machinename> SPN\n"));
3558 TALLOC_FREE(tmp_ctx);
3562 status = ads_startup(c, true, tmp_ctx, &ads);
3563 if (!ADS_ERR_OK(status)) {
3568 ok = ads_setspn_add(ads, argv[0], argv[1]);
3570 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3575 TALLOC_FREE(tmp_ctx);
3579 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3581 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3582 ADS_STRUCT *ads = NULL;
3587 if (c->display_usage || argc < 1) {
3590 _("net ads setspn delete <machinename> SPN\n"));
3591 TALLOC_FREE(tmp_ctx);
3595 status = ads_startup(c, true, tmp_ctx, &ads);
3596 if (!ADS_ERR_OK(status)) {
3601 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3603 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3608 TALLOC_FREE(tmp_ctx);
3612 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3614 struct functable func[] = {
3617 net_ads_setspn_list,
3619 N_("List Service Principal Names (SPN)"),
3620 N_("net ads setspn list machine\n"
3621 " List Service Principal Names (SPN)")
3627 N_("Add Service Principal Names (SPN)"),
3628 N_("net ads setspn add machine spn\n"
3629 " Add Service Principal Names (SPN)")
3633 net_ads_setspn_delete,
3635 N_("Delete Service Principal Names (SPN)"),
3636 N_("net ads setspn delete machine spn\n"
3637 " Delete Service Principal Names (SPN)")
3639 {NULL, NULL, 0, NULL, NULL}
3642 return net_run_function(c, argc, argv, "net ads setspn", func);
3645 static int net_ads_enctype_lookup_account(struct net_context *c,
3647 const char *account,
3649 const char **enctype_str)
3652 const char *attrs[] = {
3653 "msDS-SupportedEncryptionTypes",
3660 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3662 if (filter == NULL) {
3666 status = ads_search(ads, res, filter, attrs);
3667 if (!ADS_ERR_OK(status)) {
3668 d_printf(_("no account found with filter: %s\n"), filter);
3672 count = ads_count_replies(ads, *res);
3677 d_printf(_("no account found with filter: %s\n"), filter);
3680 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3685 *enctype_str = ads_pull_string(ads, c, *res,
3686 "msDS-SupportedEncryptionTypes");
3687 if (*enctype_str == NULL) {
3688 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3698 static void net_ads_enctype_dump_enctypes(const char *username,
3699 const char *enctype_str)
3701 int enctypes = atoi(enctype_str);
3703 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3704 username, enctypes, enctypes);
3706 printf("[%s] 0x%08x DES-CBC-CRC\n",
3707 enctypes & ENC_CRC32 ? "X" : " ",
3709 printf("[%s] 0x%08x DES-CBC-MD5\n",
3710 enctypes & ENC_RSA_MD5 ? "X" : " ",
3712 printf("[%s] 0x%08x RC4-HMAC\n",
3713 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3715 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3716 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3717 ENC_HMAC_SHA1_96_AES128);
3718 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3719 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3720 ENC_HMAC_SHA1_96_AES256);
3721 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3722 enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3723 ENC_HMAC_SHA1_96_AES256_SK);
3724 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3725 enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3726 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3729 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3731 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3733 ADS_STRUCT *ads = NULL;
3734 LDAPMessage *res = NULL;
3735 const char *str = NULL;
3738 if (c->display_usage || (argc < 1)) {
3740 "net ads enctypes list\n"
3743 _("List supported enctypes"));
3744 TALLOC_FREE(tmp_ctx);
3748 status = ads_startup(c, false, tmp_ctx, &ads);
3749 if (!ADS_ERR_OK(status)) {
3753 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3758 net_ads_enctype_dump_enctypes(argv[0], str);
3762 ads_msgfree(ads, res);
3763 TALLOC_FREE(tmp_ctx);
3767 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3769 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3772 ADS_STRUCT *ads = NULL;
3773 LDAPMessage *res = NULL;
3774 const char *etype_list_str = NULL;
3775 const char *dn = NULL;
3776 ADS_MODLIST mods = NULL;
3777 uint32_t etype_list;
3778 const char *str = NULL;
3780 if (c->display_usage || argc < 1) {
3782 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3785 _("Set supported enctypes"));
3786 TALLOC_FREE(tmp_ctx);
3790 status = ads_startup(c, false, tmp_ctx, &ads);
3791 if (!ADS_ERR_OK(status)) {
3795 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3800 dn = ads_get_dn(ads, tmp_ctx, res);
3806 etype_list |= ENC_RC4_HMAC_MD5;
3807 etype_list |= ENC_HMAC_SHA1_96_AES128;
3808 etype_list |= ENC_HMAC_SHA1_96_AES256;
3810 if (argv[1] != NULL) {
3811 sscanf(argv[1], "%i", &etype_list);
3814 etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3815 if (!etype_list_str) {
3819 mods = ads_init_mods(tmp_ctx);
3824 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3826 if (!ADS_ERR_OK(status)) {
3830 status = ads_gen_mod(ads, dn, mods);
3831 if (!ADS_ERR_OK(status)) {
3832 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3833 ads_errstr(status));
3837 ads_msgfree(ads, res);
3840 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3845 net_ads_enctype_dump_enctypes(argv[0], str);
3849 ads_msgfree(ads, res);
3850 TALLOC_FREE(tmp_ctx);
3854 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3856 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3859 ADS_STRUCT *ads = NULL;
3860 LDAPMessage *res = NULL;
3861 const char *dn = NULL;
3862 ADS_MODLIST mods = NULL;
3864 if (c->display_usage || argc < 1) {
3866 "net ads enctypes delete <sAMAccountName>\n"
3869 _("Delete supported enctypes"));
3870 TALLOC_FREE(tmp_ctx);
3874 status = ads_startup(c, false, tmp_ctx, &ads);
3875 if (!ADS_ERR_OK(status)) {
3879 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3884 dn = ads_get_dn(ads, tmp_ctx, res);
3889 mods = ads_init_mods(tmp_ctx);
3894 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3895 if (!ADS_ERR_OK(status)) {
3899 status = ads_gen_mod(ads, dn, mods);
3900 if (!ADS_ERR_OK(status)) {
3901 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3902 ads_errstr(status));
3909 ads_msgfree(ads, res);
3910 TALLOC_FREE(tmp_ctx);
3914 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3916 struct functable func[] = {
3919 net_ads_enctypes_list,
3921 N_("List the supported encryption types"),
3922 N_("net ads enctypes list\n"
3923 " List the supported encryption types")
3927 net_ads_enctypes_set,
3929 N_("Set the supported encryption types"),
3930 N_("net ads enctypes set\n"
3931 " Set the supported encryption types")
3935 net_ads_enctypes_delete,
3937 N_("Delete the supported encryption types"),
3938 N_("net ads enctypes delete\n"
3939 " Delete the supported encryption types")
3942 {NULL, NULL, 0, NULL, NULL}
3945 return net_run_function(c, argc, argv, "net ads enctypes", func);
3949 int net_ads(struct net_context *c, int argc, const char **argv)
3951 struct functable func[] = {
3956 N_("Display details on remote ADS server"),
3958 " Display details on remote ADS server")
3964 N_("Join the local machine to ADS realm"),
3966 " Join the local machine to ADS realm")
3972 N_("Validate machine account"),
3973 N_("net ads testjoin\n"
3974 " Validate machine account")
3980 N_("Remove the local machine from ADS"),
3981 N_("net ads leave\n"
3982 " Remove the local machine from ADS")
3988 N_("Display machine account details"),
3989 N_("net ads status\n"
3990 " Display machine account details")
3996 N_("List/modify users"),
3998 " List/modify users")
4004 N_("List/modify groups"),
4005 N_("net ads group\n"
4006 " List/modify groups")
4012 N_("Issue dynamic DNS update"),
4014 " Issue dynamic DNS update")
4020 N_("Change user passwords"),
4021 N_("net ads password\n"
4022 " Change user passwords")
4026 net_ads_changetrustpw,
4028 N_("Change trust account password"),
4029 N_("net ads changetrustpw\n"
4030 " Change trust account password")
4036 N_("List/modify printer entries"),
4037 N_("net ads printer\n"
4038 " List/modify printer entries")
4044 N_("Issue LDAP search using filter"),
4045 N_("net ads search\n"
4046 " Issue LDAP search using filter")
4052 N_("Issue LDAP search by DN"),
4054 " Issue LDAP search by DN")
4060 N_("Issue LDAP search by SID"),
4062 " Issue LDAP search by SID")
4068 N_("Display workgroup name"),
4069 N_("net ads workgroup\n"
4070 " Display the workgroup name")
4076 N_("Perform CLDAP query on DC"),
4077 N_("net ads lookup\n"
4078 " Find the ADS DC using CLDAP lookups")
4084 N_("Manage local keytab file"),
4085 N_("net ads keytab\n"
4086 " Manage local keytab file")
4092 N_("Manage Service Principal Names (SPN)s"),
4093 N_("net ads spnset\n"
4094 " Manage Service Principal Names (SPN)s")
4100 N_("Manage group policy objects"),
4102 " Manage group policy objects")
4108 N_("Manage kerberos keytab"),
4109 N_("net ads kerberos\n"
4110 " Manage kerberos keytab")
4116 N_("List/modify supported encryption types"),
4117 N_("net ads enctypes\n"
4118 " List/modify enctypes")
4120 {NULL, NULL, 0, NULL, NULL}
4123 return net_run_function(c, argc, argv, "net ads", func);
4128 static int net_ads_noads(void)
4130 d_fprintf(stderr, _("ADS support not compiled in\n"));
4134 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4136 return net_ads_noads();
4139 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4141 return net_ads_noads();
4144 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4146 return net_ads_noads();
4149 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4151 return net_ads_noads();
4154 int net_ads_join(struct net_context *c, int argc, const char **argv)
4156 return net_ads_noads();
4159 int net_ads_user(struct net_context *c, int argc, const char **argv)
4161 return net_ads_noads();
4164 int net_ads_group(struct net_context *c, int argc, const char **argv)
4166 return net_ads_noads();
4169 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4171 return net_ads_noads();
4174 /* this one shouldn't display a message */
4175 int net_ads_check(struct net_context *c)
4180 int net_ads_check_our_domain(struct net_context *c)
4185 int net_ads(struct net_context *c, int argc, const char **argv)
4187 return net_ads_noads();
4190 #endif /* HAVE_ADS */