s3:smbprofile: track connect_count and disconnect_count
[Samba.git] / source3 / utils / net_ads.c
blob7f3d74d78290505b009c89bc38c56bfc8764c58e
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];
181 if (c->display_usage) {
182 d_printf("%s\n"
183 "net ads info\n"
184 " %s",
185 _("Usage:"),
186 _("Display information about an Active Directory "
187 "server.\n"));
188 return 0;
191 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
192 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
193 return -1;
196 if (!ads || !ads->config.realm) {
197 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
198 ads_destroy(&ads);
199 return -1;
202 /* Try to set the server's current time since we didn't do a full
203 TCP LDAP session initially */
205 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
206 d_fprintf( stderr, _("Failed to get server's current time!\n"));
209 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
211 d_printf(_("LDAP server: %s\n"), addr);
212 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
213 d_printf(_("Realm: %s\n"), ads->config.realm);
214 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
215 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
216 d_printf(_("Server time: %s\n"),
217 http_timestring(talloc_tos(), ads->config.current_time));
219 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
220 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
222 ads_destroy(&ads);
223 return 0;
226 static void use_in_memory_ccache(void) {
227 /* Use in-memory credentials cache so we do not interfere with
228 * existing credentials */
229 setenv(KRB5_ENV_CCNAME, "MEMORY:net_ads", 1);
232 static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
233 uint32 auth_flags, ADS_STRUCT **ads_ret)
235 ADS_STRUCT *ads = NULL;
236 ADS_STATUS status;
237 bool need_password = false;
238 bool second_time = false;
239 char *cp;
240 const char *realm = NULL;
241 bool tried_closest_dc = false;
243 /* lp_realm() should be handled by a command line param,
244 However, the join requires that realm be set in smb.conf
245 and compares our realm with the remote server's so this is
246 ok until someone needs more flexibility */
248 *ads_ret = NULL;
250 retry_connect:
251 if (only_own_domain) {
252 realm = lp_realm();
253 } else {
254 realm = assume_own_realm(c);
257 ads = ads_init(realm, c->opt_target_workgroup, c->opt_host);
259 if (!c->opt_user_name) {
260 c->opt_user_name = "administrator";
263 if (c->opt_user_specified) {
264 need_password = true;
267 retry:
268 if (!c->opt_password && need_password && !c->opt_machine_pass) {
269 c->opt_password = net_prompt_pass(c, c->opt_user_name);
270 if (!c->opt_password) {
271 ads_destroy(&ads);
272 return ADS_ERROR(LDAP_NO_MEMORY);
276 if (c->opt_password) {
277 use_in_memory_ccache();
278 SAFE_FREE(ads->auth.password);
279 ads->auth.password = smb_xstrdup(c->opt_password);
282 ads->auth.flags |= auth_flags;
283 SAFE_FREE(ads->auth.user_name);
284 ads->auth.user_name = smb_xstrdup(c->opt_user_name);
287 * If the username is of the form "name@realm",
288 * extract the realm and convert to upper case.
289 * This is only used to establish the connection.
291 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
292 *cp++ = '\0';
293 SAFE_FREE(ads->auth.realm);
294 ads->auth.realm = smb_xstrdup(cp);
295 if (!strupper_m(ads->auth.realm)) {
296 ads_destroy(&ads);
297 return ADS_ERROR(LDAP_NO_MEMORY);
301 status = ads_connect(ads);
303 if (!ADS_ERR_OK(status)) {
305 if (NT_STATUS_EQUAL(ads_ntstatus(status),
306 NT_STATUS_NO_LOGON_SERVERS)) {
307 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
308 ads_destroy(&ads);
309 return status;
312 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
313 need_password = true;
314 second_time = true;
315 goto retry;
316 } else {
317 ads_destroy(&ads);
318 return status;
322 /* when contacting our own domain, make sure we use the closest DC.
323 * This is done by reconnecting to ADS because only the first call to
324 * ads_connect will give us our own sitename */
326 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
328 tried_closest_dc = true; /* avoid loop */
330 if (!ads_closest_dc(ads)) {
332 namecache_delete(ads->server.realm, 0x1C);
333 namecache_delete(ads->server.workgroup, 0x1C);
335 ads_destroy(&ads);
336 ads = NULL;
338 goto retry_connect;
342 *ads_ret = ads;
343 return status;
346 ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
348 return ads_startup_int(c, only_own_domain, 0, ads);
351 ADS_STATUS ads_startup_nobind(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
353 return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads);
357 Check to see if connection can be made via ads.
358 ads_startup() stores the password in opt_password if it needs to so
359 that rpc or rap can use it without re-prompting.
361 static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
363 ADS_STRUCT *ads;
364 ADS_STATUS status;
366 if ( (ads = ads_init( realm, workgroup, host )) == NULL ) {
367 return -1;
370 ads->auth.flags |= ADS_AUTH_NO_BIND;
372 status = ads_connect(ads);
373 if ( !ADS_ERR_OK(status) ) {
374 return -1;
377 ads_destroy(&ads);
378 return 0;
381 int net_ads_check_our_domain(struct net_context *c)
383 return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
386 int net_ads_check(struct net_context *c)
388 return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host);
392 determine the netbios workgroup name for a domain
394 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
396 ADS_STRUCT *ads;
397 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
399 if (c->display_usage) {
400 d_printf ("%s\n"
401 "net ads workgroup\n"
402 " %s\n",
403 _("Usage:"),
404 _("Print the workgroup name"));
405 return 0;
408 if (!ADS_ERR_OK(ads_startup_nobind(c, false, &ads))) {
409 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
410 return -1;
413 if (!ads->config.realm) {
414 ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
415 ads->ldap.port = 389;
418 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
419 d_fprintf(stderr, _("CLDAP query failed!\n"));
420 ads_destroy(&ads);
421 return -1;
424 d_printf(_("Workgroup: %s\n"), reply.domain_name);
426 ads_destroy(&ads);
428 return 0;
433 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
435 char **disp_fields = (char **) data_area;
437 if (!field) { /* must be end of record */
438 if (disp_fields[0]) {
439 if (!strchr_m(disp_fields[0], '$')) {
440 if (disp_fields[1])
441 d_printf("%-21.21s %s\n",
442 disp_fields[0], disp_fields[1]);
443 else
444 d_printf("%s\n", disp_fields[0]);
447 SAFE_FREE(disp_fields[0]);
448 SAFE_FREE(disp_fields[1]);
449 return true;
451 if (!values) /* must be new field, indicate string field */
452 return true;
453 if (strcasecmp_m(field, "sAMAccountName") == 0) {
454 disp_fields[0] = SMB_STRDUP((char *) values[0]);
456 if (strcasecmp_m(field, "description") == 0)
457 disp_fields[1] = SMB_STRDUP((char *) values[0]);
458 return true;
461 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
463 return net_user_usage(c, argc, argv);
466 static int ads_user_add(struct net_context *c, int argc, const char **argv)
468 ADS_STRUCT *ads;
469 ADS_STATUS status;
470 char *upn, *userdn;
471 LDAPMessage *res=NULL;
472 int rc = -1;
473 char *ou_str = NULL;
475 if (argc < 1 || c->display_usage)
476 return net_ads_user_usage(c, argc, argv);
478 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
479 return -1;
482 status = ads_find_user_acct(ads, &res, argv[0]);
484 if (!ADS_ERR_OK(status)) {
485 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
486 goto done;
489 if (ads_count_replies(ads, res)) {
490 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
491 argv[0]);
492 goto done;
495 if (c->opt_container) {
496 ou_str = SMB_STRDUP(c->opt_container);
497 } else {
498 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
501 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
503 if (!ADS_ERR_OK(status)) {
504 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
505 ads_errstr(status));
506 goto done;
509 /* if no password is to be set, we're done */
510 if (argc == 1) {
511 d_printf(_("User %s added\n"), argv[0]);
512 rc = 0;
513 goto done;
516 /* try setting the password */
517 if (asprintf(&upn, "%s@%s", argv[0], ads->config.realm) == -1) {
518 goto done;
520 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
521 ads->auth.time_offset);
522 SAFE_FREE(upn);
523 if (ADS_ERR_OK(status)) {
524 d_printf(_("User %s added\n"), argv[0]);
525 rc = 0;
526 goto done;
529 /* password didn't set, delete account */
530 d_fprintf(stderr, _("Could not add user %s. "
531 "Error setting password %s\n"),
532 argv[0], ads_errstr(status));
533 ads_msgfree(ads, res);
534 status=ads_find_user_acct(ads, &res, argv[0]);
535 if (ADS_ERR_OK(status)) {
536 userdn = ads_get_dn(ads, talloc_tos(), res);
537 ads_del_dn(ads, userdn);
538 TALLOC_FREE(userdn);
541 done:
542 if (res)
543 ads_msgfree(ads, res);
544 ads_destroy(&ads);
545 SAFE_FREE(ou_str);
546 return rc;
549 static int ads_user_info(struct net_context *c, int argc, const char **argv)
551 ADS_STRUCT *ads = NULL;
552 ADS_STATUS rc;
553 LDAPMessage *res = NULL;
554 TALLOC_CTX *frame;
555 int ret = 0;
556 wbcErr wbc_status;
557 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
558 char *searchstring=NULL;
559 char **grouplist;
560 char *primary_group;
561 char *escaped_user;
562 struct dom_sid primary_group_sid;
563 uint32_t group_rid;
564 enum wbcSidType type;
566 if (argc < 1 || c->display_usage) {
567 return net_ads_user_usage(c, argc, argv);
570 frame = talloc_new(talloc_tos());
571 if (frame == NULL) {
572 return -1;
575 escaped_user = escape_ldap_string(frame, argv[0]);
576 if (!escaped_user) {
577 d_fprintf(stderr,
578 _("ads_user_info: failed to escape user %s\n"),
579 argv[0]);
580 return -1;
583 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
584 ret = -1;
585 goto error;
588 if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) {
589 ret =-1;
590 goto error;
592 rc = ads_search(ads, &res, searchstring, attrs);
593 SAFE_FREE(searchstring);
595 if (!ADS_ERR_OK(rc)) {
596 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(rc));
597 ret = -1;
598 goto error;
601 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
602 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
603 ret = -1;
604 goto error;
607 rc = ads_domain_sid(ads, &primary_group_sid);
608 if (!ADS_ERR_OK(rc)) {
609 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(rc));
610 ret = -1;
611 goto error;
614 sid_append_rid(&primary_group_sid, group_rid);
616 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
617 NULL, /* don't look up domain */
618 &primary_group,
619 &type);
620 if (!WBC_ERROR_IS_OK(wbc_status)) {
621 d_fprintf(stderr, "wbcLookupSid: %s\n",
622 wbcErrorString(wbc_status));
623 ret = -1;
624 goto error;
627 d_printf("%s\n", primary_group);
629 wbcFreeMemory(primary_group);
631 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
632 (LDAPMessage *)res, "memberOf");
634 if (grouplist) {
635 int i;
636 char **groupname;
637 for (i=0;grouplist[i];i++) {
638 groupname = ldap_explode_dn(grouplist[i], 1);
639 d_printf("%s\n", groupname[0]);
640 ldap_value_free(groupname);
642 ldap_value_free(grouplist);
645 error:
646 if (res) ads_msgfree(ads, res);
647 if (ads) ads_destroy(&ads);
648 TALLOC_FREE(frame);
649 return ret;
652 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
654 ADS_STRUCT *ads;
655 ADS_STATUS rc;
656 LDAPMessage *res = NULL;
657 char *userdn;
659 if (argc < 1) {
660 return net_ads_user_usage(c, argc, argv);
663 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
664 return -1;
667 rc = ads_find_user_acct(ads, &res, argv[0]);
668 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
669 d_printf(_("User %s does not exist.\n"), argv[0]);
670 ads_msgfree(ads, res);
671 ads_destroy(&ads);
672 return -1;
674 userdn = ads_get_dn(ads, talloc_tos(), res);
675 ads_msgfree(ads, res);
676 rc = ads_del_dn(ads, userdn);
677 TALLOC_FREE(userdn);
678 if (ADS_ERR_OK(rc)) {
679 d_printf(_("User %s deleted\n"), argv[0]);
680 ads_destroy(&ads);
681 return 0;
683 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
684 ads_errstr(rc));
685 ads_destroy(&ads);
686 return -1;
689 int net_ads_user(struct net_context *c, int argc, const char **argv)
691 struct functable func[] = {
693 "add",
694 ads_user_add,
695 NET_TRANSPORT_ADS,
696 N_("Add an AD user"),
697 N_("net ads user add\n"
698 " Add an AD user")
701 "info",
702 ads_user_info,
703 NET_TRANSPORT_ADS,
704 N_("Display information about an AD user"),
705 N_("net ads user info\n"
706 " Display information about an AD user")
709 "delete",
710 ads_user_delete,
711 NET_TRANSPORT_ADS,
712 N_("Delete an AD user"),
713 N_("net ads user delete\n"
714 " Delete an AD user")
716 {NULL, NULL, 0, NULL, NULL}
718 ADS_STRUCT *ads;
719 ADS_STATUS rc;
720 const char *shortattrs[] = {"sAMAccountName", NULL};
721 const char *longattrs[] = {"sAMAccountName", "description", NULL};
722 char *disp_fields[2] = {NULL, NULL};
724 if (argc == 0) {
725 if (c->display_usage) {
726 d_printf( "%s\n"
727 "net ads user\n"
728 " %s\n",
729 _("Usage:"),
730 _("List AD users"));
731 net_display_usage_from_functable(func);
732 return 0;
735 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
736 return -1;
739 if (c->opt_long_list_entries)
740 d_printf(_("\nUser name Comment"
741 "\n-----------------------------\n"));
743 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
744 LDAP_SCOPE_SUBTREE,
745 "(objectCategory=user)",
746 c->opt_long_list_entries ? longattrs :
747 shortattrs, usergrp_display,
748 disp_fields);
749 ads_destroy(&ads);
750 return ADS_ERR_OK(rc) ? 0 : -1;
753 return net_run_function(c, argc, argv, "net ads user", func);
756 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
758 return net_group_usage(c, argc, argv);
761 static int ads_group_add(struct net_context *c, int argc, const char **argv)
763 ADS_STRUCT *ads;
764 ADS_STATUS status;
765 LDAPMessage *res=NULL;
766 int rc = -1;
767 char *ou_str = NULL;
769 if (argc < 1 || c->display_usage) {
770 return net_ads_group_usage(c, argc, argv);
773 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
774 return -1;
777 status = ads_find_user_acct(ads, &res, argv[0]);
779 if (!ADS_ERR_OK(status)) {
780 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
781 goto done;
784 if (ads_count_replies(ads, res)) {
785 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
786 goto done;
789 if (c->opt_container) {
790 ou_str = SMB_STRDUP(c->opt_container);
791 } else {
792 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
795 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
797 if (ADS_ERR_OK(status)) {
798 d_printf(_("Group %s added\n"), argv[0]);
799 rc = 0;
800 } else {
801 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
802 ads_errstr(status));
805 done:
806 if (res)
807 ads_msgfree(ads, res);
808 ads_destroy(&ads);
809 SAFE_FREE(ou_str);
810 return rc;
813 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
815 ADS_STRUCT *ads;
816 ADS_STATUS rc;
817 LDAPMessage *res = NULL;
818 char *groupdn;
820 if (argc < 1 || c->display_usage) {
821 return net_ads_group_usage(c, argc, argv);
824 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
825 return -1;
828 rc = ads_find_user_acct(ads, &res, argv[0]);
829 if (!ADS_ERR_OK(rc) || ads_count_replies(ads, res) != 1) {
830 d_printf(_("Group %s does not exist.\n"), argv[0]);
831 ads_msgfree(ads, res);
832 ads_destroy(&ads);
833 return -1;
835 groupdn = ads_get_dn(ads, talloc_tos(), res);
836 ads_msgfree(ads, res);
837 rc = ads_del_dn(ads, groupdn);
838 TALLOC_FREE(groupdn);
839 if (ADS_ERR_OK(rc)) {
840 d_printf(_("Group %s deleted\n"), argv[0]);
841 ads_destroy(&ads);
842 return 0;
844 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
845 ads_errstr(rc));
846 ads_destroy(&ads);
847 return -1;
850 int net_ads_group(struct net_context *c, int argc, const char **argv)
852 struct functable func[] = {
854 "add",
855 ads_group_add,
856 NET_TRANSPORT_ADS,
857 N_("Add an AD group"),
858 N_("net ads group add\n"
859 " Add an AD group")
862 "delete",
863 ads_group_delete,
864 NET_TRANSPORT_ADS,
865 N_("Delete an AD group"),
866 N_("net ads group delete\n"
867 " Delete an AD group")
869 {NULL, NULL, 0, NULL, NULL}
871 ADS_STRUCT *ads;
872 ADS_STATUS rc;
873 const char *shortattrs[] = {"sAMAccountName", NULL};
874 const char *longattrs[] = {"sAMAccountName", "description", NULL};
875 char *disp_fields[2] = {NULL, NULL};
877 if (argc == 0) {
878 if (c->display_usage) {
879 d_printf( "%s\n"
880 "net ads group\n"
881 " %s\n",
882 _("Usage:"),
883 _("List AD groups"));
884 net_display_usage_from_functable(func);
885 return 0;
888 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
889 return -1;
892 if (c->opt_long_list_entries)
893 d_printf(_("\nGroup name Comment"
894 "\n-----------------------------\n"));
895 rc = ads_do_search_all_fn(ads, ads->config.bind_path,
896 LDAP_SCOPE_SUBTREE,
897 "(objectCategory=group)",
898 c->opt_long_list_entries ? longattrs :
899 shortattrs, usergrp_display,
900 disp_fields);
902 ads_destroy(&ads);
903 return ADS_ERR_OK(rc) ? 0 : -1;
905 return net_run_function(c, argc, argv, "net ads group", func);
908 static int net_ads_status(struct net_context *c, int argc, const char **argv)
910 ADS_STRUCT *ads;
911 ADS_STATUS rc;
912 LDAPMessage *res;
914 if (c->display_usage) {
915 d_printf( "%s\n"
916 "net ads status\n"
917 " %s\n",
918 _("Usage:"),
919 _("Display machine account details"));
920 return 0;
923 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
924 return -1;
927 rc = ads_find_machine_acct(ads, &res, lp_netbios_name());
928 if (!ADS_ERR_OK(rc)) {
929 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"), ads_errstr(rc));
930 ads_destroy(&ads);
931 return -1;
934 if (ads_count_replies(ads, res) == 0) {
935 d_fprintf(stderr, _("No machine account for '%s' found\n"), lp_netbios_name());
936 ads_destroy(&ads);
937 return -1;
940 ads_dump(ads, res);
941 ads_destroy(&ads);
942 return 0;
945 /*******************************************************************
946 Leave an AD domain. Windows XP disables the machine account.
947 We'll try the same. The old code would do an LDAP delete.
948 That only worked using the machine creds because added the machine
949 with full control to the computer object's ACL.
950 *******************************************************************/
952 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
954 TALLOC_CTX *ctx;
955 struct libnet_UnjoinCtx *r = NULL;
956 WERROR werr;
958 if (c->display_usage) {
959 d_printf( "%s\n"
960 "net ads leave\n"
961 " %s\n",
962 _("Usage:"),
963 _("Leave an AD domain"));
964 return 0;
967 if (!*lp_realm()) {
968 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
969 return -1;
972 if (!(ctx = talloc_init("net_ads_leave"))) {
973 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
974 return -1;
977 if (!c->opt_kerberos) {
978 use_in_memory_ccache();
981 if (!c->msg_ctx) {
982 d_fprintf(stderr, _("Could not initialise message context. "
983 "Try running as root\n"));
984 return -1;
987 werr = libnet_init_UnjoinCtx(ctx, &r);
988 if (!W_ERROR_IS_OK(werr)) {
989 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
990 return -1;
993 r->in.debug = true;
994 r->in.use_kerberos = c->opt_kerberos;
995 r->in.dc_name = c->opt_host;
996 r->in.domain_name = lp_realm();
997 r->in.admin_account = c->opt_user_name;
998 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
999 r->in.modify_config = lp_config_backend_is_registry();
1001 /* Try to delete it, but if that fails, disable it. The
1002 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1003 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1004 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1005 r->in.delete_machine_account = true;
1006 r->in.msg_ctx = c->msg_ctx;
1008 werr = libnet_Unjoin(ctx, r);
1009 if (!W_ERROR_IS_OK(werr)) {
1010 d_printf(_("Failed to leave domain: %s\n"),
1011 r->out.error_string ? r->out.error_string :
1012 get_friendly_werror_msg(werr));
1013 goto done;
1016 if (r->out.deleted_machine_account) {
1017 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1018 r->in.machine_name, r->out.dns_domain_name);
1019 goto done;
1022 /* We couldn't delete it - see if the disable succeeded. */
1023 if (r->out.disabled_machine_account) {
1024 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1025 r->in.machine_name, r->out.dns_domain_name);
1026 werr = WERR_OK;
1027 goto done;
1030 /* Based on what we requested, we shouldn't get here, but if
1031 we did, it means the secrets were removed, and therefore
1032 we have left the domain */
1033 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1034 r->in.machine_name, r->out.dns_domain_name);
1036 done:
1037 TALLOC_FREE(r);
1038 TALLOC_FREE(ctx);
1040 if (W_ERROR_IS_OK(werr)) {
1041 return 0;
1044 return -1;
1047 static NTSTATUS net_ads_join_ok(struct net_context *c)
1049 ADS_STRUCT *ads = NULL;
1050 ADS_STATUS status;
1051 fstring dc_name;
1052 struct sockaddr_storage dcip;
1054 if (!secrets_init()) {
1055 DEBUG(1,("Failed to initialise secrets database\n"));
1056 return NT_STATUS_ACCESS_DENIED;
1059 net_use_krb_machine_account(c);
1061 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1063 status = ads_startup(c, true, &ads);
1064 if (!ADS_ERR_OK(status)) {
1065 return ads_ntstatus(status);
1068 ads_destroy(&ads);
1069 return NT_STATUS_OK;
1073 check that an existing join is OK
1075 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1077 NTSTATUS status;
1078 use_in_memory_ccache();
1080 if (c->display_usage) {
1081 d_printf( "%s\n"
1082 "net ads testjoin\n"
1083 " %s\n",
1084 _("Usage:"),
1085 _("Test if the existing join is ok"));
1086 return 0;
1089 /* Display success or failure */
1090 status = net_ads_join_ok(c);
1091 if (!NT_STATUS_IS_OK(status)) {
1092 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1093 get_friendly_nt_error_msg(status));
1094 return -1;
1097 printf(_("Join is OK\n"));
1098 return 0;
1101 /*******************************************************************
1102 Simple configu checks before beginning the join
1103 ********************************************************************/
1105 static WERROR check_ads_config( void )
1107 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1108 d_printf(_("Host is not configured as a member server.\n"));
1109 return WERR_INVALID_DOMAIN_ROLE;
1112 if (strlen(lp_netbios_name()) > 15) {
1113 d_printf(_("Our netbios name can be at most 15 chars long, "
1114 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1115 (unsigned int)strlen(lp_netbios_name()));
1116 return WERR_INVALID_COMPUTERNAME;
1119 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1120 d_fprintf(stderr, _("realm must be set in in %s for ADS "
1121 "join to succeed.\n"), get_dyn_CONFIGFILE());
1122 return WERR_INVALID_PARAM;
1125 return WERR_OK;
1128 /*******************************************************************
1129 Send a DNS update request
1130 *******************************************************************/
1132 #if defined(WITH_DNS_UPDATES)
1133 #include "../lib/addns/dns.h"
1135 static NTSTATUS net_update_dns_internal(struct net_context *c,
1136 TALLOC_CTX *ctx, ADS_STRUCT *ads,
1137 const char *machine_name,
1138 const struct sockaddr_storage *addrs,
1139 int num_addrs)
1141 struct dns_rr_ns *nameservers = NULL;
1142 int ns_count = 0, i;
1143 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
1144 DNS_ERROR dns_err;
1145 fstring dns_server;
1146 const char *dns_hosts_file;
1147 const char *dnsdomain = NULL;
1148 char *root_domain = NULL;
1150 if ( (dnsdomain = strchr_m( machine_name, '.')) == NULL ) {
1151 d_printf(_("No DNS domain configured for %s. "
1152 "Unable to perform DNS Update.\n"), machine_name);
1153 status = NT_STATUS_INVALID_PARAMETER;
1154 goto done;
1156 dnsdomain++;
1158 dns_hosts_file = lp_parm_const_string(-1, "resolv", "host file", NULL);
1159 status = ads_dns_lookup_ns(ctx, dns_hosts_file,
1160 dnsdomain, &nameservers, &ns_count);
1161 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1162 /* Child domains often do not have NS records. Look
1163 for the NS record for the forest root domain
1164 (rootDomainNamingContext in therootDSE) */
1166 const char *rootname_attrs[] = { "rootDomainNamingContext", NULL };
1167 LDAPMessage *msg = NULL;
1168 char *root_dn;
1169 ADS_STATUS ads_status;
1171 if ( !ads->ldap.ld ) {
1172 ads_status = ads_connect( ads );
1173 if ( !ADS_ERR_OK(ads_status) ) {
1174 DEBUG(0,("net_update_dns_internal: Failed to connect to our DC!\n"));
1175 goto done;
1179 ads_status = ads_do_search(ads, "", LDAP_SCOPE_BASE,
1180 "(objectclass=*)", rootname_attrs, &msg);
1181 if (!ADS_ERR_OK(ads_status)) {
1182 goto done;
1185 root_dn = ads_pull_string(ads, ctx, msg, "rootDomainNamingContext");
1186 if ( !root_dn ) {
1187 ads_msgfree( ads, msg );
1188 goto done;
1191 root_domain = ads_build_domain( root_dn );
1193 /* cleanup */
1194 ads_msgfree( ads, msg );
1196 /* try again for NS servers */
1198 status = ads_dns_lookup_ns(ctx, dns_hosts_file, root_domain,
1199 &nameservers, &ns_count);
1201 if ( !NT_STATUS_IS_OK(status) || (ns_count == 0)) {
1202 DEBUG(3,("net_update_dns_internal: Failed to find name server for the %s "
1203 "realm\n", ads->config.realm));
1204 goto done;
1207 dnsdomain = root_domain;
1211 for (i=0; i < ns_count; i++) {
1213 uint32_t flags = DNS_UPDATE_SIGNED |
1214 DNS_UPDATE_UNSIGNED |
1215 DNS_UPDATE_UNSIGNED_SUFFICIENT |
1216 DNS_UPDATE_PROBE |
1217 DNS_UPDATE_PROBE_SUFFICIENT;
1219 if (c->opt_force) {
1220 flags &= ~DNS_UPDATE_PROBE_SUFFICIENT;
1221 flags &= ~DNS_UPDATE_UNSIGNED_SUFFICIENT;
1224 status = NT_STATUS_UNSUCCESSFUL;
1226 /* Now perform the dns update - we'll try non-secure and if we fail,
1227 we'll follow it up with a secure update */
1229 fstrcpy( dns_server, nameservers[i].hostname );
1231 dns_err = DoDNSUpdate(dns_server, dnsdomain, machine_name, addrs, num_addrs, flags);
1232 if (ERR_DNS_IS_OK(dns_err)) {
1233 status = NT_STATUS_OK;
1234 goto done;
1237 if (ERR_DNS_EQUAL(dns_err, ERROR_DNS_INVALID_NAME_SERVER) ||
1238 ERR_DNS_EQUAL(dns_err, ERROR_DNS_CONNECTION_FAILED) ||
1239 ERR_DNS_EQUAL(dns_err, ERROR_DNS_SOCKET_ERROR)) {
1240 DEBUG(1,("retrying DNS update with next nameserver after receiving %s\n",
1241 dns_errstr(dns_err)));
1242 continue;
1245 d_printf(_("DNS Update for %s failed: %s\n"),
1246 machine_name, dns_errstr(dns_err));
1247 status = NT_STATUS_UNSUCCESSFUL;
1248 goto done;
1251 done:
1253 SAFE_FREE( root_domain );
1255 return status;
1258 static NTSTATUS net_update_dns_ext(struct net_context *c,
1259 TALLOC_CTX *mem_ctx, ADS_STRUCT *ads,
1260 const char *hostname,
1261 struct sockaddr_storage *iplist,
1262 int num_addrs)
1264 struct sockaddr_storage *iplist_alloc = NULL;
1265 fstring machine_name;
1266 NTSTATUS status;
1268 if (hostname) {
1269 fstrcpy(machine_name, hostname);
1270 } else {
1271 name_to_fqdn( machine_name, lp_netbios_name() );
1273 if (!strlower_m( machine_name )) {
1274 return NT_STATUS_INVALID_PARAMETER;
1277 if (num_addrs == 0 || iplist == NULL) {
1279 * Get our ip address
1280 * (not the 127.0.0.x address but a real ip address)
1282 num_addrs = get_my_ip_address(&iplist_alloc);
1283 if ( num_addrs <= 0 ) {
1284 DEBUG(4, ("net_update_dns_ext: Failed to find my "
1285 "non-loopback IP addresses!\n"));
1286 return NT_STATUS_INVALID_PARAMETER;
1288 iplist = iplist_alloc;
1291 status = net_update_dns_internal(c, mem_ctx, ads, machine_name,
1292 iplist, num_addrs);
1294 SAFE_FREE(iplist_alloc);
1295 return status;
1298 static NTSTATUS net_update_dns(struct net_context *c, TALLOC_CTX *mem_ctx, ADS_STRUCT *ads, const char *hostname)
1300 NTSTATUS status;
1302 status = net_update_dns_ext(c, mem_ctx, ads, hostname, NULL, 0);
1303 return status;
1305 #endif
1308 /*******************************************************************
1309 ********************************************************************/
1311 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1313 d_printf(_("net ads join [options]\n"
1314 "Valid options:\n"));
1315 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1316 " The deault UPN is in the form host/netbiosname@REALM.\n"));
1317 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1318 " The OU string read from top to bottom without RDNs and delimited by a '/'.\n"
1319 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1320 " NB: A backslash '\\' is used as escape at multiple levels and may\n"
1321 " need to be doubled or even quadrupled. It is not used as a separator.\n"));
1322 d_printf(_(" machinepass=PASS Set the machine password to a specific value during the join.\n"
1323 " The deault password is random.\n"));
1324 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1325 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during the join.\n"
1326 " NB: osName and osVer must be specified together for either to take effect.\n"
1327 " Also, the operatingSystemService attribute is also set when along with\n"
1328 " the two other attributes.\n"));
1330 return -1;
1334 static void _net_ads_join_dns_updates(struct net_context *c, TALLOC_CTX *ctx, struct libnet_JoinCtx *r)
1336 #if defined(WITH_DNS_UPDATES)
1337 ADS_STRUCT *ads_dns = NULL;
1338 int ret;
1339 NTSTATUS status;
1342 * In a clustered environment, don't do dynamic dns updates:
1343 * Registering the set of ip addresses that are assigned to
1344 * the interfaces of the node that performs the join does usually
1345 * not have the desired effect, since the local interfaces do not
1346 * carry the complete set of the cluster's public IP addresses.
1347 * And it can also contain internal addresses that should not
1348 * be visible to the outside at all.
1349 * In order to do dns updates in a clustererd setup, use
1350 * net ads dns register.
1352 if (lp_clustering()) {
1353 d_fprintf(stderr, _("Not doing automatic DNS update in a "
1354 "clustered setup.\n"));
1355 return;
1358 if (!r->out.domain_is_ad) {
1359 return;
1363 * We enter this block with user creds.
1364 * kinit with the machine password to do dns update.
1367 ads_dns = ads_init(lp_realm(), NULL, r->in.dc_name);
1369 if (ads_dns == NULL) {
1370 d_fprintf(stderr, _("DNS update failed: out of memory!\n"));
1371 goto done;
1374 use_in_memory_ccache();
1376 ret = asprintf(&ads_dns->auth.user_name, "%s$", lp_netbios_name());
1377 if (ret == -1) {
1378 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1379 goto done;
1382 ads_dns->auth.password = secrets_fetch_machine_password(
1383 r->out.netbios_domain_name, NULL, NULL);
1384 if (ads_dns->auth.password == NULL) {
1385 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1386 goto done;
1389 ads_dns->auth.realm = SMB_STRDUP(r->out.dns_domain_name);
1390 if (ads_dns->auth.realm == NULL) {
1391 d_fprintf(stderr, _("DNS update failed: out of memory\n"));
1392 goto done;
1395 if (!strupper_m(ads_dns->auth.realm)) {
1396 d_fprintf(stderr, _("strupper_m %s failed\n"), ads_dns->auth.realm);
1397 goto done;
1400 ret = ads_kinit_password(ads_dns);
1401 if (ret != 0) {
1402 d_fprintf(stderr,
1403 _("DNS update failed: kinit failed: %s\n"),
1404 error_message(ret));
1405 goto done;
1408 status = net_update_dns(c, ctx, ads_dns, NULL);
1409 if (!NT_STATUS_IS_OK(status)) {
1410 d_fprintf( stderr, _("DNS update failed: %s\n"),
1411 nt_errstr(status));
1414 done:
1415 ads_destroy(&ads_dns);
1416 #endif
1418 return;
1422 int net_ads_join(struct net_context *c, int argc, const char **argv)
1424 TALLOC_CTX *ctx = NULL;
1425 struct libnet_JoinCtx *r = NULL;
1426 const char *domain = lp_realm();
1427 WERROR werr = WERR_SETUP_NOT_JOINED;
1428 bool createupn = false;
1429 const char *machineupn = NULL;
1430 const char *machine_password = NULL;
1431 const char *create_in_ou = NULL;
1432 int i;
1433 const char *os_name = NULL;
1434 const char *os_version = NULL;
1435 bool modify_config = lp_config_backend_is_registry();
1437 if (c->display_usage)
1438 return net_ads_join_usage(c, argc, argv);
1440 if (!modify_config) {
1442 werr = check_ads_config();
1443 if (!W_ERROR_IS_OK(werr)) {
1444 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1445 goto fail;
1449 if (!(ctx = talloc_init("net_ads_join"))) {
1450 d_fprintf(stderr, _("Could not initialise talloc context.\n"));
1451 werr = WERR_NOMEM;
1452 goto fail;
1455 if (!c->opt_kerberos) {
1456 use_in_memory_ccache();
1459 werr = libnet_init_JoinCtx(ctx, &r);
1460 if (!W_ERROR_IS_OK(werr)) {
1461 goto fail;
1464 /* process additional command line args */
1466 for ( i=0; i<argc; i++ ) {
1467 if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1468 createupn = true;
1469 machineupn = get_string_param(argv[i]);
1471 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1472 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1473 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1474 werr = WERR_INVALID_PARAM;
1475 goto fail;
1478 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1479 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1480 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1481 werr = WERR_INVALID_PARAM;
1482 goto fail;
1485 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1486 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1487 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1488 werr = WERR_INVALID_PARAM;
1489 goto fail;
1492 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1493 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1494 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1495 werr = WERR_INVALID_PARAM;
1496 goto fail;
1499 else {
1500 domain = argv[i];
1504 if (!*domain) {
1505 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1506 werr = WERR_INVALID_PARAM;
1507 goto fail;
1510 if (!c->msg_ctx) {
1511 d_fprintf(stderr, _("Could not initialise message context. "
1512 "Try running as root\n"));
1513 werr = WERR_ACCESS_DENIED;
1514 goto fail;
1517 /* Do the domain join here */
1519 r->in.domain_name = domain;
1520 r->in.create_upn = createupn;
1521 r->in.upn = machineupn;
1522 r->in.account_ou = create_in_ou;
1523 r->in.os_name = os_name;
1524 r->in.os_version = os_version;
1525 r->in.dc_name = c->opt_host;
1526 r->in.admin_account = c->opt_user_name;
1527 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1528 r->in.machine_password = machine_password;
1529 r->in.debug = true;
1530 r->in.use_kerberos = c->opt_kerberos;
1531 r->in.modify_config = modify_config;
1532 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1533 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1534 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1535 r->in.msg_ctx = c->msg_ctx;
1537 werr = libnet_Join(ctx, r);
1538 if (W_ERROR_EQUAL(werr, WERR_DCNOTFOUND) &&
1539 strequal(domain, lp_realm())) {
1540 r->in.domain_name = lp_workgroup();
1541 werr = libnet_Join(ctx, r);
1543 if (!W_ERROR_IS_OK(werr)) {
1544 goto fail;
1547 /* Check the short name of the domain */
1549 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1550 d_printf(_("The workgroup in %s does not match the short\n"
1551 "domain name obtained from the server.\n"
1552 "Using the name [%s] from the server.\n"
1553 "You should set \"workgroup = %s\" in %s.\n"),
1554 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1555 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1558 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1560 if (r->out.dns_domain_name) {
1561 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1562 r->out.dns_domain_name);
1563 } else {
1564 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1565 r->out.netbios_domain_name);
1569 * We try doing the dns update (if it was compiled in).
1570 * If the dns update fails, we still consider the join
1571 * operation as succeeded if we came this far.
1573 _net_ads_join_dns_updates(c, ctx, r);
1575 TALLOC_FREE(r);
1576 TALLOC_FREE( ctx );
1578 return 0;
1580 fail:
1581 /* issue an overall failure message at the end. */
1582 d_printf(_("Failed to join domain: %s\n"),
1583 r && r->out.error_string ? r->out.error_string :
1584 get_friendly_werror_msg(werr));
1585 TALLOC_FREE( ctx );
1587 return -1;
1590 /*******************************************************************
1591 ********************************************************************/
1593 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1595 #if defined(WITH_DNS_UPDATES)
1596 ADS_STRUCT *ads;
1597 ADS_STATUS status;
1598 NTSTATUS ntstatus;
1599 TALLOC_CTX *ctx;
1600 const char *hostname = NULL;
1601 const char **addrs_list = NULL;
1602 struct sockaddr_storage *addrs = NULL;
1603 int num_addrs = 0;
1604 int count;
1606 #ifdef DEVELOPER
1607 talloc_enable_leak_report();
1608 #endif
1610 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1611 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1612 "detection of addresses in a clustered "
1613 "setup.\n"));
1614 c->display_usage = true;
1617 if (c->display_usage) {
1618 d_printf( "%s\n"
1619 "net ads dns register [hostname [IP [IP...]]]\n"
1620 " %s\n",
1621 _("Usage:"),
1622 _("Register hostname with DNS\n"));
1623 return -1;
1626 if (!(ctx = talloc_init("net_ads_dns"))) {
1627 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1628 return -1;
1631 if (argc >= 1) {
1632 hostname = argv[0];
1635 if (argc > 1) {
1636 num_addrs = argc - 1;
1637 addrs_list = &argv[1];
1638 } else if (lp_clustering()) {
1639 addrs_list = lp_cluster_addresses();
1640 num_addrs = str_list_length(addrs_list);
1643 if (num_addrs > 0) {
1644 addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
1645 if (addrs == NULL) {
1646 d_fprintf(stderr, _("Error allocating memory!\n"));
1647 talloc_free(ctx);
1648 return -1;
1652 for (count = 0; count < num_addrs; count++) {
1653 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1654 d_fprintf(stderr, "%s '%s'.\n",
1655 _("Cannot interpret address"),
1656 addrs_list[count]);
1657 talloc_free(ctx);
1658 return -1;
1662 status = ads_startup(c, true, &ads);
1663 if ( !ADS_ERR_OK(status) ) {
1664 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1665 TALLOC_FREE(ctx);
1666 return -1;
1669 ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs);
1670 if (!NT_STATUS_IS_OK(ntstatus)) {
1671 d_fprintf( stderr, _("DNS update failed!\n") );
1672 ads_destroy( &ads );
1673 TALLOC_FREE( ctx );
1674 return -1;
1677 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1679 ads_destroy(&ads);
1680 TALLOC_FREE( ctx );
1682 return 0;
1683 #else
1684 d_fprintf(stderr,
1685 _("DNS update support not enabled at compile time!\n"));
1686 return -1;
1687 #endif
1690 static int net_ads_dns_gethostbyname(struct net_context *c, int argc, const char **argv)
1692 #if defined(WITH_DNS_UPDATES)
1693 DNS_ERROR err;
1695 #ifdef DEVELOPER
1696 talloc_enable_leak_report();
1697 #endif
1699 if (argc != 2 || c->display_usage) {
1700 d_printf( "%s\n"
1701 " %s\n"
1702 " %s\n",
1703 _("Usage:"),
1704 _("net ads dns gethostbyname <server> <name>\n"),
1705 _(" Look up hostname from the AD\n"
1706 " server\tName server to use\n"
1707 " name\tName to look up\n"));
1708 return -1;
1711 err = do_gethostbyname(argv[0], argv[1]);
1713 d_printf(_("do_gethostbyname returned %s (%d)\n"),
1714 dns_errstr(err), ERROR_DNS_V(err));
1715 #endif
1716 return 0;
1719 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
1721 struct functable func[] = {
1723 "register",
1724 net_ads_dns_register,
1725 NET_TRANSPORT_ADS,
1726 N_("Add host dns entry to AD"),
1727 N_("net ads dns register\n"
1728 " Add host dns entry to AD")
1731 "gethostbyname",
1732 net_ads_dns_gethostbyname,
1733 NET_TRANSPORT_ADS,
1734 N_("Look up host"),
1735 N_("net ads dns gethostbyname\n"
1736 " Look up host")
1738 {NULL, NULL, 0, NULL, NULL}
1741 return net_run_function(c, argc, argv, "net ads dns", func);
1744 /*******************************************************************
1745 ********************************************************************/
1747 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
1749 d_printf(_(
1750 "\nnet ads printer search <printer>"
1751 "\n\tsearch for a printer in the directory\n"
1752 "\nnet ads printer info <printer> <server>"
1753 "\n\tlookup info in directory for printer on server"
1754 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
1755 "\nnet ads printer publish <printername>"
1756 "\n\tpublish printer in directory"
1757 "\n\t(note: printer name is required)\n"
1758 "\nnet ads printer remove <printername>"
1759 "\n\tremove printer from directory"
1760 "\n\t(note: printer name is required)\n"));
1761 return -1;
1764 /*******************************************************************
1765 ********************************************************************/
1767 static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
1769 ADS_STRUCT *ads;
1770 ADS_STATUS rc;
1771 LDAPMessage *res = NULL;
1773 if (c->display_usage) {
1774 d_printf( "%s\n"
1775 "net ads printer search\n"
1776 " %s\n",
1777 _("Usage:"),
1778 _("List printers in the AD"));
1779 return 0;
1782 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1783 return -1;
1786 rc = ads_find_printers(ads, &res);
1788 if (!ADS_ERR_OK(rc)) {
1789 d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
1790 ads_msgfree(ads, res);
1791 ads_destroy(&ads);
1792 return -1;
1795 if (ads_count_replies(ads, res) == 0) {
1796 d_fprintf(stderr, _("No results found\n"));
1797 ads_msgfree(ads, res);
1798 ads_destroy(&ads);
1799 return -1;
1802 ads_dump(ads, res);
1803 ads_msgfree(ads, res);
1804 ads_destroy(&ads);
1805 return 0;
1808 static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
1810 ADS_STRUCT *ads;
1811 ADS_STATUS rc;
1812 const char *servername, *printername;
1813 LDAPMessage *res = NULL;
1815 if (c->display_usage) {
1816 d_printf("%s\n%s",
1817 _("Usage:"),
1818 _("net ads printer info [printername [servername]]\n"
1819 " Display printer info from AD\n"
1820 " printername\tPrinter name or wildcard\n"
1821 " servername\tName of the print server\n"));
1822 return 0;
1825 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
1826 return -1;
1829 if (argc > 0) {
1830 printername = argv[0];
1831 } else {
1832 printername = "*";
1835 if (argc > 1) {
1836 servername = argv[1];
1837 } else {
1838 servername = lp_netbios_name();
1841 rc = ads_find_printer_on_server(ads, &res, printername, servername);
1843 if (!ADS_ERR_OK(rc)) {
1844 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
1845 servername, ads_errstr(rc));
1846 ads_msgfree(ads, res);
1847 ads_destroy(&ads);
1848 return -1;
1851 if (ads_count_replies(ads, res) == 0) {
1852 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
1853 ads_msgfree(ads, res);
1854 ads_destroy(&ads);
1855 return -1;
1858 ads_dump(ads, res);
1859 ads_msgfree(ads, res);
1860 ads_destroy(&ads);
1862 return 0;
1865 static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
1867 ADS_STRUCT *ads;
1868 ADS_STATUS rc;
1869 const char *servername, *printername;
1870 struct cli_state *cli = NULL;
1871 struct rpc_pipe_client *pipe_hnd = NULL;
1872 struct sockaddr_storage server_ss;
1873 NTSTATUS nt_status;
1874 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
1875 ADS_MODLIST mods = ads_init_mods(mem_ctx);
1876 char *prt_dn, *srv_dn, **srv_cn;
1877 char *srv_cn_escaped = NULL, *printername_escaped = NULL;
1878 LDAPMessage *res = NULL;
1880 if (argc < 1 || c->display_usage) {
1881 d_printf("%s\n%s",
1882 _("Usage:"),
1883 _("net ads printer publish <printername> [servername]\n"
1884 " Publish printer in AD\n"
1885 " printername\tName of the printer\n"
1886 " servername\tName of the print server\n"));
1887 talloc_destroy(mem_ctx);
1888 return -1;
1891 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
1892 talloc_destroy(mem_ctx);
1893 return -1;
1896 printername = argv[0];
1898 if (argc == 2) {
1899 servername = argv[1];
1900 } else {
1901 servername = lp_netbios_name();
1904 /* Get printer data from SPOOLSS */
1906 resolve_name(servername, &server_ss, 0x20, false);
1908 nt_status = cli_full_connection(&cli, lp_netbios_name(), servername,
1909 &server_ss, 0,
1910 "IPC$", "IPC",
1911 c->opt_user_name, c->opt_workgroup,
1912 c->opt_password ? c->opt_password : "",
1913 CLI_FULL_CONNECTION_USE_KERBEROS,
1914 SMB_SIGNING_DEFAULT);
1916 if (NT_STATUS_IS_ERR(nt_status)) {
1917 d_fprintf(stderr, _("Unable to open a connection to %s to "
1918 "obtain data for %s\n"),
1919 servername, printername);
1920 ads_destroy(&ads);
1921 talloc_destroy(mem_ctx);
1922 return -1;
1925 /* Publish on AD server */
1927 ads_find_machine_acct(ads, &res, servername);
1929 if (ads_count_replies(ads, res) == 0) {
1930 d_fprintf(stderr, _("Could not find machine account for server "
1931 "%s\n"),
1932 servername);
1933 ads_destroy(&ads);
1934 talloc_destroy(mem_ctx);
1935 return -1;
1938 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
1939 srv_cn = ldap_explode_dn(srv_dn, 1);
1941 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
1942 printername_escaped = escape_rdn_val_string_alloc(printername);
1943 if (!srv_cn_escaped || !printername_escaped) {
1944 SAFE_FREE(srv_cn_escaped);
1945 SAFE_FREE(printername_escaped);
1946 d_fprintf(stderr, _("Internal error, out of memory!"));
1947 ads_destroy(&ads);
1948 talloc_destroy(mem_ctx);
1949 return -1;
1952 if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
1953 SAFE_FREE(srv_cn_escaped);
1954 SAFE_FREE(printername_escaped);
1955 d_fprintf(stderr, _("Internal error, out of memory!"));
1956 ads_destroy(&ads);
1957 talloc_destroy(mem_ctx);
1958 return -1;
1961 SAFE_FREE(srv_cn_escaped);
1962 SAFE_FREE(printername_escaped);
1964 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
1965 if (!NT_STATUS_IS_OK(nt_status)) {
1966 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
1967 servername);
1968 SAFE_FREE(prt_dn);
1969 ads_destroy(&ads);
1970 talloc_destroy(mem_ctx);
1971 return -1;
1974 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
1975 printername))) {
1976 SAFE_FREE(prt_dn);
1977 ads_destroy(&ads);
1978 talloc_destroy(mem_ctx);
1979 return -1;
1982 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
1983 if (!ADS_ERR_OK(rc)) {
1984 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
1985 SAFE_FREE(prt_dn);
1986 ads_destroy(&ads);
1987 talloc_destroy(mem_ctx);
1988 return -1;
1991 d_printf("published printer\n");
1992 SAFE_FREE(prt_dn);
1993 ads_destroy(&ads);
1994 talloc_destroy(mem_ctx);
1996 return 0;
1999 static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
2001 ADS_STRUCT *ads;
2002 ADS_STATUS rc;
2003 const char *servername;
2004 char *prt_dn;
2005 LDAPMessage *res = NULL;
2007 if (argc < 1 || c->display_usage) {
2008 d_printf("%s\n%s",
2009 _("Usage:"),
2010 _("net ads printer remove <printername> [servername]\n"
2011 " Remove a printer from the AD\n"
2012 " printername\tName of the printer\n"
2013 " servername\tName of the print server\n"));
2014 return -1;
2017 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2018 return -1;
2021 if (argc > 1) {
2022 servername = argv[1];
2023 } else {
2024 servername = lp_netbios_name();
2027 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
2029 if (!ADS_ERR_OK(rc)) {
2030 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
2031 ads_msgfree(ads, res);
2032 ads_destroy(&ads);
2033 return -1;
2036 if (ads_count_replies(ads, res) == 0) {
2037 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2038 ads_msgfree(ads, res);
2039 ads_destroy(&ads);
2040 return -1;
2043 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2044 ads_msgfree(ads, res);
2045 rc = ads_del_dn(ads, prt_dn);
2046 TALLOC_FREE(prt_dn);
2048 if (!ADS_ERR_OK(rc)) {
2049 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
2050 ads_destroy(&ads);
2051 return -1;
2054 ads_destroy(&ads);
2055 return 0;
2058 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2060 struct functable func[] = {
2062 "search",
2063 net_ads_printer_search,
2064 NET_TRANSPORT_ADS,
2065 N_("Search for a printer"),
2066 N_("net ads printer search\n"
2067 " Search for a printer")
2070 "info",
2071 net_ads_printer_info,
2072 NET_TRANSPORT_ADS,
2073 N_("Display printer information"),
2074 N_("net ads printer info\n"
2075 " Display printer information")
2078 "publish",
2079 net_ads_printer_publish,
2080 NET_TRANSPORT_ADS,
2081 N_("Publish a printer"),
2082 N_("net ads printer publish\n"
2083 " Publish a printer")
2086 "remove",
2087 net_ads_printer_remove,
2088 NET_TRANSPORT_ADS,
2089 N_("Delete a printer"),
2090 N_("net ads printer remove\n"
2091 " Delete a printer")
2093 {NULL, NULL, 0, NULL, NULL}
2096 return net_run_function(c, argc, argv, "net ads printer", func);
2100 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2102 ADS_STRUCT *ads;
2103 const char *auth_principal = c->opt_user_name;
2104 const char *auth_password = c->opt_password;
2105 const char *realm = NULL;
2106 const char *new_password = NULL;
2107 char *chr, *prompt;
2108 const char *user;
2109 char pwd[256] = {0};
2110 ADS_STATUS ret;
2112 if (c->display_usage) {
2113 d_printf("%s\n%s",
2114 _("Usage:"),
2115 _("net ads password <username>\n"
2116 " Change password for user\n"
2117 " username\tName of user to change password for\n"));
2118 return 0;
2121 if (c->opt_user_name == NULL || c->opt_password == NULL) {
2122 d_fprintf(stderr, _("You must supply an administrator "
2123 "username/password\n"));
2124 return -1;
2127 if (argc < 1) {
2128 d_fprintf(stderr, _("ERROR: You must say which username to "
2129 "change password for\n"));
2130 return -1;
2133 user = argv[0];
2134 if (!strchr_m(user, '@')) {
2135 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
2136 return -1;
2138 user = chr;
2141 use_in_memory_ccache();
2142 chr = strchr_m(auth_principal, '@');
2143 if (chr) {
2144 realm = ++chr;
2145 } else {
2146 realm = lp_realm();
2149 /* use the realm so we can eventually change passwords for users
2150 in realms other than default */
2151 if (!(ads = ads_init(realm, c->opt_workgroup, c->opt_host))) {
2152 return -1;
2155 /* we don't actually need a full connect, but it's the easy way to
2156 fill in the KDC's addresss */
2157 ads_connect(ads);
2159 if (!ads->config.realm) {
2160 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2161 ads_destroy(&ads);
2162 return -1;
2165 if (argv[1]) {
2166 new_password = (const char *)argv[1];
2167 } else {
2168 int rc;
2170 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2171 return -1;
2173 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2174 if (rc < 0) {
2175 return -1;
2177 new_password = pwd;
2178 free(prompt);
2181 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2182 auth_password, user, new_password, ads->auth.time_offset);
2183 memset(pwd, '\0', sizeof(pwd));
2184 if (!ADS_ERR_OK(ret)) {
2185 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2186 ads_destroy(&ads);
2187 return -1;
2190 d_printf(_("Password change for %s completed.\n"), user);
2191 ads_destroy(&ads);
2193 return 0;
2196 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2198 ADS_STRUCT *ads;
2199 char *host_principal;
2200 fstring my_name;
2201 ADS_STATUS ret;
2203 if (c->display_usage) {
2204 d_printf( "%s\n"
2205 "net ads changetrustpw\n"
2206 " %s\n",
2207 _("Usage:"),
2208 _("Change the machine account's trust password"));
2209 return 0;
2212 if (!secrets_init()) {
2213 DEBUG(1,("Failed to initialise secrets database\n"));
2214 return -1;
2217 net_use_krb_machine_account(c);
2219 use_in_memory_ccache();
2221 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2222 return -1;
2225 fstrcpy(my_name, lp_netbios_name());
2226 if (!strlower_m(my_name)) {
2227 ads_destroy(&ads);
2228 return -1;
2231 if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2232 ads_destroy(&ads);
2233 return -1;
2235 d_printf(_("Changing password for principal: %s\n"), host_principal);
2237 ret = ads_change_trust_account_password(ads, host_principal);
2239 if (!ADS_ERR_OK(ret)) {
2240 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2241 ads_destroy(&ads);
2242 SAFE_FREE(host_principal);
2243 return -1;
2246 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2248 if (USE_SYSTEM_KEYTAB) {
2249 d_printf(_("Attempting to update system keytab with new password.\n"));
2250 if (ads_keytab_create_default(ads)) {
2251 d_printf(_("Failed to update system keytab.\n"));
2255 ads_destroy(&ads);
2256 SAFE_FREE(host_principal);
2258 return 0;
2262 help for net ads search
2264 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2266 d_printf(_(
2267 "\nnet ads search <expression> <attributes...>\n"
2268 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2269 "The expression is a standard LDAP search expression, and the\n"
2270 "attributes are a list of LDAP fields to show in the results.\n\n"
2271 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2273 net_common_flags_usage(c, argc, argv);
2274 return -1;
2279 general ADS search function. Useful in diagnosing problems in ADS
2281 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2283 ADS_STRUCT *ads;
2284 ADS_STATUS rc;
2285 const char *ldap_exp;
2286 const char **attrs;
2287 LDAPMessage *res = NULL;
2289 if (argc < 1 || c->display_usage) {
2290 return net_ads_search_usage(c, argc, argv);
2293 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2294 return -1;
2297 ldap_exp = argv[0];
2298 attrs = (argv + 1);
2300 rc = ads_do_search_retry(ads, ads->config.bind_path,
2301 LDAP_SCOPE_SUBTREE,
2302 ldap_exp, attrs, &res);
2303 if (!ADS_ERR_OK(rc)) {
2304 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2305 ads_destroy(&ads);
2306 return -1;
2309 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2311 /* dump the results */
2312 ads_dump(ads, res);
2314 ads_msgfree(ads, res);
2315 ads_destroy(&ads);
2317 return 0;
2322 help for net ads search
2324 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2326 d_printf(_(
2327 "\nnet ads dn <dn> <attributes...>\n"
2328 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2329 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2330 "to show in the results\n\n"
2331 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2332 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2334 net_common_flags_usage(c, argc, argv);
2335 return -1;
2340 general ADS search function. Useful in diagnosing problems in ADS
2342 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2344 ADS_STRUCT *ads;
2345 ADS_STATUS rc;
2346 const char *dn;
2347 const char **attrs;
2348 LDAPMessage *res = NULL;
2350 if (argc < 1 || c->display_usage) {
2351 return net_ads_dn_usage(c, argc, argv);
2354 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2355 return -1;
2358 dn = argv[0];
2359 attrs = (argv + 1);
2361 rc = ads_do_search_all(ads, dn,
2362 LDAP_SCOPE_BASE,
2363 "(objectclass=*)", attrs, &res);
2364 if (!ADS_ERR_OK(rc)) {
2365 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2366 ads_destroy(&ads);
2367 return -1;
2370 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2372 /* dump the results */
2373 ads_dump(ads, res);
2375 ads_msgfree(ads, res);
2376 ads_destroy(&ads);
2378 return 0;
2382 help for net ads sid search
2384 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2386 d_printf(_(
2387 "\nnet ads sid <sid> <attributes...>\n"
2388 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2389 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2390 "to show in the results\n\n"
2391 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2393 net_common_flags_usage(c, argc, argv);
2394 return -1;
2399 general ADS search function. Useful in diagnosing problems in ADS
2401 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2403 ADS_STRUCT *ads;
2404 ADS_STATUS rc;
2405 const char *sid_string;
2406 const char **attrs;
2407 LDAPMessage *res = NULL;
2408 struct dom_sid sid;
2410 if (argc < 1 || c->display_usage) {
2411 return net_ads_sid_usage(c, argc, argv);
2414 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2415 return -1;
2418 sid_string = argv[0];
2419 attrs = (argv + 1);
2421 if (!string_to_sid(&sid, sid_string)) {
2422 d_fprintf(stderr, _("could not convert sid\n"));
2423 ads_destroy(&ads);
2424 return -1;
2427 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2428 if (!ADS_ERR_OK(rc)) {
2429 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2430 ads_destroy(&ads);
2431 return -1;
2434 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2436 /* dump the results */
2437 ads_dump(ads, res);
2439 ads_msgfree(ads, res);
2440 ads_destroy(&ads);
2442 return 0;
2445 static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2447 int ret;
2448 ADS_STRUCT *ads;
2450 if (c->display_usage) {
2451 d_printf( "%s\n"
2452 "net ads keytab flush\n"
2453 " %s\n",
2454 _("Usage:"),
2455 _("Delete the whole keytab"));
2456 return 0;
2459 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2460 return -1;
2462 ret = ads_keytab_flush(ads);
2463 ads_destroy(&ads);
2464 return ret;
2467 static int net_ads_keytab_add(struct net_context *c, int argc, const char **argv)
2469 int i;
2470 int ret = 0;
2471 ADS_STRUCT *ads;
2473 if (c->display_usage) {
2474 d_printf("%s\n%s",
2475 _("Usage:"),
2476 _("net ads keytab add <principal> [principal ...]\n"
2477 " Add principals to local keytab\n"
2478 " principal\tKerberos principal to add to "
2479 "keytab\n"));
2480 return 0;
2483 d_printf(_("Processing principals to add...\n"));
2484 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2485 return -1;
2487 for (i = 0; i < argc; i++) {
2488 ret |= ads_keytab_add_entry(ads, argv[i]);
2490 ads_destroy(&ads);
2491 return ret;
2494 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2496 ADS_STRUCT *ads;
2497 int ret;
2499 if (c->display_usage) {
2500 d_printf( "%s\n"
2501 "net ads keytab create\n"
2502 " %s\n",
2503 _("Usage:"),
2504 _("Create new default keytab"));
2505 return 0;
2508 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2509 return -1;
2511 ret = ads_keytab_create_default(ads);
2512 ads_destroy(&ads);
2513 return ret;
2516 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2518 const char *keytab = NULL;
2520 if (c->display_usage) {
2521 d_printf("%s\n%s",
2522 _("Usage:"),
2523 _("net ads keytab list [keytab]\n"
2524 " List a local keytab\n"
2525 " keytab\tKeytab to list\n"));
2526 return 0;
2529 if (argc >= 1) {
2530 keytab = argv[0];
2533 return ads_keytab_list(keytab);
2537 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2539 struct functable func[] = {
2541 "add",
2542 net_ads_keytab_add,
2543 NET_TRANSPORT_ADS,
2544 N_("Add a service principal"),
2545 N_("net ads keytab add\n"
2546 " Add a service principal")
2549 "create",
2550 net_ads_keytab_create,
2551 NET_TRANSPORT_ADS,
2552 N_("Create a fresh keytab"),
2553 N_("net ads keytab create\n"
2554 " Create a fresh keytab")
2557 "flush",
2558 net_ads_keytab_flush,
2559 NET_TRANSPORT_ADS,
2560 N_("Remove all keytab entries"),
2561 N_("net ads keytab flush\n"
2562 " Remove all keytab entries")
2565 "list",
2566 net_ads_keytab_list,
2567 NET_TRANSPORT_ADS,
2568 N_("List a keytab"),
2569 N_("net ads keytab list\n"
2570 " List a keytab")
2572 {NULL, NULL, 0, NULL, NULL}
2575 if (!USE_KERBEROS_KEYTAB) {
2576 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
2577 "keytab method to use keytab functions.\n"));
2580 return net_run_function(c, argc, argv, "net ads keytab", func);
2583 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
2585 int ret = -1;
2587 if (c->display_usage) {
2588 d_printf( "%s\n"
2589 "net ads kerberos renew\n"
2590 " %s\n",
2591 _("Usage:"),
2592 _("Renew TGT from existing credential cache"));
2593 return 0;
2596 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
2597 if (ret) {
2598 d_printf(_("failed to renew kerberos ticket: %s\n"),
2599 error_message(ret));
2601 return ret;
2604 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
2605 struct PAC_DATA_CTR **pac_data_ctr)
2607 NTSTATUS status;
2608 int ret = -1;
2609 const char *impersonate_princ_s = NULL;
2610 const char *local_service = NULL;
2611 int i;
2613 for (i=0; i<argc; i++) {
2614 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
2615 impersonate_princ_s = get_string_param(argv[i]);
2616 if (impersonate_princ_s == NULL) {
2617 return -1;
2620 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
2621 local_service = get_string_param(argv[i]);
2622 if (local_service == NULL) {
2623 return -1;
2628 if (local_service == NULL) {
2629 local_service = talloc_asprintf(c, "%s$@%s",
2630 lp_netbios_name(), lp_realm());
2631 if (local_service == NULL) {
2632 goto out;
2636 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2638 status = kerberos_return_pac(c,
2639 c->opt_user_name,
2640 c->opt_password,
2642 NULL,
2643 NULL,
2644 NULL,
2645 true,
2646 true,
2647 2592000, /* one month */
2648 impersonate_princ_s,
2649 local_service,
2650 pac_data_ctr);
2651 if (!NT_STATUS_IS_OK(status)) {
2652 d_printf(_("failed to query kerberos PAC: %s\n"),
2653 nt_errstr(status));
2654 goto out;
2657 ret = 0;
2658 out:
2659 return ret;
2662 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
2664 struct PAC_DATA_CTR *pac_data_ctr = NULL;
2665 int i;
2666 int ret = -1;
2667 enum PAC_TYPE type = 0;
2669 if (c->display_usage) {
2670 d_printf( "%s\n"
2671 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
2672 " %s\n",
2673 _("Usage:"),
2674 _("Dump the Kerberos PAC"));
2675 return -1;
2678 for (i=0; i<argc; i++) {
2679 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
2680 type = get_int_param(argv[i]);
2684 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2685 if (ret) {
2686 return ret;
2689 if (type == 0) {
2691 char *s = NULL;
2693 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
2694 pac_data_ctr->pac_data);
2695 if (s != NULL) {
2696 d_printf(_("The Pac: %s\n"), s);
2697 talloc_free(s);
2700 return 0;
2703 for (i=0; i < pac_data_ctr->pac_data->num_buffers; i++) {
2705 char *s = NULL;
2707 if (pac_data_ctr->pac_data->buffers[i].type != type) {
2708 continue;
2711 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
2712 pac_data_ctr->pac_data->buffers[i].info);
2713 if (s != NULL) {
2714 d_printf(_("The Pac: %s\n"), s);
2715 talloc_free(s);
2717 break;
2720 return 0;
2723 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
2725 struct PAC_DATA_CTR *pac_data_ctr = NULL;
2726 char *filename = NULL;
2727 int ret = -1;
2728 int i;
2730 if (c->display_usage) {
2731 d_printf( "%s\n"
2732 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
2733 " %s\n",
2734 _("Usage:"),
2735 _("Save the Kerberos PAC"));
2736 return -1;
2739 for (i=0; i<argc; i++) {
2740 if (strnequal(argv[i], "filename", strlen("filename"))) {
2741 filename = get_string_param(argv[i]);
2742 if (filename == NULL) {
2743 return -1;
2748 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
2749 if (ret) {
2750 return ret;
2753 if (filename == NULL) {
2754 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
2755 return -1;
2758 /* save the raw format */
2759 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
2760 d_printf(_("failed to save PAC in %s\n"), filename);
2761 return -1;
2764 return 0;
2767 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
2769 struct functable func[] = {
2771 "dump",
2772 net_ads_kerberos_pac_dump,
2773 NET_TRANSPORT_ADS,
2774 N_("Dump Kerberos PAC"),
2775 N_("net ads kerberos pac dump\n"
2776 " Dump a Kerberos PAC to stdout")
2779 "save",
2780 net_ads_kerberos_pac_save,
2781 NET_TRANSPORT_ADS,
2782 N_("Save Kerberos PAC"),
2783 N_("net ads kerberos pac save\n"
2784 " Save a Kerberos PAC in a file")
2787 {NULL, NULL, 0, NULL, NULL}
2790 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
2793 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
2795 TALLOC_CTX *mem_ctx = NULL;
2796 int ret = -1;
2797 NTSTATUS status;
2799 if (c->display_usage) {
2800 d_printf( "%s\n"
2801 "net ads kerberos kinit\n"
2802 " %s\n",
2803 _("Usage:"),
2804 _("Get Ticket Granting Ticket (TGT) for the user"));
2805 return 0;
2808 mem_ctx = talloc_init("net_ads_kerberos_kinit");
2809 if (!mem_ctx) {
2810 goto out;
2813 c->opt_password = net_prompt_pass(c, c->opt_user_name);
2815 ret = kerberos_kinit_password_ext(c->opt_user_name,
2816 c->opt_password,
2818 NULL,
2819 NULL,
2820 NULL,
2821 true,
2822 true,
2823 2592000, /* one month */
2824 &status);
2825 if (ret) {
2826 d_printf(_("failed to kinit password: %s\n"),
2827 nt_errstr(status));
2829 out:
2830 return ret;
2833 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
2835 struct functable func[] = {
2837 "kinit",
2838 net_ads_kerberos_kinit,
2839 NET_TRANSPORT_ADS,
2840 N_("Retrieve Ticket Granting Ticket (TGT)"),
2841 N_("net ads kerberos kinit\n"
2842 " Receive Ticket Granting Ticket (TGT)")
2845 "renew",
2846 net_ads_kerberos_renew,
2847 NET_TRANSPORT_ADS,
2848 N_("Renew Ticket Granting Ticket from credential cache"),
2849 N_("net ads kerberos renew\n"
2850 " Renew Ticket Granting Ticket (TGT) from "
2851 "credential cache")
2854 "pac",
2855 net_ads_kerberos_pac,
2856 NET_TRANSPORT_ADS,
2857 N_("Dump Kerberos PAC"),
2858 N_("net ads kerberos pac\n"
2859 " Dump Kerberos PAC")
2861 {NULL, NULL, 0, NULL, NULL}
2864 return net_run_function(c, argc, argv, "net ads kerberos", func);
2867 static int net_ads_enctype_lookup_account(struct net_context *c,
2868 ADS_STRUCT *ads,
2869 const char *account,
2870 LDAPMessage **res,
2871 const char **enctype_str)
2873 const char *filter;
2874 const char *attrs[] = {
2875 "msDS-SupportedEncryptionTypes",
2876 NULL
2878 int count;
2879 int ret = -1;
2880 ADS_STATUS status;
2882 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
2883 account);
2884 if (filter == NULL) {
2885 goto done;
2888 status = ads_search(ads, res, filter, attrs);
2889 if (!ADS_ERR_OK(status)) {
2890 d_printf(_("no account found with filter: %s\n"), filter);
2891 goto done;
2894 count = ads_count_replies(ads, *res);
2895 switch (count) {
2896 case 1:
2897 break;
2898 case 0:
2899 d_printf(_("no account found with filter: %s\n"), filter);
2900 goto done;
2901 default:
2902 d_printf(_("multiple accounts found with filter: %s\n"), filter);
2903 goto done;
2906 if (enctype_str) {
2907 *enctype_str = ads_pull_string(ads, c, *res,
2908 "msDS-SupportedEncryptionTypes");
2909 if (*enctype_str == NULL) {
2910 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
2911 goto done;
2915 ret = 0;
2916 done:
2917 return ret;
2920 static void net_ads_enctype_dump_enctypes(const char *username,
2921 const char *enctype_str)
2923 int enctypes = atoi(enctype_str);
2925 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
2926 username, enctypes, enctypes);
2928 printf("[%s] 0x%08x DES-CBC-CRC\n",
2929 enctypes & ENC_CRC32 ? "X" : " ",
2930 ENC_CRC32);
2931 printf("[%s] 0x%08x DES-CBC-MD5\n",
2932 enctypes & ENC_RSA_MD5 ? "X" : " ",
2933 ENC_RSA_MD5);
2934 printf("[%s] 0x%08x RC4-HMAC\n",
2935 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
2936 ENC_RC4_HMAC_MD5);
2937 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
2938 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
2939 ENC_HMAC_SHA1_96_AES128);
2940 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
2941 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
2942 ENC_HMAC_SHA1_96_AES256);
2945 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
2947 int ret = -1;
2948 ADS_STATUS status;
2949 ADS_STRUCT *ads = NULL;
2950 LDAPMessage *res = NULL;
2951 const char *str = NULL;
2953 if (c->display_usage || (argc < 1)) {
2954 d_printf( "%s\n"
2955 "net ads enctypes list\n"
2956 " %s\n",
2957 _("Usage:"),
2958 _("List supported enctypes"));
2959 return 0;
2962 status = ads_startup(c, false, &ads);
2963 if (!ADS_ERR_OK(status)) {
2964 printf("startup failed\n");
2965 return ret;
2968 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
2969 if (ret) {
2970 goto done;
2973 net_ads_enctype_dump_enctypes(argv[0], str);
2975 ret = 0;
2976 done:
2977 ads_msgfree(ads, res);
2978 ads_destroy(&ads);
2980 return ret;
2983 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
2985 int ret = -1;
2986 ADS_STATUS status;
2987 ADS_STRUCT *ads;
2988 LDAPMessage *res = NULL;
2989 const char *etype_list_str;
2990 const char *dn;
2991 ADS_MODLIST mods;
2992 uint32_t etype_list;
2993 const char *str;
2995 if (c->display_usage || argc < 1) {
2996 d_printf( "%s\n"
2997 "net ads enctypes set <sAMAccountName> [enctypes]\n"
2998 " %s\n",
2999 _("Usage:"),
3000 _("Set supported enctypes"));
3001 return 0;
3004 status = ads_startup(c, false, &ads);
3005 if (!ADS_ERR_OK(status)) {
3006 printf("startup failed\n");
3007 return ret;
3010 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3011 if (ret) {
3012 goto done;
3015 dn = ads_get_dn(ads, c, res);
3016 if (dn == NULL) {
3017 goto done;
3020 etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
3021 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
3022 etype_list |= ENC_HMAC_SHA1_96_AES128;
3023 #endif
3024 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
3025 etype_list |= ENC_HMAC_SHA1_96_AES256;
3026 #endif
3028 if (argv[1] != NULL) {
3029 sscanf(argv[1], "%i", &etype_list);
3032 etype_list_str = talloc_asprintf(c, "%d", etype_list);
3033 if (!etype_list_str) {
3034 goto done;
3037 mods = ads_init_mods(c);
3038 if (!mods) {
3039 goto done;
3042 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
3043 etype_list_str);
3044 if (!ADS_ERR_OK(status)) {
3045 goto done;
3048 status = ads_gen_mod(ads, dn, mods);
3049 if (!ADS_ERR_OK(status)) {
3050 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3051 ads_errstr(status));
3052 goto done;
3055 ads_msgfree(ads, res);
3057 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3058 if (ret) {
3059 goto done;
3062 net_ads_enctype_dump_enctypes(argv[0], str);
3064 ret = 0;
3065 done:
3066 ads_msgfree(ads, res);
3067 ads_destroy(&ads);
3069 return ret;
3072 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3074 int ret = -1;
3075 ADS_STATUS status;
3076 ADS_STRUCT *ads;
3077 LDAPMessage *res = NULL;
3078 const char *dn;
3079 ADS_MODLIST mods;
3081 if (c->display_usage || argc < 1) {
3082 d_printf( "%s\n"
3083 "net ads enctypes delete <sAMAccountName>\n"
3084 " %s\n",
3085 _("Usage:"),
3086 _("Delete supported enctypes"));
3087 return 0;
3090 status = ads_startup(c, false, &ads);
3091 if (!ADS_ERR_OK(status)) {
3092 printf("startup failed\n");
3093 return ret;
3096 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3097 if (ret) {
3098 goto done;
3101 dn = ads_get_dn(ads, c, res);
3102 if (dn == NULL) {
3103 goto done;
3106 mods = ads_init_mods(c);
3107 if (!mods) {
3108 goto done;
3111 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
3112 if (!ADS_ERR_OK(status)) {
3113 goto done;
3116 status = ads_gen_mod(ads, dn, mods);
3117 if (!ADS_ERR_OK(status)) {
3118 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3119 ads_errstr(status));
3120 goto done;
3123 ret = 0;
3125 done:
3126 ads_msgfree(ads, res);
3127 ads_destroy(&ads);
3128 return ret;
3131 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3133 struct functable func[] = {
3135 "list",
3136 net_ads_enctypes_list,
3137 NET_TRANSPORT_ADS,
3138 N_("List the supported encryption types"),
3139 N_("net ads enctypes list\n"
3140 " List the supported encryption types")
3143 "set",
3144 net_ads_enctypes_set,
3145 NET_TRANSPORT_ADS,
3146 N_("Set the supported encryption types"),
3147 N_("net ads enctypes set\n"
3148 " Set the supported encryption types")
3151 "delete",
3152 net_ads_enctypes_delete,
3153 NET_TRANSPORT_ADS,
3154 N_("Delete the supported encryption types"),
3155 N_("net ads enctypes delete\n"
3156 " Delete the supported encryption types")
3159 {NULL, NULL, 0, NULL, NULL}
3162 return net_run_function(c, argc, argv, "net ads enctypes", func);
3166 int net_ads(struct net_context *c, int argc, const char **argv)
3168 struct functable func[] = {
3170 "info",
3171 net_ads_info,
3172 NET_TRANSPORT_ADS,
3173 N_("Display details on remote ADS server"),
3174 N_("net ads info\n"
3175 " Display details on remote ADS server")
3178 "join",
3179 net_ads_join,
3180 NET_TRANSPORT_ADS,
3181 N_("Join the local machine to ADS realm"),
3182 N_("net ads join\n"
3183 " Join the local machine to ADS realm")
3186 "testjoin",
3187 net_ads_testjoin,
3188 NET_TRANSPORT_ADS,
3189 N_("Validate machine account"),
3190 N_("net ads testjoin\n"
3191 " Validate machine account")
3194 "leave",
3195 net_ads_leave,
3196 NET_TRANSPORT_ADS,
3197 N_("Remove the local machine from ADS"),
3198 N_("net ads leave\n"
3199 " Remove the local machine from ADS")
3202 "status",
3203 net_ads_status,
3204 NET_TRANSPORT_ADS,
3205 N_("Display machine account details"),
3206 N_("net ads status\n"
3207 " Display machine account details")
3210 "user",
3211 net_ads_user,
3212 NET_TRANSPORT_ADS,
3213 N_("List/modify users"),
3214 N_("net ads user\n"
3215 " List/modify users")
3218 "group",
3219 net_ads_group,
3220 NET_TRANSPORT_ADS,
3221 N_("List/modify groups"),
3222 N_("net ads group\n"
3223 " List/modify groups")
3226 "dns",
3227 net_ads_dns,
3228 NET_TRANSPORT_ADS,
3229 N_("Issue dynamic DNS update"),
3230 N_("net ads dns\n"
3231 " Issue dynamic DNS update")
3234 "password",
3235 net_ads_password,
3236 NET_TRANSPORT_ADS,
3237 N_("Change user passwords"),
3238 N_("net ads password\n"
3239 " Change user passwords")
3242 "changetrustpw",
3243 net_ads_changetrustpw,
3244 NET_TRANSPORT_ADS,
3245 N_("Change trust account password"),
3246 N_("net ads changetrustpw\n"
3247 " Change trust account password")
3250 "printer",
3251 net_ads_printer,
3252 NET_TRANSPORT_ADS,
3253 N_("List/modify printer entries"),
3254 N_("net ads printer\n"
3255 " List/modify printer entries")
3258 "search",
3259 net_ads_search,
3260 NET_TRANSPORT_ADS,
3261 N_("Issue LDAP search using filter"),
3262 N_("net ads search\n"
3263 " Issue LDAP search using filter")
3266 "dn",
3267 net_ads_dn,
3268 NET_TRANSPORT_ADS,
3269 N_("Issue LDAP search by DN"),
3270 N_("net ads dn\n"
3271 " Issue LDAP search by DN")
3274 "sid",
3275 net_ads_sid,
3276 NET_TRANSPORT_ADS,
3277 N_("Issue LDAP search by SID"),
3278 N_("net ads sid\n"
3279 " Issue LDAP search by SID")
3282 "workgroup",
3283 net_ads_workgroup,
3284 NET_TRANSPORT_ADS,
3285 N_("Display workgroup name"),
3286 N_("net ads workgroup\n"
3287 " Display the workgroup name")
3290 "lookup",
3291 net_ads_lookup,
3292 NET_TRANSPORT_ADS,
3293 N_("Perfom CLDAP query on DC"),
3294 N_("net ads lookup\n"
3295 " Find the ADS DC using CLDAP lookups")
3298 "keytab",
3299 net_ads_keytab,
3300 NET_TRANSPORT_ADS,
3301 N_("Manage local keytab file"),
3302 N_("net ads keytab\n"
3303 " Manage local keytab file")
3306 "gpo",
3307 net_ads_gpo,
3308 NET_TRANSPORT_ADS,
3309 N_("Manage group policy objects"),
3310 N_("net ads gpo\n"
3311 " Manage group policy objects")
3314 "kerberos",
3315 net_ads_kerberos,
3316 NET_TRANSPORT_ADS,
3317 N_("Manage kerberos keytab"),
3318 N_("net ads kerberos\n"
3319 " Manage kerberos keytab")
3322 "enctypes",
3323 net_ads_enctypes,
3324 NET_TRANSPORT_ADS,
3325 N_("List/modify supported encryption types"),
3326 N_("net ads enctypes\n"
3327 " List/modify enctypes")
3329 {NULL, NULL, 0, NULL, NULL}
3332 return net_run_function(c, argc, argv, "net ads", func);
3335 #else
3337 static int net_ads_noads(void)
3339 d_fprintf(stderr, _("ADS support not compiled in\n"));
3340 return -1;
3343 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3345 return net_ads_noads();
3348 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3350 return net_ads_noads();
3353 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
3355 return net_ads_noads();
3358 int net_ads_join(struct net_context *c, int argc, const char **argv)
3360 return net_ads_noads();
3363 int net_ads_user(struct net_context *c, int argc, const char **argv)
3365 return net_ads_noads();
3368 int net_ads_group(struct net_context *c, int argc, const char **argv)
3370 return net_ads_noads();
3373 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
3375 return net_ads_noads();
3378 /* this one shouldn't display a message */
3379 int net_ads_check(struct net_context *c)
3381 return -1;
3384 int net_ads_check_our_domain(struct net_context *c)
3386 return -1;
3389 int net_ads(struct net_context *c, int argc, const char **argv)
3391 return net_ads_noads();
3394 #endif /* HAVE_ADS */