2 Samba Unix/Linux SMB client library
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "utils/net.h"
25 #include "libsmb/namequery.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "librpc/gen_ndr/ndr_krb5pac.h"
28 #include "../librpc/gen_ndr/ndr_spoolss.h"
29 #include "nsswitch/libwbclient/wbclient.h"
31 #include "libads/cldap.h"
32 #include "../lib/addns/dnsquery.h"
33 #include "../libds/common/flags.h"
34 #include "librpc/gen_ndr/libnet_join.h"
35 #include "libnet/libnet_join.h"
39 #include "../libcli/security/security.h"
40 #include "libsmb/libsmb.h"
41 #include "lib/param/loadparm.h"
42 #include "utils/net_dns.h"
43 #include "auth/kerberos/pac_utils.h"
44 #include "lib/util/string_wrappers.h"
48 #include "audit_logging.h" /* various JSON helpers */
49 #include "auth/common_auth.h"
50 #endif /* [HAVE_JANSSON] */
54 /* when we do not have sufficient input parameters to contact a remote domain
55 * we always fall back to our own realm - Guenther*/
57 static const char *assume_own_realm(struct net_context *c)
59 if (!c->opt_host && strequal(lp_workgroup(), c->opt_target_workgroup)) {
69 * note: JSON output deliberately bypasses gettext so as to provide the same
70 * output irrespective of the locale.
73 static int output_json(const struct json_object *jsobj)
75 TALLOC_CTX *ctx = NULL;
78 if (json_is_invalid(jsobj)) {
82 ctx = talloc_new(NULL);
84 d_fprintf(stderr, _("Out of memory\n"));
88 json = json_to_string(ctx, jsobj);
90 d_fprintf(stderr, _("error encoding to JSON\n"));
94 d_printf("%s\n", json);
100 static int net_ads_cldap_netlogon_json
103 const struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply)
105 struct json_object jsobj = json_new_object();
106 struct json_object flagsobj = json_new_object();
107 char response_type [32] = { '\0' };
110 if (json_is_invalid(&jsobj) || json_is_invalid(&flagsobj)) {
111 d_fprintf(stderr, _("error setting up JSON value\n"));
116 switch (reply->command) {
117 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
118 strncpy(response_type,
119 "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
120 sizeof(response_type));
122 case LOGON_SAM_LOGON_RESPONSE_EX:
123 strncpy(response_type, "LOGON_SAM_LOGON_RESPONSE_EX",
124 sizeof(response_type));
127 snprintf(response_type, sizeof(response_type), "0x%x",
132 ret = json_add_string(&jsobj, "Information for Domain Controller",
138 ret = json_add_string(&jsobj, "Response Type", response_type);
143 ret = json_add_guid(&jsobj, "GUID", &reply->domain_uuid);
148 ret = json_add_bool(&flagsobj, "Is a PDC",
149 reply->server_type & NBT_SERVER_PDC);
154 ret = json_add_bool(&flagsobj, "Is a GC of the forest",
155 reply->server_type & NBT_SERVER_GC);
160 ret = json_add_bool(&flagsobj, "Is an LDAP server",
161 reply->server_type & NBT_SERVER_LDAP);
166 ret = json_add_bool(&flagsobj, "Supports DS",
167 reply->server_type & NBT_SERVER_DS);
172 ret = json_add_bool(&flagsobj, "Is running a KDC",
173 reply->server_type & NBT_SERVER_KDC);
178 ret = json_add_bool(&flagsobj, "Is running time services",
179 reply->server_type & NBT_SERVER_TIMESERV);
184 ret = json_add_bool(&flagsobj, "Is the closest DC",
185 reply->server_type & NBT_SERVER_CLOSEST);
190 ret = json_add_bool(&flagsobj, "Is writable",
191 reply->server_type & NBT_SERVER_WRITABLE);
196 ret = json_add_bool(&flagsobj, "Has a hardware clock",
197 reply->server_type & NBT_SERVER_GOOD_TIMESERV);
202 ret = json_add_bool(&flagsobj,
203 "Is a non-domain NC serviced by LDAP server",
204 reply->server_type & NBT_SERVER_NDNC);
210 (&flagsobj, "Is NT6 DC that has some secrets",
211 reply->server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6);
217 (&flagsobj, "Is NT6 DC that has all secrets",
218 reply->server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6);
223 ret = json_add_bool(&flagsobj, "Runs Active Directory Web Services",
224 reply->server_type & NBT_SERVER_ADS_WEB_SERVICE);
229 ret = json_add_bool(&flagsobj, "Runs on Windows 2012 or later",
230 reply->server_type & NBT_SERVER_DS_8);
235 ret = json_add_string(&jsobj, "Forest", reply->forest);
240 ret = json_add_string(&jsobj, "Domain", reply->dns_domain);
245 ret = json_add_string(&jsobj, "Domain Controller", reply->pdc_dns_name);
251 ret = json_add_string(&jsobj, "Pre-Win2k Domain", reply->domain_name);
256 ret = json_add_string(&jsobj, "Pre-Win2k Hostname", reply->pdc_name);
261 if (*reply->user_name) {
262 ret = json_add_string(&jsobj, "User name", reply->user_name);
268 ret = json_add_string(&jsobj, "Server Site Name", reply->server_site);
273 ret = json_add_string(&jsobj, "Client Site Name", reply->client_site);
278 ret = json_add_int(&jsobj, "NT Version", reply->nt_version);
283 ret = json_add_int(&jsobj, "LMNT Token", reply->lmnt_token);
288 ret = json_add_int(&jsobj, "LM20 Token", reply->lm20_token);
293 ret = json_add_object(&jsobj, "Flags", &flagsobj);
298 ret = output_json(&jsobj);
299 json_free(&jsobj); /* frees flagsobj recursively */
304 json_free(&flagsobj);
310 #else /* [HAVE_JANSSON] */
312 static int net_ads_cldap_netlogon_json
315 const struct NETLOGON_SAM_LOGON_RESPONSE_EX * reply)
317 d_fprintf(stderr, _("JSON support not available\n"));
322 #endif /* [HAVE_JANSSON] */
325 do a cldap netlogon query
327 static int net_ads_cldap_netlogon(struct net_context *c, ADS_STRUCT *ads)
329 char addr[INET6_ADDRSTRLEN];
330 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
332 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
334 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads->ldap.ss, ads->server.realm, &reply ) ) {
335 d_fprintf(stderr, _("CLDAP query failed!\n"));
340 return net_ads_cldap_netlogon_json(ads, addr, &reply);
343 d_printf(_("Information for Domain Controller: %s\n\n"),
346 d_printf(_("Response Type: "));
347 switch (reply.command) {
348 case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
349 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
351 case LOGON_SAM_LOGON_RESPONSE_EX:
352 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
355 d_printf("0x%x\n", reply.command);
359 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply.domain_uuid));
361 d_printf(_("Flags:\n"
363 "\tIs a GC of the forest: %s\n"
364 "\tIs an LDAP server: %s\n"
365 "\tSupports DS: %s\n"
366 "\tIs running a KDC: %s\n"
367 "\tIs running time services: %s\n"
368 "\tIs the closest DC: %s\n"
369 "\tIs writable: %s\n"
370 "\tHas a hardware clock: %s\n"
371 "\tIs a non-domain NC serviced by LDAP server: %s\n"
372 "\tIs NT6 DC that has some secrets: %s\n"
373 "\tIs NT6 DC that has all secrets: %s\n"
374 "\tRuns Active Directory Web Services: %s\n"
375 "\tRuns on Windows 2012 or later: %s\n"),
376 (reply.server_type & NBT_SERVER_PDC) ? _("yes") : _("no"),
377 (reply.server_type & NBT_SERVER_GC) ? _("yes") : _("no"),
378 (reply.server_type & NBT_SERVER_LDAP) ? _("yes") : _("no"),
379 (reply.server_type & NBT_SERVER_DS) ? _("yes") : _("no"),
380 (reply.server_type & NBT_SERVER_KDC) ? _("yes") : _("no"),
381 (reply.server_type & NBT_SERVER_TIMESERV) ? _("yes") : _("no"),
382 (reply.server_type & NBT_SERVER_CLOSEST) ? _("yes") : _("no"),
383 (reply.server_type & NBT_SERVER_WRITABLE) ? _("yes") : _("no"),
384 (reply.server_type & NBT_SERVER_GOOD_TIMESERV) ? _("yes") : _("no"),
385 (reply.server_type & NBT_SERVER_NDNC) ? _("yes") : _("no"),
386 (reply.server_type & NBT_SERVER_SELECT_SECRET_DOMAIN_6) ? _("yes") : _("no"),
387 (reply.server_type & NBT_SERVER_FULL_SECRET_DOMAIN_6) ? _("yes") : _("no"),
388 (reply.server_type & NBT_SERVER_ADS_WEB_SERVICE) ? _("yes") : _("no"),
389 (reply.server_type & NBT_SERVER_DS_8) ? _("yes") : _("no"));
392 printf(_("Forest: %s\n"), reply.forest);
393 printf(_("Domain: %s\n"), reply.dns_domain);
394 printf(_("Domain Controller: %s\n"), reply.pdc_dns_name);
396 printf(_("Pre-Win2k Domain: %s\n"), reply.domain_name);
397 printf(_("Pre-Win2k Hostname: %s\n"), reply.pdc_name);
399 if (*reply.user_name) printf(_("User name: %s\n"), reply.user_name);
401 printf(_("Server Site Name: %s\n"), reply.server_site);
402 printf(_("Client Site Name: %s\n"), reply.client_site);
404 d_printf(_("NT Version: %d\n"), reply.nt_version);
405 d_printf(_("LMNT Token: %.2x\n"), reply.lmnt_token);
406 d_printf(_("LM20 Token: %.2x\n"), reply.lm20_token);
412 this implements the CLDAP based netlogon lookup requests
413 for finding the domain controller of a ADS domain
415 static int net_ads_lookup(struct net_context *c, int argc, const char **argv)
417 TALLOC_CTX *tmp_ctx = talloc_stackframe();
418 ADS_STRUCT *ads = NULL;
422 if (c->display_usage) {
427 _("Find the ADS DC using CLDAP lookup.\n"));
428 TALLOC_FREE(tmp_ctx);
432 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
433 if (!ADS_ERR_OK(status)) {
434 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
438 if (!ads->config.realm) {
439 ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
440 ads->ldap.port = 389;
443 ret = net_ads_cldap_netlogon(c, ads);
446 TALLOC_FREE(tmp_ctx);
453 static int net_ads_info_json(ADS_STRUCT *ads)
456 char addr[INET6_ADDRSTRLEN];
458 struct json_object jsobj = json_new_object();
460 if (json_is_invalid(&jsobj)) {
461 d_fprintf(stderr, _("error setting up JSON value\n"));
466 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
468 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
470 ret = json_add_string (&jsobj, "LDAP server", addr);
475 ret = json_add_string (&jsobj, "LDAP server name",
476 ads->config.ldap_server_name);
481 ret = json_add_string (&jsobj, "Realm", ads->config.realm);
486 ret = json_add_string (&jsobj, "Bind Path", ads->config.bind_path);
491 ret = json_add_int (&jsobj, "LDAP port", ads->ldap.port);
496 ret = json_add_int (&jsobj, "Server time", ads->config.current_time);
501 ret = json_add_string (&jsobj, "KDC server", ads->auth.kdc_server);
506 ret = json_add_int (&jsobj, "Server time offset",
507 ads->auth.time_offset);
512 ret = json_add_int (&jsobj, "Last machine account password change",
518 ret = output_json(&jsobj);
525 #else /* [HAVE_JANSSON] */
527 static int net_ads_info_json(ADS_STRUCT *ads)
529 d_fprintf(stderr, _("JSON support not available\n"));
534 #endif /* [HAVE_JANSSON] */
538 static int net_ads_info(struct net_context *c, int argc, const char **argv)
540 TALLOC_CTX *tmp_ctx = talloc_stackframe();
541 ADS_STRUCT *ads = NULL;
543 char addr[INET6_ADDRSTRLEN];
547 if (c->display_usage) {
552 _("Display information about an Active Directory "
554 TALLOC_FREE(tmp_ctx);
558 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
559 if (!ADS_ERR_OK(status)) {
560 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
564 if (!ads || !ads->config.realm) {
565 d_fprintf(stderr, _("Didn't find the ldap server!\n"));
569 /* Try to set the server's current time since we didn't do a full
570 TCP LDAP session initially */
572 if ( !ADS_ERR_OK(ads_current_time( ads )) ) {
573 d_fprintf( stderr, _("Failed to get server's current time!\n"));
577 ret = net_ads_info_json(ads);
581 pass_time = secrets_fetch_pass_last_set_time(ads->server.workgroup);
583 print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
585 d_printf(_("LDAP server: %s\n"), addr);
586 d_printf(_("LDAP server name: %s\n"), ads->config.ldap_server_name);
587 d_printf(_("Realm: %s\n"), ads->config.realm);
588 d_printf(_("Bind Path: %s\n"), ads->config.bind_path);
589 d_printf(_("LDAP port: %d\n"), ads->ldap.port);
590 d_printf(_("Server time: %s\n"),
591 http_timestring(tmp_ctx, ads->config.current_time));
593 d_printf(_("KDC server: %s\n"), ads->auth.kdc_server );
594 d_printf(_("Server time offset: %d\n"), ads->auth.time_offset );
596 d_printf(_("Last machine account password change: %s\n"),
597 http_timestring(tmp_ctx, pass_time));
602 TALLOC_FREE(tmp_ctx);
606 static ADS_STATUS ads_startup_int(struct net_context *c, bool only_own_domain,
607 uint32_t auth_flags, ADS_STRUCT **ads_ret)
609 ADS_STRUCT *ads = NULL;
611 bool need_password = false;
612 bool second_time = false;
614 const char *realm = NULL;
615 bool tried_closest_dc = false;
616 enum credentials_use_kerberos krb5_state =
617 CRED_USE_KERBEROS_DISABLED;
619 /* lp_realm() should be handled by a command line param,
620 However, the join requires that realm be set in smb.conf
621 and compares our realm with the remote server's so this is
622 ok until someone needs more flexibility */
627 if (only_own_domain) {
630 realm = assume_own_realm(c);
633 ads = ads_init(realm,
634 c->opt_target_workgroup,
638 if (!c->opt_user_name) {
639 c->opt_user_name = "administrator";
642 if (c->opt_user_specified) {
643 need_password = true;
647 if (!c->opt_password && need_password && !c->opt_machine_pass) {
648 c->opt_password = net_prompt_pass(c, c->opt_user_name);
649 if (!c->opt_password) {
651 return ADS_ERROR(LDAP_NO_MEMORY);
655 if (c->opt_password) {
656 use_in_memory_ccache();
657 SAFE_FREE(ads->auth.password);
658 ads->auth.password = smb_xstrdup(c->opt_password);
661 SAFE_FREE(ads->auth.user_name);
662 ads->auth.user_name = smb_xstrdup(c->opt_user_name);
664 ads->auth.flags |= auth_flags;
666 /* The ADS code will handle FIPS mode */
667 krb5_state = cli_credentials_get_kerberos_state(c->creds);
668 switch (krb5_state) {
669 case CRED_USE_KERBEROS_REQUIRED:
670 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
671 ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
673 case CRED_USE_KERBEROS_DESIRED:
674 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
675 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
677 case CRED_USE_KERBEROS_DISABLED:
678 ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
679 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
684 * If the username is of the form "name@realm",
685 * extract the realm and convert to upper case.
686 * This is only used to establish the connection.
688 if ((cp = strchr_m(ads->auth.user_name, '@'))!=0) {
690 SAFE_FREE(ads->auth.realm);
691 ads->auth.realm = smb_xstrdup(cp);
692 if (!strupper_m(ads->auth.realm)) {
694 return ADS_ERROR(LDAP_NO_MEMORY);
698 status = ads_connect(ads);
700 if (!ADS_ERR_OK(status)) {
702 if (NT_STATUS_EQUAL(ads_ntstatus(status),
703 NT_STATUS_NO_LOGON_SERVERS)) {
704 DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
709 if (!need_password && !second_time && !(auth_flags & ADS_AUTH_NO_BIND)) {
710 need_password = true;
719 /* when contacting our own domain, make sure we use the closest DC.
720 * This is done by reconnecting to ADS because only the first call to
721 * ads_connect will give us our own sitename */
723 if ((only_own_domain || !c->opt_host) && !tried_closest_dc) {
725 tried_closest_dc = true; /* avoid loop */
727 if (!ads_closest_dc(ads)) {
729 namecache_delete(ads->server.realm, 0x1C);
730 namecache_delete(ads->server.workgroup, 0x1C);
743 ADS_STATUS ads_startup(struct net_context *c, bool only_own_domain, ADS_STRUCT **ads)
745 return ads_startup_int(c, only_own_domain, 0, ads);
748 ADS_STATUS ads_startup_nobind(struct net_context *c,
749 bool only_own_domain,
753 return ads_startup_int(c, only_own_domain, ADS_AUTH_NO_BIND, ads);
757 Check to see if connection can be made via ads.
758 ads_startup() stores the password in opt_password if it needs to so
759 that rpc or rap can use it without re-prompting.
761 static int net_ads_check_int(const char *realm, const char *workgroup, const char *host)
766 ads = ads_init(realm, workgroup, host, ADS_SASL_PLAIN);
771 ads->auth.flags |= ADS_AUTH_NO_BIND;
773 status = ads_connect(ads);
774 if ( !ADS_ERR_OK(status) ) {
782 int net_ads_check_our_domain(struct net_context *c)
784 return net_ads_check_int(lp_realm(), lp_workgroup(), NULL);
787 int net_ads_check(struct net_context *c)
789 return net_ads_check_int(NULL, c->opt_workgroup, c->opt_host);
793 determine the netbios workgroup name for a domain
795 static int net_ads_workgroup(struct net_context *c, int argc, const char **argv)
797 TALLOC_CTX *tmp_ctx = talloc_stackframe();
798 ADS_STRUCT *ads = NULL;
800 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply;
804 if (c->display_usage) {
806 "net ads workgroup\n"
809 _("Print the workgroup name"));
810 TALLOC_FREE(tmp_ctx);
814 status = ads_startup_nobind(c, false, tmp_ctx, &ads);
815 if (!ADS_ERR_OK(status)) {
816 d_fprintf(stderr, _("Didn't find the cldap server!\n"));
820 if (!ads->config.realm) {
821 ads->config.realm = discard_const_p(char, c->opt_target_workgroup);
822 ads->ldap.port = 389;
825 ok = ads_cldap_netlogon_5(tmp_ctx,
826 &ads->ldap.ss, ads->server.realm, &reply);
828 d_fprintf(stderr, _("CLDAP query failed!\n"));
832 d_printf(_("Workgroup: %s\n"), reply.domain_name);
837 TALLOC_FREE(tmp_ctx);
844 static bool usergrp_display(ADS_STRUCT *ads, char *field, void **values, void *data_area)
846 char **disp_fields = (char **) data_area;
848 if (!field) { /* must be end of record */
849 if (disp_fields[0]) {
850 if (!strchr_m(disp_fields[0], '$')) {
852 d_printf("%-21.21s %s\n",
853 disp_fields[0], disp_fields[1]);
855 d_printf("%s\n", disp_fields[0]);
858 SAFE_FREE(disp_fields[0]);
859 SAFE_FREE(disp_fields[1]);
862 if (!values) /* must be new field, indicate string field */
864 if (strcasecmp_m(field, "sAMAccountName") == 0) {
865 disp_fields[0] = SMB_STRDUP((char *) values[0]);
867 if (strcasecmp_m(field, "description") == 0)
868 disp_fields[1] = SMB_STRDUP((char *) values[0]);
872 static int net_ads_user_usage(struct net_context *c, int argc, const char **argv)
874 return net_user_usage(c, argc, argv);
877 static int ads_user_add(struct net_context *c, int argc, const char **argv)
879 TALLOC_CTX *tmp_ctx = talloc_stackframe();
880 ADS_STRUCT *ads = NULL;
883 LDAPMessage *res=NULL;
887 if (argc < 1 || c->display_usage) {
888 TALLOC_FREE(tmp_ctx);
889 return net_ads_user_usage(c, argc, argv);
892 status = ads_startup(c, false, &ads);
893 if (!ADS_ERR_OK(status)) {
897 status = ads_find_user_acct(ads, &res, argv[0]);
898 if (!ADS_ERR_OK(status)) {
899 d_fprintf(stderr, _("ads_user_add: %s\n"), ads_errstr(status));
903 if (ads_count_replies(ads, res)) {
904 d_fprintf(stderr, _("ads_user_add: User %s already exists\n"),
909 if (c->opt_container) {
910 ou_str = SMB_STRDUP(c->opt_container);
912 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
915 status = ads_add_user_acct(ads, argv[0], ou_str, c->opt_comment);
916 if (!ADS_ERR_OK(status)) {
917 d_fprintf(stderr, _("Could not add user %s: %s\n"), argv[0],
922 /* if no password is to be set, we're done */
924 d_printf(_("User %s added\n"), argv[0]);
929 /* try setting the password */
930 upn = talloc_asprintf(tmp_ctx,
938 status = ads_krb5_set_password(ads->auth.kdc_server, upn, argv[1],
939 ads->auth.time_offset);
940 if (ADS_ERR_OK(status)) {
941 d_printf(_("User %s added\n"), argv[0]);
947 /* password didn't set, delete account */
948 d_fprintf(stderr, _("Could not add user %s. "
949 "Error setting password %s\n"),
950 argv[0], ads_errstr(status));
952 ads_msgfree(ads, res);
955 status=ads_find_user_acct(ads, &res, argv[0]);
956 if (ADS_ERR_OK(status)) {
957 userdn = ads_get_dn(ads, tmp_ctx, res);
958 ads_del_dn(ads, userdn);
963 ads_msgfree(ads, res);
966 TALLOC_FREE(tmp_ctx);
970 static int ads_user_info(struct net_context *c, int argc, const char **argv)
972 TALLOC_CTX *tmp_ctx = talloc_stackframe();
973 ADS_STRUCT *ads = NULL;
975 LDAPMessage *res = NULL;
978 const char *attrs[] = {"memberOf", "primaryGroupID", NULL};
979 char *searchstring = NULL;
980 char **grouplist = NULL;
981 char *primary_group = NULL;
982 char *escaped_user = NULL;
983 struct dom_sid primary_group_sid;
985 enum wbcSidType type;
987 if (argc < 1 || c->display_usage) {
988 TALLOC_FREE(tmp_ctx);
989 return net_ads_user_usage(c, argc, argv);
992 escaped_user = escape_ldap_string(tmp_ctx, argv[0]);
995 _("ads_user_info: failed to escape user %s\n"),
1000 status = ads_startup(c, false, &ads);
1001 if (!ADS_ERR_OK(status)) {
1005 searchstring = talloc_asprintf(tmp_ctx,
1006 "(sAMAccountName=%s)",
1008 if (searchstring == NULL) {
1012 status = ads_search(ads, &res, searchstring, attrs);
1013 if (!ADS_ERR_OK(status)) {
1014 d_fprintf(stderr, _("ads_search: %s\n"), ads_errstr(status));
1018 if (!ads_pull_uint32(ads, res, "primaryGroupID", &group_rid)) {
1019 d_fprintf(stderr, _("ads_pull_uint32 failed\n"));
1023 status = ads_domain_sid(ads, &primary_group_sid);
1024 if (!ADS_ERR_OK(status)) {
1025 d_fprintf(stderr, _("ads_domain_sid: %s\n"), ads_errstr(status));
1029 sid_append_rid(&primary_group_sid, group_rid);
1031 wbc_status = wbcLookupSid((struct wbcDomainSid *)&primary_group_sid,
1032 NULL, /* don't look up domain */
1035 if (!WBC_ERROR_IS_OK(wbc_status)) {
1036 d_fprintf(stderr, "wbcLookupSid: %s\n",
1037 wbcErrorString(wbc_status));
1041 d_printf("%s\n", primary_group);
1043 wbcFreeMemory(primary_group);
1045 grouplist = ldap_get_values((LDAP *)ads->ldap.ld,
1046 (LDAPMessage *)res, "memberOf");
1051 for (i=0;grouplist[i];i++) {
1052 groupname = ldap_explode_dn(grouplist[i], 1);
1053 d_printf("%s\n", groupname[0]);
1054 ldap_value_free(groupname);
1056 ldap_value_free(grouplist);
1061 ads_msgfree(ads, res);
1063 TALLOC_FREE(tmp_ctx);
1067 static int ads_user_delete(struct net_context *c, int argc, const char **argv)
1069 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1070 ADS_STRUCT *ads = NULL;
1072 LDAPMessage *res = NULL;
1073 char *userdn = NULL;
1077 TALLOC_FREE(tmp_ctx);
1078 return net_ads_user_usage(c, argc, argv);
1081 status = ads_startup(c, false, &ads);
1082 if (!ADS_ERR_OK(status)) {
1086 status = ads_find_user_acct(ads, &res, argv[0]);
1087 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1088 d_printf(_("User %s does not exist.\n"), argv[0]);
1092 userdn = ads_get_dn(ads, tmp_ctx, res);
1093 if (userdn == NULL) {
1097 status = ads_del_dn(ads, userdn);
1098 if (!ADS_ERR_OK(status)) {
1099 d_fprintf(stderr, _("Error deleting user %s: %s\n"), argv[0],
1100 ads_errstr(status));
1104 d_printf(_("User %s deleted\n"), argv[0]);
1108 ads_msgfree(ads, res);
1110 TALLOC_FREE(tmp_ctx);
1114 int net_ads_user(struct net_context *c, int argc, const char **argv)
1116 struct functable func[] = {
1121 N_("Add an AD user"),
1122 N_("net ads user add\n"
1129 N_("Display information about an AD user"),
1130 N_("net ads user info\n"
1131 " Display information about an AD user")
1137 N_("Delete an AD user"),
1138 N_("net ads user delete\n"
1139 " Delete an AD user")
1141 {NULL, NULL, 0, NULL, NULL}
1143 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1144 ADS_STRUCT *ads = NULL;
1146 const char *shortattrs[] = {"sAMAccountName", NULL};
1147 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1148 char *disp_fields[2] = {NULL, NULL};
1152 TALLOC_FREE(tmp_ctx);
1153 return net_run_function(c, argc, argv, "net ads user", func);
1156 if (c->display_usage) {
1161 _("List AD users"));
1162 net_display_usage_from_functable(func);
1163 TALLOC_FREE(tmp_ctx);
1167 status = ads_startup(c, false, &ads);
1168 if (!ADS_ERR_OK(status)) {
1172 if (c->opt_long_list_entries)
1173 d_printf(_("\nUser name Comment"
1174 "\n-----------------------------\n"));
1176 status = ads_do_search_all_fn(ads,
1177 ads->config.bind_path,
1179 "(objectCategory=user)",
1180 c->opt_long_list_entries ?
1181 longattrs : shortattrs,
1184 if (!ADS_ERR_OK(status)) {
1191 TALLOC_FREE(tmp_ctx);
1195 static int net_ads_group_usage(struct net_context *c, int argc, const char **argv)
1197 return net_group_usage(c, argc, argv);
1200 static int ads_group_add(struct net_context *c, int argc, const char **argv)
1202 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1203 ADS_STRUCT *ads = NULL;
1205 LDAPMessage *res = NULL;
1207 char *ou_str = NULL;
1209 if (argc < 1 || c->display_usage) {
1210 TALLOC_FREE(tmp_ctx);
1211 return net_ads_group_usage(c, argc, argv);
1214 status = ads_startup(c, false, &ads);
1215 if (!ADS_ERR_OK(status)) {
1219 status = ads_find_user_acct(ads, &res, argv[0]);
1220 if (!ADS_ERR_OK(status)) {
1221 d_fprintf(stderr, _("ads_group_add: %s\n"), ads_errstr(status));
1225 if (ads_count_replies(ads, res)) {
1226 d_fprintf(stderr, _("ads_group_add: Group %s already exists\n"), argv[0]);
1230 if (c->opt_container) {
1231 ou_str = SMB_STRDUP(c->opt_container);
1233 ou_str = ads_default_ou_string(ads, DS_GUID_USERS_CONTAINER);
1236 status = ads_add_group_acct(ads, argv[0], ou_str, c->opt_comment);
1237 if (!ADS_ERR_OK(status)) {
1238 d_fprintf(stderr, _("Could not add group %s: %s\n"), argv[0],
1239 ads_errstr(status));
1243 d_printf(_("Group %s added\n"), argv[0]);
1247 ads_msgfree(ads, res);
1250 TALLOC_FREE(tmp_ctx);
1254 static int ads_group_delete(struct net_context *c, int argc, const char **argv)
1256 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1257 ADS_STRUCT *ads = NULL;
1259 LDAPMessage *res = NULL;
1260 char *groupdn = NULL;
1263 if (argc < 1 || c->display_usage) {
1264 TALLOC_FREE(tmp_ctx);
1265 return net_ads_group_usage(c, argc, argv);
1268 status = ads_startup(c, false, &ads);
1269 if (!ADS_ERR_OK(status)) {
1273 status = ads_find_user_acct(ads, &res, argv[0]);
1274 if (!ADS_ERR_OK(status) || ads_count_replies(ads, res) != 1) {
1275 d_printf(_("Group %s does not exist.\n"), argv[0]);
1279 groupdn = ads_get_dn(ads, tmp_ctx, res);
1280 if (groupdn == NULL) {
1284 status = ads_del_dn(ads, groupdn);
1285 if (!ADS_ERR_OK(status)) {
1286 d_fprintf(stderr, _("Error deleting group %s: %s\n"), argv[0],
1287 ads_errstr(status));
1290 d_printf(_("Group %s deleted\n"), argv[0]);
1294 ads_msgfree(ads, res);
1296 TALLOC_FREE(tmp_ctx);
1300 int net_ads_group(struct net_context *c, int argc, const char **argv)
1302 struct functable func[] = {
1307 N_("Add an AD group"),
1308 N_("net ads group add\n"
1315 N_("Delete an AD group"),
1316 N_("net ads group delete\n"
1317 " Delete an AD group")
1319 {NULL, NULL, 0, NULL, NULL}
1321 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1322 ADS_STRUCT *ads = NULL;
1324 const char *shortattrs[] = {"sAMAccountName", NULL};
1325 const char *longattrs[] = {"sAMAccountName", "description", NULL};
1326 char *disp_fields[2] = {NULL, NULL};
1330 TALLOC_FREE(tmp_ctx);
1331 return net_run_function(c, argc, argv, "net ads group", func);
1334 if (c->display_usage) {
1339 _("List AD groups"));
1340 net_display_usage_from_functable(func);
1341 TALLOC_FREE(tmp_ctx);
1345 status = ads_startup(c, false, &ads);
1346 if (!ADS_ERR_OK(status)) {
1350 if (c->opt_long_list_entries)
1351 d_printf(_("\nGroup name Comment"
1352 "\n-----------------------------\n"));
1354 status = ads_do_search_all_fn(ads,
1355 ads->config.bind_path,
1357 "(objectCategory=group)",
1358 c->opt_long_list_entries ?
1359 longattrs : shortattrs,
1362 if (!ADS_ERR_OK(status)) {
1369 TALLOC_FREE(tmp_ctx);
1373 static int net_ads_status(struct net_context *c, int argc, const char **argv)
1375 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1376 ADS_STRUCT *ads = NULL;
1378 LDAPMessage *res = NULL;
1381 if (c->display_usage) {
1386 _("Display machine account details"));
1387 TALLOC_FREE(tmp_ctx);
1391 status = ads_startup(c, true, &ads);
1392 if (!ADS_ERR_OK(status)) {
1396 status = ads_find_machine_acct(ads, &res, lp_netbios_name());
1397 if (!ADS_ERR_OK(status)) {
1398 d_fprintf(stderr, _("ads_find_machine_acct: %s\n"),
1399 ads_errstr(status));
1403 if (ads_count_replies(ads, res) == 0) {
1404 d_fprintf(stderr, _("No machine account for '%s' found\n"),
1413 ads_msgfree(ads, res);
1415 TALLOC_FREE(tmp_ctx);
1419 /*******************************************************************
1420 Leave an AD domain. Windows XP disables the machine account.
1421 We'll try the same. The old code would do an LDAP delete.
1422 That only worked using the machine creds because added the machine
1423 with full control to the computer object's ACL.
1424 *******************************************************************/
1426 static int net_ads_leave(struct net_context *c, int argc, const char **argv)
1428 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1429 struct libnet_UnjoinCtx *r = NULL;
1433 if (c->display_usage) {
1435 "net ads leave [--keep-account]\n"
1438 _("Leave an AD domain"));
1439 TALLOC_FREE(tmp_ctx);
1444 d_fprintf(stderr, _("No realm set, are we joined ?\n"));
1445 TALLOC_FREE(tmp_ctx);
1449 if (!c->opt_kerberos) {
1450 use_in_memory_ccache();
1454 d_fprintf(stderr, _("Could not initialise message context. "
1455 "Try running as root\n"));
1459 werr = libnet_init_UnjoinCtx(tmp_ctx, &r);
1460 if (!W_ERROR_IS_OK(werr)) {
1461 d_fprintf(stderr, _("Could not initialise unjoin context.\n"));
1466 r->in.use_kerberos = c->opt_kerberos;
1467 r->in.dc_name = c->opt_host;
1468 r->in.domain_name = lp_realm();
1469 r->in.admin_account = c->opt_user_name;
1470 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1471 r->in.modify_config = lp_config_backend_is_registry();
1473 /* Try to delete it, but if that fails, disable it. The
1474 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1475 r->in.unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1476 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
1477 if (c->opt_keep_account) {
1478 r->in.delete_machine_account = false;
1480 r->in.delete_machine_account = true;
1483 r->in.msg_ctx = c->msg_ctx;
1485 werr = libnet_Unjoin(tmp_ctx, r);
1486 if (!W_ERROR_IS_OK(werr)) {
1487 d_printf(_("Failed to leave domain: %s\n"),
1488 r->out.error_string ? r->out.error_string :
1489 get_friendly_werror_msg(werr));
1493 if (r->out.deleted_machine_account) {
1494 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1495 r->in.machine_name, r->out.dns_domain_name);
1500 /* We couldn't delete it - see if the disable succeeded. */
1501 if (r->out.disabled_machine_account) {
1502 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1503 r->in.machine_name, r->out.dns_domain_name);
1508 /* Based on what we requested, we shouldn't get here, but if
1509 we did, it means the secrets were removed, and therefore
1510 we have left the domain */
1511 d_fprintf(stderr, _("Machine '%s' Left domain '%s'\n"),
1512 r->in.machine_name, r->out.dns_domain_name);
1516 TALLOC_FREE(tmp_ctx);
1520 static ADS_STATUS net_ads_join_ok(struct net_context *c)
1522 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1523 ADS_STRUCT *ads = NULL;
1526 struct sockaddr_storage dcip;
1528 if (!secrets_init()) {
1529 DEBUG(1,("Failed to initialise secrets database\n"));
1530 TALLOC_FREE(tmp_ctx);
1531 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
1534 net_use_krb_machine_account(c);
1536 get_dc_name(lp_workgroup(), lp_realm(), dc_name, &dcip);
1538 status = ads_startup(c, true, &ads);
1539 if (!ADS_ERR_OK(status)) {
1543 status = ADS_ERROR_NT(NT_STATUS_OK);
1546 TALLOC_FREE(tmp_ctx);
1551 check that an existing join is OK
1553 int net_ads_testjoin(struct net_context *c, int argc, const char **argv)
1556 use_in_memory_ccache();
1558 if (c->display_usage) {
1560 "net ads testjoin\n"
1563 _("Test if the existing join is ok"));
1567 /* Display success or failure */
1568 status = net_ads_join_ok(c);
1569 if (!ADS_ERR_OK(status)) {
1570 fprintf(stderr, _("Join to domain is not valid: %s\n"),
1571 get_friendly_nt_error_msg(ads_ntstatus(status)));
1575 printf(_("Join is OK\n"));
1579 /*******************************************************************
1580 Simple config checks before beginning the join
1581 ********************************************************************/
1583 static WERROR check_ads_config( void )
1585 if (lp_server_role() != ROLE_DOMAIN_MEMBER ) {
1586 d_printf(_("Host is not configured as a member server.\n"));
1587 return WERR_INVALID_DOMAIN_ROLE;
1590 if (strlen(lp_netbios_name()) > 15) {
1591 d_printf(_("Our netbios name can be at most 15 chars long, "
1592 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1593 (unsigned int)strlen(lp_netbios_name()));
1594 return WERR_INVALID_COMPUTERNAME;
1597 if ( lp_security() == SEC_ADS && !*lp_realm()) {
1598 d_fprintf(stderr, _("realm must be set in in %s for ADS "
1599 "join to succeed.\n"), get_dyn_CONFIGFILE());
1600 return WERR_INVALID_PARAMETER;
1606 /*******************************************************************
1607 ********************************************************************/
1609 static int net_ads_join_usage(struct net_context *c, int argc, const char **argv)
1611 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1612 "Valid options:\n"));
1613 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1614 " The default is in the form netbiosname.dnsdomain\n"));
1615 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1616 " The default UPN is in the form host/netbiosname@REALM.\n"));
1617 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1618 " The OU string read from top to bottom without RDNs\n"
1619 " and delimited by a '/'.\n"
1620 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1621 " NB: A backslash '\\' is used as escape at multiple\n"
1622 " levels and may need to be doubled or even\n"
1623 " quadrupled. It is not used as a separator.\n"));
1624 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1625 " the join. The default password is random.\n"));
1626 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1627 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1628 " NB: osName and osVer must be specified together for\n"
1629 " either to take effect. The operatingSystemService\n"
1630 " attribute is then also set along with the two\n"
1631 " other attributes.\n"));
1632 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1633 " during the join.\n"
1634 " NB: If not specified then by default the samba\n"
1635 " version string is used instead.\n"));
1640 int net_ads_join(struct net_context *c, int argc, const char **argv)
1642 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1643 struct libnet_JoinCtx *r = NULL;
1644 const char *domain = lp_realm();
1645 WERROR werr = WERR_NERR_SETUPNOTJOINED;
1646 bool createupn = false;
1647 const char *dnshostname = NULL;
1648 const char *machineupn = NULL;
1649 const char *machine_password = NULL;
1650 const char *create_in_ou = NULL;
1652 const char *os_name = NULL;
1653 const char *os_version = NULL;
1654 const char *os_servicepack = NULL;
1655 bool modify_config = lp_config_backend_is_registry();
1656 enum libnetjoin_JoinDomNameType domain_name_type = JoinDomNameTypeDNS;
1659 if (c->display_usage) {
1660 TALLOC_FREE(tmp_ctx);
1661 return net_ads_join_usage(c, argc, argv);
1664 if (!modify_config) {
1665 werr = check_ads_config();
1666 if (!W_ERROR_IS_OK(werr)) {
1667 d_fprintf(stderr, _("Invalid configuration. Exiting....\n"));
1672 if (!c->opt_kerberos) {
1673 use_in_memory_ccache();
1676 werr = libnet_init_JoinCtx(tmp_ctx, &r);
1677 if (!W_ERROR_IS_OK(werr)) {
1681 /* process additional command line args */
1683 for ( i=0; i<argc; i++ ) {
1684 if ( !strncasecmp_m(argv[i], "dnshostname", strlen("dnshostname")) ) {
1685 dnshostname = get_string_param(argv[i]);
1687 else if ( !strncasecmp_m(argv[i], "createupn", strlen("createupn")) ) {
1689 machineupn = get_string_param(argv[i]);
1691 else if ( !strncasecmp_m(argv[i], "createcomputer", strlen("createcomputer")) ) {
1692 if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
1693 d_fprintf(stderr, _("Please supply a valid OU path.\n"));
1694 werr = WERR_INVALID_PARAMETER;
1698 else if ( !strncasecmp_m(argv[i], "osName", strlen("osName")) ) {
1699 if ( (os_name = get_string_param(argv[i])) == NULL ) {
1700 d_fprintf(stderr, _("Please supply a operating system name.\n"));
1701 werr = WERR_INVALID_PARAMETER;
1705 else if ( !strncasecmp_m(argv[i], "osVer", strlen("osVer")) ) {
1706 if ( (os_version = get_string_param(argv[i])) == NULL ) {
1707 d_fprintf(stderr, _("Please supply a valid operating system version.\n"));
1708 werr = WERR_INVALID_PARAMETER;
1712 else if ( !strncasecmp_m(argv[i], "osServicePack", strlen("osServicePack")) ) {
1713 if ( (os_servicepack = get_string_param(argv[i])) == NULL ) {
1714 d_fprintf(stderr, _("Please supply a valid servicepack identifier.\n"));
1715 werr = WERR_INVALID_PARAMETER;
1719 else if ( !strncasecmp_m(argv[i], "machinepass", strlen("machinepass")) ) {
1720 if ( (machine_password = get_string_param(argv[i])) == NULL ) {
1721 d_fprintf(stderr, _("Please supply a valid password to set as trust account password.\n"));
1722 werr = WERR_INVALID_PARAMETER;
1727 if (strchr(domain, '.') == NULL) {
1728 domain_name_type = JoinDomNameTypeUnknown;
1730 domain_name_type = JoinDomNameTypeDNS;
1736 d_fprintf(stderr, _("Please supply a valid domain name\n"));
1737 werr = WERR_INVALID_PARAMETER;
1742 d_fprintf(stderr, _("Could not initialise message context. "
1743 "Try running as root\n"));
1744 werr = WERR_ACCESS_DENIED;
1748 /* Do the domain join here */
1750 r->in.domain_name = domain;
1751 r->in.domain_name_type = domain_name_type;
1752 r->in.create_upn = createupn;
1753 r->in.upn = machineupn;
1754 r->in.dnshostname = dnshostname;
1755 r->in.account_ou = create_in_ou;
1756 r->in.os_name = os_name;
1757 r->in.os_version = os_version;
1758 r->in.os_servicepack = os_servicepack;
1759 r->in.dc_name = c->opt_host;
1760 r->in.admin_account = c->opt_user_name;
1761 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
1762 r->in.machine_password = machine_password;
1764 r->in.use_kerberos = c->opt_kerberos;
1765 r->in.modify_config = modify_config;
1766 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
1767 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
1768 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
1769 r->in.msg_ctx = c->msg_ctx;
1771 werr = libnet_Join(tmp_ctx, r);
1772 if (W_ERROR_EQUAL(werr, WERR_NERR_DCNOTFOUND) &&
1773 strequal(domain, lp_realm())) {
1774 r->in.domain_name = lp_workgroup();
1775 r->in.domain_name_type = JoinDomNameTypeNBT;
1776 werr = libnet_Join(tmp_ctx, r);
1778 if (!W_ERROR_IS_OK(werr)) {
1782 /* Check the short name of the domain */
1784 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
1785 d_printf(_("The workgroup in %s does not match the short\n"
1786 "domain name obtained from the server.\n"
1787 "Using the name [%s] from the server.\n"
1788 "You should set \"workgroup = %s\" in %s.\n"),
1789 get_dyn_CONFIGFILE(), r->out.netbios_domain_name,
1790 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
1793 d_printf(_("Using short domain name -- %s\n"), r->out.netbios_domain_name);
1795 if (r->out.dns_domain_name) {
1796 d_printf(_("Joined '%s' to dns domain '%s'\n"), r->in.machine_name,
1797 r->out.dns_domain_name);
1799 d_printf(_("Joined '%s' to domain '%s'\n"), r->in.machine_name,
1800 r->out.netbios_domain_name);
1803 /* print out informative error string in case there is one */
1804 if (r->out.error_string != NULL) {
1805 d_printf("%s\n", r->out.error_string);
1809 * We try doing the dns update (if it was compiled in
1810 * and if it was not disabled on the command line).
1811 * If the dns update fails, we still consider the join
1812 * operation as succeeded if we came this far.
1814 if (!c->opt_no_dns_updates) {
1815 net_ads_join_dns_updates(c, tmp_ctx, r);
1822 /* issue an overall failure message at the end. */
1823 d_printf(_("Failed to join domain: %s\n"),
1824 r && r->out.error_string ? r->out.error_string :
1825 get_friendly_werror_msg(werr));
1828 TALLOC_FREE(tmp_ctx);
1833 /*******************************************************************
1834 ********************************************************************/
1836 static int net_ads_dns_register(struct net_context *c, int argc, const char **argv)
1838 #if defined(HAVE_KRB5)
1843 const char *hostname = NULL;
1844 const char **addrs_list = NULL;
1845 struct sockaddr_storage *addrs = NULL;
1850 talloc_enable_leak_report();
1853 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1854 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1855 "detection of addresses in a clustered "
1857 c->display_usage = true;
1860 if (c->display_usage) {
1862 "net ads dns register [hostname [IP [IP...]]]\n"
1865 _("Register hostname with DNS\n"));
1869 if (!(ctx = talloc_init("net_ads_dns"))) {
1870 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1879 num_addrs = argc - 1;
1880 addrs_list = &argv[1];
1881 } else if (lp_clustering()) {
1882 addrs_list = lp_cluster_addresses();
1883 num_addrs = str_list_length(addrs_list);
1886 if (num_addrs > 0) {
1887 addrs = talloc_zero_array(ctx, struct sockaddr_storage, num_addrs);
1888 if (addrs == NULL) {
1889 d_fprintf(stderr, _("Error allocating memory!\n"));
1895 for (count = 0; count < num_addrs; count++) {
1896 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1897 d_fprintf(stderr, "%s '%s'.\n",
1898 _("Cannot interpret address"),
1905 status = ads_startup(c, true, &ads);
1906 if ( !ADS_ERR_OK(status) ) {
1907 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1912 ntstatus = net_update_dns_ext(c, ctx, ads, hostname, addrs, num_addrs, false);
1913 if (!NT_STATUS_IS_OK(ntstatus)) {
1914 d_fprintf( stderr, _("DNS update failed!\n") );
1915 ads_destroy( &ads );
1920 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1928 _("DNS update support not enabled at compile time!\n"));
1933 static int net_ads_dns_unregister(struct net_context *c,
1937 #if defined(HAVE_KRB5)
1942 const char *hostname = NULL;
1945 talloc_enable_leak_report();
1949 c->display_usage = true;
1952 if (c->display_usage) {
1954 "net ads dns unregister [hostname]\n"
1957 _("Remove all IP Address entires for a given\n"
1958 " hostname from the Active Directory server.\n"));
1962 if (!(ctx = talloc_init("net_ads_dns"))) {
1963 d_fprintf(stderr, _("Could not initialise talloc context\n"));
1967 /* Get the hostname for un-registering */
1970 status = ads_startup(c, true, &ads);
1971 if ( !ADS_ERR_OK(status) ) {
1972 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1977 ntstatus = net_update_dns_ext(c, ctx, ads, hostname, NULL, 0, true);
1978 if (!NT_STATUS_IS_OK(ntstatus)) {
1979 d_fprintf( stderr, _("DNS update failed!\n") );
1980 ads_destroy( &ads );
1985 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
1993 _("DNS update support not enabled at compile time!\n"));
1999 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2001 size_t num_names = 0;
2002 char **hostnames = NULL;
2004 struct samba_sockaddr *addrs = NULL;
2007 if (argc != 1 || c->display_usage) {
2012 _("net ads dns async <name>\n"),
2013 _(" Async look up hostname from the DNS server\n"
2014 " hostname\tName to look up\n"));
2018 status = ads_dns_lookup_a(talloc_tos(),
2023 if (!NT_STATUS_IS_OK(status)) {
2024 d_printf("Looking up A record for %s got error %s\n",
2029 d_printf("Async A record lookup - got %u names for %s\n",
2030 (unsigned int)num_names,
2032 for (i = 0; i < num_names; i++) {
2033 char addr_buf[INET6_ADDRSTRLEN];
2034 print_sockaddr(addr_buf,
2037 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2043 #if defined(HAVE_IPV6)
2044 status = ads_dns_lookup_aaaa(talloc_tos(),
2049 if (!NT_STATUS_IS_OK(status)) {
2050 d_printf("Looking up AAAA record for %s got error %s\n",
2055 d_printf("Async AAAA record lookup - got %u names for %s\n",
2056 (unsigned int)num_names,
2058 for (i = 0; i < num_names; i++) {
2059 char addr_buf[INET6_ADDRSTRLEN];
2060 print_sockaddr(addr_buf,
2063 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2073 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2075 struct functable func[] = {
2078 net_ads_dns_register,
2080 N_("Add host dns entry to AD"),
2081 N_("net ads dns register\n"
2082 " Add host dns entry to AD")
2086 net_ads_dns_unregister,
2088 N_("Remove host dns entry from AD"),
2089 N_("net ads dns unregister\n"
2090 " Remove host dns entry from AD")
2097 N_("net ads dns async\n"
2098 " Look up host using async DNS")
2100 {NULL, NULL, 0, NULL, NULL}
2103 return net_run_function(c, argc, argv, "net ads dns", func);
2106 /*******************************************************************
2107 ********************************************************************/
2109 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2112 "\nnet ads printer search <printer>"
2113 "\n\tsearch for a printer in the directory\n"
2114 "\nnet ads printer info <printer> <server>"
2115 "\n\tlookup info in directory for printer on server"
2116 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2117 "\nnet ads printer publish <printername>"
2118 "\n\tpublish printer in directory"
2119 "\n\t(note: printer name is required)\n"
2120 "\nnet ads printer remove <printername>"
2121 "\n\tremove printer from directory"
2122 "\n\t(note: printer name is required)\n"));
2126 /*******************************************************************
2127 ********************************************************************/
2129 static int net_ads_printer_search(struct net_context *c, int argc, const char **argv)
2133 LDAPMessage *res = NULL;
2135 if (c->display_usage) {
2137 "net ads printer search\n"
2140 _("List printers in the AD"));
2144 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2148 rc = ads_find_printers(ads, &res);
2150 if (!ADS_ERR_OK(rc)) {
2151 d_fprintf(stderr, _("ads_find_printer: %s\n"), ads_errstr(rc));
2152 ads_msgfree(ads, res);
2157 if (ads_count_replies(ads, res) == 0) {
2158 d_fprintf(stderr, _("No results found\n"));
2159 ads_msgfree(ads, res);
2165 ads_msgfree(ads, res);
2170 static int net_ads_printer_info(struct net_context *c, int argc, const char **argv)
2174 const char *servername, *printername;
2175 LDAPMessage *res = NULL;
2177 if (c->display_usage) {
2180 _("net ads printer info [printername [servername]]\n"
2181 " Display printer info from AD\n"
2182 " printername\tPrinter name or wildcard\n"
2183 " servername\tName of the print server\n"));
2187 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2192 printername = argv[0];
2198 servername = argv[1];
2200 servername = lp_netbios_name();
2203 rc = ads_find_printer_on_server(ads, &res, printername, servername);
2205 if (!ADS_ERR_OK(rc)) {
2206 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2207 servername, ads_errstr(rc));
2208 ads_msgfree(ads, res);
2213 if (ads_count_replies(ads, res) == 0) {
2214 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2215 ads_msgfree(ads, res);
2221 ads_msgfree(ads, res);
2227 static int net_ads_printer_publish(struct net_context *c, int argc, const char **argv)
2231 const char *servername, *printername;
2232 struct cli_state *cli = NULL;
2233 struct rpc_pipe_client *pipe_hnd = NULL;
2234 struct sockaddr_storage server_ss;
2236 TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
2237 ADS_MODLIST mods = ads_init_mods(mem_ctx);
2238 char *prt_dn, *srv_dn, **srv_cn;
2239 char *srv_cn_escaped = NULL, *printername_escaped = NULL;
2240 LDAPMessage *res = NULL;
2243 if (argc < 1 || c->display_usage) {
2246 _("net ads printer publish <printername> [servername]\n"
2247 " Publish printer in AD\n"
2248 " printername\tName of the printer\n"
2249 " servername\tName of the print server\n"));
2250 talloc_destroy(mem_ctx);
2254 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2255 talloc_destroy(mem_ctx);
2259 printername = argv[0];
2262 servername = argv[1];
2264 servername = lp_netbios_name();
2267 /* Get printer data from SPOOLSS */
2269 ok = resolve_name(servername, &server_ss, 0x20, false);
2271 d_fprintf(stderr, _("Could not find server %s\n"),
2274 talloc_destroy(mem_ctx);
2278 cli_credentials_set_kerberos_state(c->creds,
2279 CRED_USE_KERBEROS_REQUIRED,
2282 nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2286 CLI_FULL_CONNECTION_IPC);
2288 if (NT_STATUS_IS_ERR(nt_status)) {
2289 d_fprintf(stderr, _("Unable to open a connection to %s to "
2290 "obtain data for %s\n"),
2291 servername, printername);
2293 talloc_destroy(mem_ctx);
2297 /* Publish on AD server */
2299 ads_find_machine_acct(ads, &res, servername);
2301 if (ads_count_replies(ads, res) == 0) {
2302 d_fprintf(stderr, _("Could not find machine account for server "
2306 talloc_destroy(mem_ctx);
2310 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2311 srv_cn = ldap_explode_dn(srv_dn, 1);
2313 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2314 printername_escaped = escape_rdn_val_string_alloc(printername);
2315 if (!srv_cn_escaped || !printername_escaped) {
2316 SAFE_FREE(srv_cn_escaped);
2317 SAFE_FREE(printername_escaped);
2318 d_fprintf(stderr, _("Internal error, out of memory!"));
2320 talloc_destroy(mem_ctx);
2324 if (asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn) == -1) {
2325 SAFE_FREE(srv_cn_escaped);
2326 SAFE_FREE(printername_escaped);
2327 d_fprintf(stderr, _("Internal error, out of memory!"));
2329 talloc_destroy(mem_ctx);
2333 SAFE_FREE(srv_cn_escaped);
2334 SAFE_FREE(printername_escaped);
2336 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2337 if (!NT_STATUS_IS_OK(nt_status)) {
2338 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2342 talloc_destroy(mem_ctx);
2346 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
2350 talloc_destroy(mem_ctx);
2354 rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
2355 if (!ADS_ERR_OK(rc)) {
2356 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
2359 talloc_destroy(mem_ctx);
2363 d_printf("published printer\n");
2366 talloc_destroy(mem_ctx);
2371 static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
2375 const char *servername;
2377 LDAPMessage *res = NULL;
2379 if (argc < 1 || c->display_usage) {
2382 _("net ads printer remove <printername> [servername]\n"
2383 " Remove a printer from the AD\n"
2384 " printername\tName of the printer\n"
2385 " servername\tName of the print server\n"));
2389 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2394 servername = argv[1];
2396 servername = lp_netbios_name();
2399 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
2401 if (!ADS_ERR_OK(rc)) {
2402 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
2403 ads_msgfree(ads, res);
2408 if (ads_count_replies(ads, res) == 0) {
2409 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2410 ads_msgfree(ads, res);
2415 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2416 ads_msgfree(ads, res);
2417 rc = ads_del_dn(ads, prt_dn);
2418 TALLOC_FREE(prt_dn);
2420 if (!ADS_ERR_OK(rc)) {
2421 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
2430 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2432 struct functable func[] = {
2435 net_ads_printer_search,
2437 N_("Search for a printer"),
2438 N_("net ads printer search\n"
2439 " Search for a printer")
2443 net_ads_printer_info,
2445 N_("Display printer information"),
2446 N_("net ads printer info\n"
2447 " Display printer information")
2451 net_ads_printer_publish,
2453 N_("Publish a printer"),
2454 N_("net ads printer publish\n"
2455 " Publish a printer")
2459 net_ads_printer_remove,
2461 N_("Delete a printer"),
2462 N_("net ads printer remove\n"
2463 " Delete a printer")
2465 {NULL, NULL, 0, NULL, NULL}
2468 return net_run_function(c, argc, argv, "net ads printer", func);
2472 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2475 const char *auth_principal = cli_credentials_get_username(c->creds);
2476 const char *auth_password = cli_credentials_get_password(c->creds);
2477 const char *realm = NULL;
2478 const char *new_password = NULL;
2481 char pwd[256] = {0};
2484 if (c->display_usage) {
2487 _("net ads password <username>\n"
2488 " Change password for user\n"
2489 " username\tName of user to change password for\n"));
2493 if (auth_principal == NULL || auth_password == NULL) {
2494 d_fprintf(stderr, _("You must supply an administrator "
2495 "username/password\n"));
2500 d_fprintf(stderr, _("ERROR: You must say which username to "
2501 "change password for\n"));
2506 if (!strchr_m(user, '@')) {
2507 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
2513 use_in_memory_ccache();
2514 chr = strchr_m(auth_principal, '@');
2521 /* use the realm so we can eventually change passwords for users
2522 in realms other than default */
2523 ads = ads_init(realm, c->opt_workgroup, c->opt_host, ADS_SASL_PLAIN);
2528 /* we don't actually need a full connect, but it's the easy way to
2529 fill in the KDC's addresss */
2532 if (!ads->config.realm) {
2533 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2539 new_password = (const char *)argv[1];
2543 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2546 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2554 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2555 auth_password, user, new_password, ads->auth.time_offset);
2556 memset(pwd, '\0', sizeof(pwd));
2557 if (!ADS_ERR_OK(ret)) {
2558 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2563 d_printf(_("Password change for %s completed.\n"), user);
2569 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2572 char *host_principal;
2576 if (c->display_usage) {
2578 "net ads changetrustpw\n"
2581 _("Change the machine account's trust password"));
2585 if (!secrets_init()) {
2586 DEBUG(1,("Failed to initialise secrets database\n"));
2590 net_use_krb_machine_account(c);
2592 use_in_memory_ccache();
2594 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2598 fstrcpy(my_name, lp_netbios_name());
2599 if (!strlower_m(my_name)) {
2604 if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2608 d_printf(_("Changing password for principal: %s\n"), host_principal);
2610 ret = ads_change_trust_account_password(ads, host_principal);
2612 if (!ADS_ERR_OK(ret)) {
2613 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2615 SAFE_FREE(host_principal);
2619 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2621 if (USE_SYSTEM_KEYTAB) {
2622 d_printf(_("Attempting to update system keytab with new password.\n"));
2623 if (ads_keytab_create_default(ads)) {
2624 d_printf(_("Failed to update system keytab.\n"));
2629 SAFE_FREE(host_principal);
2635 help for net ads search
2637 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2640 "\nnet ads search <expression> <attributes...>\n"
2641 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2642 "The expression is a standard LDAP search expression, and the\n"
2643 "attributes are a list of LDAP fields to show in the results.\n\n"
2644 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2646 net_common_flags_usage(c, argc, argv);
2652 general ADS search function. Useful in diagnosing problems in ADS
2654 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2658 const char *ldap_exp;
2660 LDAPMessage *res = NULL;
2662 if (argc < 1 || c->display_usage) {
2663 return net_ads_search_usage(c, argc, argv);
2666 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2673 rc = ads_do_search_retry(ads, ads->config.bind_path,
2675 ldap_exp, attrs, &res);
2676 if (!ADS_ERR_OK(rc)) {
2677 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2682 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2684 /* dump the results */
2687 ads_msgfree(ads, res);
2695 help for net ads search
2697 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2700 "\nnet ads dn <dn> <attributes...>\n"
2701 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2702 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2703 "to show in the results\n\n"
2704 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2705 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2707 net_common_flags_usage(c, argc, argv);
2713 general ADS search function. Useful in diagnosing problems in ADS
2715 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2721 LDAPMessage *res = NULL;
2723 if (argc < 1 || c->display_usage) {
2724 return net_ads_dn_usage(c, argc, argv);
2727 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2734 rc = ads_do_search_all(ads, dn,
2736 "(objectclass=*)", attrs, &res);
2737 if (!ADS_ERR_OK(rc)) {
2738 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2743 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2745 /* dump the results */
2748 ads_msgfree(ads, res);
2755 help for net ads sid search
2757 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2760 "\nnet ads sid <sid> <attributes...>\n"
2761 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2762 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2763 "to show in the results\n\n"
2764 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2766 net_common_flags_usage(c, argc, argv);
2772 general ADS search function. Useful in diagnosing problems in ADS
2774 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2778 const char *sid_string;
2780 LDAPMessage *res = NULL;
2783 if (argc < 1 || c->display_usage) {
2784 return net_ads_sid_usage(c, argc, argv);
2787 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2791 sid_string = argv[0];
2794 if (!string_to_sid(&sid, sid_string)) {
2795 d_fprintf(stderr, _("could not convert sid\n"));
2800 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2801 if (!ADS_ERR_OK(rc)) {
2802 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2807 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2809 /* dump the results */
2812 ads_msgfree(ads, res);
2818 static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2823 if (c->display_usage) {
2825 "net ads keytab flush\n"
2828 _("Delete the whole keytab"));
2832 if (!c->opt_user_specified && c->opt_password == NULL) {
2833 net_use_krb_machine_account(c);
2836 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2839 ret = ads_keytab_flush(ads);
2844 static int net_ads_keytab_add(struct net_context *c,
2853 if (c->display_usage) {
2856 _("net ads keytab add <principal> [principal ...]\n"
2857 " Add principals to local keytab\n"
2858 " principal\tKerberos principal to add to "
2863 d_printf(_("Processing principals to add...\n"));
2865 if (!c->opt_user_specified && c->opt_password == NULL) {
2866 net_use_krb_machine_account(c);
2869 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2872 for (i = 0; i < argc; i++) {
2873 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
2879 static int net_ads_keytab_add_default(struct net_context *c,
2883 return net_ads_keytab_add(c, argc, argv, false);
2886 static int net_ads_keytab_add_update_ads(struct net_context *c,
2890 return net_ads_keytab_add(c, argc, argv, true);
2893 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2898 if (c->display_usage) {
2900 "net ads keytab create\n"
2903 _("Create new default keytab"));
2907 if (!c->opt_user_specified && c->opt_password == NULL) {
2908 net_use_krb_machine_account(c);
2911 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2914 ret = ads_keytab_create_default(ads);
2919 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2921 const char *keytab = NULL;
2923 if (c->display_usage) {
2926 _("net ads keytab list [keytab]\n"
2927 " List a local keytab\n"
2928 " keytab\tKeytab to list\n"));
2936 return ads_keytab_list(keytab);
2940 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2942 struct functable func[] = {
2945 net_ads_keytab_add_default,
2947 N_("Add a service principal"),
2948 N_("net ads keytab add\n"
2949 " Add a service principal, updates keytab file only.")
2953 net_ads_keytab_add_update_ads,
2955 N_("Add a service principal"),
2956 N_("net ads keytab add_update_ads\n"
2957 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
2961 net_ads_keytab_create,
2963 N_("Create a fresh keytab"),
2964 N_("net ads keytab create\n"
2965 " Create a fresh keytab or update existing one.")
2969 net_ads_keytab_flush,
2971 N_("Remove all keytab entries"),
2972 N_("net ads keytab flush\n"
2973 " Remove all keytab entries")
2977 net_ads_keytab_list,
2979 N_("List a keytab"),
2980 N_("net ads keytab list\n"
2983 {NULL, NULL, 0, NULL, NULL}
2986 if (!USE_KERBEROS_KEYTAB) {
2987 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
2988 "keytab method to use keytab functions.\n"));
2991 return net_run_function(c, argc, argv, "net ads keytab", func);
2994 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
2998 if (c->display_usage) {
3000 "net ads kerberos renew\n"
3003 _("Renew TGT from existing credential cache"));
3007 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3009 d_printf(_("failed to renew kerberos ticket: %s\n"),
3010 error_message(ret));
3015 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3016 struct PAC_DATA_CTR **pac_data_ctr)
3020 const char *impersonate_princ_s = NULL;
3021 const char *local_service = NULL;
3024 for (i=0; i<argc; i++) {
3025 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3026 impersonate_princ_s = get_string_param(argv[i]);
3027 if (impersonate_princ_s == NULL) {
3031 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3032 local_service = get_string_param(argv[i]);
3033 if (local_service == NULL) {
3039 if (local_service == NULL) {
3040 local_service = talloc_asprintf(c, "%s$@%s",
3041 lp_netbios_name(), lp_realm());
3042 if (local_service == NULL) {
3047 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3049 status = kerberos_return_pac(c,
3058 2592000, /* one month */
3059 impersonate_princ_s,
3064 if (!NT_STATUS_IS_OK(status)) {
3065 d_printf(_("failed to query kerberos PAC: %s\n"),
3075 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3077 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3080 enum PAC_TYPE type = 0;
3082 if (c->display_usage) {
3084 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3087 _("Dump the Kerberos PAC"));
3091 for (i=0; i<argc; i++) {
3092 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3093 type = get_int_param(argv[i]);
3097 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3106 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3107 pac_data_ctr->pac_data);
3109 d_printf(_("The Pac: %s\n"), s);
3116 num_buffers = pac_data_ctr->pac_data->num_buffers;
3118 for (i=0; i<num_buffers; i++) {
3122 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3126 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3127 pac_data_ctr->pac_data->buffers[i].info);
3129 d_printf(_("The Pac: %s\n"), s);
3138 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3140 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3141 char *filename = NULL;
3145 if (c->display_usage) {
3147 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3150 _("Save the Kerberos PAC"));
3154 for (i=0; i<argc; i++) {
3155 if (strnequal(argv[i], "filename", strlen("filename"))) {
3156 filename = get_string_param(argv[i]);
3157 if (filename == NULL) {
3163 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3168 if (filename == NULL) {
3169 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3173 /* save the raw format */
3174 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3175 d_printf(_("failed to save PAC in %s\n"), filename);
3182 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3184 struct functable func[] = {
3187 net_ads_kerberos_pac_dump,
3189 N_("Dump Kerberos PAC"),
3190 N_("net ads kerberos pac dump\n"
3191 " Dump a Kerberos PAC to stdout")
3195 net_ads_kerberos_pac_save,
3197 N_("Save Kerberos PAC"),
3198 N_("net ads kerberos pac save\n"
3199 " Save a Kerberos PAC in a file")
3202 {NULL, NULL, 0, NULL, NULL}
3205 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3208 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3210 TALLOC_CTX *mem_ctx = NULL;
3214 if (c->display_usage) {
3216 "net ads kerberos kinit\n"
3219 _("Get Ticket Granting Ticket (TGT) for the user"));
3223 mem_ctx = talloc_init("net_ads_kerberos_kinit");
3228 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3230 ret = kerberos_kinit_password_ext(c->opt_user_name,
3238 2592000, /* one month */
3244 d_printf(_("failed to kinit password: %s\n"),
3251 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3253 struct functable func[] = {
3256 net_ads_kerberos_kinit,
3258 N_("Retrieve Ticket Granting Ticket (TGT)"),
3259 N_("net ads kerberos kinit\n"
3260 " Receive Ticket Granting Ticket (TGT)")
3264 net_ads_kerberos_renew,
3266 N_("Renew Ticket Granting Ticket from credential cache"),
3267 N_("net ads kerberos renew\n"
3268 " Renew Ticket Granting Ticket (TGT) from "
3273 net_ads_kerberos_pac,
3275 N_("Dump Kerberos PAC"),
3276 N_("net ads kerberos pac\n"
3277 " Dump Kerberos PAC")
3279 {NULL, NULL, 0, NULL, NULL}
3282 return net_run_function(c, argc, argv, "net ads kerberos", func);
3285 static int net_ads_setspn_list(struct net_context *c, int argc, const char **argv)
3289 ADS_STRUCT *ads = NULL;
3290 if (c->display_usage) {
3293 _("net ads setspn list <machinename>\n"));
3297 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
3302 ok = ads_setspn_list(ads, argv[0]);
3304 ok = ads_setspn_list(ads, lp_netbios_name());
3316 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3320 ADS_STRUCT *ads = NULL;
3321 if (c->display_usage || argc < 1) {
3324 _("net ads setspn add <machinename> SPN\n"));
3328 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
3333 ok = ads_setspn_add(ads, argv[0], argv[1]);
3335 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3347 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3351 ADS_STRUCT *ads = NULL;
3352 if (c->display_usage || argc < 1) {
3355 _("net ads setspn delete <machinename> SPN\n"));
3359 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
3364 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3366 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3378 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3380 struct functable func[] = {
3383 net_ads_setspn_list,
3385 N_("List Service Principal Names (SPN)"),
3386 N_("net ads setspn list machine\n"
3387 " List Service Principal Names (SPN)")
3393 N_("Add Service Principal Names (SPN)"),
3394 N_("net ads setspn add machine spn\n"
3395 " Add Service Principal Names (SPN)")
3399 net_ads_setspn_delete,
3401 N_("Delete Service Principal Names (SPN)"),
3402 N_("net ads setspn delete machine spn\n"
3403 " Delete Service Principal Names (SPN)")
3405 {NULL, NULL, 0, NULL, NULL}
3408 return net_run_function(c, argc, argv, "net ads setspn", func);
3411 static int net_ads_enctype_lookup_account(struct net_context *c,
3413 const char *account,
3415 const char **enctype_str)
3418 const char *attrs[] = {
3419 "msDS-SupportedEncryptionTypes",
3426 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3428 if (filter == NULL) {
3432 status = ads_search(ads, res, filter, attrs);
3433 if (!ADS_ERR_OK(status)) {
3434 d_printf(_("no account found with filter: %s\n"), filter);
3438 count = ads_count_replies(ads, *res);
3443 d_printf(_("no account found with filter: %s\n"), filter);
3446 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3451 *enctype_str = ads_pull_string(ads, c, *res,
3452 "msDS-SupportedEncryptionTypes");
3453 if (*enctype_str == NULL) {
3454 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3464 static void net_ads_enctype_dump_enctypes(const char *username,
3465 const char *enctype_str)
3467 int enctypes = atoi(enctype_str);
3469 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3470 username, enctypes, enctypes);
3472 printf("[%s] 0x%08x DES-CBC-CRC\n",
3473 enctypes & ENC_CRC32 ? "X" : " ",
3475 printf("[%s] 0x%08x DES-CBC-MD5\n",
3476 enctypes & ENC_RSA_MD5 ? "X" : " ",
3478 printf("[%s] 0x%08x RC4-HMAC\n",
3479 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3481 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3482 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3483 ENC_HMAC_SHA1_96_AES128);
3484 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3485 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3486 ENC_HMAC_SHA1_96_AES256);
3489 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3493 ADS_STRUCT *ads = NULL;
3494 LDAPMessage *res = NULL;
3495 const char *str = NULL;
3497 if (c->display_usage || (argc < 1)) {
3499 "net ads enctypes list\n"
3502 _("List supported enctypes"));
3506 status = ads_startup(c, false, &ads);
3507 if (!ADS_ERR_OK(status)) {
3508 printf("startup failed\n");
3512 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3517 net_ads_enctype_dump_enctypes(argv[0], str);
3521 ads_msgfree(ads, res);
3527 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3532 LDAPMessage *res = NULL;
3533 const char *etype_list_str;
3536 uint32_t etype_list;
3539 if (c->display_usage || argc < 1) {
3541 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3544 _("Set supported enctypes"));
3548 status = ads_startup(c, false, &ads);
3549 if (!ADS_ERR_OK(status)) {
3550 printf("startup failed\n");
3554 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3559 dn = ads_get_dn(ads, c, res);
3564 etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
3565 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
3566 etype_list |= ENC_HMAC_SHA1_96_AES128;
3568 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
3569 etype_list |= ENC_HMAC_SHA1_96_AES256;
3572 if (argv[1] != NULL) {
3573 sscanf(argv[1], "%i", &etype_list);
3576 etype_list_str = talloc_asprintf(c, "%d", etype_list);
3577 if (!etype_list_str) {
3581 mods = ads_init_mods(c);
3586 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
3588 if (!ADS_ERR_OK(status)) {
3592 status = ads_gen_mod(ads, dn, mods);
3593 if (!ADS_ERR_OK(status)) {
3594 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3595 ads_errstr(status));
3599 ads_msgfree(ads, res);
3601 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3606 net_ads_enctype_dump_enctypes(argv[0], str);
3610 ads_msgfree(ads, res);
3616 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3621 LDAPMessage *res = NULL;
3625 if (c->display_usage || argc < 1) {
3627 "net ads enctypes delete <sAMAccountName>\n"
3630 _("Delete supported enctypes"));
3634 status = ads_startup(c, false, &ads);
3635 if (!ADS_ERR_OK(status)) {
3636 printf("startup failed\n");
3640 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3645 dn = ads_get_dn(ads, c, res);
3650 mods = ads_init_mods(c);
3655 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
3656 if (!ADS_ERR_OK(status)) {
3660 status = ads_gen_mod(ads, dn, mods);
3661 if (!ADS_ERR_OK(status)) {
3662 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3663 ads_errstr(status));
3670 ads_msgfree(ads, res);
3675 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3677 struct functable func[] = {
3680 net_ads_enctypes_list,
3682 N_("List the supported encryption types"),
3683 N_("net ads enctypes list\n"
3684 " List the supported encryption types")
3688 net_ads_enctypes_set,
3690 N_("Set the supported encryption types"),
3691 N_("net ads enctypes set\n"
3692 " Set the supported encryption types")
3696 net_ads_enctypes_delete,
3698 N_("Delete the supported encryption types"),
3699 N_("net ads enctypes delete\n"
3700 " Delete the supported encryption types")
3703 {NULL, NULL, 0, NULL, NULL}
3706 return net_run_function(c, argc, argv, "net ads enctypes", func);
3710 int net_ads(struct net_context *c, int argc, const char **argv)
3712 struct functable func[] = {
3717 N_("Display details on remote ADS server"),
3719 " Display details on remote ADS server")
3725 N_("Join the local machine to ADS realm"),
3727 " Join the local machine to ADS realm")
3733 N_("Validate machine account"),
3734 N_("net ads testjoin\n"
3735 " Validate machine account")
3741 N_("Remove the local machine from ADS"),
3742 N_("net ads leave\n"
3743 " Remove the local machine from ADS")
3749 N_("Display machine account details"),
3750 N_("net ads status\n"
3751 " Display machine account details")
3757 N_("List/modify users"),
3759 " List/modify users")
3765 N_("List/modify groups"),
3766 N_("net ads group\n"
3767 " List/modify groups")
3773 N_("Issue dynamic DNS update"),
3775 " Issue dynamic DNS update")
3781 N_("Change user passwords"),
3782 N_("net ads password\n"
3783 " Change user passwords")
3787 net_ads_changetrustpw,
3789 N_("Change trust account password"),
3790 N_("net ads changetrustpw\n"
3791 " Change trust account password")
3797 N_("List/modify printer entries"),
3798 N_("net ads printer\n"
3799 " List/modify printer entries")
3805 N_("Issue LDAP search using filter"),
3806 N_("net ads search\n"
3807 " Issue LDAP search using filter")
3813 N_("Issue LDAP search by DN"),
3815 " Issue LDAP search by DN")
3821 N_("Issue LDAP search by SID"),
3823 " Issue LDAP search by SID")
3829 N_("Display workgroup name"),
3830 N_("net ads workgroup\n"
3831 " Display the workgroup name")
3837 N_("Perform CLDAP query on DC"),
3838 N_("net ads lookup\n"
3839 " Find the ADS DC using CLDAP lookups")
3845 N_("Manage local keytab file"),
3846 N_("net ads keytab\n"
3847 " Manage local keytab file")
3853 N_("Manage Service Principal Names (SPN)s"),
3854 N_("net ads spnset\n"
3855 " Manage Service Principal Names (SPN)s")
3861 N_("Manage group policy objects"),
3863 " Manage group policy objects")
3869 N_("Manage kerberos keytab"),
3870 N_("net ads kerberos\n"
3871 " Manage kerberos keytab")
3877 N_("List/modify supported encryption types"),
3878 N_("net ads enctypes\n"
3879 " List/modify enctypes")
3881 {NULL, NULL, 0, NULL, NULL}
3884 return net_run_function(c, argc, argv, "net ads", func);
3889 static int net_ads_noads(void)
3891 d_fprintf(stderr, _("ADS support not compiled in\n"));
3895 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3897 return net_ads_noads();
3900 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3902 return net_ads_noads();
3905 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3907 return net_ads_noads();
3910 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
3912 return net_ads_noads();
3915 int net_ads_join(struct net_context *c, int argc, const char **argv)
3917 return net_ads_noads();
3920 int net_ads_user(struct net_context *c, int argc, const char **argv)
3922 return net_ads_noads();
3925 int net_ads_group(struct net_context *c, int argc, const char **argv)
3927 return net_ads_noads();
3930 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
3932 return net_ads_noads();
3935 /* this one shouldn't display a message */
3936 int net_ads_check(struct net_context *c)
3941 int net_ads_check_our_domain(struct net_context *c)
3946 int net_ads(struct net_context *c, int argc, const char **argv)
3948 return net_ads_noads();
3951 #endif /* HAVE_ADS */