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 "rpc_client/cli_pipe.h"
26 #include "librpc/gen_ndr/ndr_krb5pac.h"
27 #include "../librpc/gen_ndr/ndr_spoolss.h"
28 #include "nsswitch/libwbclient/wbclient.h"
30 #include "libads/cldap.h"
31 #include "../lib/addns/dnsquery.h"
32 #include "../libds/common/flags.h"
33 #include "librpc/gen_ndr/libnet_join.h"
34 #include "libnet/libnet_join.h"
38 #include "../libcli/security/security.h"
39 #include "libsmb/libsmb.h"
40 #include "lib/param/loadparm.h"
41 #include "utils/net_dns.h"
45 /* when we do not have sufficient input parameters to contact a remote domain
46 * we always fall back to our own realm - Guenther*/
48 static const char *assume_own_realm(struct net_context *c)
50 if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
58 do a cldap netlogon query
60 static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
62 char addr[INET6_ADDRSTRLEN];
63 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
65 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
67 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
68 d_fprintf(stderr, _("CLDAP query failed!\n"));
72 d_printf(_("Information for Domain Controller: %s\n\n"),
75 d_printf(_("Response Type: "));
76 switch (reply.command) {
77 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
78 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
80 case LOGON_SAM_LOGON_RESPONSE_EX:
81 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
84 d_printf("0x%x\n", reply.command);
88 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
92 "\tIs a GC of the forest: %s\n"
93 "\tIs an LDAP server: %s\n"
95 "\tIs running a KDC: %s\n"
96 "\tIs running time services: %s\n"
97 "\tIs the closest DC: %s\n"
99 "\tHas a hardware clock: %s\n"
100 "\tIs a non-domain NC serviced by LDAP server: %s\n"
101 "\tIs NT6 DC that has some secrets: %s\n"
102 "\tIs NT6 DC that has all secrets: %s\n"
103 "\tRuns Active Directory Web Services: %s\n"
104 "\tRuns on Windows 2012 or later: %s\n"),
105 (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
106 (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
107 (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
108 (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
109 (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
110 (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
111 (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
112 (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
113 (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
114 (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
115 (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
116 (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
117 (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
118 (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"));
121 printf(_("Forest:\t\t\t%s\n"), reply.forest);
122 printf(_("Domain:\t\t\t%s\n"), reply.dns_domain);
123 printf(_("Domain Controller:\t%s\n"), reply.pdc_dns_name);
125 printf(_("Pre-Win2k Domain:\t%s\n"), reply.domain_name);
126 printf(_("Pre-Win2k Hostname:\t%s\n"), reply.pdc_name);
128 if (*reply.user_name) printf(_("User name:\t%s\n"), reply.user_name);
130 printf(_("Server Site Name :\t\t%s\n"), reply.server_site);
131 printf(_("Client Site Name :\t\t%s\n"), reply.client_site);
133 d_printf(_("NT Version: %d\n"), reply.nt_version);
134 d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
135 d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
141 this implements the CLDAP based netlogon lookup requests
142 for finding the domain controller of a ADS domain
144 static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
149 if (c->display_usage) {
154 _("Find the ADS DC using CLDAP lookup.\n"));
158 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
159 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
164 if (!ads->config.realm) {
165 ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
166 ads->ldap.port = 389;
169 ret = net_ads_cldap_netlogon(c, ads);
176 static int net_ads_info(struct net_context *c, int argc, const char **argv)
179 char addr[INET6_ADDRSTRLEN];
182 if (c->display_usage) {
187 _("Display information about an Active Directory "
192 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
193 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
197 if (!ads || !ads->config.realm) {
198 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
203 /* Try to set the server's current time since we didn't do a full
204 TCP LDAP session initially */
206 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
207 d_fprintf( stderr, _("Failed to get server's current time!\n"));
210 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
212 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
214 d_printf(_("LDAP server: %s\n"), addr);
215 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
216 d_printf(_("Realm: %s\n"), ads->config.realm);
217 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
218 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
219 d_printf(_("Server time: %s\n"),
220 http_timestring(talloc_tos(), ads->config.current_time));
222 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
223 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
225 d_printf(_("Last machine account password change: %s\n"),
226 http_timestring(talloc_tos(), pass_time));
232 static void use_in_memory_ccache(void) {
233 /* Use in-memory credentials cache so we do not interfere with
234 * existing credentials */
235 setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
238 static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
239 uint32_t auth_flags, ADS_STRUCT **ads_ret)
241 ADS_STRUCT *ads = NULL;
243 bool need_password = false;
244 bool second_time = false;
246 const char *realm = NULL;
247 bool tried_closest_dc = false;
249 /* lp_realm() should be handled by a command line param,
250 However, the join requires that realm be set in smb.conf
251 and compares our realm with the remote server's so this is
252 ok until someone needs more flexibility */
257 if (only_own_domain) {
260 realm = assume_own_realm(c);
263 ads = ads_init(realm, c->opt_target_workgroup, c->opt_host);
265 if (!c->opt_user_name) {
266 c->opt_user_name = "administrator";
269 if (c->opt_user_specified) {
270 need_password = true;
274 if (!c->opt_password && need_password && !c->opt_machine_pass) {
275 c->opt_password = net_prompt_pass(c, c->opt_user_name);
276 if (!c->opt_password) {
278 return ADS_ERROR(LDAP_NO_MEMORY);
282 if (c->opt_password) {
283 use_in_memory_ccache();
284 SAFE_FREE(ads->auth.password);
285 ads->auth.password = smb_xstrdup(c->opt_password);
288 ads->auth.flags |= auth_flags;
289 SAFE_FREE(ads->auth.user_name);
290 ads->auth.user_name = smb_xstrdup(c->opt_user_name);
293 * If the username is of the form "name@realm",
294 * extract the realm and convert to upper case.
295 * This is only used to establish the connection.
297 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
299 SAFE_FREE(ads->auth.realm);
300 ads->auth.realm = smb_xstrdup(cp);
301 if (!strupper_m(ads->auth.realm)) {
303 return ADS_ERROR(LDAP_NO_MEMORY);
307 status = ads_connect(ads);
309 if (!ADS_ERR_OK(status)) {
311 if (NT_STATUS_EQUAL(ads_ntstatus(status),
312 NT_STATUS_NO_LOGON_SERVERS)) {
313 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
318 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
319 need_password = true;
328 /* when contacting our own domain, make sure we use the closest DC.
329 * This is done by reconnecting to ADS because only the first call to
330 * ads_connect will give us our own sitename */
332 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
334 tried_closest_dc = true; /* avoid loop */
336 if (!ads_closest_dc(ads)) {
338 namecache_delete(ads->server.realm, 0x1C);
339 namecache_delete(ads->server.workgroup, 0x1C);
352 ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
354 return ads_startup_int(c, only_own_domain, 0, ads);
357 ADS_STATUS ads_startup_nobind(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
359 return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads);
363 Check to see if connection can be made via ads.
364 ads_startup() stores the password in opt_password if it needs to so
365 that rpc or rap can use it without re-prompting.
367 static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
372 if ( (ads = ads_init( realm, workgroup, host )) == NULL ) {
376 ads->auth.flags |= ADS_AUTH_NO_BIND;
378 status = ads_connect(ads);
379 if ( !ADS_ERR_OK(status) ) {
387 int net_ads_check_our_domain(struct net_context *c)
389 return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
392 int net_ads_check(struct net_context *c)
394 return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host);
398 determine the netbios workgroup name for a domain
400 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
403 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
405 if (c->display_usage) {
407 "net ads workgroup\n"
410 _("Print the workgroup name"));
414 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
415 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
419 if (!ads->config.realm) {
420 ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
421 ads->ldap.port = 389;
424 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
425 d_fprintf(stderr, _("CLDAP query failed!\n"));
430 d_printf(_("Workgroup: %s\n"), reply.domain_name);
439 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
441 char **disp_fields = (char **) data_area;
443 if (!field) { /* must be end of record */
444 if (disp_fields[0]) {
445 if (!strchr_m(disp_fields[0], '$')) {
447 d_printf("%-21.21s %s\n",
448 disp_fields[0], disp_fields[1]);
450 d_printf("%s\n", disp_fields[0]);
453 SAFE_FREE(disp_fields[0]);
454 SAFE_FREE(disp_fields[1]);
457 if (!values) /* must be new field, indicate string field */
459 if (strcasecmp_m(field, "sAMAccountName") == 0) {
460 disp_fields[0] = SMB_STRDUP((char *) values[0]);
462 if (strcasecmp_m(field, "description") == 0)
463 disp_fields[1] = SMB_STRDUP((char *) values[0]);
467 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
469 return net_user_usage(c, argc, argv);
472 static int ads_user_add(struct net_context *c, int argc, const char **argv)
477 LDAPMessage *res=NULL;
481 if (argc < 1 || c->display_usage)
482 return net_ads_user_usage(c, argc, argv);
484 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
488 status = ads_find_user_acct(ads, &res, argv[0]);
490 if (!ADS_ERR_OK(status)) {
491 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
495 if (ads_count_replies(ads, res)) {
496 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
501 if (c->opt_container) {
502 ou_str = SMB_STRDUP(c->opt_container);
504 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
507 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
509 if (!ADS_ERR_OK(status)) {
510 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
515 /* if no password is to be set, we're done */
517 d_printf(_("User %s added\n"), argv[0]);
522 /* try setting the password */
523 if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) {
526 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
527 ads->auth.time_offset);
529 if (ADS_ERR_OK(status)) {
530 d_printf(_("User %s added\n"), argv[0]);
535 /* password didn't set, delete account */
536 d_fprintf(stderr, _("Could not add user %s. "
537 "Error setting password %s\n"),
538 argv[0], ads_errstr(status));
539 ads_msgfree(ads, res);
540 status=ads_find_user_acct(ads, &res, argv[0]);
541 if (ADS_ERR_OK(status)) {
542 userdn = ads_get_dn(ads, talloc_tos(), res);
543 ads_del_dn(ads, userdn);
549 ads_msgfree(ads, res);
555 static int ads_user_info(struct net_context *c, int argc, const char **argv)
557 ADS_STRUCT *ads = NULL;
559 LDAPMessage *res = NULL;
563 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
564 char *searchstring=NULL;
568 struct dom_sid primary_group_sid;
570 enum wbcSidType type;
572 if (argc < 1 || c->display_usage) {
573 return net_ads_user_usage(c, argc, argv);
576 frame = talloc_new(talloc_tos());
581 escaped_user = escape_ldap_string(frame, argv[0]);
584 _("ads_user_info: failed to escape user %s\n"),
589 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
594 if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) {
598 rc = ads_search(ads, &res, searchstring, attrs);
599 SAFE_FREE(searchstring);
601 if (!ADS_ERR_OK(rc)) {
602 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(rc));
607 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
608 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
613 rc = ads_domain_sid(ads, &primary_group_sid);
614 if (!ADS_ERR_OK(rc)) {
615 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(rc));
620 sid_append_rid(&primary_group_sid, group_rid);
622 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
623 NULL, /* don't look up domain */
626 if (!WBC_ERROR_IS_OK(wbc_status)) {
627 d_fprintf(stderr, "wbcLookupSid: %s\n",
628 wbcErrorString(wbc_status));
633 d_printf("%s\n", primary_group);
635 wbcFreeMemory(primary_group);
637 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
638 (LDAPMessage *)res, "memberOf");
643 for (i=0;grouplist[i];i++) {
644 groupname = ldap_explode_dn(grouplist[i], 1);
645 d_printf("%s\n", groupname[0]);
646 ldap_value_free(groupname);
648 ldap_value_free(grouplist);
652 if (res) ads_msgfree(ads, res);
653 if (ads) ads_destroy(&ads);
658 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
662 LDAPMessage *res = NULL;
666 return net_ads_user_usage(c, argc, argv);
669 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
673 rc = ads_find_user_acct(ads, &res, argv[0]);
674 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
675 d_printf(_("User %s does not exist.\n"), argv[0]);
676 ads_msgfree(ads, res);
680 userdn = ads_get_dn(ads, talloc_tos(), res);
681 ads_msgfree(ads, res);
682 rc = ads_del_dn(ads, userdn);
684 if (ADS_ERR_OK(rc)) {
685 d_printf(_("User %s deleted\n"), argv[0]);
689 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
695 int net_ads_user(struct net_context *c, int argc, const char **argv)
697 struct functable func[] = {
702 N_("Add an AD user"),
703 N_("net ads user add\n"
710 N_("Display information about an AD user"),
711 N_("net ads user info\n"
712 " Display information about an AD user")
718 N_("Delete an AD user"),
719 N_("net ads user delete\n"
720 " Delete an AD user")
722 {NULL, NULL, 0, NULL, NULL}
726 const char *shortattrs[] = {"sAMAccountName", NULL};
727 const char *longattrs[] = {"sAMAccountName", "description", NULL};
728 char *disp_fields[2] = {NULL, NULL};
731 if (c->display_usage) {
737 net_display_usage_from_functable(func);
741 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
745 if (c->opt_long_list_entries)
746 d_printf(_("\nUser name Comment"
747 "\n-----------------------------\n"));
749 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
751 "(objectCategory=user)",
752 c->opt_long_list_entries ? longattrs :
753 shortattrs, usergrp_display,
756 return ADS_ERR_OK(rc) ? 0 : -1;
759 return net_run_function(c, argc, argv, "net ads user", func);
762 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
764 return net_group_usage(c, argc, argv);
767 static int ads_group_add(struct net_context *c, int argc, const char **argv)
771 LDAPMessage *res=NULL;
775 if (argc < 1 || c->display_usage) {
776 return net_ads_group_usage(c, argc, argv);
779 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
783 status = ads_find_user_acct(ads, &res, argv[0]);
785 if (!ADS_ERR_OK(status)) {
786 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
790 if (ads_count_replies(ads, res)) {
791 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
795 if (c->opt_container) {
796 ou_str = SMB_STRDUP(c->opt_container);
798 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
801 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
803 if (ADS_ERR_OK(status)) {
804 d_printf(_("Group %s added\n"), argv[0]);
807 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
813 ads_msgfree(ads, res);
819 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
823 LDAPMessage *res = NULL;
826 if (argc < 1 || c->display_usage) {
827 return net_ads_group_usage(c, argc, argv);
830 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
834 rc = ads_find_user_acct(ads, &res, argv[0]);
835 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
836 d_printf(_("Group %s does not exist.\n"), argv[0]);
837 ads_msgfree(ads, res);
841 groupdn = ads_get_dn(ads, talloc_tos(), res);
842 ads_msgfree(ads, res);
843 rc = ads_del_dn(ads, groupdn);
844 TALLOC_FREE(groupdn);
845 if (ADS_ERR_OK(rc)) {
846 d_printf(_("Group %s deleted\n"), argv[0]);
850 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
856 int net_ads_group(struct net_context *c, int argc, const char **argv)
858 struct functable func[] = {
863 N_("Add an AD group"),
864 N_("net ads group add\n"
871 N_("Delete an AD group"),
872 N_("net ads group delete\n"
873 " Delete an AD group")
875 {NULL, NULL, 0, NULL, NULL}
879 const char *shortattrs[] = {"sAMAccountName", NULL};
880 const char *longattrs[] = {"sAMAccountName", "description", NULL};
881 char *disp_fields[2] = {NULL, NULL};
884 if (c->display_usage) {
889 _("List AD groups"));
890 net_display_usage_from_functable(func);
894 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
898 if (c->opt_long_list_entries)
899 d_printf(_("\nGroup name Comment"
900 "\n-----------------------------\n"));
901 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
903 "(objectCategory=group)",
904 c->opt_long_list_entries ? longattrs :
905 shortattrs, usergrp_display,
909 return ADS_ERR_OK(rc) ? 0 : -1;
911 return net_run_function(c, argc, argv, "net ads group", func);
914 static int net_ads_status(struct net_context *c, int argc, const char **argv)
920 if (c->display_usage) {
925 _("Display machine account details"));
929 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
933 rc = ads_find_machine_acct(ads, &res, lp_netbios_name());
934 if (!ADS_ERR_OK(rc)) {
935 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"), ads_errstr(rc));
940 if (ads_count_replies(ads, res) == 0) {
941 d_fprintf(stderr, _("No machine account for '%s' found\n"), lp_netbios_name());
951 /*******************************************************************
952 Leave an AD domain. Windows XP disables the machine account.
953 We'll try the same. The old code would do an LDAP delete.
954 That only worked using the machine creds because added the machine
955 with full control to the computer object's ACL.
956 *******************************************************************/
958 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
961 struct libnet_UnjoinCtx *r = NULL;
964 if (c->display_usage) {
969 _("Leave an AD domain"));
974 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
978 if (!(ctx = talloc_init("net_ads_leave"))) {
979 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
983 if (!c->opt_kerberos) {
984 use_in_memory_ccache();
988 d_fprintf(stderr, _("Could not initialise message context. "
989 "Try running as root\n"));
993 werr = libnet_init_UnjoinCtx(ctx, &r);
994 if (!W_ERROR_IS_OK(werr)) {
995 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1000 r->in.use_kerberos = c->opt_kerberos;
1001 r->in.dc_name = c->opt_host;
1002 r->in.domain_name = lp_realm();
1003 r->in.admin_account = c->opt_user_name;
1004 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1005 r->in.modify_config = lp_config_backend_is_registry();
1007 /* Try to delete it, but if that fails, disable it. The
1008 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1009 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1010 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1011 r->in.delete_machine_account = true;
1012 r->in.msg_ctx = c->msg_ctx;
1014 werr = libnet_Unjoin(ctx, r);
1015 if (!W_ERROR_IS_OK(werr)) {
1016 d_printf(_("Failed to leave domain: %s\n"),
1017 r->out.error_string ? r->out.error_string :
1018 get_friendly_werror_msg(werr));
1022 if (r->out.deleted_machine_account) {
1023 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1024 r->in.machine_name, r->out.dns_domain_name);
1028 /* We couldn't delete it - see if the disable succeeded. */
1029 if (r->out.disabled_machine_account) {
1030 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1031 r->in.machine_name, r->out.dns_domain_name);
1036 /* Based on what we requested, we shouldn't get here, but if
1037 we did, it means the secrets were removed, and therefore
1038 we have left the domain */
1039 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1040 r->in.machine_name, r->out.dns_domain_name);
1046 if (W_ERROR_IS_OK(werr)) {
1053 static NTSTATUS net_ads_join_ok(struct net_context *c)
1055 ADS_STRUCT *ads = NULL;
1058 struct sockaddr_storage dcip;
1060 if (!secrets_init()) {
1061 DEBUG(1,("Failed to initialise secrets database\n"));
1062 return NT_STATUS_ACCESS_DENIED;
1065 net_use_krb_machine_account(c);
1067 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1069 status = ads_startup(c, true, &ads);
1070 if (!ADS_ERR_OK(status)) {
1071 return ads_ntstatus(status);
1075 return NT_STATUS_OK;
1079 check that an existing join is OK
1081 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1084 use_in_memory_ccache();
1086 if (c->display_usage) {
1088 "net ads testjoin\n"
1091 _("Test if the existing join is ok"));
1095 /* Display success or failure */
1096 status = net_ads_join_ok(c);
1097 if (!NT_STATUS_IS_OK(status)) {
1098 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1099 get_friendly_nt_error_msg(status));
1103 printf(_("Join is OK\n"));
1107 /*******************************************************************
1108 Simple configu checks before beginning the join
1109 ********************************************************************/
1111 static WERROR check_ads_config( void )
1113 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1114 d_printf(_("Host is not configured as a member server.\n"));
1115 return WERR_INVALID_DOMAIN_ROLE;
1118 if (strlen(lp_netbios_name()) > 15) {
1119 d_printf(_("Our netbios name can be at most 15 chars long, "
1120 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1121 (unsigned int)strlen(lp_netbios_name()));
1122 return WERR_INVALID_COMPUTERNAME;
1125 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1126 d_fprintf(stderr, _("realm must be set in in %s for ADS "
1127 "join to succeed.\n"), get_dyn_CONFIGFILE());
1128 return WERR_INVALID_PARAM;
1134 /*******************************************************************
1135 Send a DNS update request
1136 *******************************************************************/
1138 #if defined(WITH_DNS_UPDATES)
1139 #include "../lib/addns/dns.h"
1141 static NTSTATUS net_update_dns_internal(struct net_context *c,
1142 TALLOC_CTX *ctx, ADS_STRUCT *ads,
1143 const char *machine_name,
1144 const struct sockaddr_storage *addrs,
1147 struct dns_rr_ns *nameservers = NULL;
1148 int ns_count = 0, i;
1149 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1152 const char *dnsdomain = NULL;
1153 char *root_domain = NULL;
1155 if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
1156 d_printf(_("No DNS domain configured for %s. "
1157 "Unable to perform DNS Update.\n"), machine_name);
1158 status = NT_STATUS_INVALID_PARAMETER;
1163 status = ads_dns_lookup_ns(ctx,
1167 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1168 /* Child domains often do not have NS records. Look
1169 for the NS record for the forest root domain
1170 (rootDomainNamingContext in therootDSE) */
1172 const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
1173 LDAPMessage *msg = NULL;
1175 ADS_STATUS ads_status;
1177 if ( !ads->ldap.ld ) {
1178 ads_status = ads_connect( ads );
1179 if ( !ADS_ERR_OK(ads_status) ) {
1180 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
1185 ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
1186 "(objectclass=*)", rootname_attrs, &msg);
1187 if (!ADS_ERR_OK(ads_status)) {
1191 root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
1193 ads_msgfree( ads, msg );
1197 root_domain = ads_build_domain( root_dn );
1200 ads_msgfree( ads, msg );
1202 /* try again for NS servers */
1204 status = ads_dns_lookup_ns(ctx,
1209 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1210 DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
1211 "realm\n", ads->config.realm));
1215 dnsdomain = root_domain;
1219 for (i=0; i < ns_count; i++) {
1221 uint32_t flags = DNS_UPDATE_SIGNED |
1222 DNS_UPDATE_UNSIGNED |
1223 DNS_UPDATE_UNSIGNED_SUFFICIENT |
1225 DNS_UPDATE_PROBE_SUFFICIENT;
1228 flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
1229 flags &= ~DNS_UPDATE_UNSIGNED_SUFFICIENT;
1232 status = NT_STATUS_UNSUCCESSFUL;
1234 /* Now perform the dns update - we'll try non-secure and if we fail,
1235 we'll follow it up with a secure update */
1237 fstrcpy( dns_server, nameservers[i].hostname );
1239 dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs, flags);
1240 if (ERR_DNS_IS_OK(dns_err)) {
1241 status = NT_STATUS_OK;
1245 if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
1246 ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
1247 ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
1248 DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
1249 dns_errstr(dns_err)));
1253 d_printf(_("DNS Update for %s failed: %s\n"),
1254 machine_name, dns_errstr(dns_err));
1255 status = NT_STATUS_UNSUCCESSFUL;
1261 SAFE_FREE( root_domain );
1266 static NTSTATUS net_update_dns_ext(struct net_context *c,
1267 TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
1268 const char *hostname,
1269 struct sockaddr_storage *iplist,
1272 struct sockaddr_storage *iplist_alloc = NULL;
1273 fstring machine_name;
1277 fstrcpy(machine_name, hostname);
1279 name_to_fqdn( machine_name, lp_netbios_name() );
1281 if (!strlower_m( machine_name )) {
1282 return NT_STATUS_INVALID_PARAMETER;
1285 if (num_addrs == 0 || iplist == NULL) {
1287 * Get our ip address
1288 * (not the 127.0.0.x address but a real ip address)
1290 num_addrs = get_my_ip_address(&iplist_alloc);
1291 if ( num_addrs <= 0 ) {
1292 DEBUG(4, ("net_update_dns_ext: Failed to find my "
1293 "non-loopback IP addresses!\n"));
1294 return NT_STATUS_INVALID_PARAMETER;
1296 iplist = iplist_alloc;
1299 status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
1302 SAFE_FREE(iplist_alloc);
1306 static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
1310 status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0);
1316 /*******************************************************************
1317 ********************************************************************/
1319 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1321 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1322 "Valid options:\n"));
1323 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1324 " The deault UPN is in the form host/netbiosname@REALM.\n"));
1325 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1326 " The OU string read from top to bottom without RDNs and delimited by a '/'.\n"
1327 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1328 " NB: A backslash '\\' is used as escape at multiple levels and may\n"
1329 " need to be doubled or even quadrupled. It is not used as a separator.\n"));
1330 d_printf(_(" machinepass=PASS Set the machine password to a specific value during the join.\n"
1331 " The deault password is random.\n"));
1332 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1333 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during the join.\n"
1334 " NB: osName and osVer must be specified together for either to take effect.\n"
1335 " Also, the operatingSystemService attribute is also set when along with\n"
1336 " the two other attributes.\n"));
1338 d_printf(_(" osServicePack=string Set the operatingSystemServicePack "
1339 "attribute during the join. Note: if not specified then by "
1340 "default the samba version string is used instead.\n"));
1345 static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
1347 #if defined(WITH_DNS_UPDATES)
1348 ADS_STRUCT *ads_dns = NULL;
1353 * In a clustered environment, don't do dynamic dns updates:
1354 * Registering the set of ip addresses that are assigned to
1355 * the interfaces of the node that performs the join does usually
1356 * not have the desired effect, since the local interfaces do not
1357 * carry the complete set of the cluster's public IP addresses.
1358 * And it can also contain internal addresses that should not
1359 * be visible to the outside at all.
1360 * In order to do dns updates in a clustererd setup, use
1361 * net ads dns register.
1363 if (lp_clustering()) {
1364 d_fprintf(stderr, _("Not doing automatic DNS update in a "
1365 "clustered setup.\n"));
1369 if (!r->out.domain_is_ad) {
1374 * We enter this block with user creds.
1375 * kinit with the machine password to do dns update.
1378 ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name);
1380 if (ads_dns == NULL) {
1381 d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
1385 use_in_memory_ccache();
1387 ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
1389 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1393 ads_dns->auth.password = secrets_fetch_machine_password(
1394 r->out.netbios_domain_name, NULL, NULL);
1395 if (ads_dns->auth.password == NULL) {
1396 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1400 ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
1401 if (ads_dns->auth.realm == NULL) {
1402 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1406 if (!strupper_m(ads_dns->auth.realm)) {
1407 d_fprintf(stderr, _("strupper_m %s failed\n"), ads_dns->auth.realm);
1411 ret = ads_kinit_password(ads_dns);
1414 _("DNS update failed: kinit failed: %s\n"),
1415 error_message(ret));
1419 status = net_update_dns(c, ctx, ads_dns, NULL);
1420 if (!NT_STATUS_IS_OK(status)) {
1421 d_fprintf( stderr, _("DNS update failed: %s\n"),
1426 ads_destroy(&ads_dns);
1433 int net_ads_join(struct net_context *c, int argc, const char **argv)
1435 TALLOC_CTX *ctx = NULL;
1436 struct libnet_JoinCtx *r = NULL;
1437 const char *domain = lp_realm();
1438 WERROR werr = WERR_SETUP_NOT_JOINED;
1439 bool createupn = false;
1440 const char *machineupn = NULL;
1441 const char *machine_password = NULL;
1442 const char *create_in_ou = NULL;
1444 const char *os_name = NULL;
1445 const char *os_version = NULL;
1446 const char *os_servicepack = NULL;
1447 bool modify_config = lp_config_backend_is_registry();
1448 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1450 if (c->display_usage)
1451 return net_ads_join_usage(c, argc, argv);
1453 if (!modify_config) {
1455 werr = check_ads_config();
1456 if (!W_ERROR_IS_OK(werr)) {
1457 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1462 if (!(ctx = talloc_init("net_ads_join"))) {
1463 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
1468 if (!c->opt_kerberos) {
1469 use_in_memory_ccache();
1472 werr = libnet_init_JoinCtx(ctx, &r);
1473 if (!W_ERROR_IS_OK(werr)) {
1477 /* process additional command line args */
1479 for ( i=0; i<argc; i++ ) {
1480 if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1482 machineupn = get_string_param(argv[i]);
1484 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1485 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1486 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1487 werr = WERR_INVALID_PARAM;
1491 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1492 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1493 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1494 werr = WERR_INVALID_PARAM;
1498 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1499 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1500 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1501 werr = WERR_INVALID_PARAM;
1505 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1506 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1507 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1508 werr = WERR_INVALID_PARAM;
1512 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1513 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1514 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1515 werr = WERR_INVALID_PARAM;
1521 if (strchr(domain, '.') == NULL) {
1522 domain_name_type = JoinDomNameTypeUnknown;
1524 domain_name_type = JoinDomNameTypeDNS;
1530 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1531 werr = WERR_INVALID_PARAM;
1536 d_fprintf(stderr, _("Could not initialise message context. "
1537 "Try running as root\n"));
1538 werr = WERR_ACCESS_DENIED;
1542 /* Do the domain join here */
1544 r->in.domain_name = domain;
1545 r->in.domain_name_type = domain_name_type;
1546 r->in.create_upn = createupn;
1547 r->in.upn = machineupn;
1548 r->in.account_ou = create_in_ou;
1549 r->in.os_name = os_name;
1550 r->in.os_version = os_version;
1551 r->in.os_servicepack = os_servicepack;
1552 r->in.dc_name = c->opt_host;
1553 r->in.admin_account = c->opt_user_name;
1554 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1555 r->in.machine_password = machine_password;
1557 r->in.use_kerberos = c->opt_kerberos;
1558 r->in.modify_config = modify_config;
1559 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1560 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1561 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1562 r->in.msg_ctx = c->msg_ctx;
1564 werr = libnet_Join(ctx, r);
1565 if (W_ERROR_EQUAL(werr, WERR_DCNOTFOUND) &&
1566 strequal(domain, lp_realm())) {
1567 r->in.domain_name = lp_workgroup();
1568 r->in.domain_name_type = JoinDomNameTypeNBT;
1569 werr = libnet_Join(ctx, r);
1571 if (!W_ERROR_IS_OK(werr)) {
1575 /* Check the short name of the domain */
1577 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1578 d_printf(_("The workgroup in %s does not match the short\n"
1579 "domain name obtained from the server.\n"
1580 "Using the name [%s] from the server.\n"
1581 "You should set \"workgroup = %s\" in %s.\n"),
1582 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1583 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1586 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1588 if (r->out.dns_domain_name) {
1589 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1590 r->out.dns_domain_name);
1592 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1593 r->out.netbios_domain_name);
1597 * We try doing the dns update (if it was compiled in
1598 * and if it was not disabled on the command line).
1599 * If the dns update fails, we still consider the join
1600 * operation as succeeded if we came this far.
1602 if (!c->opt_no_dns_updates) {
1603 _net_ads_join_dns_updates(c, ctx, r);
1612 /* issue an overall failure message at the end. */
1613 d_printf(_("Failed to join domain: %s\n"),
1614 r && r->out.error_string ? r->out.error_string :
1615 get_friendly_werror_msg(werr));
1621 /*******************************************************************
1622 ********************************************************************/
1624 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1626 #if defined(WITH_DNS_UPDATES)
1631 const char *hostname = NULL;
1632 const char **addrs_list = NULL;
1633 struct sockaddr_storage *addrs = NULL;
1638 talloc_enable_leak_report();
1641 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1642 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1643 "detection of addresses in a clustered "
1645 c->display_usage = true;
1648 if (c->display_usage) {
1650 "net ads dns register [hostname [IP [IP...]]]\n"
1653 _("Register hostname with DNS\n"));
1657 if (!(ctx = talloc_init("net_ads_dns"))) {
1658 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1667 num_addrs = argc - 1;
1668 addrs_list = &argv[1];
1669 } else if (lp_clustering()) {
1670 addrs_list = lp_cluster_addresses();
1671 num_addrs = str_list_length(addrs_list);
1674 if (num_addrs > 0) {
1675 addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
1676 if (addrs == NULL) {
1677 d_fprintf(stderr, _("Error allocating memory!\n"));
1683 for (count = 0; count < num_addrs; count++) {
1684 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1685 d_fprintf(stderr, "%s '%s'.\n",
1686 _("Cannot interpret address"),
1693 status = ads_startup(c, true, &ads);
1694 if ( !ADS_ERR_OK(status) ) {
1695 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1700 ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs);
1701 if (!NT_STATUS_IS_OK(ntstatus)) {
1702 d_fprintf( stderr, _("DNS update failed!\n") );
1703 ads_destroy( &ads );
1708 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1716 _("DNS update support not enabled at compile time!\n"));
1721 static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv)
1723 #if defined(WITH_DNS_UPDATES)
1727 talloc_enable_leak_report();
1730 if (argc != 2 || c->display_usage) {
1735 _("net ads dns gethostbyname <server> <name>\n"),
1736 _(" Look up hostname from the AD\n"
1737 " server\tName server to use\n"
1738 " name\tName to look up\n"));
1742 err = do_gethostbyname(argv[0], argv[1]);
1744 d_printf(_("do_gethostbyname returned %s (%d)\n"),
1745 dns_errstr(err), ERROR_DNS_V(err));
1750 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
1752 struct functable func[] = {
1755 net_ads_dns_register,
1757 N_("Add host dns entry to AD"),
1758 N_("net ads dns register\n"
1759 " Add host dns entry to AD")
1763 net_ads_dns_gethostbyname,
1766 N_("net ads dns gethostbyname\n"
1769 {NULL, NULL, 0, NULL, NULL}
1772 return net_run_function(c, argc, argv, "net ads dns", func);
1775 /*******************************************************************
1776 ********************************************************************/
1778 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
1781 "\nnet ads printer search <printer>"
1782 "\n\tsearch for a printer in the directory\n"
1783 "\nnet ads printer info <printer> <server>"
1784 "\n\tlookup info in directory for printer on server"
1785 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
1786 "\nnet ads printer publish <printername>"
1787 "\n\tpublish printer in directory"
1788 "\n\t(note: printer name is required)\n"
1789 "\nnet ads printer remove <printername>"
1790 "\n\tremove printer from directory"
1791 "\n\t(note: printer name is required)\n"));
1795 /*******************************************************************
1796 ********************************************************************/
1798 static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
1802 LDAPMessage *res = NULL;
1804 if (c->display_usage) {
1806 "net ads printer search\n"
1809 _("List printers in the AD"));
1813 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1817 rc = ads_find_printers(ads, &res);
1819 if (!ADS_ERR_OK(rc)) {
1820 d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
1821 ads_msgfree(ads, res);
1826 if (ads_count_replies(ads, res) == 0) {
1827 d_fprintf(stderr, _("No results found\n"));
1828 ads_msgfree(ads, res);
1834 ads_msgfree(ads, res);
1839 static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
1843 const char *servername, *printername;
1844 LDAPMessage *res = NULL;
1846 if (c->display_usage) {
1849 _("net ads printer info [printername [servername]]\n"
1850 " Display printer info from AD\n"
1851 " printername\tPrinter name or wildcard\n"
1852 " servername\tName of the print server\n"));
1856 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1861 printername = argv[0];
1867 servername = argv[1];
1869 servername = lp_netbios_name();
1872 rc = ads_find_printer_on_server(ads, &res, printername, servername);
1874 if (!ADS_ERR_OK(rc)) {
1875 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
1876 servername, ads_errstr(rc));
1877 ads_msgfree(ads, res);
1882 if (ads_count_replies(ads, res) == 0) {
1883 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
1884 ads_msgfree(ads, res);
1890 ads_msgfree(ads, res);
1896 static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
1900 const char *servername, *printername;
1901 struct cli_state *cli = NULL;
1902 struct rpc_pipe_client *pipe_hnd = NULL;
1903 struct sockaddr_storage server_ss;
1905 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
1906 ADS_MODLIST mods = ads_init_mods(mem_ctx);
1907 char *prt_dn, *srv_dn, **srv_cn;
1908 char *srv_cn_escaped = NULL, *printername_escaped = NULL;
1909 LDAPMessage *res = NULL;
1911 if (argc < 1 || c->display_usage) {
1914 _("net ads printer publish <printername> [servername]\n"
1915 " Publish printer in AD\n"
1916 " printername\tName of the printer\n"
1917 " servername\tName of the print server\n"));
1918 talloc_destroy(mem_ctx);
1922 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1923 talloc_destroy(mem_ctx);
1927 printername = argv[0];
1930 servername = argv[1];
1932 servername = lp_netbios_name();
1935 /* Get printer data from SPOOLSS */
1937 resolve_name(servername, &server_ss, 0x20, false);
1939 nt_status = cli_full_connection(&cli, lp_netbios_name(), servername,
1942 c->opt_user_name, c->opt_workgroup,
1943 c->opt_password ? c->opt_password : "",
1944 CLI_FULL_CONNECTION_USE_KERBEROS,
1945 SMB_SIGNING_DEFAULT);
1947 if (NT_STATUS_IS_ERR(nt_status)) {
1948 d_fprintf(stderr, _("Unable to open a connection to %s to "
1949 "obtain data for %s\n"),
1950 servername, printername);
1952 talloc_destroy(mem_ctx);
1956 /* Publish on AD server */
1958 ads_find_machine_acct(ads, &res, servername);
1960 if (ads_count_replies(ads, res) == 0) {
1961 d_fprintf(stderr, _("Could not find machine account for server "
1965 talloc_destroy(mem_ctx);
1969 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1970 srv_cn = ldap_explode_dn(srv_dn, 1);
1972 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
1973 printername_escaped = escape_rdn_val_string_alloc(printername);
1974 if (!srv_cn_escaped || !printername_escaped) {
1975 SAFE_FREE(srv_cn_escaped);
1976 SAFE_FREE(printername_escaped);
1977 d_fprintf(stderr, _("Internal error, out of memory!"));
1979 talloc_destroy(mem_ctx);
1983 if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
1984 SAFE_FREE(srv_cn_escaped);
1985 SAFE_FREE(printername_escaped);
1986 d_fprintf(stderr, _("Internal error, out of memory!"));
1988 talloc_destroy(mem_ctx);
1992 SAFE_FREE(srv_cn_escaped);
1993 SAFE_FREE(printername_escaped);
1995 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
1996 if (!NT_STATUS_IS_OK(nt_status)) {
1997 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2001 talloc_destroy(mem_ctx);
2005 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
2009 talloc_destroy(mem_ctx);
2013 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
2014 if (!ADS_ERR_OK(rc)) {
2015 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
2018 talloc_destroy(mem_ctx);
2022 d_printf("published printer\n");
2025 talloc_destroy(mem_ctx);
2030 static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
2034 const char *servername;
2036 LDAPMessage *res = NULL;
2038 if (argc < 1 || c->display_usage) {
2041 _("net ads printer remove <printername> [servername]\n"
2042 " Remove a printer from the AD\n"
2043 " printername\tName of the printer\n"
2044 " servername\tName of the print server\n"));
2048 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2053 servername = argv[1];
2055 servername = lp_netbios_name();
2058 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
2060 if (!ADS_ERR_OK(rc)) {
2061 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
2062 ads_msgfree(ads, res);
2067 if (ads_count_replies(ads, res) == 0) {
2068 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2069 ads_msgfree(ads, res);
2074 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2075 ads_msgfree(ads, res);
2076 rc = ads_del_dn(ads, prt_dn);
2077 TALLOC_FREE(prt_dn);
2079 if (!ADS_ERR_OK(rc)) {
2080 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
2089 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2091 struct functable func[] = {
2094 net_ads_printer_search,
2096 N_("Search for a printer"),
2097 N_("net ads printer search\n"
2098 " Search for a printer")
2102 net_ads_printer_info,
2104 N_("Display printer information"),
2105 N_("net ads printer info\n"
2106 " Display printer information")
2110 net_ads_printer_publish,
2112 N_("Publish a printer"),
2113 N_("net ads printer publish\n"
2114 " Publish a printer")
2118 net_ads_printer_remove,
2120 N_("Delete a printer"),
2121 N_("net ads printer remove\n"
2122 " Delete a printer")
2124 {NULL, NULL, 0, NULL, NULL}
2127 return net_run_function(c, argc, argv, "net ads printer", func);
2131 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2134 const char *auth_principal = c->opt_user_name;
2135 const char *auth_password = c->opt_password;
2136 const char *realm = NULL;
2137 const char *new_password = NULL;
2140 char pwd[256] = {0};
2143 if (c->display_usage) {
2146 _("net ads password <username>\n"
2147 " Change password for user\n"
2148 " username\tName of user to change password for\n"));
2152 if (c->opt_user_name == NULL || c->opt_password == NULL) {
2153 d_fprintf(stderr, _("You must supply an administrator "
2154 "username/password\n"));
2159 d_fprintf(stderr, _("ERROR: You must say which username to "
2160 "change password for\n"));
2165 if (!strchr_m(user, '@')) {
2166 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
2172 use_in_memory_ccache();
2173 chr = strchr_m(auth_principal, '@');
2180 /* use the realm so we can eventually change passwords for users
2181 in realms other than default */
2182 if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) {
2186 /* we don't actually need a full connect, but it's the easy way to
2187 fill in the KDC's addresss */
2190 if (!ads->config.realm) {
2191 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2197 new_password = (const char *)argv[1];
2201 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2204 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2212 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2213 auth_password, user, new_password, ads->auth.time_offset);
2214 memset(pwd, '\0', sizeof(pwd));
2215 if (!ADS_ERR_OK(ret)) {
2216 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2221 d_printf(_("Password change for %s completed.\n"), user);
2227 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2230 char *host_principal;
2234 if (c->display_usage) {
2236 "net ads changetrustpw\n"
2239 _("Change the machine account's trust password"));
2243 if (!secrets_init()) {
2244 DEBUG(1,("Failed to initialise secrets database\n"));
2248 net_use_krb_machine_account(c);
2250 use_in_memory_ccache();
2252 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2256 fstrcpy(my_name, lp_netbios_name());
2257 if (!strlower_m(my_name)) {
2262 if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2266 d_printf(_("Changing password for principal: %s\n"), host_principal);
2268 ret = ads_change_trust_account_password(ads, host_principal);
2270 if (!ADS_ERR_OK(ret)) {
2271 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2273 SAFE_FREE(host_principal);
2277 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2279 if (USE_SYSTEM_KEYTAB) {
2280 d_printf(_("Attempting to update system keytab with new password.\n"));
2281 if (ads_keytab_create_default(ads)) {
2282 d_printf(_("Failed to update system keytab.\n"));
2287 SAFE_FREE(host_principal);
2293 help for net ads search
2295 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2298 "\nnet ads search <expression> <attributes...>\n"
2299 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2300 "The expression is a standard LDAP search expression, and the\n"
2301 "attributes are a list of LDAP fields to show in the results.\n\n"
2302 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2304 net_common_flags_usage(c, argc, argv);
2310 general ADS search function. Useful in diagnosing problems in ADS
2312 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2316 const char *ldap_exp;
2318 LDAPMessage *res = NULL;
2320 if (argc < 1 || c->display_usage) {
2321 return net_ads_search_usage(c, argc, argv);
2324 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2331 rc = ads_do_search_retry(ads, ads->config.bind_path,
2333 ldap_exp, attrs, &res);
2334 if (!ADS_ERR_OK(rc)) {
2335 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2340 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2342 /* dump the results */
2345 ads_msgfree(ads, res);
2353 help for net ads search
2355 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2358 "\nnet ads dn <dn> <attributes...>\n"
2359 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2360 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2361 "to show in the results\n\n"
2362 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2363 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2365 net_common_flags_usage(c, argc, argv);
2371 general ADS search function. Useful in diagnosing problems in ADS
2373 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2379 LDAPMessage *res = NULL;
2381 if (argc < 1 || c->display_usage) {
2382 return net_ads_dn_usage(c, argc, argv);
2385 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2392 rc = ads_do_search_all(ads, dn,
2394 "(objectclass=*)", attrs, &res);
2395 if (!ADS_ERR_OK(rc)) {
2396 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2401 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2403 /* dump the results */
2406 ads_msgfree(ads, res);
2413 help for net ads sid search
2415 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2418 "\nnet ads sid <sid> <attributes...>\n"
2419 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2420 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2421 "to show in the results\n\n"
2422 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2424 net_common_flags_usage(c, argc, argv);
2430 general ADS search function. Useful in diagnosing problems in ADS
2432 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2436 const char *sid_string;
2438 LDAPMessage *res = NULL;
2441 if (argc < 1 || c->display_usage) {
2442 return net_ads_sid_usage(c, argc, argv);
2445 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2449 sid_string = argv[0];
2452 if (!string_to_sid(&sid, sid_string)) {
2453 d_fprintf(stderr, _("could not convert sid\n"));
2458 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2459 if (!ADS_ERR_OK(rc)) {
2460 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2465 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2467 /* dump the results */
2470 ads_msgfree(ads, res);
2476 static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2481 if (c->display_usage) {
2483 "net ads keytab flush\n"
2486 _("Delete the whole keytab"));
2490 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2493 ret = ads_keytab_flush(ads);
2498 static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv)
2504 if (c->display_usage) {
2507 _("net ads keytab add <principal> [principal ...]\n"
2508 " Add principals to local keytab\n"
2509 " principal\tKerberos principal to add to "
2514 d_printf(_("Processing principals to add...\n"));
2515 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2518 for (i = 0; i < argc; i++) {
2519 ret |= ads_keytab_add_entry(ads, argv[i]);
2525 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2530 if (c->display_usage) {
2532 "net ads keytab create\n"
2535 _("Create new default keytab"));
2539 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2542 ret = ads_keytab_create_default(ads);
2547 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2549 const char *keytab = NULL;
2551 if (c->display_usage) {
2554 _("net ads keytab list [keytab]\n"
2555 " List a local keytab\n"
2556 " keytab\tKeytab to list\n"));
2564 return ads_keytab_list(keytab);
2568 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2570 struct functable func[] = {
2575 N_("Add a service principal"),
2576 N_("net ads keytab add\n"
2577 " Add a service principal")
2581 net_ads_keytab_create,
2583 N_("Create a fresh keytab"),
2584 N_("net ads keytab create\n"
2585 " Create a fresh keytab")
2589 net_ads_keytab_flush,
2591 N_("Remove all keytab entries"),
2592 N_("net ads keytab flush\n"
2593 " Remove all keytab entries")
2597 net_ads_keytab_list,
2599 N_("List a keytab"),
2600 N_("net ads keytab list\n"
2603 {NULL, NULL, 0, NULL, NULL}
2606 if (!USE_KERBEROS_KEYTAB) {
2607 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
2608 "keytab method to use keytab functions.\n"));
2611 return net_run_function(c, argc, argv, "net ads keytab", func);
2614 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
2618 if (c->display_usage) {
2620 "net ads kerberos renew\n"
2623 _("Renew TGT from existing credential cache"));
2627 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
2629 d_printf(_("failed to renew kerberos ticket: %s\n"),
2630 error_message(ret));
2635 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
2636 struct PAC_DATA_CTR **pac_data_ctr)
2640 const char *impersonate_princ_s = NULL;
2641 const char *local_service = NULL;
2644 for (i=0; i<argc; i++) {
2645 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
2646 impersonate_princ_s = get_string_param(argv[i]);
2647 if (impersonate_princ_s == NULL) {
2651 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
2652 local_service = get_string_param(argv[i]);
2653 if (local_service == NULL) {
2659 if (local_service == NULL) {
2660 local_service = talloc_asprintf(c, "%s$@%s",
2661 lp_netbios_name(), lp_realm());
2662 if (local_service == NULL) {
2667 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2669 status = kerberos_return_pac(c,
2678 2592000, /* one month */
2679 impersonate_princ_s,
2682 if (!NT_STATUS_IS_OK(status)) {
2683 d_printf(_("failed to query kerberos PAC: %s\n"),
2693 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
2695 struct PAC_DATA_CTR *pac_data_ctr = NULL;
2698 enum PAC_TYPE type = 0;
2700 if (c->display_usage) {
2702 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
2705 _("Dump the Kerberos PAC"));
2709 for (i=0; i<argc; i++) {
2710 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
2711 type = get_int_param(argv[i]);
2715 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2724 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
2725 pac_data_ctr->pac_data);
2727 d_printf(_("The Pac: %s\n"), s);
2734 for (i=0; i < pac_data_ctr->pac_data->num_buffers; i++) {
2738 if (pac_data_ctr->pac_data->buffers[i].type != type) {
2742 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
2743 pac_data_ctr->pac_data->buffers[i].info);
2745 d_printf(_("The Pac: %s\n"), s);
2754 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
2756 struct PAC_DATA_CTR *pac_data_ctr = NULL;
2757 char *filename = NULL;
2761 if (c->display_usage) {
2763 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
2766 _("Save the Kerberos PAC"));
2770 for (i=0; i<argc; i++) {
2771 if (strnequal(argv[i], "filename", strlen("filename"))) {
2772 filename = get_string_param(argv[i]);
2773 if (filename == NULL) {
2779 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2784 if (filename == NULL) {
2785 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
2789 /* save the raw format */
2790 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
2791 d_printf(_("failed to save PAC in %s\n"), filename);
2798 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
2800 struct functable func[] = {
2803 net_ads_kerberos_pac_dump,
2805 N_("Dump Kerberos PAC"),
2806 N_("net ads kerberos pac dump\n"
2807 " Dump a Kerberos PAC to stdout")
2811 net_ads_kerberos_pac_save,
2813 N_("Save Kerberos PAC"),
2814 N_("net ads kerberos pac save\n"
2815 " Save a Kerberos PAC in a file")
2818 {NULL, NULL, 0, NULL, NULL}
2821 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
2824 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
2826 TALLOC_CTX *mem_ctx = NULL;
2830 if (c->display_usage) {
2832 "net ads kerberos kinit\n"
2835 _("Get Ticket Granting Ticket (TGT) for the user"));
2839 mem_ctx = talloc_init("net_ads_kerberos_kinit");
2844 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2846 ret = kerberos_kinit_password_ext(c->opt_user_name,
2854 2592000, /* one month */
2857 d_printf(_("failed to kinit password: %s\n"),
2864 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2866 struct functable func[] = {
2869 net_ads_kerberos_kinit,
2871 N_("Retrieve Ticket Granting Ticket (TGT)"),
2872 N_("net ads kerberos kinit\n"
2873 " Receive Ticket Granting Ticket (TGT)")
2877 net_ads_kerberos_renew,
2879 N_("Renew Ticket Granting Ticket from credential cache"),
2880 N_("net ads kerberos renew\n"
2881 " Renew Ticket Granting Ticket (TGT) from "
2886 net_ads_kerberos_pac,
2888 N_("Dump Kerberos PAC"),
2889 N_("net ads kerberos pac\n"
2890 " Dump Kerberos PAC")
2892 {NULL, NULL, 0, NULL, NULL}
2895 return net_run_function(c, argc, argv, "net ads kerberos", func);
2898 static int net_ads_enctype_lookup_account(struct net_context *c,
2900 const char *account,
2902 const char **enctype_str)
2905 const char *attrs[] = {
2906 "msDS-SupportedEncryptionTypes",
2913 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
2915 if (filter == NULL) {
2919 status = ads_search(ads, res, filter, attrs);
2920 if (!ADS_ERR_OK(status)) {
2921 d_printf(_("no account found with filter: %s\n"), filter);
2925 count = ads_count_replies(ads, *res);
2930 d_printf(_("no account found with filter: %s\n"), filter);
2933 d_printf(_("multiple accounts found with filter: %s\n"), filter);
2938 *enctype_str = ads_pull_string(ads, c, *res,
2939 "msDS-SupportedEncryptionTypes");
2940 if (*enctype_str == NULL) {
2941 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
2951 static void net_ads_enctype_dump_enctypes(const char *username,
2952 const char *enctype_str)
2954 int enctypes = atoi(enctype_str);
2956 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
2957 username, enctypes, enctypes);
2959 printf("[%s] 0x%08x DES-CBC-CRC\n",
2960 enctypes & ENC_CRC32 ? "X" : " ",
2962 printf("[%s] 0x%08x DES-CBC-MD5\n",
2963 enctypes & ENC_RSA_MD5 ? "X" : " ",
2965 printf("[%s] 0x%08x RC4-HMAC\n",
2966 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
2968 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
2969 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
2970 ENC_HMAC_SHA1_96_AES128);
2971 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
2972 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
2973 ENC_HMAC_SHA1_96_AES256);
2976 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
2980 ADS_STRUCT *ads = NULL;
2981 LDAPMessage *res = NULL;
2982 const char *str = NULL;
2984 if (c->display_usage || (argc < 1)) {
2986 "net ads enctypes list\n"
2989 _("List supported enctypes"));
2993 status = ads_startup(c, false, &ads);
2994 if (!ADS_ERR_OK(status)) {
2995 printf("startup failed\n");
2999 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3004 net_ads_enctype_dump_enctypes(argv[0], str);
3008 ads_msgfree(ads, res);
3014 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3019 LDAPMessage *res = NULL;
3020 const char *etype_list_str;
3023 uint32_t etype_list;
3026 if (c->display_usage || argc < 1) {
3028 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3031 _("Set supported enctypes"));
3035 status = ads_startup(c, false, &ads);
3036 if (!ADS_ERR_OK(status)) {
3037 printf("startup failed\n");
3041 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3046 dn = ads_get_dn(ads, c, res);
3051 etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
3052 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
3053 etype_list |= ENC_HMAC_SHA1_96_AES128;
3055 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
3056 etype_list |= ENC_HMAC_SHA1_96_AES256;
3059 if (argv[1] != NULL) {
3060 sscanf(argv[1], "%i", &etype_list);
3063 etype_list_str = talloc_asprintf(c, "%d", etype_list);
3064 if (!etype_list_str) {
3068 mods = ads_init_mods(c);
3073 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
3075 if (!ADS_ERR_OK(status)) {
3079 status = ads_gen_mod(ads, dn, mods);
3080 if (!ADS_ERR_OK(status)) {
3081 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3082 ads_errstr(status));
3086 ads_msgfree(ads, res);
3088 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3093 net_ads_enctype_dump_enctypes(argv[0], str);
3097 ads_msgfree(ads, res);
3103 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3108 LDAPMessage *res = NULL;
3112 if (c->display_usage || argc < 1) {
3114 "net ads enctypes delete <sAMAccountName>\n"
3117 _("Delete supported enctypes"));
3121 status = ads_startup(c, false, &ads);
3122 if (!ADS_ERR_OK(status)) {
3123 printf("startup failed\n");
3127 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3132 dn = ads_get_dn(ads, c, res);
3137 mods = ads_init_mods(c);
3142 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
3143 if (!ADS_ERR_OK(status)) {
3147 status = ads_gen_mod(ads, dn, mods);
3148 if (!ADS_ERR_OK(status)) {
3149 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3150 ads_errstr(status));
3157 ads_msgfree(ads, res);
3162 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3164 struct functable func[] = {
3167 net_ads_enctypes_list,
3169 N_("List the supported encryption types"),
3170 N_("net ads enctypes list\n"
3171 " List the supported encryption types")
3175 net_ads_enctypes_set,
3177 N_("Set the supported encryption types"),
3178 N_("net ads enctypes set\n"
3179 " Set the supported encryption types")
3183 net_ads_enctypes_delete,
3185 N_("Delete the supported encryption types"),
3186 N_("net ads enctypes delete\n"
3187 " Delete the supported encryption types")
3190 {NULL, NULL, 0, NULL, NULL}
3193 return net_run_function(c, argc, argv, "net ads enctypes", func);
3197 int net_ads(struct net_context *c, int argc, const char **argv)
3199 struct functable func[] = {
3204 N_("Display details on remote ADS server"),
3206 " Display details on remote ADS server")
3212 N_("Join the local machine to ADS realm"),
3214 " Join the local machine to ADS realm")
3220 N_("Validate machine account"),
3221 N_("net ads testjoin\n"
3222 " Validate machine account")
3228 N_("Remove the local machine from ADS"),
3229 N_("net ads leave\n"
3230 " Remove the local machine from ADS")
3236 N_("Display machine account details"),
3237 N_("net ads status\n"
3238 " Display machine account details")
3244 N_("List/modify users"),
3246 " List/modify users")
3252 N_("List/modify groups"),
3253 N_("net ads group\n"
3254 " List/modify groups")
3260 N_("Issue dynamic DNS update"),
3262 " Issue dynamic DNS update")
3268 N_("Change user passwords"),
3269 N_("net ads password\n"
3270 " Change user passwords")
3274 net_ads_changetrustpw,
3276 N_("Change trust account password"),
3277 N_("net ads changetrustpw\n"
3278 " Change trust account password")
3284 N_("List/modify printer entries"),
3285 N_("net ads printer\n"
3286 " List/modify printer entries")
3292 N_("Issue LDAP search using filter"),
3293 N_("net ads search\n"
3294 " Issue LDAP search using filter")
3300 N_("Issue LDAP search by DN"),
3302 " Issue LDAP search by DN")
3308 N_("Issue LDAP search by SID"),
3310 " Issue LDAP search by SID")
3316 N_("Display workgroup name"),
3317 N_("net ads workgroup\n"
3318 " Display the workgroup name")
3324 N_("Perfom CLDAP query on DC"),
3325 N_("net ads lookup\n"
3326 " Find the ADS DC using CLDAP lookups")
3332 N_("Manage local keytab file"),
3333 N_("net ads keytab\n"
3334 " Manage local keytab file")
3340 N_("Manage group policy objects"),
3342 " Manage group policy objects")
3348 N_("Manage kerberos keytab"),
3349 N_("net ads kerberos\n"
3350 " Manage kerberos keytab")
3356 N_("List/modify supported encryption types"),
3357 N_("net ads enctypes\n"
3358 " List/modify enctypes")
3360 {NULL, NULL, 0, NULL, NULL}
3363 return net_run_function(c, argc, argv, "net ads", func);
3368 static int net_ads_noads(void)
3370 d_fprintf(stderr, _("ADS support not compiled in\n"));
3374 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3376 return net_ads_noads();
3379 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3381 return net_ads_noads();
3384 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
3386 return net_ads_noads();
3389 int net_ads_join(struct net_context *c, int argc, const char **argv)
3391 return net_ads_noads();
3394 int net_ads_user(struct net_context *c, int argc, const char **argv)
3396 return net_ads_noads();
3399 int net_ads_group(struct net_context *c, int argc, const char **argv)
3401 return net_ads_noads();
3404 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
3406 return net_ads_noads();
3409 /* this one shouldn't display a message */
3410 int net_ads_check(struct net_context *c)
3415 int net_ads_check_our_domain(struct net_context *c)
3420 int net_ads(struct net_context *c, int argc, const char **argv)
3422 return net_ads_noads();
3425 #endif /* HAVE_ADS */