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"
45 #include "lib/util/util_file.h"
49 #include "audit_logging.h" /* various JSON helpers */
50 #include "auth/common_auth.h"
51 #endif /* [HAVE_JANSSON] */
55 /* when we do not have sufficient input parameters to contact a remote domain
56 * we always fall back to our own realm - Guenther*/
58 static const char *assume_own_realm(struct net_context
*c
)
60 if (!c
->opt_host
&& strequal(lp_workgroup(), c
->opt_target_workgroup
)) {
70 * note: JSON output deliberately bypasses gettext so as to provide the same
71 * output irrespective of the locale.
74 static int output_json(const struct json_object
*jsobj
)
76 TALLOC_CTX
*ctx
= NULL
;
79 if (json_is_invalid(jsobj
)) {
83 ctx
= talloc_new(NULL
);
85 d_fprintf(stderr
, _("Out of memory\n"));
89 json
= json_to_string(ctx
, jsobj
);
91 d_fprintf(stderr
, _("error encoding to JSON\n"));
95 d_printf("%s\n", json
);
101 static int net_ads_cldap_netlogon_json
104 const struct NETLOGON_SAM_LOGON_RESPONSE_EX
*reply
)
106 struct json_object jsobj
= json_new_object();
107 struct json_object flagsobj
= json_new_object();
108 char response_type
[32] = { '\0' };
111 if (json_is_invalid(&jsobj
) || json_is_invalid(&flagsobj
)) {
112 d_fprintf(stderr
, _("error setting up JSON value\n"));
117 switch (reply
->command
) {
118 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
119 strncpy(response_type
,
120 "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
121 sizeof(response_type
));
123 case LOGON_SAM_LOGON_RESPONSE_EX
:
124 strncpy(response_type
, "LOGON_SAM_LOGON_RESPONSE_EX",
125 sizeof(response_type
));
128 snprintf(response_type
, sizeof(response_type
), "0x%x",
133 ret
= json_add_string(&jsobj
, "Information for Domain Controller",
139 ret
= json_add_string(&jsobj
, "Response Type", response_type
);
144 ret
= json_add_guid(&jsobj
, "GUID", &reply
->domain_uuid
);
149 ret
= json_add_bool(&flagsobj
, "Is a PDC",
150 reply
->server_type
& NBT_SERVER_PDC
);
155 ret
= json_add_bool(&flagsobj
, "Is a GC of the forest",
156 reply
->server_type
& NBT_SERVER_GC
);
161 ret
= json_add_bool(&flagsobj
, "Is an LDAP server",
162 reply
->server_type
& NBT_SERVER_LDAP
);
167 ret
= json_add_bool(&flagsobj
, "Supports DS",
168 reply
->server_type
& NBT_SERVER_DS
);
173 ret
= json_add_bool(&flagsobj
, "Is running a KDC",
174 reply
->server_type
& NBT_SERVER_KDC
);
179 ret
= json_add_bool(&flagsobj
, "Is running time services",
180 reply
->server_type
& NBT_SERVER_TIMESERV
);
185 ret
= json_add_bool(&flagsobj
, "Is the closest DC",
186 reply
->server_type
& NBT_SERVER_CLOSEST
);
191 ret
= json_add_bool(&flagsobj
, "Is writable",
192 reply
->server_type
& NBT_SERVER_WRITABLE
);
197 ret
= json_add_bool(&flagsobj
, "Has a hardware clock",
198 reply
->server_type
& NBT_SERVER_GOOD_TIMESERV
);
203 ret
= json_add_bool(&flagsobj
,
204 "Is a non-domain NC serviced by LDAP server",
205 reply
->server_type
& NBT_SERVER_NDNC
);
211 (&flagsobj
, "Is NT6 DC that has some secrets",
212 reply
->server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
);
218 (&flagsobj
, "Is NT6 DC that has all secrets",
219 reply
->server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
);
224 ret
= json_add_bool(&flagsobj
, "Runs Active Directory Web Services",
225 reply
->server_type
& NBT_SERVER_ADS_WEB_SERVICE
);
230 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2012 or later",
231 reply
->server_type
& NBT_SERVER_DS_8
);
236 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2012R2 or later",
237 reply
->server_type
& NBT_SERVER_DS_9
);
242 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2016 or later",
243 reply
->server_type
& NBT_SERVER_DS_10
);
248 ret
= json_add_bool(&flagsobj
, "Has a DNS name",
249 reply
->server_type
& NBT_SERVER_HAS_DNS_NAME
);
254 ret
= json_add_bool(&flagsobj
, "Is a default NC",
255 reply
->server_type
& NBT_SERVER_IS_DEFAULT_NC
);
260 ret
= json_add_bool(&flagsobj
, "Is the forest root",
261 reply
->server_type
& NBT_SERVER_FOREST_ROOT
);
266 ret
= json_add_string(&jsobj
, "Forest", reply
->forest
);
271 ret
= json_add_string(&jsobj
, "Domain", reply
->dns_domain
);
276 ret
= json_add_string(&jsobj
, "Domain Controller", reply
->pdc_dns_name
);
282 ret
= json_add_string(&jsobj
, "Pre-Win2k Domain", reply
->domain_name
);
287 ret
= json_add_string(&jsobj
, "Pre-Win2k Hostname", reply
->pdc_name
);
292 if (*reply
->user_name
) {
293 ret
= json_add_string(&jsobj
, "User name", reply
->user_name
);
299 ret
= json_add_string(&jsobj
, "Server Site Name", reply
->server_site
);
304 ret
= json_add_string(&jsobj
, "Client Site Name", reply
->client_site
);
309 ret
= json_add_int(&jsobj
, "NT Version", reply
->nt_version
);
314 ret
= json_add_int(&jsobj
, "LMNT Token", reply
->lmnt_token
);
319 ret
= json_add_int(&jsobj
, "LM20 Token", reply
->lm20_token
);
324 ret
= json_add_object(&jsobj
, "Flags", &flagsobj
);
329 ret
= output_json(&jsobj
);
330 json_free(&jsobj
); /* frees flagsobj recursively */
335 json_free(&flagsobj
);
341 #else /* [HAVE_JANSSON] */
343 static int net_ads_cldap_netlogon_json
346 const struct NETLOGON_SAM_LOGON_RESPONSE_EX
* reply
)
348 d_fprintf(stderr
, _("JSON support not available\n"));
353 #endif /* [HAVE_JANSSON] */
356 do a cldap netlogon query
358 static int net_ads_cldap_netlogon(struct net_context
*c
, ADS_STRUCT
*ads
)
360 char addr
[INET6_ADDRSTRLEN
];
361 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
363 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
365 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads
->ldap
.ss
, ads
->server
.realm
, &reply
) ) {
366 d_fprintf(stderr
, _("CLDAP query failed!\n"));
371 return net_ads_cldap_netlogon_json(ads
, addr
, &reply
);
374 d_printf(_("Information for Domain Controller: %s\n\n"),
377 d_printf(_("Response Type: "));
378 switch (reply
.command
) {
379 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
380 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
382 case LOGON_SAM_LOGON_RESPONSE_EX
:
383 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
386 d_printf("0x%x\n", reply
.command
);
390 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply
.domain_uuid
));
392 d_printf(_("Flags:\n"
394 "\tIs a GC of the forest: %s\n"
395 "\tIs an LDAP server: %s\n"
396 "\tSupports DS: %s\n"
397 "\tIs running a KDC: %s\n"
398 "\tIs running time services: %s\n"
399 "\tIs the closest DC: %s\n"
400 "\tIs writable: %s\n"
401 "\tHas a hardware clock: %s\n"
402 "\tIs a non-domain NC serviced by LDAP server: %s\n"
403 "\tIs NT6 DC that has some secrets: %s\n"
404 "\tIs NT6 DC that has all secrets: %s\n"
405 "\tRuns Active Directory Web Services: %s\n"
406 "\tRuns on Windows 2012 or later: %s\n"
407 "\tRuns on Windows 2012R2 or later: %s\n"
408 "\tRuns on Windows 2016 or later: %s\n"
409 "\tHas a DNS name: %s\n"
410 "\tIs a default NC: %s\n"
411 "\tIs the forest root: %s\n"),
412 (reply
.server_type
& NBT_SERVER_PDC
) ? _("yes") : _("no"),
413 (reply
.server_type
& NBT_SERVER_GC
) ? _("yes") : _("no"),
414 (reply
.server_type
& NBT_SERVER_LDAP
) ? _("yes") : _("no"),
415 (reply
.server_type
& NBT_SERVER_DS
) ? _("yes") : _("no"),
416 (reply
.server_type
& NBT_SERVER_KDC
) ? _("yes") : _("no"),
417 (reply
.server_type
& NBT_SERVER_TIMESERV
) ? _("yes") : _("no"),
418 (reply
.server_type
& NBT_SERVER_CLOSEST
) ? _("yes") : _("no"),
419 (reply
.server_type
& NBT_SERVER_WRITABLE
) ? _("yes") : _("no"),
420 (reply
.server_type
& NBT_SERVER_GOOD_TIMESERV
) ? _("yes") : _("no"),
421 (reply
.server_type
& NBT_SERVER_NDNC
) ? _("yes") : _("no"),
422 (reply
.server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
423 (reply
.server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
424 (reply
.server_type
& NBT_SERVER_ADS_WEB_SERVICE
) ? _("yes") : _("no"),
425 (reply
.server_type
& NBT_SERVER_DS_8
) ? _("yes") : _("no"),
426 (reply
.server_type
& NBT_SERVER_DS_9
) ? _("yes") : _("no"),
427 (reply
.server_type
& NBT_SERVER_DS_10
) ? _("yes") : _("no"),
428 (reply
.server_type
& NBT_SERVER_HAS_DNS_NAME
) ? _("yes") : _("no"),
429 (reply
.server_type
& NBT_SERVER_IS_DEFAULT_NC
) ? _("yes") : _("no"),
430 (reply
.server_type
& NBT_SERVER_FOREST_ROOT
) ? _("yes") : _("no"));
433 printf(_("Forest: %s\n"), reply
.forest
);
434 printf(_("Domain: %s\n"), reply
.dns_domain
);
435 printf(_("Domain Controller: %s\n"), reply
.pdc_dns_name
);
437 printf(_("Pre-Win2k Domain: %s\n"), reply
.domain_name
);
438 printf(_("Pre-Win2k Hostname: %s\n"), reply
.pdc_name
);
440 if (*reply
.user_name
) printf(_("User name: %s\n"), reply
.user_name
);
442 printf(_("Server Site Name: %s\n"), reply
.server_site
);
443 printf(_("Client Site Name: %s\n"), reply
.client_site
);
445 d_printf(_("NT Version: %d\n"), reply
.nt_version
);
446 d_printf(_("LMNT Token: %.2x\n"), reply
.lmnt_token
);
447 d_printf(_("LM20 Token: %.2x\n"), reply
.lm20_token
);
453 this implements the CLDAP based netlogon lookup requests
454 for finding the domain controller of a ADS domain
456 static int net_ads_lookup(struct net_context
*c
, int argc
, const char **argv
)
458 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
459 ADS_STRUCT
*ads
= NULL
;
463 if (c
->display_usage
) {
468 _("Find the ADS DC using CLDAP lookup.\n"));
469 TALLOC_FREE(tmp_ctx
);
473 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
474 if (!ADS_ERR_OK(status
)) {
475 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
479 if (!ads
->config
.realm
) {
480 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
481 if (ads
->config
.realm
== NULL
) {
482 d_fprintf(stderr
, _("Out of memory\n"));
485 ads
->ldap
.port
= 389;
488 ret
= net_ads_cldap_netlogon(c
, ads
);
490 TALLOC_FREE(tmp_ctx
);
497 static int net_ads_info_json(ADS_STRUCT
*ads
)
500 char addr
[INET6_ADDRSTRLEN
];
502 struct json_object jsobj
= json_new_object();
504 if (json_is_invalid(&jsobj
)) {
505 d_fprintf(stderr
, _("error setting up JSON value\n"));
510 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
512 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
514 ret
= json_add_string (&jsobj
, "LDAP server", addr
);
519 ret
= json_add_string (&jsobj
, "LDAP server name",
520 ads
->config
.ldap_server_name
);
525 ret
= json_add_string (&jsobj
, "Workgroup", ads
->config
.workgroup
);
530 ret
= json_add_string (&jsobj
, "Realm", ads
->config
.realm
);
535 ret
= json_add_string (&jsobj
, "Bind Path", ads
->config
.bind_path
);
540 ret
= json_add_int (&jsobj
, "LDAP port", ads
->ldap
.port
);
545 ret
= json_add_int (&jsobj
, "Server time", ads
->config
.current_time
);
550 ret
= json_add_string (&jsobj
, "KDC server", ads
->auth
.kdc_server
);
555 ret
= json_add_int (&jsobj
, "Server time offset",
556 ads
->auth
.time_offset
);
561 ret
= json_add_int (&jsobj
, "Last machine account password change",
567 ret
= output_json(&jsobj
);
574 #else /* [HAVE_JANSSON] */
576 static int net_ads_info_json(ADS_STRUCT
*ads
)
578 d_fprintf(stderr
, _("JSON support not available\n"));
583 #endif /* [HAVE_JANSSON] */
587 static int net_ads_info(struct net_context
*c
, int argc
, const char **argv
)
589 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
590 ADS_STRUCT
*ads
= NULL
;
592 char addr
[INET6_ADDRSTRLEN
];
596 if (c
->display_usage
) {
601 _("Display information about an Active Directory "
603 TALLOC_FREE(tmp_ctx
);
607 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
608 if (!ADS_ERR_OK(status
)) {
609 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
613 if (!ads
|| !ads
->config
.realm
) {
614 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
618 /* Try to set the server's current time since we didn't do a full
619 TCP LDAP session initially */
621 if ( !ADS_ERR_OK(ads_current_time( ads
)) ) {
622 d_fprintf( stderr
, _("Failed to get server's current time!\n"));
626 ret
= net_ads_info_json(ads
);
630 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
632 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
634 d_printf(_("LDAP server: %s\n"), addr
);
635 d_printf(_("LDAP server name: %s\n"), ads
->config
.ldap_server_name
);
636 d_printf(_("Workgroup: %s\n"), ads
->config
.workgroup
);
637 d_printf(_("Realm: %s\n"), ads
->config
.realm
);
638 d_printf(_("Bind Path: %s\n"), ads
->config
.bind_path
);
639 d_printf(_("LDAP port: %d\n"), ads
->ldap
.port
);
640 d_printf(_("Server time: %s\n"),
641 http_timestring(tmp_ctx
, ads
->config
.current_time
));
643 d_printf(_("KDC server: %s\n"), ads
->auth
.kdc_server
);
644 d_printf(_("Server time offset: %d\n"), ads
->auth
.time_offset
);
646 d_printf(_("Last machine account password change: %s\n"),
647 http_timestring(tmp_ctx
, pass_time
));
651 TALLOC_FREE(tmp_ctx
);
655 static ADS_STATUS
ads_startup_int(struct net_context
*c
,
656 bool only_own_domain
,
659 ADS_STRUCT
**ads_ret
)
661 ADS_STRUCT
*ads
= NULL
;
663 bool need_password
= false;
664 bool second_time
= false;
666 const char *realm
= NULL
;
667 bool tried_closest_dc
= false;
668 enum credentials_use_kerberos krb5_state
=
669 CRED_USE_KERBEROS_DISABLED
;
671 /* lp_realm() should be handled by a command line param,
672 However, the join requires that realm be set in smb.conf
673 and compares our realm with the remote server's so this is
674 ok until someone needs more flexibility */
679 if (only_own_domain
) {
682 realm
= assume_own_realm(c
);
685 ads
= ads_init(mem_ctx
,
687 c
->opt_target_workgroup
,
691 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
694 if (!c
->opt_user_name
) {
695 c
->opt_user_name
= "administrator";
698 if (c
->opt_user_specified
) {
699 need_password
= true;
703 if (!c
->opt_password
&& need_password
&& !c
->opt_machine_pass
) {
704 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
705 if (!c
->opt_password
) {
707 return ADS_ERROR(LDAP_NO_MEMORY
);
711 if (c
->opt_password
) {
712 use_in_memory_ccache();
713 ADS_TALLOC_CONST_FREE(ads
->auth
.password
);
714 ads
->auth
.password
= talloc_strdup(ads
, c
->opt_password
);
715 if (ads
->auth
.password
== NULL
) {
717 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
721 ADS_TALLOC_CONST_FREE(ads
->auth
.user_name
);
722 ads
->auth
.user_name
= talloc_strdup(ads
, c
->opt_user_name
);
723 if (ads
->auth
.user_name
== NULL
) {
725 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
728 ads
->auth
.flags
|= auth_flags
;
730 /* The ADS code will handle FIPS mode */
731 krb5_state
= cli_credentials_get_kerberos_state(c
->creds
);
732 switch (krb5_state
) {
733 case CRED_USE_KERBEROS_REQUIRED
:
734 ads
->auth
.flags
&= ~ADS_AUTH_DISABLE_KERBEROS
;
735 ads
->auth
.flags
&= ~ADS_AUTH_ALLOW_NTLMSSP
;
737 case CRED_USE_KERBEROS_DESIRED
:
738 ads
->auth
.flags
&= ~ADS_AUTH_DISABLE_KERBEROS
;
739 ads
->auth
.flags
|= ADS_AUTH_ALLOW_NTLMSSP
;
741 case CRED_USE_KERBEROS_DISABLED
:
742 ads
->auth
.flags
|= ADS_AUTH_DISABLE_KERBEROS
;
743 ads
->auth
.flags
|= ADS_AUTH_ALLOW_NTLMSSP
;
748 * If the username is of the form "name@realm",
749 * extract the realm and convert to upper case.
750 * This is only used to establish the connection.
752 if ((cp
= strchr_m(ads
->auth
.user_name
, '@'))!=0) {
754 ADS_TALLOC_CONST_FREE(ads
->auth
.realm
);
755 ads
->auth
.realm
= talloc_asprintf_strupper_m(ads
, "%s", cp
);
756 if (ads
->auth
.realm
== NULL
) {
758 return ADS_ERROR(LDAP_NO_MEMORY
);
760 } else if (ads
->auth
.realm
== NULL
) {
761 const char *c_realm
= cli_credentials_get_realm(c
->creds
);
763 if (c_realm
!= NULL
) {
764 ads
->auth
.realm
= talloc_strdup(ads
, c_realm
);
765 if (ads
->auth
.realm
== NULL
) {
767 return ADS_ERROR(LDAP_NO_MEMORY
);
772 status
= ads_connect(ads
);
774 if (!ADS_ERR_OK(status
)) {
776 if (NT_STATUS_EQUAL(ads_ntstatus(status
),
777 NT_STATUS_NO_LOGON_SERVERS
)) {
778 DEBUG(0,("ads_connect: %s\n", ads_errstr(status
)));
783 if (!need_password
&& !second_time
&& !(auth_flags
& ADS_AUTH_NO_BIND
)) {
784 need_password
= true;
793 /* when contacting our own domain, make sure we use the closest DC.
794 * This is done by reconnecting to ADS because only the first call to
795 * ads_connect will give us our own sitename */
797 if ((only_own_domain
|| !c
->opt_host
) && !tried_closest_dc
) {
799 tried_closest_dc
= true; /* avoid loop */
801 if (!ads_closest_dc(ads
)) {
803 namecache_delete(ads
->server
.realm
, 0x1C);
804 namecache_delete(ads
->server
.workgroup
, 0x1C);
812 *ads_ret
= talloc_move(mem_ctx
, &ads
);
816 ADS_STATUS
ads_startup(struct net_context
*c
,
817 bool only_own_domain
,
821 return ads_startup_int(c
, only_own_domain
, 0, mem_ctx
, ads
);
824 ADS_STATUS
ads_startup_nobind(struct net_context
*c
,
825 bool only_own_domain
,
829 return ads_startup_int(c
,
837 Check to see if connection can be made via ads.
838 ads_startup() stores the password in opt_password if it needs to so
839 that rpc or rap can use it without re-prompting.
841 static int net_ads_check_int(struct net_context
*c
,
843 const char *workgroup
,
846 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
851 ads
= ads_init(tmp_ctx
, realm
, workgroup
, host
, ADS_SASL_PLAIN
);
856 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
858 status
= ads_connect(ads
);
859 if ( !ADS_ERR_OK(status
) ) {
865 TALLOC_FREE(tmp_ctx
);
869 int net_ads_check_our_domain(struct net_context
*c
)
871 return net_ads_check_int(c
, lp_realm(), lp_workgroup(), NULL
);
874 int net_ads_check(struct net_context
*c
)
876 return net_ads_check_int(c
, NULL
, c
->opt_workgroup
, c
->opt_host
);
880 determine the netbios workgroup name for a domain
882 static int net_ads_workgroup(struct net_context
*c
, int argc
, const char **argv
)
884 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
885 ADS_STRUCT
*ads
= NULL
;
887 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
891 if (c
->display_usage
) {
893 "net ads workgroup\n"
896 _("Print the workgroup name"));
897 TALLOC_FREE(tmp_ctx
);
901 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
902 if (!ADS_ERR_OK(status
)) {
903 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
907 if (!ads
->config
.realm
) {
908 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
909 if (ads
->config
.realm
== NULL
) {
910 d_fprintf(stderr
, _("Out of memory\n"));
913 ads
->ldap
.port
= 389;
916 ok
= ads_cldap_netlogon_5(tmp_ctx
,
917 &ads
->ldap
.ss
, ads
->server
.realm
, &reply
);
919 d_fprintf(stderr
, _("CLDAP query failed!\n"));
923 d_printf(_("Workgroup: %s\n"), reply
.domain_name
);
927 TALLOC_FREE(tmp_ctx
);
934 static bool usergrp_display(ADS_STRUCT
*ads
, char *field
, void **values
, void *data_area
)
936 char **disp_fields
= (char **) data_area
;
938 if (!field
) { /* must be end of record */
939 if (disp_fields
[0]) {
940 if (!strchr_m(disp_fields
[0], '$')) {
942 d_printf("%-21.21s %s\n",
943 disp_fields
[0], disp_fields
[1]);
945 d_printf("%s\n", disp_fields
[0]);
948 SAFE_FREE(disp_fields
[0]);
949 SAFE_FREE(disp_fields
[1]);
952 if (!values
) /* must be new field, indicate string field */
954 if (strcasecmp_m(field
, "sAMAccountName") == 0) {
955 disp_fields
[0] = SMB_STRDUP((char *) values
[0]);
957 if (strcasecmp_m(field
, "description") == 0)
958 disp_fields
[1] = SMB_STRDUP((char *) values
[0]);
962 static int net_ads_user_usage(struct net_context
*c
, int argc
, const char **argv
)
964 return net_user_usage(c
, argc
, argv
);
967 static int ads_user_add(struct net_context
*c
, int argc
, const char **argv
)
969 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
970 ADS_STRUCT
*ads
= NULL
;
973 LDAPMessage
*res
=NULL
;
977 if (argc
< 1 || c
->display_usage
) {
978 TALLOC_FREE(tmp_ctx
);
979 return net_ads_user_usage(c
, argc
, argv
);
982 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
983 if (!ADS_ERR_OK(status
)) {
987 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
988 if (!ADS_ERR_OK(status
)) {
989 d_fprintf(stderr
, _("ads_user_add: %s\n"), ads_errstr(status
));
993 if (ads_count_replies(ads
, res
)) {
994 d_fprintf(stderr
, _("ads_user_add: User %s already exists\n"),
999 if (c
->opt_container
) {
1000 ou_str
= SMB_STRDUP(c
->opt_container
);
1002 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
1005 status
= ads_add_user_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
1006 if (!ADS_ERR_OK(status
)) {
1007 d_fprintf(stderr
, _("Could not add user %s: %s\n"), argv
[0],
1008 ads_errstr(status
));
1012 /* if no password is to be set, we're done */
1014 d_printf(_("User %s added\n"), argv
[0]);
1019 /* try setting the password */
1020 upn
= talloc_asprintf(tmp_ctx
,
1028 status
= ads_krb5_set_password(ads
->auth
.kdc_server
, upn
, argv
[1],
1029 ads
->auth
.time_offset
);
1030 if (ADS_ERR_OK(status
)) {
1031 d_printf(_("User %s added\n"), argv
[0]);
1037 /* password didn't set, delete account */
1038 d_fprintf(stderr
, _("Could not add user %s. "
1039 "Error setting password %s\n"),
1040 argv
[0], ads_errstr(status
));
1042 ads_msgfree(ads
, res
);
1045 status
=ads_find_user_acct(ads
, &res
, argv
[0]);
1046 if (ADS_ERR_OK(status
)) {
1047 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1048 ads_del_dn(ads
, userdn
);
1049 TALLOC_FREE(userdn
);
1053 ads_msgfree(ads
, res
);
1055 TALLOC_FREE(tmp_ctx
);
1059 static int ads_user_info(struct net_context
*c
, int argc
, const char **argv
)
1061 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1062 ADS_STRUCT
*ads
= NULL
;
1064 LDAPMessage
*res
= NULL
;
1067 const char *attrs
[] = {"memberOf", "primaryGroupID", NULL
};
1068 char *searchstring
= NULL
;
1069 char **grouplist
= NULL
;
1070 char *primary_group
= NULL
;
1071 char *escaped_user
= NULL
;
1072 struct dom_sid primary_group_sid
;
1074 enum wbcSidType type
;
1076 if (argc
< 1 || c
->display_usage
) {
1077 TALLOC_FREE(tmp_ctx
);
1078 return net_ads_user_usage(c
, argc
, argv
);
1081 escaped_user
= escape_ldap_string(tmp_ctx
, argv
[0]);
1082 if (!escaped_user
) {
1084 _("ads_user_info: failed to escape user %s\n"),
1089 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1090 if (!ADS_ERR_OK(status
)) {
1094 searchstring
= talloc_asprintf(tmp_ctx
,
1095 "(sAMAccountName=%s)",
1097 if (searchstring
== NULL
) {
1101 status
= ads_search(ads
, &res
, searchstring
, attrs
);
1102 if (!ADS_ERR_OK(status
)) {
1103 d_fprintf(stderr
, _("ads_search: %s\n"), ads_errstr(status
));
1107 if (!ads_pull_uint32(ads
, res
, "primaryGroupID", &group_rid
)) {
1108 d_fprintf(stderr
, _("ads_pull_uint32 failed\n"));
1112 status
= ads_domain_sid(ads
, &primary_group_sid
);
1113 if (!ADS_ERR_OK(status
)) {
1114 d_fprintf(stderr
, _("ads_domain_sid: %s\n"), ads_errstr(status
));
1118 sid_append_rid(&primary_group_sid
, group_rid
);
1120 wbc_status
= wbcLookupSid((struct wbcDomainSid
*)&primary_group_sid
,
1121 NULL
, /* don't look up domain */
1124 if (!WBC_ERROR_IS_OK(wbc_status
)) {
1125 d_fprintf(stderr
, "wbcLookupSid: %s\n",
1126 wbcErrorString(wbc_status
));
1130 d_printf("%s\n", primary_group
);
1132 wbcFreeMemory(primary_group
);
1134 grouplist
= ldap_get_values((LDAP
*)ads
->ldap
.ld
,
1135 (LDAPMessage
*)res
, "memberOf");
1140 for (i
=0;grouplist
[i
];i
++) {
1141 groupname
= ldap_explode_dn(grouplist
[i
], 1);
1142 d_printf("%s\n", groupname
[0]);
1143 ldap_value_free(groupname
);
1145 ldap_value_free(grouplist
);
1150 TALLOC_FREE(escaped_user
);
1151 TALLOC_FREE(searchstring
);
1152 ads_msgfree(ads
, res
);
1153 TALLOC_FREE(tmp_ctx
);
1157 static int ads_user_delete(struct net_context
*c
, int argc
, const char **argv
)
1159 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1160 ADS_STRUCT
*ads
= NULL
;
1162 LDAPMessage
*res
= NULL
;
1163 char *userdn
= NULL
;
1167 TALLOC_FREE(tmp_ctx
);
1168 return net_ads_user_usage(c
, argc
, argv
);
1171 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1172 if (!ADS_ERR_OK(status
)) {
1176 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1177 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1178 d_printf(_("User %s does not exist.\n"), argv
[0]);
1182 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1183 if (userdn
== NULL
) {
1187 status
= ads_del_dn(ads
, userdn
);
1188 if (!ADS_ERR_OK(status
)) {
1189 d_fprintf(stderr
, _("Error deleting user %s: %s\n"), argv
[0],
1190 ads_errstr(status
));
1194 d_printf(_("User %s deleted\n"), argv
[0]);
1198 ads_msgfree(ads
, res
);
1199 TALLOC_FREE(tmp_ctx
);
1203 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
1205 struct functable func
[] = {
1210 N_("Add an AD user"),
1211 N_("net ads user add\n"
1218 N_("Display information about an AD user"),
1219 N_("net ads user info\n"
1220 " Display information about an AD user")
1226 N_("Delete an AD user"),
1227 N_("net ads user delete\n"
1228 " Delete an AD user")
1230 {NULL
, NULL
, 0, NULL
, NULL
}
1232 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1233 ADS_STRUCT
*ads
= NULL
;
1235 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1236 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1237 char *disp_fields
[2] = {NULL
, NULL
};
1241 TALLOC_FREE(tmp_ctx
);
1242 return net_run_function(c
, argc
, argv
, "net ads user", func
);
1245 if (c
->display_usage
) {
1250 _("List AD users"));
1251 net_display_usage_from_functable(func
);
1252 TALLOC_FREE(tmp_ctx
);
1256 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1257 if (!ADS_ERR_OK(status
)) {
1261 if (c
->opt_long_list_entries
)
1262 d_printf(_("\nUser name Comment"
1263 "\n-----------------------------\n"));
1265 status
= ads_do_search_all_fn(ads
,
1266 ads
->config
.bind_path
,
1268 "(objectCategory=user)",
1269 c
->opt_long_list_entries
?
1270 longattrs
: shortattrs
,
1273 if (!ADS_ERR_OK(status
)) {
1279 TALLOC_FREE(tmp_ctx
);
1283 static int net_ads_group_usage(struct net_context
*c
, int argc
, const char **argv
)
1285 return net_group_usage(c
, argc
, argv
);
1288 static int ads_group_add(struct net_context
*c
, int argc
, const char **argv
)
1290 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1291 ADS_STRUCT
*ads
= NULL
;
1293 LDAPMessage
*res
= NULL
;
1295 char *ou_str
= NULL
;
1297 if (argc
< 1 || c
->display_usage
) {
1298 TALLOC_FREE(tmp_ctx
);
1299 return net_ads_group_usage(c
, argc
, argv
);
1302 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1303 if (!ADS_ERR_OK(status
)) {
1307 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1308 if (!ADS_ERR_OK(status
)) {
1309 d_fprintf(stderr
, _("ads_group_add: %s\n"), ads_errstr(status
));
1313 if (ads_count_replies(ads
, res
)) {
1314 d_fprintf(stderr
, _("ads_group_add: Group %s already exists\n"), argv
[0]);
1318 if (c
->opt_container
) {
1319 ou_str
= SMB_STRDUP(c
->opt_container
);
1321 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
1324 status
= ads_add_group_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
1325 if (!ADS_ERR_OK(status
)) {
1326 d_fprintf(stderr
, _("Could not add group %s: %s\n"), argv
[0],
1327 ads_errstr(status
));
1331 d_printf(_("Group %s added\n"), argv
[0]);
1335 ads_msgfree(ads
, res
);
1337 TALLOC_FREE(tmp_ctx
);
1341 static int ads_group_delete(struct net_context
*c
, int argc
, const char **argv
)
1343 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1344 ADS_STRUCT
*ads
= NULL
;
1346 LDAPMessage
*res
= NULL
;
1347 char *groupdn
= NULL
;
1350 if (argc
< 1 || c
->display_usage
) {
1351 TALLOC_FREE(tmp_ctx
);
1352 return net_ads_group_usage(c
, argc
, argv
);
1355 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1356 if (!ADS_ERR_OK(status
)) {
1360 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1361 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1362 d_printf(_("Group %s does not exist.\n"), argv
[0]);
1366 groupdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1367 if (groupdn
== NULL
) {
1371 status
= ads_del_dn(ads
, groupdn
);
1372 if (!ADS_ERR_OK(status
)) {
1373 d_fprintf(stderr
, _("Error deleting group %s: %s\n"), argv
[0],
1374 ads_errstr(status
));
1377 d_printf(_("Group %s deleted\n"), argv
[0]);
1381 ads_msgfree(ads
, res
);
1382 TALLOC_FREE(tmp_ctx
);
1386 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
1388 struct functable func
[] = {
1393 N_("Add an AD group"),
1394 N_("net ads group add\n"
1401 N_("Delete an AD group"),
1402 N_("net ads group delete\n"
1403 " Delete an AD group")
1405 {NULL
, NULL
, 0, NULL
, NULL
}
1407 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1408 ADS_STRUCT
*ads
= NULL
;
1410 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1411 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1412 char *disp_fields
[2] = {NULL
, NULL
};
1416 TALLOC_FREE(tmp_ctx
);
1417 return net_run_function(c
, argc
, argv
, "net ads group", func
);
1420 if (c
->display_usage
) {
1425 _("List AD groups"));
1426 net_display_usage_from_functable(func
);
1427 TALLOC_FREE(tmp_ctx
);
1431 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1432 if (!ADS_ERR_OK(status
)) {
1436 if (c
->opt_long_list_entries
)
1437 d_printf(_("\nGroup name Comment"
1438 "\n-----------------------------\n"));
1440 status
= ads_do_search_all_fn(ads
,
1441 ads
->config
.bind_path
,
1443 "(objectCategory=group)",
1444 c
->opt_long_list_entries
?
1445 longattrs
: shortattrs
,
1448 if (!ADS_ERR_OK(status
)) {
1454 TALLOC_FREE(tmp_ctx
);
1458 static int net_ads_status(struct net_context
*c
, int argc
, const char **argv
)
1460 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1461 ADS_STRUCT
*ads
= NULL
;
1463 LDAPMessage
*res
= NULL
;
1466 if (c
->display_usage
) {
1471 _("Display machine account details"));
1472 TALLOC_FREE(tmp_ctx
);
1476 net_warn_member_options();
1478 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1479 if (!ADS_ERR_OK(status
)) {
1483 status
= ads_find_machine_acct(ads
, &res
, lp_netbios_name());
1484 if (!ADS_ERR_OK(status
)) {
1485 d_fprintf(stderr
, _("ads_find_machine_acct: %s\n"),
1486 ads_errstr(status
));
1490 if (ads_count_replies(ads
, res
) == 0) {
1491 d_fprintf(stderr
, _("No machine account for '%s' found\n"),
1500 ads_msgfree(ads
, res
);
1501 TALLOC_FREE(tmp_ctx
);
1505 /*******************************************************************
1506 Leave an AD domain. Windows XP disables the machine account.
1507 We'll try the same. The old code would do an LDAP delete.
1508 That only worked using the machine creds because added the machine
1509 with full control to the computer object's ACL.
1510 *******************************************************************/
1512 static int net_ads_leave(struct net_context
*c
, int argc
, const char **argv
)
1514 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1515 struct libnet_UnjoinCtx
*r
= NULL
;
1519 if (c
->display_usage
) {
1521 "net ads leave [--keep-account]\n"
1524 _("Leave an AD domain"));
1525 TALLOC_FREE(tmp_ctx
);
1530 d_fprintf(stderr
, _("No realm set, are we joined ?\n"));
1531 TALLOC_FREE(tmp_ctx
);
1535 if (!c
->opt_kerberos
) {
1536 use_in_memory_ccache();
1540 d_fprintf(stderr
, _("Could not initialise message context. "
1541 "Try running as root\n"));
1545 werr
= libnet_init_UnjoinCtx(tmp_ctx
, &r
);
1546 if (!W_ERROR_IS_OK(werr
)) {
1547 d_fprintf(stderr
, _("Could not initialise unjoin context.\n"));
1552 r
->in
.use_kerberos
= c
->opt_kerberos
;
1553 r
->in
.dc_name
= c
->opt_host
;
1554 r
->in
.domain_name
= lp_realm();
1555 r
->in
.admin_account
= c
->opt_user_name
;
1556 r
->in
.admin_password
= net_prompt_pass(c
, c
->opt_user_name
);
1557 r
->in
.modify_config
= lp_config_backend_is_registry();
1559 /* Try to delete it, but if that fails, disable it. The
1560 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1561 r
->in
.unjoin_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1562 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
;
1563 if (c
->opt_keep_account
) {
1564 r
->in
.delete_machine_account
= false;
1566 r
->in
.delete_machine_account
= true;
1569 r
->in
.msg_ctx
= c
->msg_ctx
;
1571 werr
= libnet_Unjoin(tmp_ctx
, r
);
1572 if (!W_ERROR_IS_OK(werr
)) {
1573 d_printf(_("Failed to leave domain: %s\n"),
1574 r
->out
.error_string
? r
->out
.error_string
:
1575 get_friendly_werror_msg(werr
));
1579 if (r
->out
.deleted_machine_account
) {
1580 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1581 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1586 /* We couldn't delete it - see if the disable succeeded. */
1587 if (r
->out
.disabled_machine_account
) {
1588 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1589 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1594 /* Based on what we requested, we shouldn't get here, but if
1595 we did, it means the secrets were removed, and therefore
1596 we have left the domain */
1597 d_fprintf(stderr
, _("Machine '%s' Left domain '%s'\n"),
1598 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1602 TALLOC_FREE(tmp_ctx
);
1606 static ADS_STATUS
net_ads_join_ok(struct net_context
*c
)
1608 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1609 ADS_STRUCT
*ads
= NULL
;
1612 struct sockaddr_storage dcip
;
1614 if (!secrets_init()) {
1615 DEBUG(1,("Failed to initialise secrets database\n"));
1616 TALLOC_FREE(tmp_ctx
);
1617 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
1620 net_warn_member_options();
1622 net_use_krb_machine_account(c
);
1624 get_dc_name(lp_workgroup(), lp_realm(), dc_name
, &dcip
);
1626 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1627 if (!ADS_ERR_OK(status
)) {
1631 status
= ADS_ERROR_NT(NT_STATUS_OK
);
1633 TALLOC_FREE(tmp_ctx
);
1638 check that an existing join is OK
1640 int net_ads_testjoin(struct net_context
*c
, int argc
, const char **argv
)
1643 use_in_memory_ccache();
1645 if (c
->display_usage
) {
1647 "net ads testjoin\n"
1650 _("Test if the existing join is ok"));
1654 net_warn_member_options();
1656 /* Display success or failure */
1657 status
= net_ads_join_ok(c
);
1658 if (!ADS_ERR_OK(status
)) {
1659 fprintf(stderr
, _("Join to domain is not valid: %s\n"),
1660 get_friendly_nt_error_msg(ads_ntstatus(status
)));
1664 printf(_("Join is OK\n"));
1668 /*******************************************************************
1669 Simple config checks before beginning the join
1670 ********************************************************************/
1672 static WERROR
check_ads_config( void )
1674 if (lp_server_role() != ROLE_DOMAIN_MEMBER
) {
1675 d_printf(_("Host is not configured as a member server.\n"));
1676 return WERR_INVALID_DOMAIN_ROLE
;
1679 if (strlen(lp_netbios_name()) > 15) {
1680 d_printf(_("Our netbios name can be at most 15 chars long, "
1681 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1682 (unsigned int)strlen(lp_netbios_name()));
1683 return WERR_INVALID_COMPUTERNAME
;
1686 if ( lp_security() == SEC_ADS
&& !*lp_realm()) {
1687 d_fprintf(stderr
, _("realm must be set in %s for ADS "
1688 "join to succeed.\n"), get_dyn_CONFIGFILE());
1689 return WERR_INVALID_PARAMETER
;
1695 /*******************************************************************
1696 ********************************************************************/
1698 static int net_ads_join_usage(struct net_context
*c
, int argc
, const char **argv
)
1700 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1701 "Valid options:\n"));
1702 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1703 " The default is in the form netbiosname.dnsdomain\n"));
1704 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1705 " The default UPN is in the form host/netbiosname@REALM.\n"));
1706 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1707 " The OU string read from top to bottom without RDNs\n"
1708 " and delimited by a '/'.\n"
1709 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1710 " NB: A backslash '\\' is used as escape at multiple\n"
1711 " levels and may need to be doubled or even\n"
1712 " quadrupled. It is not used as a separator.\n"));
1713 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1714 " the join. The default password is random.\n"));
1715 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1716 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1717 " NB: osName and osVer must be specified together for\n"
1718 " either to take effect. The operatingSystemService\n"
1719 " attribute is then also set along with the two\n"
1720 " other attributes.\n"));
1721 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1722 " during the join.\n"
1723 " NB: If not specified then by default the samba\n"
1724 " version string is used instead.\n"));
1729 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
1731 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1732 struct libnet_JoinCtx
*r
= NULL
;
1733 const char *domain
= lp_realm();
1734 WERROR werr
= WERR_NERR_SETUPNOTJOINED
;
1735 bool createupn
= false;
1736 const char *dnshostname
= NULL
;
1737 const char *machineupn
= NULL
;
1738 const char *machine_password
= NULL
;
1739 const char *create_in_ou
= NULL
;
1741 const char *os_name
= NULL
;
1742 const char *os_version
= NULL
;
1743 const char *os_servicepack
= NULL
;
1744 bool modify_config
= lp_config_backend_is_registry();
1745 enum libnetjoin_JoinDomNameType domain_name_type
= JoinDomNameTypeDNS
;
1748 if (c
->display_usage
) {
1749 TALLOC_FREE(tmp_ctx
);
1750 return net_ads_join_usage(c
, argc
, argv
);
1753 net_warn_member_options();
1755 if (!modify_config
) {
1756 werr
= check_ads_config();
1757 if (!W_ERROR_IS_OK(werr
)) {
1758 d_fprintf(stderr
, _("Invalid configuration. Exiting....\n"));
1763 if (!c
->opt_kerberos
) {
1764 use_in_memory_ccache();
1767 werr
= libnet_init_JoinCtx(tmp_ctx
, &r
);
1768 if (!W_ERROR_IS_OK(werr
)) {
1772 /* process additional command line args */
1774 for ( i
=0; i
<argc
; i
++ ) {
1775 if ( !strncasecmp_m(argv
[i
], "dnshostname", strlen("dnshostname")) ) {
1776 dnshostname
= get_string_param(argv
[i
]);
1778 else if ( !strncasecmp_m(argv
[i
], "createupn", strlen("createupn")) ) {
1780 machineupn
= get_string_param(argv
[i
]);
1782 else if ( !strncasecmp_m(argv
[i
], "createcomputer", strlen("createcomputer")) ) {
1783 if ( (create_in_ou
= get_string_param(argv
[i
])) == NULL
) {
1784 d_fprintf(stderr
, _("Please supply a valid OU path.\n"));
1785 werr
= WERR_INVALID_PARAMETER
;
1789 else if ( !strncasecmp_m(argv
[i
], "osName", strlen("osName")) ) {
1790 if ( (os_name
= get_string_param(argv
[i
])) == NULL
) {
1791 d_fprintf(stderr
, _("Please supply a operating system name.\n"));
1792 werr
= WERR_INVALID_PARAMETER
;
1796 else if ( !strncasecmp_m(argv
[i
], "osVer", strlen("osVer")) ) {
1797 if ( (os_version
= get_string_param(argv
[i
])) == NULL
) {
1798 d_fprintf(stderr
, _("Please supply a valid operating system version.\n"));
1799 werr
= WERR_INVALID_PARAMETER
;
1803 else if ( !strncasecmp_m(argv
[i
], "osServicePack", strlen("osServicePack")) ) {
1804 if ( (os_servicepack
= get_string_param(argv
[i
])) == NULL
) {
1805 d_fprintf(stderr
, _("Please supply a valid servicepack identifier.\n"));
1806 werr
= WERR_INVALID_PARAMETER
;
1810 else if ( !strncasecmp_m(argv
[i
], "machinepass", strlen("machinepass")) ) {
1811 if ( (machine_password
= get_string_param(argv
[i
])) == NULL
) {
1812 d_fprintf(stderr
, _("Please supply a valid password to set as trust account password.\n"));
1813 werr
= WERR_INVALID_PARAMETER
;
1818 if (strchr(domain
, '.') == NULL
) {
1819 domain_name_type
= JoinDomNameTypeUnknown
;
1821 domain_name_type
= JoinDomNameTypeDNS
;
1827 d_fprintf(stderr
, _("Please supply a valid domain name\n"));
1828 werr
= WERR_INVALID_PARAMETER
;
1833 d_fprintf(stderr
, _("Could not initialise message context. "
1834 "Try running as root\n"));
1835 werr
= WERR_ACCESS_DENIED
;
1839 /* Do the domain join here */
1841 r
->in
.domain_name
= domain
;
1842 r
->in
.domain_name_type
= domain_name_type
;
1843 r
->in
.create_upn
= createupn
;
1844 r
->in
.upn
= machineupn
;
1845 r
->in
.dnshostname
= dnshostname
;
1846 r
->in
.account_ou
= create_in_ou
;
1847 r
->in
.os_name
= os_name
;
1848 r
->in
.os_version
= os_version
;
1849 r
->in
.os_servicepack
= os_servicepack
;
1850 r
->in
.dc_name
= c
->opt_host
;
1851 r
->in
.admin_account
= c
->opt_user_name
;
1852 r
->in
.admin_password
= net_prompt_pass(c
, c
->opt_user_name
);
1853 r
->in
.machine_password
= machine_password
;
1855 r
->in
.use_kerberos
= c
->opt_kerberos
;
1856 r
->in
.modify_config
= modify_config
;
1857 r
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1858 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
|
1859 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
;
1860 r
->in
.msg_ctx
= c
->msg_ctx
;
1862 werr
= libnet_Join(tmp_ctx
, r
);
1863 if (W_ERROR_EQUAL(werr
, WERR_NERR_DCNOTFOUND
) &&
1864 strequal(domain
, lp_realm())) {
1865 r
->in
.domain_name
= lp_workgroup();
1866 r
->in
.domain_name_type
= JoinDomNameTypeNBT
;
1867 werr
= libnet_Join(tmp_ctx
, r
);
1869 if (!W_ERROR_IS_OK(werr
)) {
1873 /* Check the short name of the domain */
1875 if (!modify_config
&& !strequal(lp_workgroup(), r
->out
.netbios_domain_name
)) {
1876 d_printf(_("The workgroup in %s does not match the short\n"
1877 "domain name obtained from the server.\n"
1878 "Using the name [%s] from the server.\n"
1879 "You should set \"workgroup = %s\" in %s.\n"),
1880 get_dyn_CONFIGFILE(), r
->out
.netbios_domain_name
,
1881 r
->out
.netbios_domain_name
, get_dyn_CONFIGFILE());
1884 d_printf(_("Using short domain name -- %s\n"), r
->out
.netbios_domain_name
);
1886 if (r
->out
.dns_domain_name
) {
1887 d_printf(_("Joined '%s' to dns domain '%s'\n"), r
->in
.machine_name
,
1888 r
->out
.dns_domain_name
);
1890 d_printf(_("Joined '%s' to domain '%s'\n"), r
->in
.machine_name
,
1891 r
->out
.netbios_domain_name
);
1894 /* print out informative error string in case there is one */
1895 if (r
->out
.error_string
!= NULL
) {
1896 d_printf("%s\n", r
->out
.error_string
);
1900 * We try doing the dns update (if it was compiled in
1901 * and if it was not disabled on the command line).
1902 * If the dns update fails, we still consider the join
1903 * operation as succeeded if we came this far.
1905 if (!c
->opt_no_dns_updates
) {
1906 net_ads_join_dns_updates(c
, tmp_ctx
, r
);
1913 /* issue an overall failure message at the end. */
1914 d_printf(_("Failed to join domain: %s\n"),
1915 r
&& r
->out
.error_string
? r
->out
.error_string
:
1916 get_friendly_werror_msg(werr
));
1919 TALLOC_FREE(tmp_ctx
);
1924 /*******************************************************************
1925 ********************************************************************/
1927 static int net_ads_dns_register(struct net_context
*c
, int argc
, const char **argv
)
1929 #if defined(HAVE_KRB5)
1930 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1931 ADS_STRUCT
*ads
= NULL
;
1934 const char *hostname
= NULL
;
1935 const char **addrs_list
= NULL
;
1936 struct sockaddr_storage
*addrs
= NULL
;
1942 talloc_enable_leak_report();
1945 if (argc
<= 1 && lp_clustering() && lp_cluster_addresses() == NULL
) {
1946 d_fprintf(stderr
, _("Refusing DNS updates with automatic "
1947 "detection of addresses in a clustered "
1949 c
->display_usage
= true;
1952 if (c
->display_usage
) {
1954 "net ads dns register [hostname [IP [IP...]]] "
1955 "[--force] [--dns-ttl TTL]\n"
1958 _("Register hostname with DNS\n"));
1959 TALLOC_FREE(tmp_ctx
);
1968 num_addrs
= argc
- 1;
1969 addrs_list
= &argv
[1];
1970 } else if (lp_clustering()) {
1971 addrs_list
= lp_cluster_addresses();
1972 num_addrs
= str_list_length(addrs_list
);
1975 if (num_addrs
> 0) {
1976 addrs
= talloc_zero_array(tmp_ctx
,
1977 struct sockaddr_storage
,
1979 if (addrs
== NULL
) {
1980 d_fprintf(stderr
, _("Error allocating memory!\n"));
1985 for (count
= 0; count
< num_addrs
; count
++) {
1986 if (!interpret_string_addr(&addrs
[count
], addrs_list
[count
], 0)) {
1987 d_fprintf(stderr
, "%s '%s'.\n",
1988 _("Cannot interpret address"),
1994 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1995 if ( !ADS_ERR_OK(status
) ) {
1996 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
2000 ntstatus
= net_update_dns_ext(c
,
2007 if (!NT_STATUS_IS_OK(ntstatus
)) {
2008 d_fprintf( stderr
, _("DNS update failed!\n") );
2012 d_fprintf( stderr
, _("Successfully registered hostname with DNS\n") );
2016 TALLOC_FREE(tmp_ctx
);
2021 _("DNS update support not enabled at compile time!\n"));
2026 static int net_ads_dns_unregister(struct net_context
*c
,
2030 #if defined(HAVE_KRB5)
2031 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2032 ADS_STRUCT
*ads
= NULL
;
2035 const char *hostname
= NULL
;
2039 talloc_enable_leak_report();
2043 c
->display_usage
= true;
2046 if (c
->display_usage
) {
2048 "net ads dns unregister [hostname]\n"
2051 _("Remove all IP Address entries for a given\n"
2052 " hostname from the Active Directory server.\n"));
2053 TALLOC_FREE(tmp_ctx
);
2057 /* Get the hostname for un-registering */
2060 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2061 if ( !ADS_ERR_OK(status
) ) {
2062 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
2066 ntstatus
= net_update_dns_ext(c
,
2073 if (!NT_STATUS_IS_OK(ntstatus
)) {
2074 d_fprintf( stderr
, _("DNS update failed!\n") );
2078 d_fprintf( stderr
, _("Successfully un-registered hostname from DNS\n"));
2082 TALLOC_FREE(tmp_ctx
);
2087 _("DNS update support not enabled at compile time!\n"));
2093 static int net_ads_dns_async(struct net_context
*c
, int argc
, const char **argv
)
2095 size_t num_names
= 0;
2096 char **hostnames
= NULL
;
2098 struct samba_sockaddr
*addrs
= NULL
;
2101 if (argc
!= 1 || c
->display_usage
) {
2106 _("net ads dns async <name>\n"),
2107 _(" Async look up hostname from the DNS server\n"
2108 " hostname\tName to look up\n"));
2112 status
= ads_dns_lookup_a(talloc_tos(),
2117 if (!NT_STATUS_IS_OK(status
)) {
2118 d_printf("Looking up A record for %s got error %s\n",
2123 d_printf("Async A record lookup - got %u names for %s\n",
2124 (unsigned int)num_names
,
2126 for (i
= 0; i
< num_names
; i
++) {
2127 char addr_buf
[INET6_ADDRSTRLEN
];
2128 print_sockaddr(addr_buf
,
2131 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2137 #if defined(HAVE_IPV6)
2138 status
= ads_dns_lookup_aaaa(talloc_tos(),
2143 if (!NT_STATUS_IS_OK(status
)) {
2144 d_printf("Looking up AAAA record for %s got error %s\n",
2149 d_printf("Async AAAA record lookup - got %u names for %s\n",
2150 (unsigned int)num_names
,
2152 for (i
= 0; i
< num_names
; i
++) {
2153 char addr_buf
[INET6_ADDRSTRLEN
];
2154 print_sockaddr(addr_buf
,
2157 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2167 static int net_ads_dns(struct net_context
*c
, int argc
, const char *argv
[])
2169 struct functable func
[] = {
2172 net_ads_dns_register
,
2174 N_("Add host dns entry to AD"),
2175 N_("net ads dns register\n"
2176 " Add host dns entry to AD")
2180 net_ads_dns_unregister
,
2182 N_("Remove host dns entry from AD"),
2183 N_("net ads dns unregister\n"
2184 " Remove host dns entry from AD")
2191 N_("net ads dns async\n"
2192 " Look up host using async DNS")
2194 {NULL
, NULL
, 0, NULL
, NULL
}
2197 return net_run_function(c
, argc
, argv
, "net ads dns", func
);
2200 /*******************************************************************
2201 ********************************************************************/
2203 int net_ads_printer_usage(struct net_context
*c
, int argc
, const char **argv
)
2206 "\nnet ads printer search <printer>"
2207 "\n\tsearch for a printer in the directory\n"
2208 "\nnet ads printer info <printer> <server>"
2209 "\n\tlookup info in directory for printer on server"
2210 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2211 "\nnet ads printer publish <printername>"
2212 "\n\tpublish printer in directory"
2213 "\n\t(note: printer name is required)\n"
2214 "\nnet ads printer remove <printername>"
2215 "\n\tremove printer from directory"
2216 "\n\t(note: printer name is required)\n"));
2220 /*******************************************************************
2221 ********************************************************************/
2223 static int net_ads_printer_search(struct net_context
*c
,
2227 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2228 ADS_STRUCT
*ads
= NULL
;
2230 LDAPMessage
*res
= NULL
;
2233 if (c
->display_usage
) {
2235 "net ads printer search\n"
2238 _("List printers in the AD"));
2239 TALLOC_FREE(tmp_ctx
);
2243 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2244 if (!ADS_ERR_OK(status
)) {
2248 status
= ads_find_printers(ads
, &res
);
2249 if (!ADS_ERR_OK(status
)) {
2250 d_fprintf(stderr
, _("ads_find_printer: %s\n"),
2251 ads_errstr(status
));
2255 if (ads_count_replies(ads
, res
) == 0) {
2256 d_fprintf(stderr
, _("No results found\n"));
2264 ads_msgfree(ads
, res
);
2265 TALLOC_FREE(tmp_ctx
);
2269 static int net_ads_printer_info(struct net_context
*c
,
2273 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2274 ADS_STRUCT
*ads
= NULL
;
2276 const char *servername
= NULL
;
2277 const char *printername
= NULL
;
2278 LDAPMessage
*res
= NULL
;
2281 if (c
->display_usage
) {
2284 _("net ads printer info [printername [servername]]\n"
2285 " Display printer info from AD\n"
2286 " printername\tPrinter name or wildcard\n"
2287 " servername\tName of the print server\n"));
2288 TALLOC_FREE(tmp_ctx
);
2292 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2293 if (!ADS_ERR_OK(status
)) {
2298 printername
= argv
[0];
2304 servername
= argv
[1];
2306 servername
= lp_netbios_name();
2309 status
= ads_find_printer_on_server(ads
, &res
, printername
, servername
);
2310 if (!ADS_ERR_OK(status
)) {
2311 d_fprintf(stderr
, _("Server '%s' not found: %s\n"),
2312 servername
, ads_errstr(status
));
2316 if (ads_count_replies(ads
, res
) == 0) {
2317 d_fprintf(stderr
, _("Printer '%s' not found\n"), printername
);
2325 ads_msgfree(ads
, res
);
2326 TALLOC_FREE(tmp_ctx
);
2330 static int net_ads_printer_publish(struct net_context
*c
,
2334 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2335 ADS_STRUCT
*ads
= NULL
;
2337 const char *servername
= NULL
;
2338 const char *printername
= NULL
;
2339 struct cli_state
*cli
= NULL
;
2340 struct rpc_pipe_client
*pipe_hnd
= NULL
;
2341 struct sockaddr_storage server_ss
= { 0 };
2343 ADS_MODLIST mods
= NULL
;
2344 char *prt_dn
= NULL
;
2345 char *srv_dn
= NULL
;
2346 char **srv_cn
= NULL
;
2347 char *srv_cn_escaped
= NULL
;
2348 char *printername_escaped
= NULL
;
2349 LDAPMessage
*res
= NULL
;
2353 if (argc
< 1 || c
->display_usage
) {
2356 _("net ads printer publish <printername> [servername]\n"
2357 " Publish printer in AD\n"
2358 " printername\tName of the printer\n"
2359 " servername\tName of the print server\n"));
2360 TALLOC_FREE(tmp_ctx
);
2364 mods
= ads_init_mods(tmp_ctx
);
2366 d_fprintf(stderr
, _("Out of memory\n"));
2370 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2371 if (!ADS_ERR_OK(status
)) {
2375 printername
= argv
[0];
2378 servername
= argv
[1];
2380 servername
= lp_netbios_name();
2383 /* Get printer data from SPOOLSS */
2385 ok
= resolve_name(servername
, &server_ss
, 0x20, false);
2387 d_fprintf(stderr
, _("Could not find server %s\n"),
2392 cli_credentials_set_kerberos_state(c
->creds
,
2393 CRED_USE_KERBEROS_REQUIRED
,
2396 nt_status
= cli_full_connection_creds(&cli
, lp_netbios_name(), servername
,
2400 CLI_FULL_CONNECTION_IPC
);
2402 if (NT_STATUS_IS_ERR(nt_status
)) {
2403 d_fprintf(stderr
, _("Unable to open a connection to %s to "
2404 "obtain data for %s\n"),
2405 servername
, printername
);
2409 /* Publish on AD server */
2411 ads_find_machine_acct(ads
, &res
, servername
);
2413 if (ads_count_replies(ads
, res
) == 0) {
2414 d_fprintf(stderr
, _("Could not find machine account for server "
2420 srv_dn
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
2421 srv_cn
= ldap_explode_dn(srv_dn
, 1);
2423 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn
[0]);
2424 printername_escaped
= escape_rdn_val_string_alloc(printername
);
2425 if (!srv_cn_escaped
|| !printername_escaped
) {
2426 SAFE_FREE(srv_cn_escaped
);
2427 SAFE_FREE(printername_escaped
);
2428 d_fprintf(stderr
, _("Internal error, out of memory!"));
2432 prt_dn
= talloc_asprintf(tmp_ctx
,
2435 printername_escaped
,
2437 if (prt_dn
== NULL
) {
2438 SAFE_FREE(srv_cn_escaped
);
2439 SAFE_FREE(printername_escaped
);
2440 d_fprintf(stderr
, _("Internal error, out of memory!"));
2444 SAFE_FREE(srv_cn_escaped
);
2445 SAFE_FREE(printername_escaped
);
2447 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_spoolss
, &pipe_hnd
);
2448 if (!NT_STATUS_IS_OK(nt_status
)) {
2449 d_fprintf(stderr
, _("Unable to open a connection to the spoolss pipe on %s\n"),
2454 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd
,
2461 status
= ads_add_printer_entry(ads
, prt_dn
, tmp_ctx
, &mods
);
2462 if (!ADS_ERR_OK(status
)) {
2463 d_fprintf(stderr
, "ads_publish_printer: %s\n",
2464 ads_errstr(status
));
2468 d_printf("published printer\n");
2472 talloc_destroy(tmp_ctx
);
2477 static int net_ads_printer_remove(struct net_context
*c
,
2481 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2482 ADS_STRUCT
*ads
= NULL
;
2484 const char *servername
= NULL
;
2485 char *prt_dn
= NULL
;
2486 LDAPMessage
*res
= NULL
;
2489 if (argc
< 1 || c
->display_usage
) {
2492 _("net ads printer remove <printername> [servername]\n"
2493 " Remove a printer from the AD\n"
2494 " printername\tName of the printer\n"
2495 " servername\tName of the print server\n"));
2496 TALLOC_FREE(tmp_ctx
);
2500 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2501 if (!ADS_ERR_OK(status
)) {
2506 servername
= argv
[1];
2508 servername
= lp_netbios_name();
2511 status
= ads_find_printer_on_server(ads
, &res
, argv
[0], servername
);
2512 if (!ADS_ERR_OK(status
)) {
2513 d_fprintf(stderr
, _("ads_find_printer_on_server: %s\n"),
2514 ads_errstr(status
));
2518 if (ads_count_replies(ads
, res
) == 0) {
2519 d_fprintf(stderr
, _("Printer '%s' not found\n"), argv
[1]);
2523 prt_dn
= ads_get_dn(ads
, tmp_ctx
, res
);
2524 if (prt_dn
== NULL
) {
2525 d_fprintf(stderr
, _("Out of memory\n"));
2529 status
= ads_del_dn(ads
, prt_dn
);
2530 if (!ADS_ERR_OK(status
)) {
2531 d_fprintf(stderr
, _("ads_del_dn: %s\n"), ads_errstr(status
));
2537 ads_msgfree(ads
, res
);
2538 TALLOC_FREE(tmp_ctx
);
2542 static int net_ads_printer(struct net_context
*c
, int argc
, const char **argv
)
2544 struct functable func
[] = {
2547 net_ads_printer_search
,
2549 N_("Search for a printer"),
2550 N_("net ads printer search\n"
2551 " Search for a printer")
2555 net_ads_printer_info
,
2557 N_("Display printer information"),
2558 N_("net ads printer info\n"
2559 " Display printer information")
2563 net_ads_printer_publish
,
2565 N_("Publish a printer"),
2566 N_("net ads printer publish\n"
2567 " Publish a printer")
2571 net_ads_printer_remove
,
2573 N_("Delete a printer"),
2574 N_("net ads printer remove\n"
2575 " Delete a printer")
2577 {NULL
, NULL
, 0, NULL
, NULL
}
2580 return net_run_function(c
, argc
, argv
, "net ads printer", func
);
2584 static int net_ads_password(struct net_context
*c
, int argc
, const char **argv
)
2586 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2587 ADS_STRUCT
*ads
= NULL
;
2588 const char *auth_principal
= cli_credentials_get_username(c
->creds
);
2589 const char *auth_password
= cli_credentials_get_password(c
->creds
);
2590 const char *realm
= NULL
;
2591 char *new_password
= NULL
;
2593 char *prompt
= NULL
;
2594 const char *user
= NULL
;
2595 char pwd
[256] = {0};
2599 if (c
->display_usage
) {
2602 _("net ads password <username>\n"
2603 " Change password for user\n"
2604 " username\tName of user to change password for\n"));
2605 TALLOC_FREE(tmp_ctx
);
2609 if (auth_principal
== NULL
|| auth_password
== NULL
) {
2610 d_fprintf(stderr
, _("You must supply an administrator "
2611 "username/password\n"));
2612 TALLOC_FREE(tmp_ctx
);
2617 d_fprintf(stderr
, _("ERROR: You must say which username to "
2618 "change password for\n"));
2619 TALLOC_FREE(tmp_ctx
);
2623 if (strchr_m(argv
[0], '@')) {
2624 user
= talloc_strdup(tmp_ctx
, argv
[0]);
2626 user
= talloc_asprintf(tmp_ctx
, "%s@%s", argv
[0], lp_realm());
2629 d_fprintf(stderr
, _("Out of memory\n"));
2633 use_in_memory_ccache();
2634 chr
= strchr_m(auth_principal
, '@');
2641 /* use the realm so we can eventually change passwords for users
2642 in realms other than default */
2643 ads
= ads_init(tmp_ctx
,
2652 /* we don't actually need a full connect, but it's the easy way to
2653 fill in the KDC's address */
2656 if (!ads
->config
.realm
) {
2657 d_fprintf(stderr
, _("Didn't find the kerberos server!\n"));
2661 if (argv
[1] != NULL
) {
2662 new_password
= talloc_strdup(tmp_ctx
, argv
[1]);
2666 prompt
= talloc_asprintf(tmp_ctx
, _("Enter new password for %s:"), user
);
2667 if (prompt
== NULL
) {
2668 d_fprintf(stderr
, _("Out of memory\n"));
2672 rc
= samba_getpass(prompt
, pwd
, sizeof(pwd
), false, true);
2676 new_password
= talloc_strdup(tmp_ctx
, pwd
);
2677 memset(pwd
, '\0', sizeof(pwd
));
2680 if (new_password
== NULL
) {
2681 d_fprintf(stderr
, _("Out of memory\n"));
2685 status
= kerberos_set_password(ads
->auth
.kdc_server
,
2690 ads
->auth
.time_offset
);
2691 memset(new_password
, '\0', strlen(new_password
));
2692 if (!ADS_ERR_OK(status
)) {
2693 d_fprintf(stderr
, _("Password change failed: %s\n"),
2694 ads_errstr(status
));
2698 d_printf(_("Password change for %s completed.\n"), user
);
2702 TALLOC_FREE(tmp_ctx
);
2706 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
2708 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2709 ADS_STRUCT
*ads
= NULL
;
2710 char *host_principal
= NULL
;
2711 char *my_name
= NULL
;
2715 if (c
->display_usage
) {
2717 "net ads changetrustpw\n"
2720 _("Change the machine account's trust password"));
2721 TALLOC_FREE(tmp_ctx
);
2725 if (!secrets_init()) {
2726 DEBUG(1,("Failed to initialise secrets database\n"));
2730 net_warn_member_options();
2732 net_use_krb_machine_account(c
);
2734 use_in_memory_ccache();
2736 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2737 if (!ADS_ERR_OK(status
)) {
2741 my_name
= talloc_asprintf_strlower_m(tmp_ctx
, "%s", lp_netbios_name());
2742 if (my_name
== NULL
) {
2743 d_fprintf(stderr
, _("Out of memory\n"));
2747 host_principal
= talloc_asprintf(tmp_ctx
, "%s$@%s", my_name
, ads
->config
.realm
);
2748 if (host_principal
== NULL
) {
2749 d_fprintf(stderr
, _("Out of memory\n"));
2753 d_printf(_("Changing password for principal: %s\n"), host_principal
);
2755 status
= ads_change_trust_account_password(ads
, host_principal
);
2756 if (!ADS_ERR_OK(status
)) {
2757 d_fprintf(stderr
, _("Password change failed: %s\n"), ads_errstr(status
));
2761 d_printf(_("Password change for principal %s succeeded.\n"), host_principal
);
2763 if (USE_SYSTEM_KEYTAB
) {
2764 d_printf(_("Attempting to update system keytab with new password.\n"));
2765 if (ads_keytab_create_default(ads
)) {
2766 d_printf(_("Failed to update system keytab.\n"));
2772 TALLOC_FREE(tmp_ctx
);
2778 help for net ads search
2780 static int net_ads_search_usage(struct net_context
*c
, int argc
, const char **argv
)
2783 "\nnet ads search <expression> <attributes...>\n"
2784 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2785 "The expression is a standard LDAP search expression, and the\n"
2786 "attributes are a list of LDAP fields to show in the results.\n\n"
2787 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2789 net_common_flags_usage(c
, argc
, argv
);
2795 general ADS search function. Useful in diagnosing problems in ADS
2797 static int net_ads_search(struct net_context
*c
, int argc
, const char **argv
)
2799 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2800 ADS_STRUCT
*ads
= NULL
;
2802 const char *ldap_exp
= NULL
;
2803 const char **attrs
= NULL
;
2804 LDAPMessage
*res
= NULL
;
2807 if (argc
< 1 || c
->display_usage
) {
2808 TALLOC_FREE(tmp_ctx
);
2809 return net_ads_search_usage(c
, argc
, argv
);
2812 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2813 if (!ADS_ERR_OK(status
)) {
2820 status
= ads_do_search_retry(ads
,
2821 ads
->config
.bind_path
,
2826 if (!ADS_ERR_OK(status
)) {
2827 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2831 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2833 /* dump the results */
2838 ads_msgfree(ads
, res
);
2839 TALLOC_FREE(tmp_ctx
);
2845 help for net ads search
2847 static int net_ads_dn_usage(struct net_context
*c
, int argc
, const char **argv
)
2850 "\nnet ads dn <dn> <attributes...>\n"
2851 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2852 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2853 "to show in the results\n\n"
2854 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2855 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2857 net_common_flags_usage(c
, argc
, argv
);
2863 general ADS search function. Useful in diagnosing problems in ADS
2865 static int net_ads_dn(struct net_context
*c
, int argc
, const char **argv
)
2867 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2868 ADS_STRUCT
*ads
= NULL
;
2870 const char *dn
= NULL
;
2871 const char **attrs
= NULL
;
2872 LDAPMessage
*res
= NULL
;
2875 if (argc
< 1 || c
->display_usage
) {
2876 TALLOC_FREE(tmp_ctx
);
2877 return net_ads_dn_usage(c
, argc
, argv
);
2880 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2881 if (!ADS_ERR_OK(status
)) {
2888 status
= ads_do_search_all(ads
,
2894 if (!ADS_ERR_OK(status
)) {
2895 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2899 d_printf("Got %d replies\n\n", ads_count_replies(ads
, res
));
2901 /* dump the results */
2906 ads_msgfree(ads
, res
);
2907 TALLOC_FREE(tmp_ctx
);
2912 help for net ads sid search
2914 static int net_ads_sid_usage(struct net_context
*c
, int argc
, const char **argv
)
2917 "\nnet ads sid <sid> <attributes...>\n"
2918 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2919 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2920 "to show in the results\n\n"
2921 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2923 net_common_flags_usage(c
, argc
, argv
);
2929 general ADS search function. Useful in diagnosing problems in ADS
2931 static int net_ads_sid(struct net_context
*c
, int argc
, const char **argv
)
2933 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2934 ADS_STRUCT
*ads
= NULL
;
2936 const char *sid_string
= NULL
;
2937 const char **attrs
= NULL
;
2938 LDAPMessage
*res
= NULL
;
2939 struct dom_sid sid
= { 0 };
2942 if (argc
< 1 || c
->display_usage
) {
2943 TALLOC_FREE(tmp_ctx
);
2944 return net_ads_sid_usage(c
, argc
, argv
);
2947 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2948 if (!ADS_ERR_OK(status
)) {
2952 sid_string
= argv
[0];
2955 if (!string_to_sid(&sid
, sid_string
)) {
2956 d_fprintf(stderr
, _("could not convert sid\n"));
2960 status
= ads_search_retry_sid(ads
, &res
, &sid
, attrs
);
2961 if (!ADS_ERR_OK(status
)) {
2962 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2966 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2968 /* dump the results */
2973 ads_msgfree(ads
, res
);
2974 TALLOC_FREE(tmp_ctx
);
2978 static int net_ads_keytab_flush(struct net_context
*c
,
2982 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2983 ADS_STRUCT
*ads
= NULL
;
2987 if (c
->display_usage
) {
2989 "net ads keytab flush\n"
2992 _("Delete the whole keytab"));
2993 TALLOC_FREE(tmp_ctx
);
2997 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
2998 net_use_krb_machine_account(c
);
3001 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3002 if (!ADS_ERR_OK(status
)) {
3006 ret
= ads_keytab_flush(ads
);
3008 TALLOC_FREE(tmp_ctx
);
3012 static int net_ads_keytab_add(struct net_context
*c
,
3017 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3018 ADS_STRUCT
*ads
= NULL
;
3023 if (c
->display_usage
) {
3026 _("net ads keytab add <principal> [principal ...]\n"
3027 " Add principals to local keytab\n"
3028 " principal\tKerberos principal to add to "
3030 TALLOC_FREE(tmp_ctx
);
3034 net_warn_member_options();
3036 d_printf(_("Processing principals to add...\n"));
3038 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
3039 net_use_krb_machine_account(c
);
3042 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3043 if (!ADS_ERR_OK(status
)) {
3047 for (ret
= 0, i
= 0; i
< argc
; i
++) {
3048 ret
|= ads_keytab_add_entry(ads
, argv
[i
], update_ads
);
3051 TALLOC_FREE(tmp_ctx
);
3055 static int net_ads_keytab_add_default(struct net_context
*c
,
3059 return net_ads_keytab_add(c
, argc
, argv
, false);
3062 static int net_ads_keytab_add_update_ads(struct net_context
*c
,
3066 return net_ads_keytab_add(c
, argc
, argv
, true);
3069 static int net_ads_keytab_delete(struct net_context
*c
,
3073 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3074 ADS_STRUCT
*ads
= NULL
;
3079 if (c
->display_usage
) {
3082 _("net ads keytab delete <principal> [principal ...]\n"
3083 " Remove entries for service principal, "
3084 " from the keytab file only."
3085 " Remove principals from local keytab\n"
3086 " principal\tKerberos principal to remove from "
3088 TALLOC_FREE(tmp_ctx
);
3092 d_printf(_("Processing principals to delete...\n"));
3094 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
3095 net_use_krb_machine_account(c
);
3098 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3099 if (!ADS_ERR_OK(status
)) {
3103 for (ret
= 0, i
= 0; i
< argc
; i
++) {
3104 ret
|= ads_keytab_delete_entry(ads
, argv
[i
]);
3107 TALLOC_FREE(tmp_ctx
);
3111 static int net_ads_keytab_create(struct net_context
*c
, int argc
, const char **argv
)
3113 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3114 ADS_STRUCT
*ads
= NULL
;
3118 if (c
->display_usage
) {
3120 "net ads keytab create\n"
3123 _("Create new default keytab"));
3124 TALLOC_FREE(tmp_ctx
);
3128 net_warn_member_options();
3130 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
3131 net_use_krb_machine_account(c
);
3134 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3135 if (!ADS_ERR_OK(status
)) {
3139 ret
= ads_keytab_create_default(ads
);
3141 TALLOC_FREE(tmp_ctx
);
3145 static int net_ads_keytab_list(struct net_context
*c
, int argc
, const char **argv
)
3147 const char *keytab
= NULL
;
3149 if (c
->display_usage
) {
3152 _("net ads keytab list [keytab]\n"
3153 " List a local keytab\n"
3154 " keytab\tKeytab to list\n"));
3162 return ads_keytab_list(keytab
);
3166 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
3168 struct functable func
[] = {
3171 net_ads_keytab_add_default
,
3173 N_("Add a service principal"),
3174 N_("net ads keytab add\n"
3175 " Add a service principal, updates keytab file only.")
3179 net_ads_keytab_delete
,
3181 N_("Delete a service principal"),
3182 N_("net ads keytab delete\n"
3183 " Remove entries for service principal, from the keytab file only.")
3187 net_ads_keytab_add_update_ads
,
3189 N_("Add a service principal"),
3190 N_("net ads keytab add_update_ads\n"
3191 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3195 net_ads_keytab_create
,
3197 N_("Create a fresh keytab"),
3198 N_("net ads keytab create\n"
3199 " Create a fresh keytab or update existing one.")
3203 net_ads_keytab_flush
,
3205 N_("Remove all keytab entries"),
3206 N_("net ads keytab flush\n"
3207 " Remove all keytab entries")
3211 net_ads_keytab_list
,
3213 N_("List a keytab"),
3214 N_("net ads keytab list\n"
3217 {NULL
, NULL
, 0, NULL
, NULL
}
3220 if (!USE_KERBEROS_KEYTAB
) {
3221 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3222 "keytab method to use keytab functions.\n"));
3225 return net_run_function(c
, argc
, argv
, "net ads keytab", func
);
3228 static int net_ads_kerberos_renew(struct net_context
*c
, int argc
, const char **argv
)
3232 if (c
->display_usage
) {
3234 "net ads kerberos renew\n"
3237 _("Renew TGT from existing credential cache"));
3241 ret
= smb_krb5_renew_ticket(NULL
, NULL
, NULL
, NULL
);
3243 d_printf(_("failed to renew kerberos ticket: %s\n"),
3244 error_message(ret
));
3249 static int net_ads_kerberos_pac_common(struct net_context
*c
, int argc
, const char **argv
,
3250 struct PAC_DATA_CTR
**pac_data_ctr
)
3254 const char *impersonate_princ_s
= NULL
;
3255 const char *local_service
= NULL
;
3258 for (i
=0; i
<argc
; i
++) {
3259 if (strnequal(argv
[i
], "impersonate", strlen("impersonate"))) {
3260 impersonate_princ_s
= get_string_param(argv
[i
]);
3261 if (impersonate_princ_s
== NULL
) {
3265 if (strnequal(argv
[i
], "local_service", strlen("local_service"))) {
3266 local_service
= get_string_param(argv
[i
]);
3267 if (local_service
== NULL
) {
3273 if (local_service
== NULL
) {
3274 local_service
= talloc_asprintf(c
, "%s$@%s",
3275 lp_netbios_name(), lp_realm());
3276 if (local_service
== NULL
) {
3281 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
3283 status
= kerberos_return_pac(c
,
3292 2592000, /* one month */
3293 impersonate_princ_s
,
3298 if (!NT_STATUS_IS_OK(status
)) {
3299 d_printf(_("failed to query kerberos PAC: %s\n"),
3309 static int net_ads_kerberos_pac_dump(struct net_context
*c
, int argc
, const char **argv
)
3311 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3314 enum PAC_TYPE type
= 0;
3316 if (c
->display_usage
) {
3318 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3321 _("Dump the Kerberos PAC"));
3325 for (i
=0; i
<argc
; i
++) {
3326 if (strnequal(argv
[i
], "pac_buffer_type", strlen("pac_buffer_type"))) {
3327 type
= get_int_param(argv
[i
]);
3331 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3340 s
= NDR_PRINT_STRUCT_STRING(c
, PAC_DATA
,
3341 pac_data_ctr
->pac_data
);
3343 d_printf(_("The Pac: %s\n"), s
);
3350 num_buffers
= pac_data_ctr
->pac_data
->num_buffers
;
3352 for (i
=0; i
<num_buffers
; i
++) {
3356 if (pac_data_ctr
->pac_data
->buffers
[i
].type
!= type
) {
3360 s
= NDR_PRINT_UNION_STRING(c
, PAC_INFO
, type
,
3361 pac_data_ctr
->pac_data
->buffers
[i
].info
);
3363 d_printf(_("The Pac: %s\n"), s
);
3372 static int net_ads_kerberos_pac_save(struct net_context
*c
, int argc
, const char **argv
)
3374 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3375 char *filename
= NULL
;
3379 if (c
->display_usage
) {
3381 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3384 _("Save the Kerberos PAC"));
3388 for (i
=0; i
<argc
; i
++) {
3389 if (strnequal(argv
[i
], "filename", strlen("filename"))) {
3390 filename
= get_string_param(argv
[i
]);
3391 if (filename
== NULL
) {
3397 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3402 if (filename
== NULL
) {
3403 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3407 /* save the raw format */
3408 if (!file_save(filename
, pac_data_ctr
->pac_blob
.data
, pac_data_ctr
->pac_blob
.length
)) {
3409 d_printf(_("failed to save PAC in %s\n"), filename
);
3416 static int net_ads_kerberos_pac(struct net_context
*c
, int argc
, const char **argv
)
3418 struct functable func
[] = {
3421 net_ads_kerberos_pac_dump
,
3423 N_("Dump Kerberos PAC"),
3424 N_("net ads kerberos pac dump\n"
3425 " Dump a Kerberos PAC to stdout")
3429 net_ads_kerberos_pac_save
,
3431 N_("Save Kerberos PAC"),
3432 N_("net ads kerberos pac save\n"
3433 " Save a Kerberos PAC in a file")
3436 {NULL
, NULL
, 0, NULL
, NULL
}
3439 return net_run_function(c
, argc
, argv
, "net ads kerberos pac", func
);
3442 static int net_ads_kerberos_kinit(struct net_context
*c
, int argc
, const char **argv
)
3447 if (c
->display_usage
) {
3449 "net ads kerberos kinit\n"
3452 _("Get Ticket Granting Ticket (TGT) for the user"));
3456 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
3458 ret
= kerberos_kinit_password_ext(c
->opt_user_name
,
3466 2592000, /* one month */
3472 d_printf(_("failed to kinit password: %s\n"),
3478 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
3480 struct functable func
[] = {
3483 net_ads_kerberos_kinit
,
3485 N_("Retrieve Ticket Granting Ticket (TGT)"),
3486 N_("net ads kerberos kinit\n"
3487 " Receive Ticket Granting Ticket (TGT)")
3491 net_ads_kerberos_renew
,
3493 N_("Renew Ticket Granting Ticket from credential cache"),
3494 N_("net ads kerberos renew\n"
3495 " Renew Ticket Granting Ticket (TGT) from "
3500 net_ads_kerberos_pac
,
3502 N_("Dump Kerberos PAC"),
3503 N_("net ads kerberos pac\n"
3504 " Dump Kerberos PAC")
3506 {NULL
, NULL
, 0, NULL
, NULL
}
3509 return net_run_function(c
, argc
, argv
, "net ads kerberos", func
);
3512 static int net_ads_setspn_list(struct net_context
*c
,
3516 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3517 ADS_STRUCT
*ads
= NULL
;
3522 if (c
->display_usage
) {
3525 _("net ads setspn list <machinename>\n"));
3526 TALLOC_FREE(tmp_ctx
);
3530 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3531 if (!ADS_ERR_OK(status
)) {
3536 ok
= ads_setspn_list(ads
, argv
[0]);
3538 ok
= ads_setspn_list(ads
, lp_netbios_name());
3543 TALLOC_FREE(tmp_ctx
);
3547 static int net_ads_setspn_add(struct net_context
*c
, int argc
, const char **argv
)
3549 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3550 ADS_STRUCT
*ads
= NULL
;
3555 if (c
->display_usage
|| argc
< 1) {
3558 _("net ads setspn add <machinename> SPN\n"));
3559 TALLOC_FREE(tmp_ctx
);
3563 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3564 if (!ADS_ERR_OK(status
)) {
3569 ok
= ads_setspn_add(ads
, argv
[0], argv
[1]);
3571 ok
= ads_setspn_add(ads
, lp_netbios_name(), argv
[0]);
3576 TALLOC_FREE(tmp_ctx
);
3580 static int net_ads_setspn_delete(struct net_context
*c
, int argc
, const char **argv
)
3582 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3583 ADS_STRUCT
*ads
= NULL
;
3588 if (c
->display_usage
|| argc
< 1) {
3591 _("net ads setspn delete <machinename> SPN\n"));
3592 TALLOC_FREE(tmp_ctx
);
3596 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3597 if (!ADS_ERR_OK(status
)) {
3602 ok
= ads_setspn_delete(ads
, argv
[0], argv
[1]);
3604 ok
= ads_setspn_delete(ads
, lp_netbios_name(), argv
[0]);
3609 TALLOC_FREE(tmp_ctx
);
3613 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
3615 struct functable func
[] = {
3618 net_ads_setspn_list
,
3620 N_("List Service Principal Names (SPN)"),
3621 N_("net ads setspn list machine\n"
3622 " List Service Principal Names (SPN)")
3628 N_("Add Service Principal Names (SPN)"),
3629 N_("net ads setspn add machine spn\n"
3630 " Add Service Principal Names (SPN)")
3634 net_ads_setspn_delete
,
3636 N_("Delete Service Principal Names (SPN)"),
3637 N_("net ads setspn delete machine spn\n"
3638 " Delete Service Principal Names (SPN)")
3640 {NULL
, NULL
, 0, NULL
, NULL
}
3643 return net_run_function(c
, argc
, argv
, "net ads setspn", func
);
3646 static int net_ads_enctype_lookup_account(struct net_context
*c
,
3648 const char *account
,
3650 const char **enctype_str
)
3653 const char *attrs
[] = {
3654 "msDS-SupportedEncryptionTypes",
3661 filter
= talloc_asprintf(c
, "(&(objectclass=user)(sAMAccountName=%s))",
3663 if (filter
== NULL
) {
3667 status
= ads_search(ads
, res
, filter
, attrs
);
3668 if (!ADS_ERR_OK(status
)) {
3669 d_printf(_("no account found with filter: %s\n"), filter
);
3673 count
= ads_count_replies(ads
, *res
);
3678 d_printf(_("no account found with filter: %s\n"), filter
);
3681 d_printf(_("multiple accounts found with filter: %s\n"), filter
);
3686 *enctype_str
= ads_pull_string(ads
, c
, *res
,
3687 "msDS-SupportedEncryptionTypes");
3688 if (*enctype_str
== NULL
) {
3689 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3699 static void net_ads_enctype_dump_enctypes(const char *username
,
3700 const char *enctype_str
)
3702 int enctypes
= atoi(enctype_str
);
3704 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3705 username
, enctypes
, enctypes
);
3707 printf("[%s] 0x%08x DES-CBC-CRC\n",
3708 enctypes
& ENC_CRC32
? "X" : " ",
3710 printf("[%s] 0x%08x DES-CBC-MD5\n",
3711 enctypes
& ENC_RSA_MD5
? "X" : " ",
3713 printf("[%s] 0x%08x RC4-HMAC\n",
3714 enctypes
& ENC_RC4_HMAC_MD5
? "X" : " ",
3716 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3717 enctypes
& ENC_HMAC_SHA1_96_AES128
? "X" : " ",
3718 ENC_HMAC_SHA1_96_AES128
);
3719 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3720 enctypes
& ENC_HMAC_SHA1_96_AES256
? "X" : " ",
3721 ENC_HMAC_SHA1_96_AES256
);
3722 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3723 enctypes
& ENC_HMAC_SHA1_96_AES256_SK
? "X" : " ",
3724 ENC_HMAC_SHA1_96_AES256_SK
);
3725 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3726 enctypes
& KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
? "X" : " ",
3727 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
);
3730 static int net_ads_enctypes_list(struct net_context
*c
, int argc
, const char **argv
)
3732 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3734 ADS_STRUCT
*ads
= NULL
;
3735 LDAPMessage
*res
= NULL
;
3736 const char *str
= NULL
;
3739 if (c
->display_usage
|| (argc
< 1)) {
3741 "net ads enctypes list\n"
3744 _("List supported enctypes"));
3745 TALLOC_FREE(tmp_ctx
);
3749 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3750 if (!ADS_ERR_OK(status
)) {
3754 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3759 net_ads_enctype_dump_enctypes(argv
[0], str
);
3763 ads_msgfree(ads
, res
);
3764 TALLOC_FREE(tmp_ctx
);
3768 static int net_ads_enctypes_set(struct net_context
*c
, int argc
, const char **argv
)
3770 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3773 ADS_STRUCT
*ads
= NULL
;
3774 LDAPMessage
*res
= NULL
;
3775 const char *etype_list_str
= NULL
;
3776 const char *dn
= NULL
;
3777 ADS_MODLIST mods
= NULL
;
3778 uint32_t etype_list
;
3779 const char *str
= NULL
;
3781 if (c
->display_usage
|| argc
< 1) {
3783 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3786 _("Set supported enctypes"));
3787 TALLOC_FREE(tmp_ctx
);
3791 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3792 if (!ADS_ERR_OK(status
)) {
3796 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3801 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3807 etype_list
|= ENC_RC4_HMAC_MD5
;
3808 etype_list
|= ENC_HMAC_SHA1_96_AES128
;
3809 etype_list
|= ENC_HMAC_SHA1_96_AES256
;
3811 if (argv
[1] != NULL
) {
3812 sscanf(argv
[1], "%i", &etype_list
);
3815 etype_list_str
= talloc_asprintf(tmp_ctx
, "%d", etype_list
);
3816 if (!etype_list_str
) {
3820 mods
= ads_init_mods(tmp_ctx
);
3825 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes",
3827 if (!ADS_ERR_OK(status
)) {
3831 status
= ads_gen_mod(ads
, dn
, mods
);
3832 if (!ADS_ERR_OK(status
)) {
3833 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3834 ads_errstr(status
));
3838 ads_msgfree(ads
, res
);
3841 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3846 net_ads_enctype_dump_enctypes(argv
[0], str
);
3850 ads_msgfree(ads
, res
);
3851 TALLOC_FREE(tmp_ctx
);
3855 static int net_ads_enctypes_delete(struct net_context
*c
, int argc
, const char **argv
)
3857 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3860 ADS_STRUCT
*ads
= NULL
;
3861 LDAPMessage
*res
= NULL
;
3862 const char *dn
= NULL
;
3863 ADS_MODLIST mods
= NULL
;
3865 if (c
->display_usage
|| argc
< 1) {
3867 "net ads enctypes delete <sAMAccountName>\n"
3870 _("Delete supported enctypes"));
3871 TALLOC_FREE(tmp_ctx
);
3875 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3876 if (!ADS_ERR_OK(status
)) {
3880 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3885 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3890 mods
= ads_init_mods(tmp_ctx
);
3895 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes", NULL
);
3896 if (!ADS_ERR_OK(status
)) {
3900 status
= ads_gen_mod(ads
, dn
, mods
);
3901 if (!ADS_ERR_OK(status
)) {
3902 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3903 ads_errstr(status
));
3910 ads_msgfree(ads
, res
);
3911 TALLOC_FREE(tmp_ctx
);
3915 static int net_ads_enctypes(struct net_context
*c
, int argc
, const char **argv
)
3917 struct functable func
[] = {
3920 net_ads_enctypes_list
,
3922 N_("List the supported encryption types"),
3923 N_("net ads enctypes list\n"
3924 " List the supported encryption types")
3928 net_ads_enctypes_set
,
3930 N_("Set the supported encryption types"),
3931 N_("net ads enctypes set\n"
3932 " Set the supported encryption types")
3936 net_ads_enctypes_delete
,
3938 N_("Delete the supported encryption types"),
3939 N_("net ads enctypes delete\n"
3940 " Delete the supported encryption types")
3943 {NULL
, NULL
, 0, NULL
, NULL
}
3946 return net_run_function(c
, argc
, argv
, "net ads enctypes", func
);
3950 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
3952 struct functable func
[] = {
3957 N_("Display details on remote ADS server"),
3959 " Display details on remote ADS server")
3965 N_("Join the local machine to ADS realm"),
3967 " Join the local machine to ADS realm")
3973 N_("Validate machine account"),
3974 N_("net ads testjoin\n"
3975 " Validate machine account")
3981 N_("Remove the local machine from ADS"),
3982 N_("net ads leave\n"
3983 " Remove the local machine from ADS")
3989 N_("Display machine account details"),
3990 N_("net ads status\n"
3991 " Display machine account details")
3997 N_("List/modify users"),
3999 " List/modify users")
4005 N_("List/modify groups"),
4006 N_("net ads group\n"
4007 " List/modify groups")
4013 N_("Issue dynamic DNS update"),
4015 " Issue dynamic DNS update")
4021 N_("Change user passwords"),
4022 N_("net ads password\n"
4023 " Change user passwords")
4027 net_ads_changetrustpw
,
4029 N_("Change trust account password"),
4030 N_("net ads changetrustpw\n"
4031 " Change trust account password")
4037 N_("List/modify printer entries"),
4038 N_("net ads printer\n"
4039 " List/modify printer entries")
4045 N_("Issue LDAP search using filter"),
4046 N_("net ads search\n"
4047 " Issue LDAP search using filter")
4053 N_("Issue LDAP search by DN"),
4055 " Issue LDAP search by DN")
4061 N_("Issue LDAP search by SID"),
4063 " Issue LDAP search by SID")
4069 N_("Display workgroup name"),
4070 N_("net ads workgroup\n"
4071 " Display the workgroup name")
4077 N_("Perform CLDAP query on DC"),
4078 N_("net ads lookup\n"
4079 " Find the ADS DC using CLDAP lookups")
4085 N_("Manage local keytab file"),
4086 N_("net ads keytab\n"
4087 " Manage local keytab file")
4093 N_("Manage Service Principal Names (SPN)s"),
4094 N_("net ads spnset\n"
4095 " Manage Service Principal Names (SPN)s")
4101 N_("Manage group policy objects"),
4103 " Manage group policy objects")
4109 N_("Manage kerberos keytab"),
4110 N_("net ads kerberos\n"
4111 " Manage kerberos keytab")
4117 N_("List/modify supported encryption types"),
4118 N_("net ads enctypes\n"
4119 " List/modify enctypes")
4121 {NULL
, NULL
, 0, NULL
, NULL
}
4124 return net_run_function(c
, argc
, argv
, "net ads", func
);
4129 static int net_ads_noads(void)
4131 d_fprintf(stderr
, _("ADS support not compiled in\n"));
4135 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
4137 return net_ads_noads();
4140 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
4142 return net_ads_noads();
4145 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
4147 return net_ads_noads();
4150 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
4152 return net_ads_noads();
4155 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
4157 return net_ads_noads();
4160 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
4162 return net_ads_noads();
4165 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
4167 return net_ads_noads();
4170 int net_ads_gpo(struct net_context
*c
, int argc
, const char **argv
)
4172 return net_ads_noads();
4175 /* this one shouldn't display a message */
4176 int net_ads_check(struct net_context
*c
)
4181 int net_ads_check_our_domain(struct net_context
*c
)
4186 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
4188 return net_ads_noads();
4191 #endif /* HAVE_ADS */