pyldb: Adapt tests to Python 3
[Samba.git] / source3 / utils / net_ads.c
blob5cc07a0abb695b16f4267c3f58c12394f2ab7d33
1 /*
2 Samba Unix/Linux SMB client library
3 net ads commands
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "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"
29 #include "ads.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"
35 #include "smb_krb5.h"
36 #include "secrets.h"
37 #include "krb5_env.h"
38 #include "../libcli/security/security.h"
39 #include "libsmb/libsmb.h"
40 #include "lib/param/loadparm.h"
41 #include "utils/net_dns.h"
43 #ifdef HAVE_ADS
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)) {
51 return lp_realm();
54 return NULL;
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"));
69 return -1;
72 d_printf(_("Information for Domain Controller: %s\n\n"),
73 addr);
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");
79 break;
80 case LOGON_SAM_LOGON_RESPONSE_EX:
81 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
82 break;
83 default:
84 d_printf("0x%x\n", reply.command);
85 break;
88 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
90 d_printf(_("Flags:\n"
91 "\tIs a PDC: %s\n"
92 "\tIs a GC of the forest: %s\n"
93 "\tIs an LDAP server: %s\n"
94 "\tSupports DS: %s\n"
95 "\tIs running a KDC: %s\n"
96 "\tIs running time services: %s\n"
97 "\tIs the closest DC: %s\n"
98 "\tIs writable: %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);
137 return 0;
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)
146 ADS_STRUCT *ads;
147 int ret;
149 if (c->display_usage) {
150 d_printf("%s\n"
151 "net ads lookup\n"
152 " %s",
153 _("Usage:"),
154 _("Find the ADS DC using CLDAP lookup.\n"));
155 return 0;
158 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
159 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
160 ads_destroy(&ads);
161 return -1;
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);
170 ads_destroy(&ads);
171 return ret;
176 static int net_ads_info(struct net_context *c, int argc, const char **argv)
178 ADS_STRUCT *ads;
179 char addr[INET6_ADDRSTRLEN];
180 time_t pass_time;
182 if (c->display_usage) {
183 d_printf("%s\n"
184 "net ads info\n"
185 " %s",
186 _("Usage:"),
187 _("Display information about an Active Directory "
188 "server.\n"));
189 return 0;
192 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
193 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
194 return -1;
197 if (!ads || !ads->config.realm) {
198 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
199 ads_destroy(&ads);
200 return -1;
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));
228 ads_destroy(&ads);
229 return 0;
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;
242 ADS_STATUS status;
243 bool need_password = false;
244 bool second_time = false;
245 char *cp;
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 */
254 *ads_ret = NULL;
256 retry_connect:
257 if (only_own_domain) {
258 realm = lp_realm();
259 } else {
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;
273 retry:
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) {
277 ads_destroy(&ads);
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) {
298 *cp++ = '\0';
299 SAFE_FREE(ads->auth.realm);
300 ads->auth.realm = smb_xstrdup(cp);
301 if (!strupper_m(ads->auth.realm)) {
302 ads_destroy(&ads);
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)));
314 ads_destroy(&ads);
315 return status;
318 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
319 need_password = true;
320 second_time = true;
321 goto retry;
322 } else {
323 ads_destroy(&ads);
324 return status;
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);
341 ads_destroy(&ads);
342 ads = NULL;
344 goto retry_connect;
348 *ads_ret = ads;
349 return status;
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)
369 ADS_STRUCT *ads;
370 ADS_STATUS status;
372 if ( (ads = ads_init( realm, workgroup, host )) == NULL ) {
373 return -1;
376 ads->auth.flags |= ADS_AUTH_NO_BIND;
378 status = ads_connect(ads);
379 if ( !ADS_ERR_OK(status) ) {
380 return -1;
383 ads_destroy(&ads);
384 return 0;
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)
402 ADS_STRUCT *ads;
403 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
405 if (c->display_usage) {
406 d_printf ("%s\n"
407 "net ads workgroup\n"
408 " %s\n",
409 _("Usage:"),
410 _("Print the workgroup name"));
411 return 0;
414 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
415 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
416 return -1;
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"));
426 ads_destroy(&ads);
427 return -1;
430 d_printf(_("Workgroup: %s\n"), reply.domain_name);
432 ads_destroy(&ads);
434 return 0;
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], '$')) {
446 if (disp_fields[1])
447 d_printf("%-21.21s %s\n",
448 disp_fields[0], disp_fields[1]);
449 else
450 d_printf("%s\n", disp_fields[0]);
453 SAFE_FREE(disp_fields[0]);
454 SAFE_FREE(disp_fields[1]);
455 return true;
457 if (!values) /* must be new field, indicate string field */
458 return true;
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]);
464 return true;
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)
474 ADS_STRUCT *ads;
475 ADS_STATUS status;
476 char *upn, *userdn;
477 LDAPMessage *res=NULL;
478 int rc = -1;
479 char *ou_str = 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))) {
485 return -1;
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));
492 goto done;
495 if (ads_count_replies(ads, res)) {
496 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
497 argv[0]);
498 goto done;
501 if (c->opt_container) {
502 ou_str = SMB_STRDUP(c->opt_container);
503 } else {
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],
511 ads_errstr(status));
512 goto done;
515 /* if no password is to be set, we're done */
516 if (argc == 1) {
517 d_printf(_("User %s added\n"), argv[0]);
518 rc = 0;
519 goto done;
522 /* try setting the password */
523 if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) {
524 goto done;
526 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
527 ads->auth.time_offset);
528 SAFE_FREE(upn);
529 if (ADS_ERR_OK(status)) {
530 d_printf(_("User %s added\n"), argv[0]);
531 rc = 0;
532 goto done;
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);
544 TALLOC_FREE(userdn);
547 done:
548 if (res)
549 ads_msgfree(ads, res);
550 ads_destroy(&ads);
551 SAFE_FREE(ou_str);
552 return rc;
555 static int ads_user_info(struct net_context *c, int argc, const char **argv)
557 ADS_STRUCT *ads = NULL;
558 ADS_STATUS rc;
559 LDAPMessage *res = NULL;
560 TALLOC_CTX *frame;
561 int ret = 0;
562 wbcErr wbc_status;
563 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
564 char *searchstring=NULL;
565 char **grouplist;
566 char *primary_group;
567 char *escaped_user;
568 struct dom_sid primary_group_sid;
569 uint32_t group_rid;
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());
577 if (frame == NULL) {
578 return -1;
581 escaped_user = escape_ldap_string(frame, argv[0]);
582 if (!escaped_user) {
583 d_fprintf(stderr,
584 _("ads_user_info: failed to escape user %s\n"),
585 argv[0]);
586 return -1;
589 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
590 ret = -1;
591 goto error;
594 if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) {
595 ret =-1;
596 goto error;
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));
603 ret = -1;
604 goto error;
607 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
608 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
609 ret = -1;
610 goto error;
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));
616 ret = -1;
617 goto error;
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 */
624 &primary_group,
625 &type);
626 if (!WBC_ERROR_IS_OK(wbc_status)) {
627 d_fprintf(stderr, "wbcLookupSid: %s\n",
628 wbcErrorString(wbc_status));
629 ret = -1;
630 goto error;
633 d_printf("%s\n", primary_group);
635 wbcFreeMemory(primary_group);
637 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
638 (LDAPMessage *)res, "memberOf");
640 if (grouplist) {
641 int i;
642 char **groupname;
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);
651 error:
652 if (res) ads_msgfree(ads, res);
653 if (ads) ads_destroy(&ads);
654 TALLOC_FREE(frame);
655 return ret;
658 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
660 ADS_STRUCT *ads;
661 ADS_STATUS rc;
662 LDAPMessage *res = NULL;
663 char *userdn;
665 if (argc < 1) {
666 return net_ads_user_usage(c, argc, argv);
669 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
670 return -1;
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);
677 ads_destroy(&ads);
678 return -1;
680 userdn = ads_get_dn(ads, talloc_tos(), res);
681 ads_msgfree(ads, res);
682 rc = ads_del_dn(ads, userdn);
683 TALLOC_FREE(userdn);
684 if (ADS_ERR_OK(rc)) {
685 d_printf(_("User %s deleted\n"), argv[0]);
686 ads_destroy(&ads);
687 return 0;
689 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
690 ads_errstr(rc));
691 ads_destroy(&ads);
692 return -1;
695 int net_ads_user(struct net_context *c, int argc, const char **argv)
697 struct functable func[] = {
699 "add",
700 ads_user_add,
701 NET_TRANSPORT_ADS,
702 N_("Add an AD user"),
703 N_("net ads user add\n"
704 " Add an AD user")
707 "info",
708 ads_user_info,
709 NET_TRANSPORT_ADS,
710 N_("Display information about an AD user"),
711 N_("net ads user info\n"
712 " Display information about an AD user")
715 "delete",
716 ads_user_delete,
717 NET_TRANSPORT_ADS,
718 N_("Delete an AD user"),
719 N_("net ads user delete\n"
720 " Delete an AD user")
722 {NULL, NULL, 0, NULL, NULL}
724 ADS_STRUCT *ads;
725 ADS_STATUS rc;
726 const char *shortattrs[] = {"sAMAccountName", NULL};
727 const char *longattrs[] = {"sAMAccountName", "description", NULL};
728 char *disp_fields[2] = {NULL, NULL};
730 if (argc == 0) {
731 if (c->display_usage) {
732 d_printf( "%s\n"
733 "net ads user\n"
734 " %s\n",
735 _("Usage:"),
736 _("List AD users"));
737 net_display_usage_from_functable(func);
738 return 0;
741 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
742 return -1;
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,
750 LDAP_SCOPE_SUBTREE,
751 "(objectCategory=user)",
752 c->opt_long_list_entries ? longattrs :
753 shortattrs, usergrp_display,
754 disp_fields);
755 ads_destroy(&ads);
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)
769 ADS_STRUCT *ads;
770 ADS_STATUS status;
771 LDAPMessage *res=NULL;
772 int rc = -1;
773 char *ou_str = 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))) {
780 return -1;
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));
787 goto done;
790 if (ads_count_replies(ads, res)) {
791 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
792 goto done;
795 if (c->opt_container) {
796 ou_str = SMB_STRDUP(c->opt_container);
797 } else {
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]);
805 rc = 0;
806 } else {
807 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
808 ads_errstr(status));
811 done:
812 if (res)
813 ads_msgfree(ads, res);
814 ads_destroy(&ads);
815 SAFE_FREE(ou_str);
816 return rc;
819 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
821 ADS_STRUCT *ads;
822 ADS_STATUS rc;
823 LDAPMessage *res = NULL;
824 char *groupdn;
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))) {
831 return -1;
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);
838 ads_destroy(&ads);
839 return -1;
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]);
847 ads_destroy(&ads);
848 return 0;
850 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
851 ads_errstr(rc));
852 ads_destroy(&ads);
853 return -1;
856 int net_ads_group(struct net_context *c, int argc, const char **argv)
858 struct functable func[] = {
860 "add",
861 ads_group_add,
862 NET_TRANSPORT_ADS,
863 N_("Add an AD group"),
864 N_("net ads group add\n"
865 " Add an AD group")
868 "delete",
869 ads_group_delete,
870 NET_TRANSPORT_ADS,
871 N_("Delete an AD group"),
872 N_("net ads group delete\n"
873 " Delete an AD group")
875 {NULL, NULL, 0, NULL, NULL}
877 ADS_STRUCT *ads;
878 ADS_STATUS rc;
879 const char *shortattrs[] = {"sAMAccountName", NULL};
880 const char *longattrs[] = {"sAMAccountName", "description", NULL};
881 char *disp_fields[2] = {NULL, NULL};
883 if (argc == 0) {
884 if (c->display_usage) {
885 d_printf( "%s\n"
886 "net ads group\n"
887 " %s\n",
888 _("Usage:"),
889 _("List AD groups"));
890 net_display_usage_from_functable(func);
891 return 0;
894 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
895 return -1;
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,
902 LDAP_SCOPE_SUBTREE,
903 "(objectCategory=group)",
904 c->opt_long_list_entries ? longattrs :
905 shortattrs, usergrp_display,
906 disp_fields);
908 ads_destroy(&ads);
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)
916 ADS_STRUCT *ads;
917 ADS_STATUS rc;
918 LDAPMessage *res;
920 if (c->display_usage) {
921 d_printf( "%s\n"
922 "net ads status\n"
923 " %s\n",
924 _("Usage:"),
925 _("Display machine account details"));
926 return 0;
929 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
930 return -1;
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));
936 ads_destroy(&ads);
937 return -1;
940 if (ads_count_replies(ads, res) == 0) {
941 d_fprintf(stderr, _("No machine account for '%s' found\n"), lp_netbios_name());
942 ads_destroy(&ads);
943 return -1;
946 ads_dump(ads, res);
947 ads_destroy(&ads);
948 return 0;
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)
960 TALLOC_CTX *ctx;
961 struct libnet_UnjoinCtx *r = NULL;
962 WERROR werr;
964 if (c->display_usage) {
965 d_printf( "%s\n"
966 "net ads leave\n"
967 " %s\n",
968 _("Usage:"),
969 _("Leave an AD domain"));
970 return 0;
973 if (!*lp_realm()) {
974 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
975 return -1;
978 if (!(ctx = talloc_init("net_ads_leave"))) {
979 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
980 return -1;
983 if (!c->opt_kerberos) {
984 use_in_memory_ccache();
987 if (!c->msg_ctx) {
988 d_fprintf(stderr, _("Could not initialise message context. "
989 "Try running as root\n"));
990 return -1;
993 werr = libnet_init_UnjoinCtx(ctx, &r);
994 if (!W_ERROR_IS_OK(werr)) {
995 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
996 return -1;
999 r->in.debug = true;
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));
1019 goto done;
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);
1025 goto done;
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);
1032 werr = WERR_OK;
1033 goto done;
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);
1042 done:
1043 TALLOC_FREE(r);
1044 TALLOC_FREE(ctx);
1046 if (W_ERROR_IS_OK(werr)) {
1047 return 0;
1050 return -1;
1053 static NTSTATUS net_ads_join_ok(struct net_context *c)
1055 ADS_STRUCT *ads = NULL;
1056 ADS_STATUS status;
1057 fstring dc_name;
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);
1074 ads_destroy(&ads);
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)
1083 NTSTATUS status;
1084 use_in_memory_ccache();
1086 if (c->display_usage) {
1087 d_printf( "%s\n"
1088 "net ads testjoin\n"
1089 " %s\n",
1090 _("Usage:"),
1091 _("Test if the existing join is ok"));
1092 return 0;
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));
1100 return -1;
1103 printf(_("Join is OK\n"));
1104 return 0;
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;
1131 return WERR_OK;
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,
1145 int num_addrs)
1147 struct dns_rr_ns *nameservers = NULL;
1148 int ns_count = 0, i;
1149 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1150 DNS_ERROR dns_err;
1151 fstring dns_server;
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;
1159 goto done;
1161 dnsdomain++;
1163 status = ads_dns_lookup_ns(ctx,
1164 dnsdomain,
1165 &nameservers,
1166 &ns_count);
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;
1174 char *root_dn;
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"));
1181 goto done;
1185 ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
1186 "(objectclass=*)", rootname_attrs, &msg);
1187 if (!ADS_ERR_OK(ads_status)) {
1188 goto done;
1191 root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
1192 if ( !root_dn ) {
1193 ads_msgfree( ads, msg );
1194 goto done;
1197 root_domain = ads_build_domain( root_dn );
1199 /* cleanup */
1200 ads_msgfree( ads, msg );
1202 /* try again for NS servers */
1204 status = ads_dns_lookup_ns(ctx,
1205 root_domain,
1206 &nameservers,
1207 &ns_count);
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));
1212 goto done;
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 |
1224 DNS_UPDATE_PROBE |
1225 DNS_UPDATE_PROBE_SUFFICIENT;
1227 if (c->opt_force) {
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;
1242 goto done;
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)));
1250 continue;
1253 d_printf(_("DNS Update for %s failed: %s\n"),
1254 machine_name, dns_errstr(dns_err));
1255 status = NT_STATUS_UNSUCCESSFUL;
1256 goto done;
1259 done:
1261 SAFE_FREE( root_domain );
1263 return status;
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,
1270 int num_addrs)
1272 struct sockaddr_storage *iplist_alloc = NULL;
1273 fstring machine_name;
1274 NTSTATUS status;
1276 if (hostname) {
1277 fstrcpy(machine_name, hostname);
1278 } else {
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,
1300 iplist, num_addrs);
1302 SAFE_FREE(iplist_alloc);
1303 return status;
1306 static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
1308 NTSTATUS status;
1310 status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0);
1311 return status;
1313 #endif
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 default 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\n"
1327 " and delimited by a '/'.\n"
1328 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1329 " NB: A backslash '\\' is used as escape at multiple\n"
1330 " levels and may need to be doubled or even\n"
1331 " quadrupled. It is not used as a separator.\n"));
1332 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1333 " the join. The default password is random.\n"));
1334 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1335 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1336 " NB: osName and osVer must be specified together for\n"
1337 " either to take effect. The operatingSystemService\n"
1338 " attribute is then also set along with the two\n"
1339 " other attributes.\n"));
1340 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1341 " during the join.\n"
1342 " NB: If not specified then by default the samba\n"
1343 " version string is used instead.\n"));
1344 return -1;
1348 static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
1350 #if defined(WITH_DNS_UPDATES)
1351 ADS_STRUCT *ads_dns = NULL;
1352 int ret;
1353 NTSTATUS status;
1356 * In a clustered environment, don't do dynamic dns updates:
1357 * Registering the set of ip addresses that are assigned to
1358 * the interfaces of the node that performs the join does usually
1359 * not have the desired effect, since the local interfaces do not
1360 * carry the complete set of the cluster's public IP addresses.
1361 * And it can also contain internal addresses that should not
1362 * be visible to the outside at all.
1363 * In order to do dns updates in a clustererd setup, use
1364 * net ads dns register.
1366 if (lp_clustering()) {
1367 d_fprintf(stderr, _("Not doing automatic DNS update in a "
1368 "clustered setup.\n"));
1369 return;
1372 if (!r->out.domain_is_ad) {
1373 return;
1377 * We enter this block with user creds.
1378 * kinit with the machine password to do dns update.
1381 ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name);
1383 if (ads_dns == NULL) {
1384 d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
1385 goto done;
1388 use_in_memory_ccache();
1390 ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
1391 if (ret == -1) {
1392 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1393 goto done;
1396 ads_dns->auth.password = secrets_fetch_machine_password(
1397 r->out.netbios_domain_name, NULL, NULL);
1398 if (ads_dns->auth.password == NULL) {
1399 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1400 goto done;
1403 ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
1404 if (ads_dns->auth.realm == NULL) {
1405 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1406 goto done;
1409 if (!strupper_m(ads_dns->auth.realm)) {
1410 d_fprintf(stderr, _("strupper_m %s failed\n"), ads_dns->auth.realm);
1411 goto done;
1414 ret = ads_kinit_password(ads_dns);
1415 if (ret != 0) {
1416 d_fprintf(stderr,
1417 _("DNS update failed: kinit failed: %s\n"),
1418 error_message(ret));
1419 goto done;
1422 status = net_update_dns(c, ctx, ads_dns, NULL);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 d_fprintf( stderr, _("DNS update failed: %s\n"),
1425 nt_errstr(status));
1428 done:
1429 ads_destroy(&ads_dns);
1430 #endif
1432 return;
1436 int net_ads_join(struct net_context *c, int argc, const char **argv)
1438 TALLOC_CTX *ctx = NULL;
1439 struct libnet_JoinCtx *r = NULL;
1440 const char *domain = lp_realm();
1441 WERROR werr = WERR_SETUP_NOT_JOINED;
1442 bool createupn = false;
1443 const char *machineupn = NULL;
1444 const char *machine_password = NULL;
1445 const char *create_in_ou = NULL;
1446 int i;
1447 const char *os_name = NULL;
1448 const char *os_version = NULL;
1449 const char *os_servicepack = NULL;
1450 bool modify_config = lp_config_backend_is_registry();
1451 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1453 if (c->display_usage)
1454 return net_ads_join_usage(c, argc, argv);
1456 if (!modify_config) {
1458 werr = check_ads_config();
1459 if (!W_ERROR_IS_OK(werr)) {
1460 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1461 goto fail;
1465 if (!(ctx = talloc_init("net_ads_join"))) {
1466 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
1467 werr = WERR_NOMEM;
1468 goto fail;
1471 if (!c->opt_kerberos) {
1472 use_in_memory_ccache();
1475 werr = libnet_init_JoinCtx(ctx, &r);
1476 if (!W_ERROR_IS_OK(werr)) {
1477 goto fail;
1480 /* process additional command line args */
1482 for ( i=0; i<argc; i++ ) {
1483 if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1484 createupn = true;
1485 machineupn = get_string_param(argv[i]);
1487 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1488 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1489 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1490 werr = WERR_INVALID_PARAM;
1491 goto fail;
1494 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1495 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1496 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1497 werr = WERR_INVALID_PARAM;
1498 goto fail;
1501 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1502 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1503 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1504 werr = WERR_INVALID_PARAM;
1505 goto fail;
1508 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1509 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1510 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1511 werr = WERR_INVALID_PARAM;
1512 goto fail;
1515 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1516 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1517 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1518 werr = WERR_INVALID_PARAM;
1519 goto fail;
1522 else {
1523 domain = argv[i];
1524 if (strchr(domain, '.') == NULL) {
1525 domain_name_type = JoinDomNameTypeUnknown;
1526 } else {
1527 domain_name_type = JoinDomNameTypeDNS;
1532 if (!*domain) {
1533 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1534 werr = WERR_INVALID_PARAM;
1535 goto fail;
1538 if (!c->msg_ctx) {
1539 d_fprintf(stderr, _("Could not initialise message context. "
1540 "Try running as root\n"));
1541 werr = WERR_ACCESS_DENIED;
1542 goto fail;
1545 /* Do the domain join here */
1547 r->in.domain_name = domain;
1548 r->in.domain_name_type = domain_name_type;
1549 r->in.create_upn = createupn;
1550 r->in.upn = machineupn;
1551 r->in.account_ou = create_in_ou;
1552 r->in.os_name = os_name;
1553 r->in.os_version = os_version;
1554 r->in.os_servicepack = os_servicepack;
1555 r->in.dc_name = c->opt_host;
1556 r->in.admin_account = c->opt_user_name;
1557 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1558 r->in.machine_password = machine_password;
1559 r->in.debug = true;
1560 r->in.use_kerberos = c->opt_kerberos;
1561 r->in.modify_config = modify_config;
1562 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1563 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1564 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1565 r->in.msg_ctx = c->msg_ctx;
1567 werr = libnet_Join(ctx, r);
1568 if (W_ERROR_EQUAL(werr, WERR_DCNOTFOUND) &&
1569 strequal(domain, lp_realm())) {
1570 r->in.domain_name = lp_workgroup();
1571 r->in.domain_name_type = JoinDomNameTypeNBT;
1572 werr = libnet_Join(ctx, r);
1574 if (!W_ERROR_IS_OK(werr)) {
1575 goto fail;
1578 /* Check the short name of the domain */
1580 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1581 d_printf(_("The workgroup in %s does not match the short\n"
1582 "domain name obtained from the server.\n"
1583 "Using the name [%s] from the server.\n"
1584 "You should set \"workgroup = %s\" in %s.\n"),
1585 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1586 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1589 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1591 if (r->out.dns_domain_name) {
1592 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1593 r->out.dns_domain_name);
1594 } else {
1595 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1596 r->out.netbios_domain_name);
1600 * We try doing the dns update (if it was compiled in
1601 * and if it was not disabled on the command line).
1602 * If the dns update fails, we still consider the join
1603 * operation as succeeded if we came this far.
1605 if (!c->opt_no_dns_updates) {
1606 _net_ads_join_dns_updates(c, ctx, r);
1609 TALLOC_FREE(r);
1610 TALLOC_FREE( ctx );
1612 return 0;
1614 fail:
1615 /* issue an overall failure message at the end. */
1616 d_printf(_("Failed to join domain: %s\n"),
1617 r && r->out.error_string ? r->out.error_string :
1618 get_friendly_werror_msg(werr));
1619 TALLOC_FREE( ctx );
1621 return -1;
1624 /*******************************************************************
1625 ********************************************************************/
1627 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1629 #if defined(WITH_DNS_UPDATES)
1630 ADS_STRUCT *ads;
1631 ADS_STATUS status;
1632 NTSTATUS ntstatus;
1633 TALLOC_CTX *ctx;
1634 const char *hostname = NULL;
1635 const char **addrs_list = NULL;
1636 struct sockaddr_storage *addrs = NULL;
1637 int num_addrs = 0;
1638 int count;
1640 #ifdef DEVELOPER
1641 talloc_enable_leak_report();
1642 #endif
1644 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1645 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1646 "detection of addresses in a clustered "
1647 "setup.\n"));
1648 c->display_usage = true;
1651 if (c->display_usage) {
1652 d_printf( "%s\n"
1653 "net ads dns register [hostname [IP [IP...]]]\n"
1654 " %s\n",
1655 _("Usage:"),
1656 _("Register hostname with DNS\n"));
1657 return -1;
1660 if (!(ctx = talloc_init("net_ads_dns"))) {
1661 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1662 return -1;
1665 if (argc >= 1) {
1666 hostname = argv[0];
1669 if (argc > 1) {
1670 num_addrs = argc - 1;
1671 addrs_list = &argv[1];
1672 } else if (lp_clustering()) {
1673 addrs_list = lp_cluster_addresses();
1674 num_addrs = str_list_length(addrs_list);
1677 if (num_addrs > 0) {
1678 addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
1679 if (addrs == NULL) {
1680 d_fprintf(stderr, _("Error allocating memory!\n"));
1681 talloc_free(ctx);
1682 return -1;
1686 for (count = 0; count < num_addrs; count++) {
1687 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1688 d_fprintf(stderr, "%s '%s'.\n",
1689 _("Cannot interpret address"),
1690 addrs_list[count]);
1691 talloc_free(ctx);
1692 return -1;
1696 status = ads_startup(c, true, &ads);
1697 if ( !ADS_ERR_OK(status) ) {
1698 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1699 TALLOC_FREE(ctx);
1700 return -1;
1703 ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs);
1704 if (!NT_STATUS_IS_OK(ntstatus)) {
1705 d_fprintf( stderr, _("DNS update failed!\n") );
1706 ads_destroy( &ads );
1707 TALLOC_FREE( ctx );
1708 return -1;
1711 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1713 ads_destroy(&ads);
1714 TALLOC_FREE( ctx );
1716 return 0;
1717 #else
1718 d_fprintf(stderr,
1719 _("DNS update support not enabled at compile time!\n"));
1720 return -1;
1721 #endif
1724 static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv)
1726 #if defined(WITH_DNS_UPDATES)
1727 DNS_ERROR err;
1729 #ifdef DEVELOPER
1730 talloc_enable_leak_report();
1731 #endif
1733 if (argc != 2 || c->display_usage) {
1734 d_printf( "%s\n"
1735 " %s\n"
1736 " %s\n",
1737 _("Usage:"),
1738 _("net ads dns gethostbyname <server> <name>\n"),
1739 _(" Look up hostname from the AD\n"
1740 " server\tName server to use\n"
1741 " name\tName to look up\n"));
1742 return -1;
1745 err = do_gethostbyname(argv[0], argv[1]);
1747 d_printf(_("do_gethostbyname returned %s (%d)\n"),
1748 dns_errstr(err), ERROR_DNS_V(err));
1749 #endif
1750 return 0;
1753 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
1755 struct functable func[] = {
1757 "register",
1758 net_ads_dns_register,
1759 NET_TRANSPORT_ADS,
1760 N_("Add host dns entry to AD"),
1761 N_("net ads dns register\n"
1762 " Add host dns entry to AD")
1765 "gethostbyname",
1766 net_ads_dns_gethostbyname,
1767 NET_TRANSPORT_ADS,
1768 N_("Look up host"),
1769 N_("net ads dns gethostbyname\n"
1770 " Look up host")
1772 {NULL, NULL, 0, NULL, NULL}
1775 return net_run_function(c, argc, argv, "net ads dns", func);
1778 /*******************************************************************
1779 ********************************************************************/
1781 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
1783 d_printf(_(
1784 "\nnet ads printer search <printer>"
1785 "\n\tsearch for a printer in the directory\n"
1786 "\nnet ads printer info <printer> <server>"
1787 "\n\tlookup info in directory for printer on server"
1788 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
1789 "\nnet ads printer publish <printername>"
1790 "\n\tpublish printer in directory"
1791 "\n\t(note: printer name is required)\n"
1792 "\nnet ads printer remove <printername>"
1793 "\n\tremove printer from directory"
1794 "\n\t(note: printer name is required)\n"));
1795 return -1;
1798 /*******************************************************************
1799 ********************************************************************/
1801 static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
1803 ADS_STRUCT *ads;
1804 ADS_STATUS rc;
1805 LDAPMessage *res = NULL;
1807 if (c->display_usage) {
1808 d_printf( "%s\n"
1809 "net ads printer search\n"
1810 " %s\n",
1811 _("Usage:"),
1812 _("List printers in the AD"));
1813 return 0;
1816 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1817 return -1;
1820 rc = ads_find_printers(ads, &res);
1822 if (!ADS_ERR_OK(rc)) {
1823 d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
1824 ads_msgfree(ads, res);
1825 ads_destroy(&ads);
1826 return -1;
1829 if (ads_count_replies(ads, res) == 0) {
1830 d_fprintf(stderr, _("No results found\n"));
1831 ads_msgfree(ads, res);
1832 ads_destroy(&ads);
1833 return -1;
1836 ads_dump(ads, res);
1837 ads_msgfree(ads, res);
1838 ads_destroy(&ads);
1839 return 0;
1842 static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
1844 ADS_STRUCT *ads;
1845 ADS_STATUS rc;
1846 const char *servername, *printername;
1847 LDAPMessage *res = NULL;
1849 if (c->display_usage) {
1850 d_printf("%s\n%s",
1851 _("Usage:"),
1852 _("net ads printer info [printername [servername]]\n"
1853 " Display printer info from AD\n"
1854 " printername\tPrinter name or wildcard\n"
1855 " servername\tName of the print server\n"));
1856 return 0;
1859 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1860 return -1;
1863 if (argc > 0) {
1864 printername = argv[0];
1865 } else {
1866 printername = "*";
1869 if (argc > 1) {
1870 servername = argv[1];
1871 } else {
1872 servername = lp_netbios_name();
1875 rc = ads_find_printer_on_server(ads, &res, printername, servername);
1877 if (!ADS_ERR_OK(rc)) {
1878 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
1879 servername, ads_errstr(rc));
1880 ads_msgfree(ads, res);
1881 ads_destroy(&ads);
1882 return -1;
1885 if (ads_count_replies(ads, res) == 0) {
1886 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
1887 ads_msgfree(ads, res);
1888 ads_destroy(&ads);
1889 return -1;
1892 ads_dump(ads, res);
1893 ads_msgfree(ads, res);
1894 ads_destroy(&ads);
1896 return 0;
1899 static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
1901 ADS_STRUCT *ads;
1902 ADS_STATUS rc;
1903 const char *servername, *printername;
1904 struct cli_state *cli = NULL;
1905 struct rpc_pipe_client *pipe_hnd = NULL;
1906 struct sockaddr_storage server_ss;
1907 NTSTATUS nt_status;
1908 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
1909 ADS_MODLIST mods = ads_init_mods(mem_ctx);
1910 char *prt_dn, *srv_dn, **srv_cn;
1911 char *srv_cn_escaped = NULL, *printername_escaped = NULL;
1912 LDAPMessage *res = NULL;
1914 if (argc < 1 || c->display_usage) {
1915 d_printf("%s\n%s",
1916 _("Usage:"),
1917 _("net ads printer publish <printername> [servername]\n"
1918 " Publish printer in AD\n"
1919 " printername\tName of the printer\n"
1920 " servername\tName of the print server\n"));
1921 talloc_destroy(mem_ctx);
1922 return -1;
1925 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1926 talloc_destroy(mem_ctx);
1927 return -1;
1930 printername = argv[0];
1932 if (argc == 2) {
1933 servername = argv[1];
1934 } else {
1935 servername = lp_netbios_name();
1938 /* Get printer data from SPOOLSS */
1940 resolve_name(servername, &server_ss, 0x20, false);
1942 nt_status = cli_full_connection(&cli, lp_netbios_name(), servername,
1943 &server_ss, 0,
1944 "IPC$", "IPC",
1945 c->opt_user_name, c->opt_workgroup,
1946 c->opt_password ? c->opt_password : "",
1947 CLI_FULL_CONNECTION_USE_KERBEROS,
1948 SMB_SIGNING_DEFAULT);
1950 if (NT_STATUS_IS_ERR(nt_status)) {
1951 d_fprintf(stderr, _("Unable to open a connection to %s to "
1952 "obtain data for %s\n"),
1953 servername, printername);
1954 ads_destroy(&ads);
1955 talloc_destroy(mem_ctx);
1956 return -1;
1959 /* Publish on AD server */
1961 ads_find_machine_acct(ads, &res, servername);
1963 if (ads_count_replies(ads, res) == 0) {
1964 d_fprintf(stderr, _("Could not find machine account for server "
1965 "%s\n"),
1966 servername);
1967 ads_destroy(&ads);
1968 talloc_destroy(mem_ctx);
1969 return -1;
1972 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1973 srv_cn = ldap_explode_dn(srv_dn, 1);
1975 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
1976 printername_escaped = escape_rdn_val_string_alloc(printername);
1977 if (!srv_cn_escaped || !printername_escaped) {
1978 SAFE_FREE(srv_cn_escaped);
1979 SAFE_FREE(printername_escaped);
1980 d_fprintf(stderr, _("Internal error, out of memory!"));
1981 ads_destroy(&ads);
1982 talloc_destroy(mem_ctx);
1983 return -1;
1986 if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
1987 SAFE_FREE(srv_cn_escaped);
1988 SAFE_FREE(printername_escaped);
1989 d_fprintf(stderr, _("Internal error, out of memory!"));
1990 ads_destroy(&ads);
1991 talloc_destroy(mem_ctx);
1992 return -1;
1995 SAFE_FREE(srv_cn_escaped);
1996 SAFE_FREE(printername_escaped);
1998 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
1999 if (!NT_STATUS_IS_OK(nt_status)) {
2000 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2001 servername);
2002 SAFE_FREE(prt_dn);
2003 ads_destroy(&ads);
2004 talloc_destroy(mem_ctx);
2005 return -1;
2008 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
2009 printername))) {
2010 SAFE_FREE(prt_dn);
2011 ads_destroy(&ads);
2012 talloc_destroy(mem_ctx);
2013 return -1;
2016 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
2017 if (!ADS_ERR_OK(rc)) {
2018 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
2019 SAFE_FREE(prt_dn);
2020 ads_destroy(&ads);
2021 talloc_destroy(mem_ctx);
2022 return -1;
2025 d_printf("published printer\n");
2026 SAFE_FREE(prt_dn);
2027 ads_destroy(&ads);
2028 talloc_destroy(mem_ctx);
2030 return 0;
2033 static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
2035 ADS_STRUCT *ads;
2036 ADS_STATUS rc;
2037 const char *servername;
2038 char *prt_dn;
2039 LDAPMessage *res = NULL;
2041 if (argc < 1 || c->display_usage) {
2042 d_printf("%s\n%s",
2043 _("Usage:"),
2044 _("net ads printer remove <printername> [servername]\n"
2045 " Remove a printer from the AD\n"
2046 " printername\tName of the printer\n"
2047 " servername\tName of the print server\n"));
2048 return -1;
2051 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2052 return -1;
2055 if (argc > 1) {
2056 servername = argv[1];
2057 } else {
2058 servername = lp_netbios_name();
2061 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
2063 if (!ADS_ERR_OK(rc)) {
2064 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
2065 ads_msgfree(ads, res);
2066 ads_destroy(&ads);
2067 return -1;
2070 if (ads_count_replies(ads, res) == 0) {
2071 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2072 ads_msgfree(ads, res);
2073 ads_destroy(&ads);
2074 return -1;
2077 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2078 ads_msgfree(ads, res);
2079 rc = ads_del_dn(ads, prt_dn);
2080 TALLOC_FREE(prt_dn);
2082 if (!ADS_ERR_OK(rc)) {
2083 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
2084 ads_destroy(&ads);
2085 return -1;
2088 ads_destroy(&ads);
2089 return 0;
2092 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2094 struct functable func[] = {
2096 "search",
2097 net_ads_printer_search,
2098 NET_TRANSPORT_ADS,
2099 N_("Search for a printer"),
2100 N_("net ads printer search\n"
2101 " Search for a printer")
2104 "info",
2105 net_ads_printer_info,
2106 NET_TRANSPORT_ADS,
2107 N_("Display printer information"),
2108 N_("net ads printer info\n"
2109 " Display printer information")
2112 "publish",
2113 net_ads_printer_publish,
2114 NET_TRANSPORT_ADS,
2115 N_("Publish a printer"),
2116 N_("net ads printer publish\n"
2117 " Publish a printer")
2120 "remove",
2121 net_ads_printer_remove,
2122 NET_TRANSPORT_ADS,
2123 N_("Delete a printer"),
2124 N_("net ads printer remove\n"
2125 " Delete a printer")
2127 {NULL, NULL, 0, NULL, NULL}
2130 return net_run_function(c, argc, argv, "net ads printer", func);
2134 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2136 ADS_STRUCT *ads;
2137 const char *auth_principal = c->opt_user_name;
2138 const char *auth_password = c->opt_password;
2139 const char *realm = NULL;
2140 const char *new_password = NULL;
2141 char *chr, *prompt;
2142 const char *user;
2143 char pwd[256] = {0};
2144 ADS_STATUS ret;
2146 if (c->display_usage) {
2147 d_printf("%s\n%s",
2148 _("Usage:"),
2149 _("net ads password <username>\n"
2150 " Change password for user\n"
2151 " username\tName of user to change password for\n"));
2152 return 0;
2155 if (c->opt_user_name == NULL || c->opt_password == NULL) {
2156 d_fprintf(stderr, _("You must supply an administrator "
2157 "username/password\n"));
2158 return -1;
2161 if (argc < 1) {
2162 d_fprintf(stderr, _("ERROR: You must say which username to "
2163 "change password for\n"));
2164 return -1;
2167 user = argv[0];
2168 if (!strchr_m(user, '@')) {
2169 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
2170 return -1;
2172 user = chr;
2175 use_in_memory_ccache();
2176 chr = strchr_m(auth_principal, '@');
2177 if (chr) {
2178 realm = ++chr;
2179 } else {
2180 realm = lp_realm();
2183 /* use the realm so we can eventually change passwords for users
2184 in realms other than default */
2185 if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) {
2186 return -1;
2189 /* we don't actually need a full connect, but it's the easy way to
2190 fill in the KDC's addresss */
2191 ads_connect(ads);
2193 if (!ads->config.realm) {
2194 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2195 ads_destroy(&ads);
2196 return -1;
2199 if (argv[1]) {
2200 new_password = (const char *)argv[1];
2201 } else {
2202 int rc;
2204 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2205 return -1;
2207 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2208 if (rc < 0) {
2209 return -1;
2211 new_password = pwd;
2212 free(prompt);
2215 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2216 auth_password, user, new_password, ads->auth.time_offset);
2217 memset(pwd, '\0', sizeof(pwd));
2218 if (!ADS_ERR_OK(ret)) {
2219 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2220 ads_destroy(&ads);
2221 return -1;
2224 d_printf(_("Password change for %s completed.\n"), user);
2225 ads_destroy(&ads);
2227 return 0;
2230 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2232 ADS_STRUCT *ads;
2233 char *host_principal;
2234 fstring my_name;
2235 ADS_STATUS ret;
2237 if (c->display_usage) {
2238 d_printf( "%s\n"
2239 "net ads changetrustpw\n"
2240 " %s\n",
2241 _("Usage:"),
2242 _("Change the machine account's trust password"));
2243 return 0;
2246 if (!secrets_init()) {
2247 DEBUG(1,("Failed to initialise secrets database\n"));
2248 return -1;
2251 net_use_krb_machine_account(c);
2253 use_in_memory_ccache();
2255 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2256 return -1;
2259 fstrcpy(my_name, lp_netbios_name());
2260 if (!strlower_m(my_name)) {
2261 ads_destroy(&ads);
2262 return -1;
2265 if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2266 ads_destroy(&ads);
2267 return -1;
2269 d_printf(_("Changing password for principal: %s\n"), host_principal);
2271 ret = ads_change_trust_account_password(ads, host_principal);
2273 if (!ADS_ERR_OK(ret)) {
2274 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2275 ads_destroy(&ads);
2276 SAFE_FREE(host_principal);
2277 return -1;
2280 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2282 if (USE_SYSTEM_KEYTAB) {
2283 d_printf(_("Attempting to update system keytab with new password.\n"));
2284 if (ads_keytab_create_default(ads)) {
2285 d_printf(_("Failed to update system keytab.\n"));
2289 ads_destroy(&ads);
2290 SAFE_FREE(host_principal);
2292 return 0;
2296 help for net ads search
2298 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2300 d_printf(_(
2301 "\nnet ads search <expression> <attributes...>\n"
2302 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2303 "The expression is a standard LDAP search expression, and the\n"
2304 "attributes are a list of LDAP fields to show in the results.\n\n"
2305 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2307 net_common_flags_usage(c, argc, argv);
2308 return -1;
2313 general ADS search function. Useful in diagnosing problems in ADS
2315 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2317 ADS_STRUCT *ads;
2318 ADS_STATUS rc;
2319 const char *ldap_exp;
2320 const char **attrs;
2321 LDAPMessage *res = NULL;
2323 if (argc < 1 || c->display_usage) {
2324 return net_ads_search_usage(c, argc, argv);
2327 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2328 return -1;
2331 ldap_exp = argv[0];
2332 attrs = (argv + 1);
2334 rc = ads_do_search_retry(ads, ads->config.bind_path,
2335 LDAP_SCOPE_SUBTREE,
2336 ldap_exp, attrs, &res);
2337 if (!ADS_ERR_OK(rc)) {
2338 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2339 ads_destroy(&ads);
2340 return -1;
2343 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2345 /* dump the results */
2346 ads_dump(ads, res);
2348 ads_msgfree(ads, res);
2349 ads_destroy(&ads);
2351 return 0;
2356 help for net ads search
2358 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2360 d_printf(_(
2361 "\nnet ads dn <dn> <attributes...>\n"
2362 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2363 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2364 "to show in the results\n\n"
2365 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2366 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2368 net_common_flags_usage(c, argc, argv);
2369 return -1;
2374 general ADS search function. Useful in diagnosing problems in ADS
2376 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2378 ADS_STRUCT *ads;
2379 ADS_STATUS rc;
2380 const char *dn;
2381 const char **attrs;
2382 LDAPMessage *res = NULL;
2384 if (argc < 1 || c->display_usage) {
2385 return net_ads_dn_usage(c, argc, argv);
2388 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2389 return -1;
2392 dn = argv[0];
2393 attrs = (argv + 1);
2395 rc = ads_do_search_all(ads, dn,
2396 LDAP_SCOPE_BASE,
2397 "(objectclass=*)", attrs, &res);
2398 if (!ADS_ERR_OK(rc)) {
2399 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2400 ads_destroy(&ads);
2401 return -1;
2404 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2406 /* dump the results */
2407 ads_dump(ads, res);
2409 ads_msgfree(ads, res);
2410 ads_destroy(&ads);
2412 return 0;
2416 help for net ads sid search
2418 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2420 d_printf(_(
2421 "\nnet ads sid <sid> <attributes...>\n"
2422 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2423 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2424 "to show in the results\n\n"
2425 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2427 net_common_flags_usage(c, argc, argv);
2428 return -1;
2433 general ADS search function. Useful in diagnosing problems in ADS
2435 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2437 ADS_STRUCT *ads;
2438 ADS_STATUS rc;
2439 const char *sid_string;
2440 const char **attrs;
2441 LDAPMessage *res = NULL;
2442 struct dom_sid sid;
2444 if (argc < 1 || c->display_usage) {
2445 return net_ads_sid_usage(c, argc, argv);
2448 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2449 return -1;
2452 sid_string = argv[0];
2453 attrs = (argv + 1);
2455 if (!string_to_sid(&sid, sid_string)) {
2456 d_fprintf(stderr, _("could not convert sid\n"));
2457 ads_destroy(&ads);
2458 return -1;
2461 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2462 if (!ADS_ERR_OK(rc)) {
2463 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2464 ads_destroy(&ads);
2465 return -1;
2468 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2470 /* dump the results */
2471 ads_dump(ads, res);
2473 ads_msgfree(ads, res);
2474 ads_destroy(&ads);
2476 return 0;
2479 static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2481 int ret;
2482 ADS_STRUCT *ads;
2484 if (c->display_usage) {
2485 d_printf( "%s\n"
2486 "net ads keytab flush\n"
2487 " %s\n",
2488 _("Usage:"),
2489 _("Delete the whole keytab"));
2490 return 0;
2493 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2494 return -1;
2496 ret = ads_keytab_flush(ads);
2497 ads_destroy(&ads);
2498 return ret;
2501 static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv)
2503 int i;
2504 int ret = 0;
2505 ADS_STRUCT *ads;
2507 if (c->display_usage) {
2508 d_printf("%s\n%s",
2509 _("Usage:"),
2510 _("net ads keytab add <principal> [principal ...]\n"
2511 " Add principals to local keytab\n"
2512 " principal\tKerberos principal to add to "
2513 "keytab\n"));
2514 return 0;
2517 d_printf(_("Processing principals to add...\n"));
2518 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2519 return -1;
2521 for (i = 0; i < argc; i++) {
2522 ret |= ads_keytab_add_entry(ads, argv[i]);
2524 ads_destroy(&ads);
2525 return ret;
2528 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2530 ADS_STRUCT *ads;
2531 int ret;
2533 if (c->display_usage) {
2534 d_printf( "%s\n"
2535 "net ads keytab create\n"
2536 " %s\n",
2537 _("Usage:"),
2538 _("Create new default keytab"));
2539 return 0;
2542 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2543 return -1;
2545 ret = ads_keytab_create_default(ads);
2546 ads_destroy(&ads);
2547 return ret;
2550 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2552 const char *keytab = NULL;
2554 if (c->display_usage) {
2555 d_printf("%s\n%s",
2556 _("Usage:"),
2557 _("net ads keytab list [keytab]\n"
2558 " List a local keytab\n"
2559 " keytab\tKeytab to list\n"));
2560 return 0;
2563 if (argc >= 1) {
2564 keytab = argv[0];
2567 return ads_keytab_list(keytab);
2571 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2573 struct functable func[] = {
2575 "add",
2576 net_ads_keytab_add,
2577 NET_TRANSPORT_ADS,
2578 N_("Add a service principal"),
2579 N_("net ads keytab add\n"
2580 " Add a service principal")
2583 "create",
2584 net_ads_keytab_create,
2585 NET_TRANSPORT_ADS,
2586 N_("Create a fresh keytab"),
2587 N_("net ads keytab create\n"
2588 " Create a fresh keytab")
2591 "flush",
2592 net_ads_keytab_flush,
2593 NET_TRANSPORT_ADS,
2594 N_("Remove all keytab entries"),
2595 N_("net ads keytab flush\n"
2596 " Remove all keytab entries")
2599 "list",
2600 net_ads_keytab_list,
2601 NET_TRANSPORT_ADS,
2602 N_("List a keytab"),
2603 N_("net ads keytab list\n"
2604 " List a keytab")
2606 {NULL, NULL, 0, NULL, NULL}
2609 if (!USE_KERBEROS_KEYTAB) {
2610 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
2611 "keytab method to use keytab functions.\n"));
2614 return net_run_function(c, argc, argv, "net ads keytab", func);
2617 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
2619 int ret = -1;
2621 if (c->display_usage) {
2622 d_printf( "%s\n"
2623 "net ads kerberos renew\n"
2624 " %s\n",
2625 _("Usage:"),
2626 _("Renew TGT from existing credential cache"));
2627 return 0;
2630 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
2631 if (ret) {
2632 d_printf(_("failed to renew kerberos ticket: %s\n"),
2633 error_message(ret));
2635 return ret;
2638 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
2639 struct PAC_DATA_CTR **pac_data_ctr)
2641 NTSTATUS status;
2642 int ret = -1;
2643 const char *impersonate_princ_s = NULL;
2644 const char *local_service = NULL;
2645 int i;
2647 for (i=0; i<argc; i++) {
2648 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
2649 impersonate_princ_s = get_string_param(argv[i]);
2650 if (impersonate_princ_s == NULL) {
2651 return -1;
2654 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
2655 local_service = get_string_param(argv[i]);
2656 if (local_service == NULL) {
2657 return -1;
2662 if (local_service == NULL) {
2663 local_service = talloc_asprintf(c, "%s$@%s",
2664 lp_netbios_name(), lp_realm());
2665 if (local_service == NULL) {
2666 goto out;
2670 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2672 status = kerberos_return_pac(c,
2673 c->opt_user_name,
2674 c->opt_password,
2676 NULL,
2677 NULL,
2678 NULL,
2679 true,
2680 true,
2681 2592000, /* one month */
2682 impersonate_princ_s,
2683 local_service,
2684 pac_data_ctr);
2685 if (!NT_STATUS_IS_OK(status)) {
2686 d_printf(_("failed to query kerberos PAC: %s\n"),
2687 nt_errstr(status));
2688 goto out;
2691 ret = 0;
2692 out:
2693 return ret;
2696 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
2698 struct PAC_DATA_CTR *pac_data_ctr = NULL;
2699 int i;
2700 int ret = -1;
2701 enum PAC_TYPE type = 0;
2703 if (c->display_usage) {
2704 d_printf( "%s\n"
2705 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
2706 " %s\n",
2707 _("Usage:"),
2708 _("Dump the Kerberos PAC"));
2709 return -1;
2712 for (i=0; i<argc; i++) {
2713 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
2714 type = get_int_param(argv[i]);
2718 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2719 if (ret) {
2720 return ret;
2723 if (type == 0) {
2725 char *s = NULL;
2727 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
2728 pac_data_ctr->pac_data);
2729 if (s != NULL) {
2730 d_printf(_("The Pac: %s\n"), s);
2731 talloc_free(s);
2734 return 0;
2737 for (i=0; i < pac_data_ctr->pac_data->num_buffers; i++) {
2739 char *s = NULL;
2741 if (pac_data_ctr->pac_data->buffers[i].type != type) {
2742 continue;
2745 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
2746 pac_data_ctr->pac_data->buffers[i].info);
2747 if (s != NULL) {
2748 d_printf(_("The Pac: %s\n"), s);
2749 talloc_free(s);
2751 break;
2754 return 0;
2757 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
2759 struct PAC_DATA_CTR *pac_data_ctr = NULL;
2760 char *filename = NULL;
2761 int ret = -1;
2762 int i;
2764 if (c->display_usage) {
2765 d_printf( "%s\n"
2766 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
2767 " %s\n",
2768 _("Usage:"),
2769 _("Save the Kerberos PAC"));
2770 return -1;
2773 for (i=0; i<argc; i++) {
2774 if (strnequal(argv[i], "filename", strlen("filename"))) {
2775 filename = get_string_param(argv[i]);
2776 if (filename == NULL) {
2777 return -1;
2782 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2783 if (ret) {
2784 return ret;
2787 if (filename == NULL) {
2788 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
2789 return -1;
2792 /* save the raw format */
2793 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
2794 d_printf(_("failed to save PAC in %s\n"), filename);
2795 return -1;
2798 return 0;
2801 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
2803 struct functable func[] = {
2805 "dump",
2806 net_ads_kerberos_pac_dump,
2807 NET_TRANSPORT_ADS,
2808 N_("Dump Kerberos PAC"),
2809 N_("net ads kerberos pac dump\n"
2810 " Dump a Kerberos PAC to stdout")
2813 "save",
2814 net_ads_kerberos_pac_save,
2815 NET_TRANSPORT_ADS,
2816 N_("Save Kerberos PAC"),
2817 N_("net ads kerberos pac save\n"
2818 " Save a Kerberos PAC in a file")
2821 {NULL, NULL, 0, NULL, NULL}
2824 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
2827 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
2829 TALLOC_CTX *mem_ctx = NULL;
2830 int ret = -1;
2831 NTSTATUS status;
2833 if (c->display_usage) {
2834 d_printf( "%s\n"
2835 "net ads kerberos kinit\n"
2836 " %s\n",
2837 _("Usage:"),
2838 _("Get Ticket Granting Ticket (TGT) for the user"));
2839 return 0;
2842 mem_ctx = talloc_init("net_ads_kerberos_kinit");
2843 if (!mem_ctx) {
2844 goto out;
2847 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2849 ret = kerberos_kinit_password_ext(c->opt_user_name,
2850 c->opt_password,
2852 NULL,
2853 NULL,
2854 NULL,
2855 true,
2856 true,
2857 2592000, /* one month */
2858 &status);
2859 if (ret) {
2860 d_printf(_("failed to kinit password: %s\n"),
2861 nt_errstr(status));
2863 out:
2864 return ret;
2867 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2869 struct functable func[] = {
2871 "kinit",
2872 net_ads_kerberos_kinit,
2873 NET_TRANSPORT_ADS,
2874 N_("Retrieve Ticket Granting Ticket (TGT)"),
2875 N_("net ads kerberos kinit\n"
2876 " Receive Ticket Granting Ticket (TGT)")
2879 "renew",
2880 net_ads_kerberos_renew,
2881 NET_TRANSPORT_ADS,
2882 N_("Renew Ticket Granting Ticket from credential cache"),
2883 N_("net ads kerberos renew\n"
2884 " Renew Ticket Granting Ticket (TGT) from "
2885 "credential cache")
2888 "pac",
2889 net_ads_kerberos_pac,
2890 NET_TRANSPORT_ADS,
2891 N_("Dump Kerberos PAC"),
2892 N_("net ads kerberos pac\n"
2893 " Dump Kerberos PAC")
2895 {NULL, NULL, 0, NULL, NULL}
2898 return net_run_function(c, argc, argv, "net ads kerberos", func);
2901 static int net_ads_enctype_lookup_account(struct net_context *c,
2902 ADS_STRUCT *ads,
2903 const char *account,
2904 LDAPMessage **res,
2905 const char **enctype_str)
2907 const char *filter;
2908 const char *attrs[] = {
2909 "msDS-SupportedEncryptionTypes",
2910 NULL
2912 int count;
2913 int ret = -1;
2914 ADS_STATUS status;
2916 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
2917 account);
2918 if (filter == NULL) {
2919 goto done;
2922 status = ads_search(ads, res, filter, attrs);
2923 if (!ADS_ERR_OK(status)) {
2924 d_printf(_("no account found with filter: %s\n"), filter);
2925 goto done;
2928 count = ads_count_replies(ads, *res);
2929 switch (count) {
2930 case 1:
2931 break;
2932 case 0:
2933 d_printf(_("no account found with filter: %s\n"), filter);
2934 goto done;
2935 default:
2936 d_printf(_("multiple accounts found with filter: %s\n"), filter);
2937 goto done;
2940 if (enctype_str) {
2941 *enctype_str = ads_pull_string(ads, c, *res,
2942 "msDS-SupportedEncryptionTypes");
2943 if (*enctype_str == NULL) {
2944 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
2945 goto done;
2949 ret = 0;
2950 done:
2951 return ret;
2954 static void net_ads_enctype_dump_enctypes(const char *username,
2955 const char *enctype_str)
2957 int enctypes = atoi(enctype_str);
2959 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
2960 username, enctypes, enctypes);
2962 printf("[%s] 0x%08x DES-CBC-CRC\n",
2963 enctypes & ENC_CRC32 ? "X" : " ",
2964 ENC_CRC32);
2965 printf("[%s] 0x%08x DES-CBC-MD5\n",
2966 enctypes & ENC_RSA_MD5 ? "X" : " ",
2967 ENC_RSA_MD5);
2968 printf("[%s] 0x%08x RC4-HMAC\n",
2969 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
2970 ENC_RC4_HMAC_MD5);
2971 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
2972 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
2973 ENC_HMAC_SHA1_96_AES128);
2974 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
2975 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
2976 ENC_HMAC_SHA1_96_AES256);
2979 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
2981 int ret = -1;
2982 ADS_STATUS status;
2983 ADS_STRUCT *ads = NULL;
2984 LDAPMessage *res = NULL;
2985 const char *str = NULL;
2987 if (c->display_usage || (argc < 1)) {
2988 d_printf( "%s\n"
2989 "net ads enctypes list\n"
2990 " %s\n",
2991 _("Usage:"),
2992 _("List supported enctypes"));
2993 return 0;
2996 status = ads_startup(c, false, &ads);
2997 if (!ADS_ERR_OK(status)) {
2998 printf("startup failed\n");
2999 return ret;
3002 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3003 if (ret) {
3004 goto done;
3007 net_ads_enctype_dump_enctypes(argv[0], str);
3009 ret = 0;
3010 done:
3011 ads_msgfree(ads, res);
3012 ads_destroy(&ads);
3014 return ret;
3017 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3019 int ret = -1;
3020 ADS_STATUS status;
3021 ADS_STRUCT *ads;
3022 LDAPMessage *res = NULL;
3023 const char *etype_list_str;
3024 const char *dn;
3025 ADS_MODLIST mods;
3026 uint32_t etype_list;
3027 const char *str;
3029 if (c->display_usage || argc < 1) {
3030 d_printf( "%s\n"
3031 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3032 " %s\n",
3033 _("Usage:"),
3034 _("Set supported enctypes"));
3035 return 0;
3038 status = ads_startup(c, false, &ads);
3039 if (!ADS_ERR_OK(status)) {
3040 printf("startup failed\n");
3041 return ret;
3044 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3045 if (ret) {
3046 goto done;
3049 dn = ads_get_dn(ads, c, res);
3050 if (dn == NULL) {
3051 goto done;
3054 etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
3055 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
3056 etype_list |= ENC_HMAC_SHA1_96_AES128;
3057 #endif
3058 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
3059 etype_list |= ENC_HMAC_SHA1_96_AES256;
3060 #endif
3062 if (argv[1] != NULL) {
3063 sscanf(argv[1], "%i", &etype_list);
3066 etype_list_str = talloc_asprintf(c, "%d", etype_list);
3067 if (!etype_list_str) {
3068 goto done;
3071 mods = ads_init_mods(c);
3072 if (!mods) {
3073 goto done;
3076 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
3077 etype_list_str);
3078 if (!ADS_ERR_OK(status)) {
3079 goto done;
3082 status = ads_gen_mod(ads, dn, mods);
3083 if (!ADS_ERR_OK(status)) {
3084 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3085 ads_errstr(status));
3086 goto done;
3089 ads_msgfree(ads, res);
3091 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3092 if (ret) {
3093 goto done;
3096 net_ads_enctype_dump_enctypes(argv[0], str);
3098 ret = 0;
3099 done:
3100 ads_msgfree(ads, res);
3101 ads_destroy(&ads);
3103 return ret;
3106 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3108 int ret = -1;
3109 ADS_STATUS status;
3110 ADS_STRUCT *ads;
3111 LDAPMessage *res = NULL;
3112 const char *dn;
3113 ADS_MODLIST mods;
3115 if (c->display_usage || argc < 1) {
3116 d_printf( "%s\n"
3117 "net ads enctypes delete <sAMAccountName>\n"
3118 " %s\n",
3119 _("Usage:"),
3120 _("Delete supported enctypes"));
3121 return 0;
3124 status = ads_startup(c, false, &ads);
3125 if (!ADS_ERR_OK(status)) {
3126 printf("startup failed\n");
3127 return ret;
3130 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3131 if (ret) {
3132 goto done;
3135 dn = ads_get_dn(ads, c, res);
3136 if (dn == NULL) {
3137 goto done;
3140 mods = ads_init_mods(c);
3141 if (!mods) {
3142 goto done;
3145 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
3146 if (!ADS_ERR_OK(status)) {
3147 goto done;
3150 status = ads_gen_mod(ads, dn, mods);
3151 if (!ADS_ERR_OK(status)) {
3152 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3153 ads_errstr(status));
3154 goto done;
3157 ret = 0;
3159 done:
3160 ads_msgfree(ads, res);
3161 ads_destroy(&ads);
3162 return ret;
3165 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3167 struct functable func[] = {
3169 "list",
3170 net_ads_enctypes_list,
3171 NET_TRANSPORT_ADS,
3172 N_("List the supported encryption types"),
3173 N_("net ads enctypes list\n"
3174 " List the supported encryption types")
3177 "set",
3178 net_ads_enctypes_set,
3179 NET_TRANSPORT_ADS,
3180 N_("Set the supported encryption types"),
3181 N_("net ads enctypes set\n"
3182 " Set the supported encryption types")
3185 "delete",
3186 net_ads_enctypes_delete,
3187 NET_TRANSPORT_ADS,
3188 N_("Delete the supported encryption types"),
3189 N_("net ads enctypes delete\n"
3190 " Delete the supported encryption types")
3193 {NULL, NULL, 0, NULL, NULL}
3196 return net_run_function(c, argc, argv, "net ads enctypes", func);
3200 int net_ads(struct net_context *c, int argc, const char **argv)
3202 struct functable func[] = {
3204 "info",
3205 net_ads_info,
3206 NET_TRANSPORT_ADS,
3207 N_("Display details on remote ADS server"),
3208 N_("net ads info\n"
3209 " Display details on remote ADS server")
3212 "join",
3213 net_ads_join,
3214 NET_TRANSPORT_ADS,
3215 N_("Join the local machine to ADS realm"),
3216 N_("net ads join\n"
3217 " Join the local machine to ADS realm")
3220 "testjoin",
3221 net_ads_testjoin,
3222 NET_TRANSPORT_ADS,
3223 N_("Validate machine account"),
3224 N_("net ads testjoin\n"
3225 " Validate machine account")
3228 "leave",
3229 net_ads_leave,
3230 NET_TRANSPORT_ADS,
3231 N_("Remove the local machine from ADS"),
3232 N_("net ads leave\n"
3233 " Remove the local machine from ADS")
3236 "status",
3237 net_ads_status,
3238 NET_TRANSPORT_ADS,
3239 N_("Display machine account details"),
3240 N_("net ads status\n"
3241 " Display machine account details")
3244 "user",
3245 net_ads_user,
3246 NET_TRANSPORT_ADS,
3247 N_("List/modify users"),
3248 N_("net ads user\n"
3249 " List/modify users")
3252 "group",
3253 net_ads_group,
3254 NET_TRANSPORT_ADS,
3255 N_("List/modify groups"),
3256 N_("net ads group\n"
3257 " List/modify groups")
3260 "dns",
3261 net_ads_dns,
3262 NET_TRANSPORT_ADS,
3263 N_("Issue dynamic DNS update"),
3264 N_("net ads dns\n"
3265 " Issue dynamic DNS update")
3268 "password",
3269 net_ads_password,
3270 NET_TRANSPORT_ADS,
3271 N_("Change user passwords"),
3272 N_("net ads password\n"
3273 " Change user passwords")
3276 "changetrustpw",
3277 net_ads_changetrustpw,
3278 NET_TRANSPORT_ADS,
3279 N_("Change trust account password"),
3280 N_("net ads changetrustpw\n"
3281 " Change trust account password")
3284 "printer",
3285 net_ads_printer,
3286 NET_TRANSPORT_ADS,
3287 N_("List/modify printer entries"),
3288 N_("net ads printer\n"
3289 " List/modify printer entries")
3292 "search",
3293 net_ads_search,
3294 NET_TRANSPORT_ADS,
3295 N_("Issue LDAP search using filter"),
3296 N_("net ads search\n"
3297 " Issue LDAP search using filter")
3300 "dn",
3301 net_ads_dn,
3302 NET_TRANSPORT_ADS,
3303 N_("Issue LDAP search by DN"),
3304 N_("net ads dn\n"
3305 " Issue LDAP search by DN")
3308 "sid",
3309 net_ads_sid,
3310 NET_TRANSPORT_ADS,
3311 N_("Issue LDAP search by SID"),
3312 N_("net ads sid\n"
3313 " Issue LDAP search by SID")
3316 "workgroup",
3317 net_ads_workgroup,
3318 NET_TRANSPORT_ADS,
3319 N_("Display workgroup name"),
3320 N_("net ads workgroup\n"
3321 " Display the workgroup name")
3324 "lookup",
3325 net_ads_lookup,
3326 NET_TRANSPORT_ADS,
3327 N_("Perfom CLDAP query on DC"),
3328 N_("net ads lookup\n"
3329 " Find the ADS DC using CLDAP lookups")
3332 "keytab",
3333 net_ads_keytab,
3334 NET_TRANSPORT_ADS,
3335 N_("Manage local keytab file"),
3336 N_("net ads keytab\n"
3337 " Manage local keytab file")
3340 "gpo",
3341 net_ads_gpo,
3342 NET_TRANSPORT_ADS,
3343 N_("Manage group policy objects"),
3344 N_("net ads gpo\n"
3345 " Manage group policy objects")
3348 "kerberos",
3349 net_ads_kerberos,
3350 NET_TRANSPORT_ADS,
3351 N_("Manage kerberos keytab"),
3352 N_("net ads kerberos\n"
3353 " Manage kerberos keytab")
3356 "enctypes",
3357 net_ads_enctypes,
3358 NET_TRANSPORT_ADS,
3359 N_("List/modify supported encryption types"),
3360 N_("net ads enctypes\n"
3361 " List/modify enctypes")
3363 {NULL, NULL, 0, NULL, NULL}
3366 return net_run_function(c, argc, argv, "net ads", func);
3369 #else
3371 static int net_ads_noads(void)
3373 d_fprintf(stderr, _("ADS support not compiled in\n"));
3374 return -1;
3377 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3379 return net_ads_noads();
3382 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3384 return net_ads_noads();
3387 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
3389 return net_ads_noads();
3392 int net_ads_join(struct net_context *c, int argc, const char **argv)
3394 return net_ads_noads();
3397 int net_ads_user(struct net_context *c, int argc, const char **argv)
3399 return net_ads_noads();
3402 int net_ads_group(struct net_context *c, int argc, const char **argv)
3404 return net_ads_noads();
3407 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
3409 return net_ads_noads();
3412 /* this one shouldn't display a message */
3413 int net_ads_check(struct net_context *c)
3415 return -1;
3418 int net_ads_check_our_domain(struct net_context *c)
3420 return -1;
3423 int net_ads(struct net_context *c, int argc, const char **argv)
3425 return net_ads_noads();
3428 #endif /* HAVE_ADS */