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)
1839 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1840 ADS_STRUCT *ads = NULL;
1843 const char *hostname = NULL;
1844 const char **addrs_list = NULL;
1845 struct sockaddr_storage *addrs = NULL;
1851 talloc_enable_leak_report();
1854 if (argc <= 1 && lp_clustering() && lp_cluster_addresses() == NULL) {
1855 d_fprintf(stderr, _("Refusing DNS updates with automatic "
1856 "detection of addresses in a clustered "
1858 c->display_usage = true;
1861 if (c->display_usage) {
1863 "net ads dns register [hostname [IP [IP...]]]\n"
1866 _("Register hostname with DNS\n"));
1867 TALLOC_FREE(tmp_ctx);
1876 num_addrs = argc - 1;
1877 addrs_list = &argv[1];
1878 } else if (lp_clustering()) {
1879 addrs_list = lp_cluster_addresses();
1880 num_addrs = str_list_length(addrs_list);
1883 if (num_addrs > 0) {
1884 addrs = talloc_zero_array(tmp_ctx,
1885 struct sockaddr_storage,
1887 if (addrs == NULL) {
1888 d_fprintf(stderr, _("Error allocating memory!\n"));
1893 for (count = 0; count < num_addrs; count++) {
1894 if (!interpret_string_addr(&addrs[count], addrs_list[count], 0)) {
1895 d_fprintf(stderr, "%s '%s'.\n",
1896 _("Cannot interpret address"),
1902 status = ads_startup(c, true, &ads);
1903 if ( !ADS_ERR_OK(status) ) {
1904 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1908 ntstatus = net_update_dns_ext(c,
1915 if (!NT_STATUS_IS_OK(ntstatus)) {
1916 d_fprintf( stderr, _("DNS update failed!\n") );
1920 d_fprintf( stderr, _("Successfully registered hostname with DNS\n") );
1925 TALLOC_FREE(tmp_ctx);
1930 _("DNS update support not enabled at compile time!\n"));
1935 static int net_ads_dns_unregister(struct net_context *c,
1939 #if defined(HAVE_KRB5)
1940 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1941 ADS_STRUCT *ads = NULL;
1944 const char *hostname = NULL;
1948 talloc_enable_leak_report();
1952 c->display_usage = true;
1955 if (c->display_usage) {
1957 "net ads dns unregister [hostname]\n"
1960 _("Remove all IP Address entires for a given\n"
1961 " hostname from the Active Directory server.\n"));
1962 TALLOC_FREE(tmp_ctx);
1966 /* Get the hostname for un-registering */
1969 status = ads_startup(c, true, &ads);
1970 if ( !ADS_ERR_OK(status) ) {
1971 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status)));
1975 ntstatus = net_update_dns_ext(c,
1982 if (!NT_STATUS_IS_OK(ntstatus)) {
1983 d_fprintf( stderr, _("DNS update failed!\n") );
1987 d_fprintf( stderr, _("Successfully un-registered hostname from DNS\n"));
1992 TALLOC_FREE(tmp_ctx);
1997 _("DNS update support not enabled at compile time!\n"));
2003 static int net_ads_dns_async(struct net_context *c, int argc, const char **argv)
2005 size_t num_names = 0;
2006 char **hostnames = NULL;
2008 struct samba_sockaddr *addrs = NULL;
2011 if (argc != 1 || c->display_usage) {
2016 _("net ads dns async <name>\n"),
2017 _(" Async look up hostname from the DNS server\n"
2018 " hostname\tName to look up\n"));
2022 status = ads_dns_lookup_a(talloc_tos(),
2027 if (!NT_STATUS_IS_OK(status)) {
2028 d_printf("Looking up A record for %s got error %s\n",
2033 d_printf("Async A record lookup - got %u names for %s\n",
2034 (unsigned int)num_names,
2036 for (i = 0; i < num_names; i++) {
2037 char addr_buf[INET6_ADDRSTRLEN];
2038 print_sockaddr(addr_buf,
2041 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2047 #if defined(HAVE_IPV6)
2048 status = ads_dns_lookup_aaaa(talloc_tos(),
2053 if (!NT_STATUS_IS_OK(status)) {
2054 d_printf("Looking up AAAA record for %s got error %s\n",
2059 d_printf("Async AAAA record lookup - got %u names for %s\n",
2060 (unsigned int)num_names,
2062 for (i = 0; i < num_names; i++) {
2063 char addr_buf[INET6_ADDRSTRLEN];
2064 print_sockaddr(addr_buf,
2067 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2077 static int net_ads_dns(struct net_context *c, int argc, const char *argv[])
2079 struct functable func[] = {
2082 net_ads_dns_register,
2084 N_("Add host dns entry to AD"),
2085 N_("net ads dns register\n"
2086 " Add host dns entry to AD")
2090 net_ads_dns_unregister,
2092 N_("Remove host dns entry from AD"),
2093 N_("net ads dns unregister\n"
2094 " Remove host dns entry from AD")
2101 N_("net ads dns async\n"
2102 " Look up host using async DNS")
2104 {NULL, NULL, 0, NULL, NULL}
2107 return net_run_function(c, argc, argv, "net ads dns", func);
2110 /*******************************************************************
2111 ********************************************************************/
2113 int net_ads_printer_usage(struct net_context *c, int argc, const char **argv)
2116 "\nnet ads printer search <printer>"
2117 "\n\tsearch for a printer in the directory\n"
2118 "\nnet ads printer info <printer> <server>"
2119 "\n\tlookup info in directory for printer on server"
2120 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2121 "\nnet ads printer publish <printername>"
2122 "\n\tpublish printer in directory"
2123 "\n\t(note: printer name is required)\n"
2124 "\nnet ads printer remove <printername>"
2125 "\n\tremove printer from directory"
2126 "\n\t(note: printer name is required)\n"));
2130 /*******************************************************************
2131 ********************************************************************/
2133 static int net_ads_printer_search(struct net_context *c,
2137 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2138 ADS_STRUCT *ads = NULL;
2140 LDAPMessage *res = NULL;
2143 if (c->display_usage) {
2145 "net ads printer search\n"
2148 _("List printers in the AD"));
2149 TALLOC_FREE(tmp_ctx);
2153 status = ads_startup(c, false, &ads);
2154 if (!ADS_ERR_OK(status)) {
2158 status = ads_find_printers(ads, &res);
2159 if (!ADS_ERR_OK(status)) {
2160 d_fprintf(stderr, _("ads_find_printer: %s\n"),
2161 ads_errstr(status));
2165 if (ads_count_replies(ads, res) == 0) {
2166 d_fprintf(stderr, _("No results found\n"));
2174 ads_msgfree(ads, res);
2176 TALLOC_FREE(tmp_ctx);
2180 static int net_ads_printer_info(struct net_context *c,
2184 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2185 ADS_STRUCT *ads = NULL;
2187 const char *servername = NULL;
2188 const char *printername = NULL;
2189 LDAPMessage *res = NULL;
2192 if (c->display_usage) {
2195 _("net ads printer info [printername [servername]]\n"
2196 " Display printer info from AD\n"
2197 " printername\tPrinter name or wildcard\n"
2198 " servername\tName of the print server\n"));
2199 TALLOC_FREE(tmp_ctx);
2203 status = ads_startup(c, false, &ads);
2204 if (!ADS_ERR_OK(status)) {
2209 printername = argv[0];
2215 servername = argv[1];
2217 servername = lp_netbios_name();
2220 status = ads_find_printer_on_server(ads, &res, printername, servername);
2221 if (!ADS_ERR_OK(status)) {
2222 d_fprintf(stderr, _("Server '%s' not found: %s\n"),
2223 servername, ads_errstr(status));
2227 if (ads_count_replies(ads, res) == 0) {
2228 d_fprintf(stderr, _("Printer '%s' not found\n"), printername);
2236 ads_msgfree(ads, res);
2238 TALLOC_FREE(tmp_ctx);
2242 static int net_ads_printer_publish(struct net_context *c,
2246 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2247 ADS_STRUCT *ads = NULL;
2249 const char *servername = NULL;
2250 const char *printername = NULL;
2251 struct cli_state *cli = NULL;
2252 struct rpc_pipe_client *pipe_hnd = NULL;
2253 struct sockaddr_storage server_ss = { 0 };
2255 ADS_MODLIST mods = NULL;
2256 char *prt_dn = NULL;
2257 char *srv_dn = NULL;
2258 char **srv_cn = NULL;
2259 char *srv_cn_escaped = NULL;
2260 char *printername_escaped = NULL;
2261 LDAPMessage *res = NULL;
2265 if (argc < 1 || c->display_usage) {
2268 _("net ads printer publish <printername> [servername]\n"
2269 " Publish printer in AD\n"
2270 " printername\tName of the printer\n"
2271 " servername\tName of the print server\n"));
2272 TALLOC_FREE(tmp_ctx);
2276 mods = ads_init_mods(tmp_ctx);
2278 d_fprintf(stderr, _("Out of memory\n"));
2282 status = ads_startup(c, true, &ads);
2283 if (!ADS_ERR_OK(status)) {
2287 printername = argv[0];
2290 servername = argv[1];
2292 servername = lp_netbios_name();
2295 /* Get printer data from SPOOLSS */
2297 ok = resolve_name(servername, &server_ss, 0x20, false);
2299 d_fprintf(stderr, _("Could not find server %s\n"),
2304 cli_credentials_set_kerberos_state(c->creds,
2305 CRED_USE_KERBEROS_REQUIRED,
2308 nt_status = cli_full_connection_creds(&cli, lp_netbios_name(), servername,
2312 CLI_FULL_CONNECTION_IPC);
2314 if (NT_STATUS_IS_ERR(nt_status)) {
2315 d_fprintf(stderr, _("Unable to open a connection to %s to "
2316 "obtain data for %s\n"),
2317 servername, printername);
2321 /* Publish on AD server */
2323 ads_find_machine_acct(ads, &res, servername);
2325 if (ads_count_replies(ads, res) == 0) {
2326 d_fprintf(stderr, _("Could not find machine account for server "
2332 srv_dn = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
2333 srv_cn = ldap_explode_dn(srv_dn, 1);
2335 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
2336 printername_escaped = escape_rdn_val_string_alloc(printername);
2337 if (!srv_cn_escaped || !printername_escaped) {
2338 SAFE_FREE(srv_cn_escaped);
2339 SAFE_FREE(printername_escaped);
2340 d_fprintf(stderr, _("Internal error, out of memory!"));
2344 prt_dn = talloc_asprintf(tmp_ctx,
2347 printername_escaped,
2349 if (prt_dn == NULL) {
2350 SAFE_FREE(srv_cn_escaped);
2351 SAFE_FREE(printername_escaped);
2352 d_fprintf(stderr, _("Internal error, out of memory!"));
2356 SAFE_FREE(srv_cn_escaped);
2357 SAFE_FREE(printername_escaped);
2359 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_spoolss, &pipe_hnd);
2360 if (!NT_STATUS_IS_OK(nt_status)) {
2361 d_fprintf(stderr, _("Unable to open a connection to the spoolss pipe on %s\n"),
2366 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd,
2373 status = ads_add_printer_entry(ads, prt_dn, tmp_ctx, &mods);
2374 if (!ADS_ERR_OK(status)) {
2375 d_fprintf(stderr, "ads_publish_printer: %s\n",
2376 ads_errstr(status));
2380 d_printf("published printer\n");
2385 talloc_destroy(tmp_ctx);
2390 static int net_ads_printer_remove(struct net_context *c, int argc, const char **argv)
2394 const char *servername;
2396 LDAPMessage *res = NULL;
2398 if (argc < 1 || c->display_usage) {
2401 _("net ads printer remove <printername> [servername]\n"
2402 " Remove a printer from the AD\n"
2403 " printername\tName of the printer\n"
2404 " servername\tName of the print server\n"));
2408 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2413 servername = argv[1];
2415 servername = lp_netbios_name();
2418 rc = ads_find_printer_on_server(ads, &res, argv[0], servername);
2420 if (!ADS_ERR_OK(rc)) {
2421 d_fprintf(stderr, _("ads_find_printer_on_server: %s\n"), ads_errstr(rc));
2422 ads_msgfree(ads, res);
2427 if (ads_count_replies(ads, res) == 0) {
2428 d_fprintf(stderr, _("Printer '%s' not found\n"), argv[1]);
2429 ads_msgfree(ads, res);
2434 prt_dn = ads_get_dn(ads, talloc_tos(), res);
2435 ads_msgfree(ads, res);
2436 rc = ads_del_dn(ads, prt_dn);
2437 TALLOC_FREE(prt_dn);
2439 if (!ADS_ERR_OK(rc)) {
2440 d_fprintf(stderr, _("ads_del_dn: %s\n"), ads_errstr(rc));
2449 static int net_ads_printer(struct net_context *c, int argc, const char **argv)
2451 struct functable func[] = {
2454 net_ads_printer_search,
2456 N_("Search for a printer"),
2457 N_("net ads printer search\n"
2458 " Search for a printer")
2462 net_ads_printer_info,
2464 N_("Display printer information"),
2465 N_("net ads printer info\n"
2466 " Display printer information")
2470 net_ads_printer_publish,
2472 N_("Publish a printer"),
2473 N_("net ads printer publish\n"
2474 " Publish a printer")
2478 net_ads_printer_remove,
2480 N_("Delete a printer"),
2481 N_("net ads printer remove\n"
2482 " Delete a printer")
2484 {NULL, NULL, 0, NULL, NULL}
2487 return net_run_function(c, argc, argv, "net ads printer", func);
2491 static int net_ads_password(struct net_context *c, int argc, const char **argv)
2494 const char *auth_principal = cli_credentials_get_username(c->creds);
2495 const char *auth_password = cli_credentials_get_password(c->creds);
2496 const char *realm = NULL;
2497 const char *new_password = NULL;
2500 char pwd[256] = {0};
2503 if (c->display_usage) {
2506 _("net ads password <username>\n"
2507 " Change password for user\n"
2508 " username\tName of user to change password for\n"));
2512 if (auth_principal == NULL || auth_password == NULL) {
2513 d_fprintf(stderr, _("You must supply an administrator "
2514 "username/password\n"));
2519 d_fprintf(stderr, _("ERROR: You must say which username to "
2520 "change password for\n"));
2525 if (!strchr_m(user, '@')) {
2526 if (asprintf(&chr, "%s@%s", argv[0], lp_realm()) == -1) {
2532 use_in_memory_ccache();
2533 chr = strchr_m(auth_principal, '@');
2540 /* use the realm so we can eventually change passwords for users
2541 in realms other than default */
2542 ads = ads_init(realm, c->opt_workgroup, c->opt_host, ADS_SASL_PLAIN);
2547 /* we don't actually need a full connect, but it's the easy way to
2548 fill in the KDC's addresss */
2551 if (!ads->config.realm) {
2552 d_fprintf(stderr, _("Didn't find the kerberos server!\n"));
2558 new_password = (const char *)argv[1];
2562 if (asprintf(&prompt, _("Enter new password for %s:"), user) == -1) {
2565 rc = samba_getpass(prompt, pwd, sizeof(pwd), false, true);
2573 ret = kerberos_set_password(ads->auth.kdc_server, auth_principal,
2574 auth_password, user, new_password, ads->auth.time_offset);
2575 memset(pwd, '\0', sizeof(pwd));
2576 if (!ADS_ERR_OK(ret)) {
2577 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2582 d_printf(_("Password change for %s completed.\n"), user);
2588 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
2591 char *host_principal;
2595 if (c->display_usage) {
2597 "net ads changetrustpw\n"
2600 _("Change the machine account's trust password"));
2604 if (!secrets_init()) {
2605 DEBUG(1,("Failed to initialise secrets database\n"));
2609 net_use_krb_machine_account(c);
2611 use_in_memory_ccache();
2613 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2617 fstrcpy(my_name, lp_netbios_name());
2618 if (!strlower_m(my_name)) {
2623 if (asprintf(&host_principal, "%s$@%s", my_name, ads->config.realm) == -1) {
2627 d_printf(_("Changing password for principal: %s\n"), host_principal);
2629 ret = ads_change_trust_account_password(ads, host_principal);
2631 if (!ADS_ERR_OK(ret)) {
2632 d_fprintf(stderr, _("Password change failed: %s\n"), ads_errstr(ret));
2634 SAFE_FREE(host_principal);
2638 d_printf(_("Password change for principal %s succeeded.\n"), host_principal);
2640 if (USE_SYSTEM_KEYTAB) {
2641 d_printf(_("Attempting to update system keytab with new password.\n"));
2642 if (ads_keytab_create_default(ads)) {
2643 d_printf(_("Failed to update system keytab.\n"));
2648 SAFE_FREE(host_principal);
2654 help for net ads search
2656 static int net_ads_search_usage(struct net_context *c, int argc, const char **argv)
2659 "\nnet ads search <expression> <attributes...>\n"
2660 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2661 "The expression is a standard LDAP search expression, and the\n"
2662 "attributes are a list of LDAP fields to show in the results.\n\n"
2663 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2665 net_common_flags_usage(c, argc, argv);
2671 general ADS search function. Useful in diagnosing problems in ADS
2673 static int net_ads_search(struct net_context *c, int argc, const char **argv)
2677 const char *ldap_exp;
2679 LDAPMessage *res = NULL;
2681 if (argc < 1 || c->display_usage) {
2682 return net_ads_search_usage(c, argc, argv);
2685 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2692 rc = ads_do_search_retry(ads, ads->config.bind_path,
2694 ldap_exp, attrs, &res);
2695 if (!ADS_ERR_OK(rc)) {
2696 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2701 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2703 /* dump the results */
2706 ads_msgfree(ads, res);
2714 help for net ads search
2716 static int net_ads_dn_usage(struct net_context *c, int argc, const char **argv)
2719 "\nnet ads dn <dn> <attributes...>\n"
2720 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2721 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2722 "to show in the results\n\n"
2723 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2724 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2726 net_common_flags_usage(c, argc, argv);
2732 general ADS search function. Useful in diagnosing problems in ADS
2734 static int net_ads_dn(struct net_context *c, int argc, const char **argv)
2740 LDAPMessage *res = NULL;
2742 if (argc < 1 || c->display_usage) {
2743 return net_ads_dn_usage(c, argc, argv);
2746 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2753 rc = ads_do_search_all(ads, dn,
2755 "(objectclass=*)", attrs, &res);
2756 if (!ADS_ERR_OK(rc)) {
2757 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2762 d_printf("Got %d replies\n\n", ads_count_replies(ads, res));
2764 /* dump the results */
2767 ads_msgfree(ads, res);
2774 help for net ads sid search
2776 static int net_ads_sid_usage(struct net_context *c, int argc, const char **argv)
2779 "\nnet ads sid <sid> <attributes...>\n"
2780 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2781 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2782 "to show in the results\n\n"
2783 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2785 net_common_flags_usage(c, argc, argv);
2791 general ADS search function. Useful in diagnosing problems in ADS
2793 static int net_ads_sid(struct net_context *c, int argc, const char **argv)
2797 const char *sid_string;
2799 LDAPMessage *res = NULL;
2802 if (argc < 1 || c->display_usage) {
2803 return net_ads_sid_usage(c, argc, argv);
2806 if (!ADS_ERR_OK(ads_startup(c, false, &ads))) {
2810 sid_string = argv[0];
2813 if (!string_to_sid(&sid, sid_string)) {
2814 d_fprintf(stderr, _("could not convert sid\n"));
2819 rc = ads_search_retry_sid(ads, &res, &sid, attrs);
2820 if (!ADS_ERR_OK(rc)) {
2821 d_fprintf(stderr, _("search failed: %s\n"), ads_errstr(rc));
2826 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads, res));
2828 /* dump the results */
2831 ads_msgfree(ads, res);
2837 static int net_ads_keytab_flush(struct net_context *c, int argc, const char **argv)
2842 if (c->display_usage) {
2844 "net ads keytab flush\n"
2847 _("Delete the whole keytab"));
2851 if (!c->opt_user_specified && c->opt_password == NULL) {
2852 net_use_krb_machine_account(c);
2855 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2858 ret = ads_keytab_flush(ads);
2863 static int net_ads_keytab_add(struct net_context *c,
2872 if (c->display_usage) {
2875 _("net ads keytab add <principal> [principal ...]\n"
2876 " Add principals to local keytab\n"
2877 " principal\tKerberos principal to add to "
2882 d_printf(_("Processing principals to add...\n"));
2884 if (!c->opt_user_specified && c->opt_password == NULL) {
2885 net_use_krb_machine_account(c);
2888 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2891 for (i = 0; i < argc; i++) {
2892 ret |= ads_keytab_add_entry(ads, argv[i], update_ads);
2898 static int net_ads_keytab_add_default(struct net_context *c,
2902 return net_ads_keytab_add(c, argc, argv, false);
2905 static int net_ads_keytab_add_update_ads(struct net_context *c,
2909 return net_ads_keytab_add(c, argc, argv, true);
2912 static int net_ads_keytab_create(struct net_context *c, int argc, const char **argv)
2917 if (c->display_usage) {
2919 "net ads keytab create\n"
2922 _("Create new default keytab"));
2926 if (!c->opt_user_specified && c->opt_password == NULL) {
2927 net_use_krb_machine_account(c);
2930 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
2933 ret = ads_keytab_create_default(ads);
2938 static int net_ads_keytab_list(struct net_context *c, int argc, const char **argv)
2940 const char *keytab = NULL;
2942 if (c->display_usage) {
2945 _("net ads keytab list [keytab]\n"
2946 " List a local keytab\n"
2947 " keytab\tKeytab to list\n"));
2955 return ads_keytab_list(keytab);
2959 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
2961 struct functable func[] = {
2964 net_ads_keytab_add_default,
2966 N_("Add a service principal"),
2967 N_("net ads keytab add\n"
2968 " Add a service principal, updates keytab file only.")
2972 net_ads_keytab_add_update_ads,
2974 N_("Add a service principal"),
2975 N_("net ads keytab add_update_ads\n"
2976 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
2980 net_ads_keytab_create,
2982 N_("Create a fresh keytab"),
2983 N_("net ads keytab create\n"
2984 " Create a fresh keytab or update existing one.")
2988 net_ads_keytab_flush,
2990 N_("Remove all keytab entries"),
2991 N_("net ads keytab flush\n"
2992 " Remove all keytab entries")
2996 net_ads_keytab_list,
2998 N_("List a keytab"),
2999 N_("net ads keytab list\n"
3002 {NULL, NULL, 0, NULL, NULL}
3005 if (!USE_KERBEROS_KEYTAB) {
3006 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3007 "keytab method to use keytab functions.\n"));
3010 return net_run_function(c, argc, argv, "net ads keytab", func);
3013 static int net_ads_kerberos_renew(struct net_context *c, int argc, const char **argv)
3017 if (c->display_usage) {
3019 "net ads kerberos renew\n"
3022 _("Renew TGT from existing credential cache"));
3026 ret = smb_krb5_renew_ticket(NULL, NULL, NULL, NULL);
3028 d_printf(_("failed to renew kerberos ticket: %s\n"),
3029 error_message(ret));
3034 static int net_ads_kerberos_pac_common(struct net_context *c, int argc, const char **argv,
3035 struct PAC_DATA_CTR **pac_data_ctr)
3039 const char *impersonate_princ_s = NULL;
3040 const char *local_service = NULL;
3043 for (i=0; i<argc; i++) {
3044 if (strnequal(argv[i], "impersonate", strlen("impersonate"))) {
3045 impersonate_princ_s = get_string_param(argv[i]);
3046 if (impersonate_princ_s == NULL) {
3050 if (strnequal(argv[i], "local_service", strlen("local_service"))) {
3051 local_service = get_string_param(argv[i]);
3052 if (local_service == NULL) {
3058 if (local_service == NULL) {
3059 local_service = talloc_asprintf(c, "%s$@%s",
3060 lp_netbios_name(), lp_realm());
3061 if (local_service == NULL) {
3066 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3068 status = kerberos_return_pac(c,
3077 2592000, /* one month */
3078 impersonate_princ_s,
3083 if (!NT_STATUS_IS_OK(status)) {
3084 d_printf(_("failed to query kerberos PAC: %s\n"),
3094 static int net_ads_kerberos_pac_dump(struct net_context *c, int argc, const char **argv)
3096 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3099 enum PAC_TYPE type = 0;
3101 if (c->display_usage) {
3103 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3106 _("Dump the Kerberos PAC"));
3110 for (i=0; i<argc; i++) {
3111 if (strnequal(argv[i], "pac_buffer_type", strlen("pac_buffer_type"))) {
3112 type = get_int_param(argv[i]);
3116 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3125 s = NDR_PRINT_STRUCT_STRING(c, PAC_DATA,
3126 pac_data_ctr->pac_data);
3128 d_printf(_("The Pac: %s\n"), s);
3135 num_buffers = pac_data_ctr->pac_data->num_buffers;
3137 for (i=0; i<num_buffers; i++) {
3141 if (pac_data_ctr->pac_data->buffers[i].type != type) {
3145 s = NDR_PRINT_UNION_STRING(c, PAC_INFO, type,
3146 pac_data_ctr->pac_data->buffers[i].info);
3148 d_printf(_("The Pac: %s\n"), s);
3157 static int net_ads_kerberos_pac_save(struct net_context *c, int argc, const char **argv)
3159 struct PAC_DATA_CTR *pac_data_ctr = NULL;
3160 char *filename = NULL;
3164 if (c->display_usage) {
3166 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3169 _("Save the Kerberos PAC"));
3173 for (i=0; i<argc; i++) {
3174 if (strnequal(argv[i], "filename", strlen("filename"))) {
3175 filename = get_string_param(argv[i]);
3176 if (filename == NULL) {
3182 ret = net_ads_kerberos_pac_common(c, argc, argv, &pac_data_ctr);
3187 if (filename == NULL) {
3188 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3192 /* save the raw format */
3193 if (!file_save(filename, pac_data_ctr->pac_blob.data, pac_data_ctr->pac_blob.length)) {
3194 d_printf(_("failed to save PAC in %s\n"), filename);
3201 static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **argv)
3203 struct functable func[] = {
3206 net_ads_kerberos_pac_dump,
3208 N_("Dump Kerberos PAC"),
3209 N_("net ads kerberos pac dump\n"
3210 " Dump a Kerberos PAC to stdout")
3214 net_ads_kerberos_pac_save,
3216 N_("Save Kerberos PAC"),
3217 N_("net ads kerberos pac save\n"
3218 " Save a Kerberos PAC in a file")
3221 {NULL, NULL, 0, NULL, NULL}
3224 return net_run_function(c, argc, argv, "net ads kerberos pac", func);
3227 static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char **argv)
3229 TALLOC_CTX *mem_ctx = NULL;
3233 if (c->display_usage) {
3235 "net ads kerberos kinit\n"
3238 _("Get Ticket Granting Ticket (TGT) for the user"));
3242 mem_ctx = talloc_init("net_ads_kerberos_kinit");
3247 c->opt_password = net_prompt_pass(c, c->opt_user_name);
3249 ret = kerberos_kinit_password_ext(c->opt_user_name,
3257 2592000, /* one month */
3263 d_printf(_("failed to kinit password: %s\n"),
3270 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3272 struct functable func[] = {
3275 net_ads_kerberos_kinit,
3277 N_("Retrieve Ticket Granting Ticket (TGT)"),
3278 N_("net ads kerberos kinit\n"
3279 " Receive Ticket Granting Ticket (TGT)")
3283 net_ads_kerberos_renew,
3285 N_("Renew Ticket Granting Ticket from credential cache"),
3286 N_("net ads kerberos renew\n"
3287 " Renew Ticket Granting Ticket (TGT) from "
3292 net_ads_kerberos_pac,
3294 N_("Dump Kerberos PAC"),
3295 N_("net ads kerberos pac\n"
3296 " Dump Kerberos PAC")
3298 {NULL, NULL, 0, NULL, NULL}
3301 return net_run_function(c, argc, argv, "net ads kerberos", func);
3304 static int net_ads_setspn_list(struct net_context *c, int argc, const char **argv)
3308 ADS_STRUCT *ads = NULL;
3309 if (c->display_usage) {
3312 _("net ads setspn list <machinename>\n"));
3316 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
3321 ok = ads_setspn_list(ads, argv[0]);
3323 ok = ads_setspn_list(ads, lp_netbios_name());
3335 static int net_ads_setspn_add(struct net_context *c, int argc, const char **argv)
3339 ADS_STRUCT *ads = NULL;
3340 if (c->display_usage || argc < 1) {
3343 _("net ads setspn add <machinename> SPN\n"));
3347 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
3352 ok = ads_setspn_add(ads, argv[0], argv[1]);
3354 ok = ads_setspn_add(ads, lp_netbios_name(), argv[0]);
3366 static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
3370 ADS_STRUCT *ads = NULL;
3371 if (c->display_usage || argc < 1) {
3374 _("net ads setspn delete <machinename> SPN\n"));
3378 if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
3383 ok = ads_setspn_delete(ads, argv[0], argv[1]);
3385 ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
3397 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3399 struct functable func[] = {
3402 net_ads_setspn_list,
3404 N_("List Service Principal Names (SPN)"),
3405 N_("net ads setspn list machine\n"
3406 " List Service Principal Names (SPN)")
3412 N_("Add Service Principal Names (SPN)"),
3413 N_("net ads setspn add machine spn\n"
3414 " Add Service Principal Names (SPN)")
3418 net_ads_setspn_delete,
3420 N_("Delete Service Principal Names (SPN)"),
3421 N_("net ads setspn delete machine spn\n"
3422 " Delete Service Principal Names (SPN)")
3424 {NULL, NULL, 0, NULL, NULL}
3427 return net_run_function(c, argc, argv, "net ads setspn", func);
3430 static int net_ads_enctype_lookup_account(struct net_context *c,
3432 const char *account,
3434 const char **enctype_str)
3437 const char *attrs[] = {
3438 "msDS-SupportedEncryptionTypes",
3445 filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))",
3447 if (filter == NULL) {
3451 status = ads_search(ads, res, filter, attrs);
3452 if (!ADS_ERR_OK(status)) {
3453 d_printf(_("no account found with filter: %s\n"), filter);
3457 count = ads_count_replies(ads, *res);
3462 d_printf(_("no account found with filter: %s\n"), filter);
3465 d_printf(_("multiple accounts found with filter: %s\n"), filter);
3470 *enctype_str = ads_pull_string(ads, c, *res,
3471 "msDS-SupportedEncryptionTypes");
3472 if (*enctype_str == NULL) {
3473 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3483 static void net_ads_enctype_dump_enctypes(const char *username,
3484 const char *enctype_str)
3486 int enctypes = atoi(enctype_str);
3488 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3489 username, enctypes, enctypes);
3491 printf("[%s] 0x%08x DES-CBC-CRC\n",
3492 enctypes & ENC_CRC32 ? "X" : " ",
3494 printf("[%s] 0x%08x DES-CBC-MD5\n",
3495 enctypes & ENC_RSA_MD5 ? "X" : " ",
3497 printf("[%s] 0x%08x RC4-HMAC\n",
3498 enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ",
3500 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3501 enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ",
3502 ENC_HMAC_SHA1_96_AES128);
3503 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3504 enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ",
3505 ENC_HMAC_SHA1_96_AES256);
3508 static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv)
3512 ADS_STRUCT *ads = NULL;
3513 LDAPMessage *res = NULL;
3514 const char *str = NULL;
3516 if (c->display_usage || (argc < 1)) {
3518 "net ads enctypes list\n"
3521 _("List supported enctypes"));
3525 status = ads_startup(c, false, &ads);
3526 if (!ADS_ERR_OK(status)) {
3527 printf("startup failed\n");
3531 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3536 net_ads_enctype_dump_enctypes(argv[0], str);
3540 ads_msgfree(ads, res);
3546 static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv)
3551 LDAPMessage *res = NULL;
3552 const char *etype_list_str;
3555 uint32_t etype_list;
3558 if (c->display_usage || argc < 1) {
3560 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3563 _("Set supported enctypes"));
3567 status = ads_startup(c, false, &ads);
3568 if (!ADS_ERR_OK(status)) {
3569 printf("startup failed\n");
3573 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3578 dn = ads_get_dn(ads, c, res);
3583 etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5;
3584 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
3585 etype_list |= ENC_HMAC_SHA1_96_AES128;
3587 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
3588 etype_list |= ENC_HMAC_SHA1_96_AES256;
3591 if (argv[1] != NULL) {
3592 sscanf(argv[1], "%i", &etype_list);
3595 etype_list_str = talloc_asprintf(c, "%d", etype_list);
3596 if (!etype_list_str) {
3600 mods = ads_init_mods(c);
3605 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes",
3607 if (!ADS_ERR_OK(status)) {
3611 status = ads_gen_mod(ads, dn, mods);
3612 if (!ADS_ERR_OK(status)) {
3613 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3614 ads_errstr(status));
3618 ads_msgfree(ads, res);
3620 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str);
3625 net_ads_enctype_dump_enctypes(argv[0], str);
3629 ads_msgfree(ads, res);
3635 static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv)
3640 LDAPMessage *res = NULL;
3644 if (c->display_usage || argc < 1) {
3646 "net ads enctypes delete <sAMAccountName>\n"
3649 _("Delete supported enctypes"));
3653 status = ads_startup(c, false, &ads);
3654 if (!ADS_ERR_OK(status)) {
3655 printf("startup failed\n");
3659 ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL);
3664 dn = ads_get_dn(ads, c, res);
3669 mods = ads_init_mods(c);
3674 status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL);
3675 if (!ADS_ERR_OK(status)) {
3679 status = ads_gen_mod(ads, dn, mods);
3680 if (!ADS_ERR_OK(status)) {
3681 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3682 ads_errstr(status));
3689 ads_msgfree(ads, res);
3694 static int net_ads_enctypes(struct net_context *c, int argc, const char **argv)
3696 struct functable func[] = {
3699 net_ads_enctypes_list,
3701 N_("List the supported encryption types"),
3702 N_("net ads enctypes list\n"
3703 " List the supported encryption types")
3707 net_ads_enctypes_set,
3709 N_("Set the supported encryption types"),
3710 N_("net ads enctypes set\n"
3711 " Set the supported encryption types")
3715 net_ads_enctypes_delete,
3717 N_("Delete the supported encryption types"),
3718 N_("net ads enctypes delete\n"
3719 " Delete the supported encryption types")
3722 {NULL, NULL, 0, NULL, NULL}
3725 return net_run_function(c, argc, argv, "net ads enctypes", func);
3729 int net_ads(struct net_context *c, int argc, const char **argv)
3731 struct functable func[] = {
3736 N_("Display details on remote ADS server"),
3738 " Display details on remote ADS server")
3744 N_("Join the local machine to ADS realm"),
3746 " Join the local machine to ADS realm")
3752 N_("Validate machine account"),
3753 N_("net ads testjoin\n"
3754 " Validate machine account")
3760 N_("Remove the local machine from ADS"),
3761 N_("net ads leave\n"
3762 " Remove the local machine from ADS")
3768 N_("Display machine account details"),
3769 N_("net ads status\n"
3770 " Display machine account details")
3776 N_("List/modify users"),
3778 " List/modify users")
3784 N_("List/modify groups"),
3785 N_("net ads group\n"
3786 " List/modify groups")
3792 N_("Issue dynamic DNS update"),
3794 " Issue dynamic DNS update")
3800 N_("Change user passwords"),
3801 N_("net ads password\n"
3802 " Change user passwords")
3806 net_ads_changetrustpw,
3808 N_("Change trust account password"),
3809 N_("net ads changetrustpw\n"
3810 " Change trust account password")
3816 N_("List/modify printer entries"),
3817 N_("net ads printer\n"
3818 " List/modify printer entries")
3824 N_("Issue LDAP search using filter"),
3825 N_("net ads search\n"
3826 " Issue LDAP search using filter")
3832 N_("Issue LDAP search by DN"),
3834 " Issue LDAP search by DN")
3840 N_("Issue LDAP search by SID"),
3842 " Issue LDAP search by SID")
3848 N_("Display workgroup name"),
3849 N_("net ads workgroup\n"
3850 " Display the workgroup name")
3856 N_("Perform CLDAP query on DC"),
3857 N_("net ads lookup\n"
3858 " Find the ADS DC using CLDAP lookups")
3864 N_("Manage local keytab file"),
3865 N_("net ads keytab\n"
3866 " Manage local keytab file")
3872 N_("Manage Service Principal Names (SPN)s"),
3873 N_("net ads spnset\n"
3874 " Manage Service Principal Names (SPN)s")
3880 N_("Manage group policy objects"),
3882 " Manage group policy objects")
3888 N_("Manage kerberos keytab"),
3889 N_("net ads kerberos\n"
3890 " Manage kerberos keytab")
3896 N_("List/modify supported encryption types"),
3897 N_("net ads enctypes\n"
3898 " List/modify enctypes")
3900 {NULL, NULL, 0, NULL, NULL}
3903 return net_run_function(c, argc, argv, "net ads", func);
3908 static int net_ads_noads(void)
3910 d_fprintf(stderr, _("ADS support not compiled in\n"));
3914 int net_ads_keytab(struct net_context *c, int argc, const char **argv)
3916 return net_ads_noads();
3919 int net_ads_kerberos(struct net_context *c, int argc, const char **argv)
3921 return net_ads_noads();
3924 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
3926 return net_ads_noads();
3929 int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv)
3931 return net_ads_noads();
3934 int net_ads_join(struct net_context *c, int argc, const char **argv)
3936 return net_ads_noads();
3939 int net_ads_user(struct net_context *c, int argc, const char **argv)
3941 return net_ads_noads();
3944 int net_ads_group(struct net_context *c, int argc, const char **argv)
3946 return net_ads_noads();
3949 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
3951 return net_ads_noads();
3954 /* this one shouldn't display a message */
3955 int net_ads_check(struct net_context *c)
3960 int net_ads_check_our_domain(struct net_context *c)
3965 int net_ads(struct net_context *c, int argc, const char **argv)
3967 return net_ads_noads();
3970 #endif /* HAVE_ADS */