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_string(&jsobj, "Forest", reply->forest);
240 ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
245 ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
251 ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
256 ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
261 if (*reply->user_name) {
262 ret = json_add_string(&jsobj, "User name", reply->user_name);
268 ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
273 ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
278 ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
283 ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
288 ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
293 ret = json_add_object(&jsobj, "Flags", &flagsobj);
298 ret = output_json(&jsobj);
299 json_free(&jsobj); /* frees flagsobj recursively */
304 json_free(&flagsobj);
310 #else /* [HAVE_JANSSON] */
312 static int net_ads_cldap_netlogon_json
315 const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
317 d_fprintf(stderr, _("JSON support not available\n"));
322 #endif /* [HAVE_JANSSON] */
325 do a cldap netlogon query
327 static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
329 char addr[INET6_ADDRSTRLEN];
330 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
332 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
334 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
335 d_fprintf(stderr, _("CLDAP query failed!\n"));
340 return net_ads_cldap_netlogon_json(ads, addr, &reply);
343 d_printf(_("Information for Domain Controller: %s\n\n"),
346 d_printf(_("Response Type: "));
347 switch (reply.command) {
348 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
349 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
351 case LOGON_SAM_LOGON_RESPONSE_EX:
352 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
355 d_printf("0x%x\n", reply.command);
359 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
361 d_printf(_("Flags:\n"
363 "\tIs a GC of the forest: %s\n"
364 "\tIs an LDAP server: %s\n"
365 "\tSupports DS: %s\n"
366 "\tIs running a KDC: %s\n"
367 "\tIs running time services: %s\n"
368 "\tIs the closest DC: %s\n"
369 "\tIs writable: %s\n"
370 "\tHas a hardware clock: %s\n"
371 "\tIs a non-domain NC serviced by LDAP server: %s\n"
372 "\tIs NT6 DC that has some secrets: %s\n"
373 "\tIs NT6 DC that has all secrets: %s\n"
374 "\tRuns Active Directory Web Services: %s\n"
375 "\tRuns on Windows 2012 or later: %s\n"),
376 (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
377 (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
378 (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
379 (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
380 (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
381 (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
382 (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
383 (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
384 (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
385 (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
386 (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
387 (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
388 (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
389 (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"));
392 printf(_("Forest: %s\n"), reply.forest);
393 printf(_("Domain: %s\n"), reply.dns_domain);
394 printf(_("Domain Controller: %s\n"), reply.pdc_dns_name);
396 printf(_("Pre-Win2k Domain: %s\n"), reply.domain_name);
397 printf(_("Pre-Win2k Hostname: %s\n"), reply.pdc_name);
399 if (*reply.user_name) printf(_("User name: %s\n"), reply.user_name);
401 printf(_("Server Site Name: %s\n"), reply.server_site);
402 printf(_("Client Site Name: %s\n"), reply.client_site);
404 d_printf(_("NT Version: %d\n"), reply.nt_version);
405 d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
406 d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
412 this implements the CLDAP based netlogon lookup requests
413 for finding the domain controller of a ADS domain
415 static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
417 TALLOC_CTX *tmp_ctx = talloc_stackframe();
418 ADS_STRUCT *ads = NULL;
422 if (c->display_usage) {
427 _("Find the ADS DC using CLDAP lookup.\n"));
428 TALLOC_FREE(tmp_ctx);
432 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
433 if (!ADS_ERR_OK(status)) {
434 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
438 if (!ads->config.realm) {
439 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
440 if (ads->config.realm == NULL) {
441 d_fprintf(stderr, _("Out of memory\n"));
444 ads->ldap.port = 389;
447 ret = net_ads_cldap_netlogon(c, ads);
449 TALLOC_FREE(tmp_ctx);
456 static int net_ads_info_json(ADS_STRUCT *ads)
459 char addr[INET6_ADDRSTRLEN];
461 struct json_object jsobj = json_new_object();
463 if (json_is_invalid(&jsobj)) {
464 d_fprintf(stderr, _("error setting up JSON value\n"));
469 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
471 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
473 ret = json_add_string (&jsobj, "LDAP server", addr);
478 ret = json_add_string (&jsobj, "LDAP server name",
479 ads->config.ldap_server_name);
484 ret = json_add_string (&jsobj, "Realm", ads->config.realm);
489 ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
494 ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
499 ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
504 ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
509 ret = json_add_int (&jsobj, "Server time offset",
510 ads->auth.time_offset);
515 ret = json_add_int (&jsobj, "Last machine account password change",
521 ret = output_json(&jsobj);
528 #else /* [HAVE_JANSSON] */
530 static int net_ads_info_json(ADS_STRUCT *ads)
532 d_fprintf(stderr, _("JSON support not available\n"));
537 #endif /* [HAVE_JANSSON] */
541 static int net_ads_info(struct net_context *c, int argc, const char **argv)
543 TALLOC_CTX *tmp_ctx = talloc_stackframe();
544 ADS_STRUCT *ads = NULL;
546 char addr[INET6_ADDRSTRLEN];
550 if (c->display_usage) {
555 _("Display information about an Active Directory "
557 TALLOC_FREE(tmp_ctx);
561 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
562 if (!ADS_ERR_OK(status)) {
563 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
567 if (!ads || !ads->config.realm) {
568 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
572 /* Try to set the server's current time since we didn't do a full
573 TCP LDAP session initially */
575 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
576 d_fprintf( stderr, _("Failed to get server's current time!\n"));
580 ret = net_ads_info_json(ads);
584 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
586 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
588 d_printf(_("LDAP server: %s\n"), addr);
589 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
590 d_printf(_("Realm: %s\n"), ads->config.realm);
591 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
592 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
593 d_printf(_("Server time: %s\n"),
594 http_timestring(tmp_ctx, ads->config.current_time));
596 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
597 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
599 d_printf(_("Last machine account password change: %s\n"),
600 http_timestring(tmp_ctx, pass_time));
604 TALLOC_FREE(tmp_ctx);
608 static ADS_STATUS ads_startup_int(struct net_context *c,
609 bool only_own_domain,
612 ADS_STRUCT **ads_ret)
614 ADS_STRUCT *ads = NULL;
616 bool need_password = false;
617 bool second_time = false;
619 const char *realm = NULL;
620 bool tried_closest_dc = false;
621 enum credentials_use_kerberos krb5_state =
622 CRED_USE_KERBEROS_DISABLED;
624 /* lp_realm() should be handled by a command line param,
625 However, the join requires that realm be set in smb.conf
626 and compares our realm with the remote server's so this is
627 ok until someone needs more flexibility */
632 if (only_own_domain) {
635 realm = assume_own_realm(c);
638 ads = ads_init(mem_ctx,
640 c->opt_target_workgroup,
644 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
647 if (!c->opt_user_name) {
648 c->opt_user_name = "administrator";
651 if (c->opt_user_specified) {
652 need_password = true;
656 if (!c->opt_password && need_password && !c->opt_machine_pass) {
657 c->opt_password = net_prompt_pass(c, c->opt_user_name);
658 if (!c->opt_password) {
660 return ADS_ERROR(LDAP_NO_MEMORY);
664 if (c->opt_password) {
665 use_in_memory_ccache();
666 ADS_TALLOC_CONST_FREE(ads->auth.password);
667 ads->auth.password = talloc_strdup(ads, c->opt_password);
668 if (ads->auth.password == NULL) {
670 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
674 ADS_TALLOC_CONST_FREE(ads->auth.user_name);
675 ads->auth.user_name = talloc_strdup(ads, c->opt_user_name);
676 if (ads->auth.user_name == NULL) {
678 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
681 ads->auth.flags |= auth_flags;
683 /* The ADS code will handle FIPS mode */
684 krb5_state = cli_credentials_get_kerberos_state(c->creds);
685 switch (krb5_state) {
686 case CRED_USE_KERBEROS_REQUIRED:
687 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
688 ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
690 case CRED_USE_KERBEROS_DESIRED:
691 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
692 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
694 case CRED_USE_KERBEROS_DISABLED:
695 ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
696 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
701 * If the username is of the form "name@realm",
702 * extract the realm and convert to upper case.
703 * This is only used to establish the connection.
705 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
707 ADS_TALLOC_CONST_FREE(ads->auth.realm);
708 ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", cp);
709 if (ads->auth.realm == NULL) {
711 return ADS_ERROR(LDAP_NO_MEMORY);
713 } else if (ads->auth.realm == NULL) {
714 const char *c_realm = cli_credentials_get_realm(c->creds);
716 ads->auth.realm = talloc_strdup(ads, c_realm);
717 if (ads->auth.realm == NULL) {
719 return ADS_ERROR(LDAP_NO_MEMORY);
723 status = ads_connect(ads);
725 if (!ADS_ERR_OK(status)) {
727 if (NT_STATUS_EQUAL(ads_ntstatus(status),
728 NT_STATUS_NO_LOGON_SERVERS)) {
729 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
734 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
735 need_password = true;
744 /* when contacting our own domain, make sure we use the closest DC.
745 * This is done by reconnecting to ADS because only the first call to
746 * ads_connect will give us our own sitename */
748 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
750 tried_closest_dc = true; /* avoid loop */
752 if (!ads_closest_dc(ads)) {
754 namecache_delete(ads->server.realm, 0x1C);
755 namecache_delete(ads->server.workgroup, 0x1C);
763 *ads_ret = talloc_move(mem_ctx, &ads);
767 ADS_STATUS ads_startup(struct net_context *c,
768 bool only_own_domain,
772 return ads_startup_int(c, only_own_domain, 0, mem_ctx, ads);
775 ADS_STATUS ads_startup_nobind(struct net_context *c,
776 bool only_own_domain,
780 return ads_startup_int(c,
788 Check to see if connection can be made via ads.
789 ads_startup() stores the password in opt_password if it needs to so
790 that rpc or rap can use it without re-prompting.
792 static int net_ads_check_int(struct net_context *c,
794 const char *workgroup,
797 TALLOC_CTX *tmp_ctx = talloc_stackframe();
802 ads = ads_init(tmp_ctx, realm, workgroup, host, ADS_SASL_PLAIN);
807 ads->auth.flags |= ADS_AUTH_NO_BIND;
809 status = ads_connect(ads);
810 if ( !ADS_ERR_OK(status) ) {
816 TALLOC_FREE(tmp_ctx);
820 int net_ads_check_our_domain(struct net_context *c)
822 return net_ads_check_int(c, lp_realm(), lp_workgroup(), NULL);
825 int net_ads_check(struct net_context *c)
827 return net_ads_check_int(c, NULL, c->opt_workgroup, c->opt_host);
831 determine the netbios workgroup name for a domain
833 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
835 TALLOC_CTX *tmp_ctx = talloc_stackframe();
836 ADS_STRUCT *ads = NULL;
838 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
842 if (c->display_usage) {
844 "net ads workgroup\n"
847 _("Print the workgroup name"));
848 TALLOC_FREE(tmp_ctx);
852 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
853 if (!ADS_ERR_OK(status)) {
854 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
858 if (!ads->config.realm) {
859 ads->config.realm = talloc_strdup(ads, c->opt_target_workgroup);
860 if (ads->config.realm == NULL) {
861 d_fprintf(stderr, _("Out of memory\n"));
864 ads->ldap.port = 389;
867 ok = ads_cldap_netlogon_5(tmp_ctx,
868 &ads->ldap.ss, ads->server.realm, &reply);
870 d_fprintf(stderr, _("CLDAP query failed!\n"));
874 d_printf(_("Workgroup: %s\n"), reply.domain_name);
878 TALLOC_FREE(tmp_ctx);
885 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
887 char **disp_fields = (char **) data_area;
889 if (!field) { /* must be end of record */
890 if (disp_fields[0]) {
891 if (!strchr_m(disp_fields[0], '$')) {
893 d_printf("%-21.21s %s\n",
894 disp_fields[0], disp_fields[1]);
896 d_printf("%s\n", disp_fields[0]);
899 SAFE_FREE(disp_fields[0]);
900 SAFE_FREE(disp_fields[1]);
903 if (!values) /* must be new field, indicate string field */
905 if (strcasecmp_m(field, "sAMAccountName") == 0) {
906 disp_fields[0] = SMB_STRDUP((char *) values[0]);
908 if (strcasecmp_m(field, "description") == 0)
909 disp_fields[1] = SMB_STRDUP((char *) values[0]);
913 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
915 return net_user_usage(c, argc, argv);
918 static int ads_user_add(struct net_context *c, int argc, const char **argv)
920 TALLOC_CTX *tmp_ctx = talloc_stackframe();
921 ADS_STRUCT *ads = NULL;
924 LDAPMessage *res=NULL;
928 if (argc < 1 || c->display_usage) {
929 TALLOC_FREE(tmp_ctx);
930 return net_ads_user_usage(c, argc, argv);
933 status = ads_startup(c, false, tmp_ctx, &ads);
934 if (!ADS_ERR_OK(status)) {
938 status = ads_find_user_acct(ads, &res, argv[0]);
939 if (!ADS_ERR_OK(status)) {
940 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
944 if (ads_count_replies(ads, res)) {
945 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
950 if (c->opt_container) {
951 ou_str = SMB_STRDUP(c->opt_container);
953 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
956 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
957 if (!ADS_ERR_OK(status)) {
958 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
963 /* if no password is to be set, we're done */
965 d_printf(_("User %s added\n"), argv[0]);
970 /* try setting the password */
971 upn = talloc_asprintf(tmp_ctx,
979 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
980 ads->auth.time_offset);
981 if (ADS_ERR_OK(status)) {
982 d_printf(_("User %s added\n"), argv[0]);
988 /* password didn't set, delete account */
989 d_fprintf(stderr, _("Could not add user %s. "
990 "Error setting password %s\n"),
991 argv[0], ads_errstr(status));
993 ads_msgfree(ads, res);
996 status=ads_find_user_acct(ads, &res, argv[0]);
997 if (ADS_ERR_OK(status)) {
998 userdn = ads_get_dn(ads, tmp_ctx, res);
999 ads_del_dn(ads, userdn);
1000 TALLOC_FREE(userdn);
1004 ads_msgfree(ads, res);
1006 TALLOC_FREE(tmp_ctx);
1010 static int ads_user_info(struct net_context *c, int argc, const char **argv)
1012 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1013 ADS_STRUCT *ads = NULL;
1015 LDAPMessage *res = NULL;
1018 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
1019 char *searchstring = NULL;
1020 char **grouplist = NULL;
1021 char *primary_group = NULL;
1022 char *escaped_user = NULL;
1023 struct dom_sid primary_group_sid;
1025 enum wbcSidType type;
1027 if (argc < 1 || c->display_usage) {
1028 TALLOC_FREE(tmp_ctx);
1029 return net_ads_user_usage(c, argc, argv);
1032 escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
1033 if (!escaped_user) {
1035 _("ads_user_info: failed to escape user %s\n"),
1040 status = ads_startup(c, false, tmp_ctx, &ads);
1041 if (!ADS_ERR_OK(status)) {
1045 searchstring = talloc_asprintf(tmp_ctx,
1046 "(sAMAccountName=%s)",
1048 if (searchstring == NULL) {
1052 status = ads_search(ads, &res, searchstring, attrs);
1053 if (!ADS_ERR_OK(status)) {
1054 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1058 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1059 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1063 status = ads_domain_sid(ads, &primary_group_sid);
1064 if (!ADS_ERR_OK(status)) {
1065 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1069 sid_append_rid(&primary_group_sid, group_rid);
1071 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1072 NULL, /* don't look up domain */
1075 if (!WBC_ERROR_IS_OK(wbc_status)) {
1076 d_fprintf(stderr, "wbcLookupSid: %s\n",
1077 wbcErrorString(wbc_status));
1081 d_printf("%s\n", primary_group);
1083 wbcFreeMemory(primary_group);
1085 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1086 (LDAPMessage *)res, "memberOf");
1091 for (i=0;grouplist[i];i++) {
1092 groupname = ldap_explode_dn(grouplist[i], 1);
1093 d_printf("%s\n", groupname[0]);
1094 ldap_value_free(groupname);
1096 ldap_value_free(grouplist);
1101 ads_msgfree(ads, res);
1102 TALLOC_FREE(tmp_ctx);
1106 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1108 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1109 ADS_STRUCT *ads = NULL;
1111 LDAPMessage *res = NULL;
1112 char *userdn = NULL;
1116 TALLOC_FREE(tmp_ctx);
1117 return net_ads_user_usage(c, argc, argv);
1120 status = ads_startup(c, false, tmp_ctx, &ads);
1121 if (!ADS_ERR_OK(status)) {
1125 status = ads_find_user_acct(ads, &res, argv[0]);
1126 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1127 d_printf(_("User %s does not exist.\n"), argv[0]);
1131 userdn = ads_get_dn(ads, tmp_ctx, res);
1132 if (userdn == NULL) {
1136 status = ads_del_dn(ads, userdn);
1137 if (!ADS_ERR_OK(status)) {
1138 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1139 ads_errstr(status));
1143 d_printf(_("User %s deleted\n"), argv[0]);
1147 ads_msgfree(ads, res);
1148 TALLOC_FREE(tmp_ctx);
1152 int net_ads_user(struct net_context *c, int argc, const char **argv)
1154 struct functable func[] = {
1159 N_("Add an AD user"),
1160 N_("net ads user add\n"
1167 N_("Display information about an AD user"),
1168 N_("net ads user info\n"
1169 " Display information about an AD user")
1175 N_("Delete an AD user"),
1176 N_("net ads user delete\n"
1177 " Delete an AD user")
1179 {NULL, NULL, 0, NULL, NULL}
1181 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1182 ADS_STRUCT *ads = NULL;
1184 const char *shortattrs[] = {"sAMAccountName", NULL};
1185 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1186 char *disp_fields[2] = {NULL, NULL};
1190 TALLOC_FREE(tmp_ctx);
1191 return net_run_function(c, argc, argv, "net ads user", func);
1194 if (c->display_usage) {
1199 _("List AD users"));
1200 net_display_usage_from_functable(func);
1201 TALLOC_FREE(tmp_ctx);
1205 status = ads_startup(c, false, tmp_ctx, &ads);
1206 if (!ADS_ERR_OK(status)) {
1210 if (c->opt_long_list_entries)
1211 d_printf(_("\nUser name Comment"
1212 "\n-----------------------------\n"));
1214 status = ads_do_search_all_fn(ads,
1215 ads->config.bind_path,
1217 "(objectCategory=user)",
1218 c->opt_long_list_entries ?
1219 longattrs : shortattrs,
1222 if (!ADS_ERR_OK(status)) {
1228 TALLOC_FREE(tmp_ctx);
1232 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1234 return net_group_usage(c, argc, argv);
1237 static int ads_group_add(struct net_context *c, int argc, const char **argv)
1239 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1240 ADS_STRUCT *ads = NULL;
1242 LDAPMessage *res = NULL;
1244 char *ou_str = NULL;
1246 if (argc < 1 || c->display_usage) {
1247 TALLOC_FREE(tmp_ctx);
1248 return net_ads_group_usage(c, argc, argv);
1251 status = ads_startup(c, false, tmp_ctx, &ads);
1252 if (!ADS_ERR_OK(status)) {
1256 status = ads_find_user_acct(ads, &res, argv[0]);
1257 if (!ADS_ERR_OK(status)) {
1258 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1262 if (ads_count_replies(ads, res)) {
1263 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1267 if (c->opt_container) {
1268 ou_str = SMB_STRDUP(c->opt_container);
1270 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1273 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1274 if (!ADS_ERR_OK(status)) {
1275 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1276 ads_errstr(status));
1280 d_printf(_("Group %s added\n"), argv[0]);
1284 ads_msgfree(ads, res);
1286 TALLOC_FREE(tmp_ctx);
1290 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1292 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1293 ADS_STRUCT *ads = NULL;
1295 LDAPMessage *res = NULL;
1296 char *groupdn = NULL;
1299 if (argc < 1 || c->display_usage) {
1300 TALLOC_FREE(tmp_ctx);
1301 return net_ads_group_usage(c, argc, argv);
1304 status = ads_startup(c, false, tmp_ctx, &ads);
1305 if (!ADS_ERR_OK(status)) {
1309 status = ads_find_user_acct(ads, &res, argv[0]);
1310 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1311 d_printf(_("Group %s does not exist.\n"), argv[0]);
1315 groupdn = ads_get_dn(ads, tmp_ctx, res);
1316 if (groupdn == NULL) {
1320 status = ads_del_dn(ads, groupdn);
1321 if (!ADS_ERR_OK(status)) {
1322 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1323 ads_errstr(status));
1326 d_printf(_("Group %s deleted\n"), argv[0]);
1330 ads_msgfree(ads, res);
1331 TALLOC_FREE(tmp_ctx);
1335 int net_ads_group(struct net_context *c, int argc, const char **argv)
1337 struct functable func[] = {
1342 N_("Add an AD group"),
1343 N_("net ads group add\n"
1350 N_("Delete an AD group"),
1351 N_("net ads group delete\n"
1352 " Delete an AD group")
1354 {NULL, NULL, 0, NULL, NULL}
1356 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1357 ADS_STRUCT *ads = NULL;
1359 const char *shortattrs[] = {"sAMAccountName", NULL};
1360 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1361 char *disp_fields[2] = {NULL, NULL};
1365 TALLOC_FREE(tmp_ctx);
1366 return net_run_function(c, argc, argv, "net ads group", func);
1369 if (c->display_usage) {
1374 _("List AD groups"));
1375 net_display_usage_from_functable(func);
1376 TALLOC_FREE(tmp_ctx);
1380 status = ads_startup(c, false, tmp_ctx, &ads);
1381 if (!ADS_ERR_OK(status)) {
1385 if (c->opt_long_list_entries)
1386 d_printf(_("\nGroup name Comment"
1387 "\n-----------------------------\n"));
1389 status = ads_do_search_all_fn(ads,
1390 ads->config.bind_path,
1392 "(objectCategory=group)",
1393 c->opt_long_list_entries ?
1394 longattrs : shortattrs,
1397 if (!ADS_ERR_OK(status)) {
1403 TALLOC_FREE(tmp_ctx);
1407 static int net_ads_status(struct net_context *c, int argc, const char **argv)
1409 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1410 ADS_STRUCT *ads = NULL;
1412 LDAPMessage *res = NULL;
1415 if (c->display_usage) {
1420 _("Display machine account details"));
1421 TALLOC_FREE(tmp_ctx);
1425 net_warn_member_options();
1427 status = ads_startup(c, true, tmp_ctx, &ads);
1428 if (!ADS_ERR_OK(status)) {
1432 status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1433 if (!ADS_ERR_OK(status)) {
1434 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1435 ads_errstr(status));
1439 if (ads_count_replies(ads, res) == 0) {
1440 d_fprintf(stderr, _("No machine account for '%s' found\n"),
1449 ads_msgfree(ads, res);
1450 TALLOC_FREE(tmp_ctx);
1454 /*******************************************************************
1455 Leave an AD domain. Windows XP disables the machine account.
1456 We'll try the same. The old code would do an LDAP delete.
1457 That only worked using the machine creds because added the machine
1458 with full control to the computer object's ACL.
1459 *******************************************************************/
1461 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1463 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1464 struct libnet_UnjoinCtx *r = NULL;
1468 if (c->display_usage) {
1470 "net ads leave [--keep-account]\n"
1473 _("Leave an AD domain"));
1474 TALLOC_FREE(tmp_ctx);
1479 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1480 TALLOC_FREE(tmp_ctx);
1484 if (!c->opt_kerberos) {
1485 use_in_memory_ccache();
1489 d_fprintf(stderr, _("Could not initialise message context. "
1490 "Try running as root\n"));
1494 werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1495 if (!W_ERROR_IS_OK(werr)) {
1496 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1501 r->in.use_kerberos = c->opt_kerberos;
1502 r->in.dc_name = c->opt_host;
1503 r->in.domain_name = lp_realm();
1504 r->in.admin_account = c->opt_user_name;
1505 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1506 r->in.modify_config = lp_config_backend_is_registry();
1508 /* Try to delete it, but if that fails, disable it. The
1509 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1510 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1511 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1512 if (c->opt_keep_account) {
1513 r->in.delete_machine_account = false;
1515 r->in.delete_machine_account = true;
1518 r->in.msg_ctx = c->msg_ctx;
1520 werr = libnet_Unjoin(tmp_ctx, r);
1521 if (!W_ERROR_IS_OK(werr)) {
1522 d_printf(_("Failed to leave domain: %s\n"),
1523 r->out.error_string ? r->out.error_string :
1524 get_friendly_werror_msg(werr));
1528 if (r->out.deleted_machine_account) {
1529 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1530 r->in.machine_name, r->out.dns_domain_name);
1535 /* We couldn't delete it - see if the disable succeeded. */
1536 if (r->out.disabled_machine_account) {
1537 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1538 r->in.machine_name, r->out.dns_domain_name);
1543 /* Based on what we requested, we shouldn't get here, but if
1544 we did, it means the secrets were removed, and therefore
1545 we have left the domain */
1546 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1547 r->in.machine_name, r->out.dns_domain_name);
1551 TALLOC_FREE(tmp_ctx);
1555 static ADS_STATUS net_ads_join_ok(struct net_context *c)
1557 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1558 ADS_STRUCT *ads = NULL;
1561 struct sockaddr_storage dcip;
1563 if (!secrets_init()) {
1564 DEBUG(1,("Failed to initialise secrets database\n"));
1565 TALLOC_FREE(tmp_ctx);
1566 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1569 net_warn_member_options();
1571 net_use_krb_machine_account(c);
1573 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1575 status = ads_startup(c, true, tmp_ctx, &ads);
1576 if (!ADS_ERR_OK(status)) {
1580 status = ADS_ERROR_NT(NT_STATUS_OK);
1582 TALLOC_FREE(tmp_ctx);
1587 check that an existing join is OK
1589 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1592 use_in_memory_ccache();
1594 if (c->display_usage) {
1596 "net ads testjoin\n"
1599 _("Test if the existing join is ok"));
1603 net_warn_member_options();
1605 /* Display success or failure */
1606 status = net_ads_join_ok(c);
1607 if (!ADS_ERR_OK(status)) {
1608 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1609 get_friendly_nt_error_msg(ads_ntstatus(status)));
1613 printf(_("Join is OK\n"));
1617 /*******************************************************************
1618 Simple config checks before beginning the join
1619 ********************************************************************/
1621 static WERROR check_ads_config( void )
1623 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1624 d_printf(_("Host is not configured as a member server.\n"));
1625 return WERR_INVALID_DOMAIN_ROLE;
1628 if (strlen(lp_netbios_name()) > 15) {
1629 d_printf(_("Our netbios name can be at most 15 chars long, "
1630 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1631 (unsigned int)strlen(lp_netbios_name()));
1632 return WERR_INVALID_COMPUTERNAME;
1635 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1636 d_fprintf(stderr, _("realm must be set in in %s for ADS "
1637 "join to succeed.\n"), get_dyn_CONFIGFILE());
1638 return WERR_INVALID_PARAMETER;
1644 /*******************************************************************
1645 ********************************************************************/
1647 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1649 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1650 "Valid options:\n"));
1651 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1652 " The default is in the form netbiosname.dnsdomain\n"));
1653 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1654 " The default UPN is in the form host/netbiosname@REALM.\n"));
1655 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1656 " The OU string read from top to bottom without RDNs\n"
1657 " and delimited by a '/'.\n"
1658 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1659 " NB: A backslash '\\' is used as escape at multiple\n"
1660 " levels and may need to be doubled or even\n"
1661 " quadrupled. It is not used as a separator.\n"));
1662 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1663 " the join. The default password is random.\n"));
1664 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1665 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1666 " NB: osName and osVer must be specified together for\n"
1667 " either to take effect. The operatingSystemService\n"
1668 " attribute is then also set along with the two\n"
1669 " other attributes.\n"));
1670 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1671 " during the join.\n"
1672 " NB: If not specified then by default the samba\n"
1673 " version string is used instead.\n"));
1678 int net_ads_join(struct net_context *c, int argc, const char **argv)
1680 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1681 struct libnet_JoinCtx *r = NULL;
1682 const char *domain = lp_realm();
1683 WERROR werr = WERR_NERR_SETUPNOTJOINED;
1684 bool createupn = false;
1685 const char *dnshostname = NULL;
1686 const char *machineupn = NULL;
1687 const char *machine_password = NULL;
1688 const char *create_in_ou = NULL;
1690 const char *os_name = NULL;
1691 const char *os_version = NULL;
1692 const char *os_servicepack = NULL;
1693 bool modify_config = lp_config_backend_is_registry();
1694 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1697 if (c->display_usage) {
1698 TALLOC_FREE(tmp_ctx);
1699 return net_ads_join_usage(c, argc, argv);
1702 net_warn_member_options();
1704 if (!modify_config) {
1705 werr = check_ads_config();
1706 if (!W_ERROR_IS_OK(werr)) {
1707 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1712 if (!c->opt_kerberos) {
1713 use_in_memory_ccache();
1716 werr = libnet_init_JoinCtx(tmp_ctx, &r);
1717 if (!W_ERROR_IS_OK(werr)) {
1721 /* process additional command line args */
1723 for ( i=0; i<argc; i++ ) {
1724 if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1725 dnshostname = get_string_param(argv[i]);
1727 else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1729 machineupn = get_string_param(argv[i]);
1731 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1732 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1733 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1734 werr = WERR_INVALID_PARAMETER;
1738 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1739 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1740 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1741 werr = WERR_INVALID_PARAMETER;
1745 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1746 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1747 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1748 werr = WERR_INVALID_PARAMETER;
1752 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1753 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1754 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1755 werr = WERR_INVALID_PARAMETER;
1759 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1760 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1761 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1762 werr = WERR_INVALID_PARAMETER;
1767 if (strchr(domain, '.') == NULL) {
1768 domain_name_type = JoinDomNameTypeUnknown;
1770 domain_name_type = JoinDomNameTypeDNS;
1776 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1777 werr = WERR_INVALID_PARAMETER;
1782 d_fprintf(stderr, _("Could not initialise message context. "
1783 "Try running as root\n"));
1784 werr = WERR_ACCESS_DENIED;
1788 /* Do the domain join here */
1790 r->in.domain_name = domain;
1791 r->in.domain_name_type = domain_name_type;
1792 r->in.create_upn = createupn;
1793 r->in.upn = machineupn;
1794 r->in.dnshostname = dnshostname;
1795 r->in.account_ou = create_in_ou;
1796 r->in.os_name = os_name;
1797 r->in.os_version = os_version;
1798 r->in.os_servicepack = os_servicepack;
1799 r->in.dc_name = c->opt_host;
1800 r->in.admin_account = c->opt_user_name;
1801 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1802 r->in.machine_password = machine_password;
1804 r->in.use_kerberos = c->opt_kerberos;
1805 r->in.modify_config = modify_config;
1806 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1807 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1808 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1809 r->in.msg_ctx = c->msg_ctx;
1811 werr = libnet_Join(tmp_ctx, r);
1812 if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1813 strequal(domain, lp_realm())) {
1814 r->in.domain_name = lp_workgroup();
1815 r->in.domain_name_type = JoinDomNameTypeNBT;
1816 werr = libnet_Join(tmp_ctx, r);
1818 if (!W_ERROR_IS_OK(werr)) {
1822 /* Check the short name of the domain */
1824 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1825 d_printf(_("The workgroup in %s does not match the short\n"
1826 "domain name obtained from the server.\n"
1827 "Using the name [%s] from the server.\n"
1828 "You should set \"workgroup = %s\" in %s.\n"),
1829 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1830 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1833 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1835 if (r->out.dns_domain_name) {
1836 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1837 r->out.dns_domain_name);
1839 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1840 r->out.netbios_domain_name);
1843 /* print out informative error string in case there is one */
1844 if (r->out.error_string != NULL) {
1845 d_printf("%s\n", r->out.error_string);
1849 * We try doing the dns update (if it was compiled in
1850 * and if it was not disabled on the command line).
1851 * If the dns update fails, we still consider the join
1852 * operation as succeeded if we came this far.
1854 if (!c->opt_no_dns_updates) {
1855 net_ads_join_dns_updates(c, tmp_ctx, r);
1862 /* issue an overall failure message at the end. */
1863 d_printf(_("Failed to join domain: %s\n"),
1864 r && r->out.error_string ? r->out.error_string :
1865 get_friendly_werror_msg(werr));
1868 TALLOC_FREE(tmp_ctx);
1873 /*******************************************************************
1874 ********************************************************************/
1876 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1878 #if defined(HAVE_KRB5)
1879 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1880 ADS_STRUCT *ads = NULL;
1883 const char *hostname = NULL;
1884 const char **addrs_list = NULL;
1885 struct sockaddr_storage *addrs = NULL;
1891 talloc_enable_leak_report();
1894 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1895 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1896 "detection of addresses in a clustered "
1898 c->display_usage = true;
1901 if (c->display_usage) {
1903 "net ads dns register [hostname [IP [IP...]]] "
1904 "[--force] [--dns-ttl TTL]\n"
1907 _("Register hostname with DNS\n"));
1908 TALLOC_FREE(tmp_ctx);
1917 num_addrs = argc - 1;
1918 addrs_list = &argv[1];
1919 } else if (lp_clustering()) {
1920 addrs_list = lp_cluster_addresses();
1921 num_addrs = str_list_length(addrs_list);
1924 if (num_addrs > 0) {
1925 addrs = talloc_zero_array(tmp_ctx,
1926 struct sockaddr_storage,
1928 if (addrs == NULL) {
1929 d_fprintf(stderr, _("Error allocating memory!\n"));
1934 for (count = 0; count < num_addrs; count++) {
1935 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1936 d_fprintf(stderr, "%s '%s'.\n",
1937 _("Cannot interpret address"),
1943 status = ads_startup(c, true, tmp_ctx, &ads);
1944 if ( !ADS_ERR_OK(status) ) {
1945 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1949 ntstatus = net_update_dns_ext(c,
1956 if (!NT_STATUS_IS_OK(ntstatus)) {
1957 d_fprintf( stderr, _("DNS update failed!\n") );
1961 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1965 TALLOC_FREE(tmp_ctx);
1970 _("DNS update support not enabled at compile time!\n"));
1975 static int net_ads_dns_unregister(struct net_context *c,
1979 #if defined(HAVE_KRB5)
1980 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1981 ADS_STRUCT *ads = NULL;
1984 const char *hostname = NULL;
1988 talloc_enable_leak_report();
1992 c->display_usage = true;
1995 if (c->display_usage) {
1997 "net ads dns unregister [hostname]\n"
2000 _("Remove all IP Address entires for a given\n"
2001 " hostname from the Active Directory server.\n"));
2002 TALLOC_FREE(tmp_ctx);
2006 /* Get the hostname for un-registering */
2009 status = ads_startup(c, true, tmp_ctx, &ads);
2010 if ( !ADS_ERR_OK(status) ) {
2011 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
2015 ntstatus = net_update_dns_ext(c,
2022 if (!NT_STATUS_IS_OK(ntstatus)) {
2023 d_fprintf( stderr, _("DNS update failed!\n") );
2027 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
2031 TALLOC_FREE(tmp_ctx);
2036 _("DNS update support not enabled at compile time!\n"));
2042 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2044 size_t num_names = 0;
2045 char **hostnames = NULL;
2047 struct samba_sockaddr *addrs = NULL;
2050 if (argc != 1 || c->display_usage) {
2055 _("net ads dns async <name>\n"),
2056 _(" Async look up hostname from the DNS server\n"
2057 " hostname\tName to look up\n"));
2061 status = ads_dns_lookup_a(talloc_tos(),
2066 if (!NT_STATUS_IS_OK(status)) {
2067 d_printf("Looking up A record for %s got error %s\n",
2072 d_printf("Async A record lookup - got %u names for %s\n",
2073 (unsigned int)num_names,
2075 for (i = 0; i < num_names; i++) {
2076 char addr_buf[INET6_ADDRSTRLEN];
2077 print_sockaddr(addr_buf,
2080 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2086 #if defined(HAVE_IPV6)
2087 status = ads_dns_lookup_aaaa(talloc_tos(),
2092 if (!NT_STATUS_IS_OK(status)) {
2093 d_printf("Looking up AAAA record for %s got error %s\n",
2098 d_printf("Async AAAA record lookup - got %u names for %s\n",
2099 (unsigned int)num_names,
2101 for (i = 0; i < num_names; i++) {
2102 char addr_buf[INET6_ADDRSTRLEN];
2103 print_sockaddr(addr_buf,
2106 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2116 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2118 struct functable func[] = {
2121 net_ads_dns_register,
2123 N_("Add host dns entry to AD"),
2124 N_("net ads dns register\n"
2125 " Add host dns entry to AD")
2129 net_ads_dns_unregister,
2131 N_("Remove host dns entry from AD"),
2132 N_("net ads dns unregister\n"
2133 " Remove host dns entry from AD")
2140 N_("net ads dns async\n"
2141 " Look up host using async DNS")
2143 {NULL, NULL, 0, NULL, NULL}
2146 return net_run_function(c, argc, argv, "net ads dns", func);
2149 /*******************************************************************
2150 ********************************************************************/
2152 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2155 "\nnet ads printer search <printer>"
2156 "\n\tsearch for a printer in the directory\n"
2157 "\nnet ads printer info <printer> <server>"
2158 "\n\tlookup info in directory for printer on server"
2159 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2160 "\nnet ads printer publish <printername>"
2161 "\n\tpublish printer in directory"
2162 "\n\t(note: printer name is required)\n"
2163 "\nnet ads printer remove <printername>"
2164 "\n\tremove printer from directory"
2165 "\n\t(note: printer name is required)\n"));
2169 /*******************************************************************
2170 ********************************************************************/
2172 static int net_ads_printer_search(struct net_context *c,
2176 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2177 ADS_STRUCT *ads = NULL;
2179 LDAPMessage *res = NULL;
2182 if (c->display_usage) {
2184 "net ads printer search\n"
2187 _("List printers in the AD"));
2188 TALLOC_FREE(tmp_ctx);
2192 status = ads_startup(c, false, tmp_ctx, &ads);
2193 if (!ADS_ERR_OK(status)) {
2197 status = ads_find_printers(ads, &res);
2198 if (!ADS_ERR_OK(status)) {
2199 d_fprintf(stderr, _("ads_find_printer: %s\n"),
2200 ads_errstr(status));
2204 if (ads_count_replies(ads, res) == 0) {
2205 d_fprintf(stderr, _("No results found\n"));
2213 ads_msgfree(ads, res);
2214 TALLOC_FREE(tmp_ctx);
2218 static int net_ads_printer_info(struct net_context *c,
2222 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2223 ADS_STRUCT *ads = NULL;
2225 const char *servername = NULL;
2226 const char *printername = NULL;
2227 LDAPMessage *res = NULL;
2230 if (c->display_usage) {
2233 _("net ads printer info [printername [servername]]\n"
2234 " Display printer info from AD\n"
2235 " printername\tPrinter name or wildcard\n"
2236 " servername\tName of the print server\n"));
2237 TALLOC_FREE(tmp_ctx);
2241 status = ads_startup(c, false, tmp_ctx, &ads);
2242 if (!ADS_ERR_OK(status)) {
2247 printername = argv[0];
2253 servername = argv[1];
2255 servername = lp_netbios_name();
2258 status = ads_find_printer_on_server(ads, &res, printername, servername);
2259 if (!ADS_ERR_OK(status)) {
2260 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2261 servername, ads_errstr(status));
2265 if (ads_count_replies(ads, res) == 0) {
2266 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2274 ads_msgfree(ads, res);
2275 TALLOC_FREE(tmp_ctx);
2279 static int net_ads_printer_publish(struct net_context *c,
2283 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2284 ADS_STRUCT *ads = NULL;
2286 const char *servername = NULL;
2287 const char *printername = NULL;
2288 struct cli_state *cli = NULL;
2289 struct rpc_pipe_client *pipe_hnd = NULL;
2290 struct sockaddr_storage server_ss = { 0 };
2292 ADS_MODLIST mods = NULL;
2293 char *prt_dn = NULL;
2294 char *srv_dn = NULL;
2295 char **srv_cn = NULL;
2296 char *srv_cn_escaped = NULL;
2297 char *printername_escaped = NULL;
2298 LDAPMessage *res = NULL;
2302 if (argc < 1 || c->display_usage) {
2305 _("net ads printer publish <printername> [servername]\n"
2306 " Publish printer in AD\n"
2307 " printername\tName of the printer\n"
2308 " servername\tName of the print server\n"));
2309 TALLOC_FREE(tmp_ctx);
2313 mods = ads_init_mods(tmp_ctx);
2315 d_fprintf(stderr, _("Out of memory\n"));
2319 status = ads_startup(c, true, tmp_ctx, &ads);
2320 if (!ADS_ERR_OK(status)) {
2324 printername = argv[0];
2327 servername = argv[1];
2329 servername = lp_netbios_name();
2332 /* Get printer data from SPOOLSS */
2334 ok = resolve_name(servername, &server_ss, 0x20, false);
2336 d_fprintf(stderr, _("Could not find server %s\n"),
2341 cli_credentials_set_kerberos_state(c->creds,
2342 CRED_USE_KERBEROS_REQUIRED,
2345 nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2349 CLI_FULL_CONNECTION_IPC);
2351 if (NT_STATUS_IS_ERR(nt_status)) {
2352 d_fprintf(stderr, _("Unable to open a connection to %s to "
2353 "obtain data for %s\n"),
2354 servername, printername);
2358 /* Publish on AD server */
2360 ads_find_machine_acct(ads, &res, servername);
2362 if (ads_count_replies(ads, res) == 0) {
2363 d_fprintf(stderr, _("Could not find machine account for server "
2369 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2370 srv_cn = ldap_explode_dn(srv_dn, 1);
2372 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2373 printername_escaped = escape_rdn_val_string_alloc(printername);
2374 if (!srv_cn_escaped || !printername_escaped) {
2375 SAFE_FREE(srv_cn_escaped);
2376 SAFE_FREE(printername_escaped);
2377 d_fprintf(stderr, _("Internal error, out of memory!"));
2381 prt_dn = talloc_asprintf(tmp_ctx,
2384 printername_escaped,
2386 if (prt_dn == NULL) {
2387 SAFE_FREE(srv_cn_escaped);
2388 SAFE_FREE(printername_escaped);
2389 d_fprintf(stderr, _("Internal error, out of memory!"));
2393 SAFE_FREE(srv_cn_escaped);
2394 SAFE_FREE(printername_escaped);
2396 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2397 if (!NT_STATUS_IS_OK(nt_status)) {
2398 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2403 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2410 status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2411 if (!ADS_ERR_OK(status)) {
2412 d_fprintf(stderr, "ads_publish_printer: %s\n",
2413 ads_errstr(status));
2417 d_printf("published printer\n");
2421 talloc_destroy(tmp_ctx);
2426 static int net_ads_printer_remove(struct net_context *c,
2430 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2431 ADS_STRUCT *ads = NULL;
2433 const char *servername = NULL;
2434 char *prt_dn = NULL;
2435 LDAPMessage *res = NULL;
2438 if (argc < 1 || c->display_usage) {
2441 _("net ads printer remove <printername> [servername]\n"
2442 " Remove a printer from the AD\n"
2443 " printername\tName of the printer\n"
2444 " servername\tName of the print server\n"));
2445 TALLOC_FREE(tmp_ctx);
2449 status = ads_startup(c, true, tmp_ctx, &ads);
2450 if (!ADS_ERR_OK(status)) {
2455 servername = argv[1];
2457 servername = lp_netbios_name();
2460 status = ads_find_printer_on_server(ads, &res, argv[0], servername);
2461 if (!ADS_ERR_OK(status)) {
2462 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"),
2463 ads_errstr(status));
2467 if (ads_count_replies(ads, res) == 0) {
2468 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2472 prt_dn = ads_get_dn(ads, tmp_ctx, res);
2473 if (prt_dn == NULL) {
2474 d_fprintf(stderr, _("Out of memory\n"));
2478 status = ads_del_dn(ads, prt_dn);
2479 if (!ADS_ERR_OK(status)) {
2480 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(status));
2486 ads_msgfree(ads, res);
2487 TALLOC_FREE(tmp_ctx);
2491 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2493 struct functable func[] = {
2496 net_ads_printer_search,
2498 N_("Search for a printer"),
2499 N_("net ads printer search\n"
2500 " Search for a printer")
2504 net_ads_printer_info,
2506 N_("Display printer information"),
2507 N_("net ads printer info\n"
2508 " Display printer information")
2512 net_ads_printer_publish,
2514 N_("Publish a printer"),
2515 N_("net ads printer publish\n"
2516 " Publish a printer")
2520 net_ads_printer_remove,
2522 N_("Delete a printer"),
2523 N_("net ads printer remove\n"
2524 " Delete a printer")
2526 {NULL, NULL, 0, NULL, NULL}
2529 return net_run_function(c, argc, argv, "net ads printer", func);
2533 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2535 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2536 ADS_STRUCT *ads = NULL;
2537 const char *auth_principal = cli_credentials_get_username(c->creds);
2538 const char *auth_password = cli_credentials_get_password(c->creds);
2539 const char *realm = NULL;
2540 char *new_password = NULL;
2542 char *prompt = NULL;
2543 const char *user = NULL;
2544 char pwd[256] = {0};
2548 if (c->display_usage) {
2551 _("net ads password <username>\n"
2552 " Change password for user\n"
2553 " username\tName of user to change password for\n"));
2554 TALLOC_FREE(tmp_ctx);
2558 if (auth_principal == NULL || auth_password == NULL) {
2559 d_fprintf(stderr, _("You must supply an administrator "
2560 "username/password\n"));
2561 TALLOC_FREE(tmp_ctx);
2566 d_fprintf(stderr, _("ERROR: You must say which username to "
2567 "change password for\n"));
2568 TALLOC_FREE(tmp_ctx);
2572 if (strchr_m(argv[0], '@')) {
2573 user = talloc_strdup(tmp_ctx, argv[0]);
2575 user = talloc_asprintf(tmp_ctx, "%s@%s", argv[0], lp_realm());
2578 d_fprintf(stderr, _("Out of memory\n"));
2582 use_in_memory_ccache();
2583 chr = strchr_m(auth_principal, '@');
2590 /* use the realm so we can eventually change passwords for users
2591 in realms other than default */
2592 ads = ads_init(tmp_ctx,
2601 /* we don't actually need a full connect, but it's the easy way to
2602 fill in the KDC's addresss */
2605 if (!ads->config.realm) {
2606 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2610 if (argv[1] != NULL) {
2611 new_password = talloc_strdup(tmp_ctx, argv[1]);
2615 prompt = talloc_asprintf(tmp_ctx, _("Enter new password for %s:"), user);
2616 if (prompt == NULL) {
2617 d_fprintf(stderr, _("Out of memory\n"));
2621 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2625 new_password = talloc_strdup(tmp_ctx, pwd);
2626 memset(pwd, '\0', sizeof(pwd));
2629 if (new_password == NULL) {
2630 d_fprintf(stderr, _("Out of memory\n"));
2634 status = kerberos_set_password(ads->auth.kdc_server,
2639 ads->auth.time_offset);
2640 memset(new_password, '\0', strlen(new_password));
2641 if (!ADS_ERR_OK(status)) {
2642 d_fprintf(stderr, _("Password change failed: %s\n"),
2643 ads_errstr(status));
2647 d_printf(_("Password change for %s completed.\n"), user);
2651 TALLOC_FREE(tmp_ctx);
2655 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2657 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2658 ADS_STRUCT *ads = NULL;
2659 char *host_principal = NULL;
2660 char *my_name = NULL;
2664 if (c->display_usage) {
2666 "net ads changetrustpw\n"
2669 _("Change the machine account's trust password"));
2670 TALLOC_FREE(tmp_ctx);
2674 if (!secrets_init()) {
2675 DEBUG(1,("Failed to initialise secrets database\n"));
2679 net_warn_member_options();
2681 net_use_krb_machine_account(c);
2683 use_in_memory_ccache();
2685 status = ads_startup(c, true, tmp_ctx, &ads);
2686 if (!ADS_ERR_OK(status)) {
2690 my_name = talloc_asprintf_strlower_m(tmp_ctx, "%s", lp_netbios_name());
2691 if (my_name == NULL) {
2692 d_fprintf(stderr, _("Out of memory\n"));
2696 host_principal = talloc_asprintf(tmp_ctx, "%s$@%s", my_name, ads->config.realm);
2697 if (host_principal == NULL) {
2698 d_fprintf(stderr, _("Out of memory\n"));
2702 d_printf(_("Changing password for principal: %s\n"), host_principal);
2704 status = ads_change_trust_account_password(ads, host_principal);
2705 if (!ADS_ERR_OK(status)) {
2706 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(status));
2710 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2712 if (USE_SYSTEM_KEYTAB) {
2713 d_printf(_("Attempting to update system keytab with new password.\n"));
2714 if (ads_keytab_create_default(ads)) {
2715 d_printf(_("Failed to update system keytab.\n"));
2721 TALLOC_FREE(tmp_ctx);
2727 help for net ads search
2729 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2732 "\nnet ads search <expression> <attributes...>\n"
2733 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2734 "The expression is a standard LDAP search expression, and the\n"
2735 "attributes are a list of LDAP fields to show in the results.\n\n"
2736 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2738 net_common_flags_usage(c, argc, argv);
2744 general ADS search function. Useful in diagnosing problems in ADS
2746 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2748 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2749 ADS_STRUCT *ads = NULL;
2751 const char *ldap_exp = NULL;
2752 const char **attrs = NULL;
2753 LDAPMessage *res = NULL;
2756 if (argc < 1 || c->display_usage) {
2757 TALLOC_FREE(tmp_ctx);
2758 return net_ads_search_usage(c, argc, argv);
2761 status = ads_startup(c, false, tmp_ctx, &ads);
2762 if (!ADS_ERR_OK(status)) {
2769 status = ads_do_search_retry(ads,
2770 ads->config.bind_path,
2775 if (!ADS_ERR_OK(status)) {
2776 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2780 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2782 /* dump the results */
2787 ads_msgfree(ads, res);
2788 TALLOC_FREE(tmp_ctx);
2794 help for net ads search
2796 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2799 "\nnet ads dn <dn> <attributes...>\n"
2800 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2801 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2802 "to show in the results\n\n"
2803 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2804 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2806 net_common_flags_usage(c, argc, argv);
2812 general ADS search function. Useful in diagnosing problems in ADS
2814 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2816 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2817 ADS_STRUCT *ads = NULL;
2819 const char *dn = NULL;
2820 const char **attrs = NULL;
2821 LDAPMessage *res = NULL;
2824 if (argc < 1 || c->display_usage) {
2825 TALLOC_FREE(tmp_ctx);
2826 return net_ads_dn_usage(c, argc, argv);
2829 status = ads_startup(c, false, tmp_ctx, &ads);
2830 if (!ADS_ERR_OK(status)) {
2837 status = ads_do_search_all(ads,
2843 if (!ADS_ERR_OK(status)) {
2844 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2848 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2850 /* dump the results */
2855 ads_msgfree(ads, res);
2856 TALLOC_FREE(tmp_ctx);
2861 help for net ads sid search
2863 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2866 "\nnet ads sid <sid> <attributes...>\n"
2867 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2868 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2869 "to show in the results\n\n"
2870 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2872 net_common_flags_usage(c, argc, argv);
2878 general ADS search function. Useful in diagnosing problems in ADS
2880 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2882 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2883 ADS_STRUCT *ads = NULL;
2885 const char *sid_string = NULL;
2886 const char **attrs = NULL;
2887 LDAPMessage *res = NULL;
2888 struct dom_sid sid = { 0 };
2891 if (argc < 1 || c->display_usage) {
2892 TALLOC_FREE(tmp_ctx);
2893 return net_ads_sid_usage(c, argc, argv);
2896 status = ads_startup(c, false, tmp_ctx, &ads);
2897 if (!ADS_ERR_OK(status)) {
2901 sid_string = argv[0];
2904 if (!string_to_sid(&sid, sid_string)) {
2905 d_fprintf(stderr, _("could not convert sid\n"));
2909 status = ads_search_retry_sid(ads, &res, &sid, attrs);
2910 if (!ADS_ERR_OK(status)) {
2911 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(status));
2915 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2917 /* dump the results */
2922 ads_msgfree(ads, res);
2923 TALLOC_FREE(tmp_ctx);
2927 static int net_ads_keytab_flush(struct net_context *c,
2931 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2932 ADS_STRUCT *ads = NULL;
2936 if (c->display_usage) {
2938 "net ads keytab flush\n"
2941 _("Delete the whole keytab"));
2942 TALLOC_FREE(tmp_ctx);
2946 if (!c->opt_user_specified && c->opt_password == NULL) {
2947 net_use_krb_machine_account(c);
2950 status = ads_startup(c, true, tmp_ctx, &ads);
2951 if (!ADS_ERR_OK(status)) {
2955 ret = ads_keytab_flush(ads);
2957 TALLOC_FREE(tmp_ctx);
2961 static int net_ads_keytab_add(struct net_context *c,
2966 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2967 ADS_STRUCT *ads = NULL;
2972 if (c->display_usage) {
2975 _("net ads keytab add <principal> [principal ...]\n"
2976 " Add principals to local keytab\n"
2977 " principal\tKerberos principal to add to "
2979 TALLOC_FREE(tmp_ctx);
2983 net_warn_member_options();
2985 d_printf(_("Processing principals to add...\n"));
2987 if (!c->opt_user_specified && c->opt_password == NULL) {
2988 net_use_krb_machine_account(c);
2991 status = ads_startup(c, true, tmp_ctx, &ads);
2992 if (!ADS_ERR_OK(status)) {
2996 for (ret = 0, i = 0; i < argc; i++) {
2997 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
3000 TALLOC_FREE(tmp_ctx);
3004 static int net_ads_keytab_add_default(struct net_context *c,
3008 return net_ads_keytab_add(c, argc, argv, false);
3011 static int net_ads_keytab_add_update_ads(struct net_context *c,
3015 return net_ads_keytab_add(c, argc, argv, true);
3018 static int net_ads_keytab_delete(struct net_context *c,
3022 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3023 ADS_STRUCT *ads = NULL;
3028 if (c->display_usage) {
3031 _("net ads keytab delete <principal> [principal ...]\n"
3032 " Remove entries for service principal, "
3033 " from the keytab file only."
3034 " Remove principals from local keytab\n"
3035 " principal\tKerberos principal to remove from "
3037 TALLOC_FREE(tmp_ctx);
3041 d_printf(_("Processing principals to delete...\n"));
3043 if (!c->opt_user_specified && c->opt_password == NULL) {
3044 net_use_krb_machine_account(c);
3047 status = ads_startup(c, true, tmp_ctx, &ads);
3048 if (!ADS_ERR_OK(status)) {
3052 for (ret = 0, i = 0; i < argc; i++) {
3053 ret |= ads_keytab_delete_entry(ads, argv[i]);
3056 TALLOC_FREE(tmp_ctx);
3060 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
3062 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3063 ADS_STRUCT *ads = NULL;
3067 if (c->display_usage) {
3069 "net ads keytab create\n"
3072 _("Create new default keytab"));
3073 TALLOC_FREE(tmp_ctx);
3077 net_warn_member_options();
3079 if (!c->opt_user_specified && c->opt_password == NULL) {
3080 net_use_krb_machine_account(c);
3083 status = ads_startup(c, true, tmp_ctx, &ads);
3084 if (!ADS_ERR_OK(status)) {
3088 ret = ads_keytab_create_default(ads);
3090 TALLOC_FREE(tmp_ctx);
3094 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
3096 const char *keytab = NULL;
3098 if (c->display_usage) {
3101 _("net ads keytab list [keytab]\n"
3102 " List a local keytab\n"
3103 " keytab\tKeytab to list\n"));
3111 return ads_keytab_list(keytab);
3115 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3117 struct functable func[] = {
3120 net_ads_keytab_add_default,
3122 N_("Add a service principal"),
3123 N_("net ads keytab add\n"
3124 " Add a service principal, updates keytab file only.")
3128 net_ads_keytab_delete,
3130 N_("Delete a service principal"),
3131 N_("net ads keytab delete\n"
3132 " Remove entries for service principal, from the keytab file only.")
3136 net_ads_keytab_add_update_ads,
3138 N_("Add a service principal"),
3139 N_("net ads keytab add_update_ads\n"
3140 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3144 net_ads_keytab_create,
3146 N_("Create a fresh keytab"),
3147 N_("net ads keytab create\n"
3148 " Create a fresh keytab or update existing one.")
3152 net_ads_keytab_flush,
3154 N_("Remove all keytab entries"),
3155 N_("net ads keytab flush\n"
3156 " Remove all keytab entries")
3160 net_ads_keytab_list,
3162 N_("List a keytab"),
3163 N_("net ads keytab list\n"
3166 {NULL, NULL, 0, NULL, NULL}
3169 if (!USE_KERBEROS_KEYTAB) {
3170 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3171 "keytab method to use keytab functions.\n"));
3174 return net_run_function(c, argc, argv, "net ads keytab", func);
3177 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3181 if (c->display_usage) {
3183 "net ads kerberos renew\n"
3186 _("Renew TGT from existing credential cache"));
3190 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3192 d_printf(_("failed to renew kerberos ticket: %s\n"),
3193 error_message(ret));
3198 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3199 struct PAC_DATA_CTR **pac_data_ctr)
3203 const char *impersonate_princ_s = NULL;
3204 const char *local_service = NULL;
3207 for (i=0; i<argc; i++) {
3208 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3209 impersonate_princ_s = get_string_param(argv[i]);
3210 if (impersonate_princ_s == NULL) {
3214 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3215 local_service = get_string_param(argv[i]);
3216 if (local_service == NULL) {
3222 if (local_service == NULL) {
3223 local_service = talloc_asprintf(c, "%s$@%s",
3224 lp_netbios_name(), lp_realm());
3225 if (local_service == NULL) {
3230 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3232 status = kerberos_return_pac(c,
3241 2592000, /* one month */
3242 impersonate_princ_s,
3247 if (!NT_STATUS_IS_OK(status)) {
3248 d_printf(_("failed to query kerberos PAC: %s\n"),
3258 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3260 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3263 enum PAC_TYPE type = 0;
3265 if (c->display_usage) {
3267 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3270 _("Dump the Kerberos PAC"));
3274 for (i=0; i<argc; i++) {
3275 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3276 type = get_int_param(argv[i]);
3280 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3289 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3290 pac_data_ctr->pac_data);
3292 d_printf(_("The Pac: %s\n"), s);
3299 num_buffers = pac_data_ctr->pac_data->num_buffers;
3301 for (i=0; i<num_buffers; i++) {
3305 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3309 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3310 pac_data_ctr->pac_data->buffers[i].info);
3312 d_printf(_("The Pac: %s\n"), s);
3321 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3323 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3324 char *filename = NULL;
3328 if (c->display_usage) {
3330 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3333 _("Save the Kerberos PAC"));
3337 for (i=0; i<argc; i++) {
3338 if (strnequal(argv[i], "filename", strlen("filename"))) {
3339 filename = get_string_param(argv[i]);
3340 if (filename == NULL) {
3346 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3351 if (filename == NULL) {
3352 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3356 /* save the raw format */
3357 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3358 d_printf(_("failed to save PAC in %s\n"), filename);
3365 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3367 struct functable func[] = {
3370 net_ads_kerberos_pac_dump,
3372 N_("Dump Kerberos PAC"),
3373 N_("net ads kerberos pac dump\n"
3374 " Dump a Kerberos PAC to stdout")
3378 net_ads_kerberos_pac_save,
3380 N_("Save Kerberos PAC"),
3381 N_("net ads kerberos pac save\n"
3382 " Save a Kerberos PAC in a file")
3385 {NULL, NULL, 0, NULL, NULL}
3388 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3391 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3396 if (c->display_usage) {
3398 "net ads kerberos kinit\n"
3401 _("Get Ticket Granting Ticket (TGT) for the user"));
3405 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3407 ret = kerberos_kinit_password_ext(c->opt_user_name,
3415 2592000, /* one month */
3421 d_printf(_("failed to kinit password: %s\n"),
3427 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3429 struct functable func[] = {
3432 net_ads_kerberos_kinit,
3434 N_("Retrieve Ticket Granting Ticket (TGT)"),
3435 N_("net ads kerberos kinit\n"
3436 " Receive Ticket Granting Ticket (TGT)")
3440 net_ads_kerberos_renew,
3442 N_("Renew Ticket Granting Ticket from credential cache"),
3443 N_("net ads kerberos renew\n"
3444 " Renew Ticket Granting Ticket (TGT) from "
3449 net_ads_kerberos_pac,
3451 N_("Dump Kerberos PAC"),
3452 N_("net ads kerberos pac\n"
3453 " Dump Kerberos PAC")
3455 {NULL, NULL, 0, NULL, NULL}
3458 return net_run_function(c, argc, argv, "net ads kerberos", func);
3461 static int net_ads_setspn_list(struct net_context *c,
3465 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3466 ADS_STRUCT *ads = NULL;
3471 if (c->display_usage) {
3474 _("net ads setspn list <machinename>\n"));
3475 TALLOC_FREE(tmp_ctx);
3479 status = ads_startup(c, true, tmp_ctx, &ads);
3480 if (!ADS_ERR_OK(status)) {
3485 ok = ads_setspn_list(ads, argv[0]);
3487 ok = ads_setspn_list(ads, lp_netbios_name());
3492 TALLOC_FREE(tmp_ctx);
3496 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3498 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3499 ADS_STRUCT *ads = NULL;
3504 if (c->display_usage || argc < 1) {
3507 _("net ads setspn add <machinename> SPN\n"));
3508 TALLOC_FREE(tmp_ctx);
3512 status = ads_startup(c, true, tmp_ctx, &ads);
3513 if (!ADS_ERR_OK(status)) {
3518 ok = ads_setspn_add(ads, argv[0], argv[1]);
3520 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3525 TALLOC_FREE(tmp_ctx);
3529 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3531 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3532 ADS_STRUCT *ads = NULL;
3537 if (c->display_usage || argc < 1) {
3540 _("net ads setspn delete <machinename> SPN\n"));
3541 TALLOC_FREE(tmp_ctx);
3545 status = ads_startup(c, true, tmp_ctx, &ads);
3546 if (!ADS_ERR_OK(status)) {
3551 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3553 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3558 TALLOC_FREE(tmp_ctx);
3562 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3564 struct functable func[] = {
3567 net_ads_setspn_list,
3569 N_("List Service Principal Names (SPN)"),
3570 N_("net ads setspn list machine\n"
3571 " List Service Principal Names (SPN)")
3577 N_("Add Service Principal Names (SPN)"),
3578 N_("net ads setspn add machine spn\n"
3579 " Add Service Principal Names (SPN)")
3583 net_ads_setspn_delete,
3585 N_("Delete Service Principal Names (SPN)"),
3586 N_("net ads setspn delete machine spn\n"
3587 " Delete Service Principal Names (SPN)")
3589 {NULL, NULL, 0, NULL, NULL}
3592 return net_run_function(c, argc, argv, "net ads setspn", func);
3595 static int net_ads_enctype_lookup_account(struct net_context *c,
3597 const char *account,
3599 const char **enctype_str)
3602 const char *attrs[] = {
3603 "msDS-SupportedEncryptionTypes",
3610 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3612 if (filter == NULL) {
3616 status = ads_search(ads, res, filter, attrs);
3617 if (!ADS_ERR_OK(status)) {
3618 d_printf(_("no account found with filter: %s\n"), filter);
3622 count = ads_count_replies(ads, *res);
3627 d_printf(_("no account found with filter: %s\n"), filter);
3630 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3635 *enctype_str = ads_pull_string(ads, c, *res,
3636 "msDS-SupportedEncryptionTypes");
3637 if (*enctype_str == NULL) {
3638 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3648 static void net_ads_enctype_dump_enctypes(const char *username,
3649 const char *enctype_str)
3651 int enctypes = atoi(enctype_str);
3653 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3654 username, enctypes, enctypes);
3656 printf("[%s] 0x%08x DES-CBC-CRC\n",
3657 enctypes & ENC_CRC32 ? "X" : " ",
3659 printf("[%s] 0x%08x DES-CBC-MD5\n",
3660 enctypes & ENC_RSA_MD5 ? "X" : " ",
3662 printf("[%s] 0x%08x RC4-HMAC\n",
3663 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3665 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3666 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3667 ENC_HMAC_SHA1_96_AES128);
3668 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3669 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3670 ENC_HMAC_SHA1_96_AES256);
3671 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3672 enctypes & ENC_HMAC_SHA1_96_AES256_SK ? "X" : " ",
3673 ENC_HMAC_SHA1_96_AES256_SK);
3674 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3675 enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED ? "X" : " ",
3676 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED);
3679 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3681 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3683 ADS_STRUCT *ads = NULL;
3684 LDAPMessage *res = NULL;
3685 const char *str = NULL;
3688 if (c->display_usage || (argc < 1)) {
3690 "net ads enctypes list\n"
3693 _("List supported enctypes"));
3694 TALLOC_FREE(tmp_ctx);
3698 status = ads_startup(c, false, tmp_ctx, &ads);
3699 if (!ADS_ERR_OK(status)) {
3703 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3708 net_ads_enctype_dump_enctypes(argv[0], str);
3712 ads_msgfree(ads, res);
3713 TALLOC_FREE(tmp_ctx);
3717 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3719 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3722 ADS_STRUCT *ads = NULL;
3723 LDAPMessage *res = NULL;
3724 const char *etype_list_str = NULL;
3725 const char *dn = NULL;
3726 ADS_MODLIST mods = NULL;
3727 uint32_t etype_list;
3728 const char *str = NULL;
3730 if (c->display_usage || argc < 1) {
3732 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3735 _("Set supported enctypes"));
3736 TALLOC_FREE(tmp_ctx);
3740 status = ads_startup(c, false, tmp_ctx, &ads);
3741 if (!ADS_ERR_OK(status)) {
3745 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3750 dn = ads_get_dn(ads, tmp_ctx, res);
3756 etype_list |= ENC_RC4_HMAC_MD5;
3757 etype_list |= ENC_HMAC_SHA1_96_AES128;
3758 etype_list |= ENC_HMAC_SHA1_96_AES256;
3760 if (argv[1] != NULL) {
3761 sscanf(argv[1], "%i", &etype_list);
3764 etype_list_str = talloc_asprintf(tmp_ctx, "%d", etype_list);
3765 if (!etype_list_str) {
3769 mods = ads_init_mods(tmp_ctx);
3774 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes",
3776 if (!ADS_ERR_OK(status)) {
3780 status = ads_gen_mod(ads, dn, mods);
3781 if (!ADS_ERR_OK(status)) {
3782 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3783 ads_errstr(status));
3787 ads_msgfree(ads, res);
3790 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3795 net_ads_enctype_dump_enctypes(argv[0], str);
3799 ads_msgfree(ads, res);
3800 TALLOC_FREE(tmp_ctx);
3804 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3806 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3809 ADS_STRUCT *ads = NULL;
3810 LDAPMessage *res = NULL;
3811 const char *dn = NULL;
3812 ADS_MODLIST mods = NULL;
3814 if (c->display_usage || argc < 1) {
3816 "net ads enctypes delete <sAMAccountName>\n"
3819 _("Delete supported enctypes"));
3820 TALLOC_FREE(tmp_ctx);
3824 status = ads_startup(c, false, tmp_ctx, &ads);
3825 if (!ADS_ERR_OK(status)) {
3829 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3834 dn = ads_get_dn(ads, tmp_ctx, res);
3839 mods = ads_init_mods(tmp_ctx);
3844 status = ads_mod_str(tmp_ctx, &mods, "msDS-SupportedEncryptionTypes", NULL);
3845 if (!ADS_ERR_OK(status)) {
3849 status = ads_gen_mod(ads, dn, mods);
3850 if (!ADS_ERR_OK(status)) {
3851 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3852 ads_errstr(status));
3859 ads_msgfree(ads, res);
3860 TALLOC_FREE(tmp_ctx);
3864 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3866 struct functable func[] = {
3869 net_ads_enctypes_list,
3871 N_("List the supported encryption types"),
3872 N_("net ads enctypes list\n"
3873 " List the supported encryption types")
3877 net_ads_enctypes_set,
3879 N_("Set the supported encryption types"),
3880 N_("net ads enctypes set\n"
3881 " Set the supported encryption types")
3885 net_ads_enctypes_delete,
3887 N_("Delete the supported encryption types"),
3888 N_("net ads enctypes delete\n"
3889 " Delete the supported encryption types")
3892 {NULL, NULL, 0, NULL, NULL}
3895 return net_run_function(c, argc, argv, "net ads enctypes", func);
3899 int net_ads(struct net_context *c, int argc, const char **argv)
3901 struct functable func[] = {
3906 N_("Display details on remote ADS server"),
3908 " Display details on remote ADS server")
3914 N_("Join the local machine to ADS realm"),
3916 " Join the local machine to ADS realm")
3922 N_("Validate machine account"),
3923 N_("net ads testjoin\n"
3924 " Validate machine account")
3930 N_("Remove the local machine from ADS"),
3931 N_("net ads leave\n"
3932 " Remove the local machine from ADS")
3938 N_("Display machine account details"),
3939 N_("net ads status\n"
3940 " Display machine account details")
3946 N_("List/modify users"),
3948 " List/modify users")
3954 N_("List/modify groups"),
3955 N_("net ads group\n"
3956 " List/modify groups")
3962 N_("Issue dynamic DNS update"),
3964 " Issue dynamic DNS update")
3970 N_("Change user passwords"),
3971 N_("net ads password\n"
3972 " Change user passwords")
3976 net_ads_changetrustpw,
3978 N_("Change trust account password"),
3979 N_("net ads changetrustpw\n"
3980 " Change trust account password")
3986 N_("List/modify printer entries"),
3987 N_("net ads printer\n"
3988 " List/modify printer entries")
3994 N_("Issue LDAP search using filter"),
3995 N_("net ads search\n"
3996 " Issue LDAP search using filter")
4002 N_("Issue LDAP search by DN"),
4004 " Issue LDAP search by DN")
4010 N_("Issue LDAP search by SID"),
4012 " Issue LDAP search by SID")
4018 N_("Display workgroup name"),
4019 N_("net ads workgroup\n"
4020 " Display the workgroup name")
4026 N_("Perform CLDAP query on DC"),
4027 N_("net ads lookup\n"
4028 " Find the ADS DC using CLDAP lookups")
4034 N_("Manage local keytab file"),
4035 N_("net ads keytab\n"
4036 " Manage local keytab file")
4042 N_("Manage Service Principal Names (SPN)s"),
4043 N_("net ads spnset\n"
4044 " Manage Service Principal Names (SPN)s")
4050 N_("Manage group policy objects"),
4052 " Manage group policy objects")
4058 N_("Manage kerberos keytab"),
4059 N_("net ads kerberos\n"
4060 " Manage kerberos keytab")
4066 N_("List/modify supported encryption types"),
4067 N_("net ads enctypes\n"
4068 " List/modify enctypes")
4070 {NULL, NULL, 0, NULL, NULL}
4073 return net_run_function(c, argc, argv, "net ads", func);
4078 static int net_ads_noads(void)
4080 d_fprintf(stderr, _("ADS support not compiled in\n"));
4084 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
4086 return net_ads_noads();
4089 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
4091 return net_ads_noads();
4094 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
4096 return net_ads_noads();
4099 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
4101 return net_ads_noads();
4104 int net_ads_join(struct net_context *c, int argc, const char **argv)
4106 return net_ads_noads();
4109 int net_ads_user(struct net_context *c, int argc, const char **argv)
4111 return net_ads_noads();
4114 int net_ads_group(struct net_context *c, int argc, const char **argv)
4116 return net_ads_noads();
4119 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
4121 return net_ads_noads();
4124 /* this one shouldn't display a message */
4125 int net_ads_check(struct net_context *c)
4130 int net_ads_check_our_domain(struct net_context *c)
4135 int net_ads(struct net_context *c, int argc, const char **argv)
4137 return net_ads_noads();
4140 #endif /* HAVE_ADS */