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
->config
.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
->config
.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
= cli_credentials_get_password(c
->creds
);
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 status
= ads_connect_cldap_only(ads
);
857 if (!ADS_ERR_OK(status
)) {
863 TALLOC_FREE(tmp_ctx
);
867 int net_ads_check_our_domain(struct net_context
*c
)
869 return net_ads_check_int(c
, lp_realm(), lp_workgroup(), NULL
);
872 int net_ads_check(struct net_context
*c
)
874 return net_ads_check_int(c
, NULL
, c
->opt_workgroup
, c
->opt_host
);
878 determine the netbios workgroup name for a domain
880 static int net_ads_workgroup(struct net_context
*c
, int argc
, const char **argv
)
882 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
883 ADS_STRUCT
*ads
= NULL
;
885 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
889 if (c
->display_usage
) {
891 "net ads workgroup\n"
894 _("Print the workgroup name"));
895 TALLOC_FREE(tmp_ctx
);
899 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
900 if (!ADS_ERR_OK(status
)) {
901 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
905 if (!ads
->config
.realm
) {
906 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
907 if (ads
->config
.realm
== NULL
) {
908 d_fprintf(stderr
, _("Out of memory\n"));
911 ads
->ldap
.port
= 389;
914 ok
= ads_cldap_netlogon_5(tmp_ctx
,
915 &ads
->ldap
.ss
, ads
->server
.realm
, &reply
);
917 d_fprintf(stderr
, _("CLDAP query failed!\n"));
921 d_printf(_("Workgroup: %s\n"), reply
.domain_name
);
925 TALLOC_FREE(tmp_ctx
);
932 static bool usergrp_display(ADS_STRUCT
*ads
, char *field
, void **values
, void *data_area
)
934 char **disp_fields
= (char **) data_area
;
936 if (!field
) { /* must be end of record */
937 if (disp_fields
[0]) {
938 if (!strchr_m(disp_fields
[0], '$')) {
940 d_printf("%-21.21s %s\n",
941 disp_fields
[0], disp_fields
[1]);
943 d_printf("%s\n", disp_fields
[0]);
946 SAFE_FREE(disp_fields
[0]);
947 SAFE_FREE(disp_fields
[1]);
950 if (!values
) /* must be new field, indicate string field */
952 if (strcasecmp_m(field
, "sAMAccountName") == 0) {
953 disp_fields
[0] = SMB_STRDUP((char *) values
[0]);
955 if (strcasecmp_m(field
, "description") == 0)
956 disp_fields
[1] = SMB_STRDUP((char *) values
[0]);
960 static int net_ads_user_usage(struct net_context
*c
, int argc
, const char **argv
)
962 return net_user_usage(c
, argc
, argv
);
965 static int ads_user_add(struct net_context
*c
, int argc
, const char **argv
)
967 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
968 ADS_STRUCT
*ads
= NULL
;
971 LDAPMessage
*res
=NULL
;
975 if (argc
< 1 || c
->display_usage
) {
976 TALLOC_FREE(tmp_ctx
);
977 return net_ads_user_usage(c
, argc
, argv
);
980 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
981 if (!ADS_ERR_OK(status
)) {
985 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
986 if (!ADS_ERR_OK(status
)) {
987 d_fprintf(stderr
, _("ads_user_add: %s\n"), ads_errstr(status
));
991 if (ads_count_replies(ads
, res
)) {
992 d_fprintf(stderr
, _("ads_user_add: User %s already exists\n"),
997 if (c
->opt_container
) {
998 ou_str
= SMB_STRDUP(c
->opt_container
);
1000 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
1003 status
= ads_add_user_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
1004 if (!ADS_ERR_OK(status
)) {
1005 d_fprintf(stderr
, _("Could not add user %s: %s\n"), argv
[0],
1006 ads_errstr(status
));
1010 /* if no password is to be set, we're done */
1012 d_printf(_("User %s added\n"), argv
[0]);
1017 /* try setting the password */
1018 upn
= talloc_asprintf(tmp_ctx
,
1026 status
= ads_krb5_set_password(ads
->auth
.kdc_server
, upn
, argv
[1], 0);
1027 if (ADS_ERR_OK(status
)) {
1028 d_printf(_("User %s added\n"), argv
[0]);
1034 /* password didn't set, delete account */
1035 d_fprintf(stderr
, _("Could not add user %s. "
1036 "Error setting password %s\n"),
1037 argv
[0], ads_errstr(status
));
1039 ads_msgfree(ads
, res
);
1042 status
=ads_find_user_acct(ads
, &res
, argv
[0]);
1043 if (ADS_ERR_OK(status
)) {
1044 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1045 ads_del_dn(ads
, userdn
);
1046 TALLOC_FREE(userdn
);
1050 ads_msgfree(ads
, res
);
1052 TALLOC_FREE(tmp_ctx
);
1056 static int ads_user_info(struct net_context
*c
, int argc
, const char **argv
)
1058 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1059 ADS_STRUCT
*ads
= NULL
;
1061 LDAPMessage
*res
= NULL
;
1064 const char *attrs
[] = {"memberOf", "primaryGroupID", NULL
};
1065 char *searchstring
= NULL
;
1066 char **grouplist
= NULL
;
1067 char *primary_group
= NULL
;
1068 char *escaped_user
= NULL
;
1069 struct dom_sid primary_group_sid
;
1071 enum wbcSidType type
;
1073 if (argc
< 1 || c
->display_usage
) {
1074 TALLOC_FREE(tmp_ctx
);
1075 return net_ads_user_usage(c
, argc
, argv
);
1078 escaped_user
= escape_ldap_string(tmp_ctx
, argv
[0]);
1079 if (!escaped_user
) {
1081 _("ads_user_info: failed to escape user %s\n"),
1086 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1087 if (!ADS_ERR_OK(status
)) {
1091 searchstring
= talloc_asprintf(tmp_ctx
,
1092 "(sAMAccountName=%s)",
1094 if (searchstring
== NULL
) {
1098 status
= ads_search(ads
, &res
, searchstring
, attrs
);
1099 if (!ADS_ERR_OK(status
)) {
1100 d_fprintf(stderr
, _("ads_search: %s\n"), ads_errstr(status
));
1104 if (!ads_pull_uint32(ads
, res
, "primaryGroupID", &group_rid
)) {
1105 d_fprintf(stderr
, _("ads_pull_uint32 failed\n"));
1109 status
= ads_domain_sid(ads
, &primary_group_sid
);
1110 if (!ADS_ERR_OK(status
)) {
1111 d_fprintf(stderr
, _("ads_domain_sid: %s\n"), ads_errstr(status
));
1115 sid_append_rid(&primary_group_sid
, group_rid
);
1117 wbc_status
= wbcLookupSid((struct wbcDomainSid
*)&primary_group_sid
,
1118 NULL
, /* don't look up domain */
1121 if (!WBC_ERROR_IS_OK(wbc_status
)) {
1122 d_fprintf(stderr
, "wbcLookupSid: %s\n",
1123 wbcErrorString(wbc_status
));
1127 d_printf("%s\n", primary_group
);
1129 wbcFreeMemory(primary_group
);
1131 grouplist
= ldap_get_values((LDAP
*)ads
->ldap
.ld
,
1132 (LDAPMessage
*)res
, "memberOf");
1137 for (i
=0;grouplist
[i
];i
++) {
1138 groupname
= ldap_explode_dn(grouplist
[i
], 1);
1139 d_printf("%s\n", groupname
[0]);
1140 ldap_value_free(groupname
);
1142 ldap_value_free(grouplist
);
1147 TALLOC_FREE(escaped_user
);
1148 TALLOC_FREE(searchstring
);
1149 ads_msgfree(ads
, res
);
1150 TALLOC_FREE(tmp_ctx
);
1154 static int ads_user_delete(struct net_context
*c
, int argc
, const char **argv
)
1156 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1157 ADS_STRUCT
*ads
= NULL
;
1159 LDAPMessage
*res
= NULL
;
1160 char *userdn
= NULL
;
1164 TALLOC_FREE(tmp_ctx
);
1165 return net_ads_user_usage(c
, argc
, argv
);
1168 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1169 if (!ADS_ERR_OK(status
)) {
1173 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1174 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1175 d_printf(_("User %s does not exist.\n"), argv
[0]);
1179 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1180 if (userdn
== NULL
) {
1184 status
= ads_del_dn(ads
, userdn
);
1185 if (!ADS_ERR_OK(status
)) {
1186 d_fprintf(stderr
, _("Error deleting user %s: %s\n"), argv
[0],
1187 ads_errstr(status
));
1191 d_printf(_("User %s deleted\n"), argv
[0]);
1195 ads_msgfree(ads
, res
);
1196 TALLOC_FREE(tmp_ctx
);
1200 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
1202 struct functable func
[] = {
1207 N_("Add an AD user"),
1208 N_("net ads user add\n"
1215 N_("Display information about an AD user"),
1216 N_("net ads user info\n"
1217 " Display information about an AD user")
1223 N_("Delete an AD user"),
1224 N_("net ads user delete\n"
1225 " Delete an AD user")
1227 {NULL
, NULL
, 0, NULL
, NULL
}
1229 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1230 ADS_STRUCT
*ads
= NULL
;
1232 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1233 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1234 char *disp_fields
[2] = {NULL
, NULL
};
1238 TALLOC_FREE(tmp_ctx
);
1239 return net_run_function(c
, argc
, argv
, "net ads user", func
);
1242 if (c
->display_usage
) {
1247 _("List AD users"));
1248 net_display_usage_from_functable(func
);
1249 TALLOC_FREE(tmp_ctx
);
1253 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1254 if (!ADS_ERR_OK(status
)) {
1258 if (c
->opt_long_list_entries
)
1259 d_printf(_("\nUser name Comment"
1260 "\n-----------------------------\n"));
1262 status
= ads_do_search_all_fn(ads
,
1263 ads
->config
.bind_path
,
1265 "(objectCategory=user)",
1266 c
->opt_long_list_entries
?
1267 longattrs
: shortattrs
,
1270 if (!ADS_ERR_OK(status
)) {
1276 TALLOC_FREE(tmp_ctx
);
1280 static int net_ads_group_usage(struct net_context
*c
, int argc
, const char **argv
)
1282 return net_group_usage(c
, argc
, argv
);
1285 static int ads_group_add(struct net_context
*c
, int argc
, const char **argv
)
1287 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1288 ADS_STRUCT
*ads
= NULL
;
1290 LDAPMessage
*res
= NULL
;
1292 char *ou_str
= NULL
;
1294 if (argc
< 1 || c
->display_usage
) {
1295 TALLOC_FREE(tmp_ctx
);
1296 return net_ads_group_usage(c
, argc
, argv
);
1299 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1300 if (!ADS_ERR_OK(status
)) {
1304 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1305 if (!ADS_ERR_OK(status
)) {
1306 d_fprintf(stderr
, _("ads_group_add: %s\n"), ads_errstr(status
));
1310 if (ads_count_replies(ads
, res
)) {
1311 d_fprintf(stderr
, _("ads_group_add: Group %s already exists\n"), argv
[0]);
1315 if (c
->opt_container
) {
1316 ou_str
= SMB_STRDUP(c
->opt_container
);
1318 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
1321 status
= ads_add_group_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
1322 if (!ADS_ERR_OK(status
)) {
1323 d_fprintf(stderr
, _("Could not add group %s: %s\n"), argv
[0],
1324 ads_errstr(status
));
1328 d_printf(_("Group %s added\n"), argv
[0]);
1332 ads_msgfree(ads
, res
);
1334 TALLOC_FREE(tmp_ctx
);
1338 static int ads_group_delete(struct net_context
*c
, int argc
, const char **argv
)
1340 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1341 ADS_STRUCT
*ads
= NULL
;
1343 LDAPMessage
*res
= NULL
;
1344 char *groupdn
= NULL
;
1347 if (argc
< 1 || c
->display_usage
) {
1348 TALLOC_FREE(tmp_ctx
);
1349 return net_ads_group_usage(c
, argc
, argv
);
1352 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1353 if (!ADS_ERR_OK(status
)) {
1357 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1358 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1359 d_printf(_("Group %s does not exist.\n"), argv
[0]);
1363 groupdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1364 if (groupdn
== NULL
) {
1368 status
= ads_del_dn(ads
, groupdn
);
1369 if (!ADS_ERR_OK(status
)) {
1370 d_fprintf(stderr
, _("Error deleting group %s: %s\n"), argv
[0],
1371 ads_errstr(status
));
1374 d_printf(_("Group %s deleted\n"), argv
[0]);
1378 ads_msgfree(ads
, res
);
1379 TALLOC_FREE(tmp_ctx
);
1383 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
1385 struct functable func
[] = {
1390 N_("Add an AD group"),
1391 N_("net ads group add\n"
1398 N_("Delete an AD group"),
1399 N_("net ads group delete\n"
1400 " Delete an AD group")
1402 {NULL
, NULL
, 0, NULL
, NULL
}
1404 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1405 ADS_STRUCT
*ads
= NULL
;
1407 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1408 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1409 char *disp_fields
[2] = {NULL
, NULL
};
1413 TALLOC_FREE(tmp_ctx
);
1414 return net_run_function(c
, argc
, argv
, "net ads group", func
);
1417 if (c
->display_usage
) {
1422 _("List AD groups"));
1423 net_display_usage_from_functable(func
);
1424 TALLOC_FREE(tmp_ctx
);
1428 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1429 if (!ADS_ERR_OK(status
)) {
1433 if (c
->opt_long_list_entries
)
1434 d_printf(_("\nGroup name Comment"
1435 "\n-----------------------------\n"));
1437 status
= ads_do_search_all_fn(ads
,
1438 ads
->config
.bind_path
,
1440 "(objectCategory=group)",
1441 c
->opt_long_list_entries
?
1442 longattrs
: shortattrs
,
1445 if (!ADS_ERR_OK(status
)) {
1451 TALLOC_FREE(tmp_ctx
);
1455 static int net_ads_status(struct net_context
*c
, int argc
, const char **argv
)
1457 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1458 ADS_STRUCT
*ads
= NULL
;
1460 LDAPMessage
*res
= NULL
;
1463 if (c
->display_usage
) {
1468 _("Display machine account details"));
1469 TALLOC_FREE(tmp_ctx
);
1473 net_warn_member_options();
1475 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1476 if (!ADS_ERR_OK(status
)) {
1480 status
= ads_find_machine_acct(ads
, &res
, lp_netbios_name());
1481 if (!ADS_ERR_OK(status
)) {
1482 d_fprintf(stderr
, _("ads_find_machine_acct: %s\n"),
1483 ads_errstr(status
));
1487 if (ads_count_replies(ads
, res
) == 0) {
1488 d_fprintf(stderr
, _("No machine account for '%s' found\n"),
1497 ads_msgfree(ads
, res
);
1498 TALLOC_FREE(tmp_ctx
);
1502 /*******************************************************************
1503 Leave an AD domain. Windows XP disables the machine account.
1504 We'll try the same. The old code would do an LDAP delete.
1505 That only worked using the machine creds because added the machine
1506 with full control to the computer object's ACL.
1507 *******************************************************************/
1509 static int net_ads_leave(struct net_context
*c
, int argc
, const char **argv
)
1511 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1512 struct libnet_UnjoinCtx
*r
= NULL
;
1516 if (c
->display_usage
) {
1518 "net ads leave [--keep-account]\n"
1521 _("Leave an AD domain"));
1522 TALLOC_FREE(tmp_ctx
);
1527 d_fprintf(stderr
, _("No realm set, are we joined ?\n"));
1528 TALLOC_FREE(tmp_ctx
);
1532 if (!c
->opt_kerberos
) {
1533 use_in_memory_ccache();
1537 d_fprintf(stderr
, _("Could not initialise message context. "
1538 "Try running as root\n"));
1542 werr
= libnet_init_UnjoinCtx(tmp_ctx
, &r
);
1543 if (!W_ERROR_IS_OK(werr
)) {
1544 d_fprintf(stderr
, _("Could not initialise unjoin context.\n"));
1549 r
->in
.dc_name
= c
->opt_host
;
1550 r
->in
.domain_name
= lp_realm();
1551 r
->in
.admin_credentials
= c
->creds
;
1552 r
->in
.modify_config
= lp_config_backend_is_registry();
1554 /* Try to delete it, but if that fails, disable it. The
1555 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1556 r
->in
.unjoin_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1557 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
;
1558 if (c
->opt_keep_account
) {
1559 r
->in
.delete_machine_account
= false;
1561 r
->in
.delete_machine_account
= true;
1564 r
->in
.msg_ctx
= c
->msg_ctx
;
1566 werr
= libnet_Unjoin(tmp_ctx
, r
);
1567 if (!W_ERROR_IS_OK(werr
)) {
1568 d_printf(_("Failed to leave domain: %s\n"),
1569 r
->out
.error_string
? r
->out
.error_string
:
1570 get_friendly_werror_msg(werr
));
1574 if (r
->out
.deleted_machine_account
) {
1575 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1576 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1581 /* We couldn't delete it - see if the disable succeeded. */
1582 if (r
->out
.disabled_machine_account
) {
1583 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1584 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1589 /* Based on what we requested, we shouldn't get here, but if
1590 we did, it means the secrets were removed, and therefore
1591 we have left the domain */
1592 d_fprintf(stderr
, _("Machine '%s' Left domain '%s'\n"),
1593 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1597 TALLOC_FREE(tmp_ctx
);
1601 static ADS_STATUS
net_ads_join_ok(struct net_context
*c
)
1603 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1604 ADS_STRUCT
*ads
= NULL
;
1607 struct sockaddr_storage dcip
;
1609 if (!secrets_init()) {
1610 DEBUG(1,("Failed to initialise secrets database\n"));
1611 TALLOC_FREE(tmp_ctx
);
1612 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
1615 net_warn_member_options();
1617 net_use_krb_machine_account(c
);
1619 get_dc_name(lp_workgroup(), lp_realm(), dc_name
, &dcip
);
1621 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1622 if (!ADS_ERR_OK(status
)) {
1626 status
= ADS_ERROR_NT(NT_STATUS_OK
);
1628 TALLOC_FREE(tmp_ctx
);
1633 check that an existing join is OK
1635 int net_ads_testjoin(struct net_context
*c
, int argc
, const char **argv
)
1638 use_in_memory_ccache();
1640 if (c
->display_usage
) {
1642 "net ads testjoin\n"
1645 _("Test if the existing join is ok"));
1649 net_warn_member_options();
1651 /* Display success or failure */
1652 status
= net_ads_join_ok(c
);
1653 if (!ADS_ERR_OK(status
)) {
1654 fprintf(stderr
, _("Join to domain is not valid: %s\n"),
1655 get_friendly_nt_error_msg(ads_ntstatus(status
)));
1659 printf(_("Join is OK\n"));
1663 /*******************************************************************
1664 Simple config checks before beginning the join
1665 ********************************************************************/
1667 static WERROR
check_ads_config( void )
1669 if (lp_server_role() != ROLE_DOMAIN_MEMBER
) {
1670 d_printf(_("Host is not configured as a member server.\n"));
1671 return WERR_INVALID_DOMAIN_ROLE
;
1674 if (strlen(lp_netbios_name()) > 15) {
1675 d_printf(_("Our netbios name can be at most 15 chars long, "
1676 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1677 (unsigned int)strlen(lp_netbios_name()));
1678 return WERR_INVALID_COMPUTERNAME
;
1681 if ( lp_security() == SEC_ADS
&& !*lp_realm()) {
1682 d_fprintf(stderr
, _("realm must be set in %s for ADS "
1683 "join to succeed.\n"), get_dyn_CONFIGFILE());
1684 return WERR_INVALID_PARAMETER
;
1690 /*******************************************************************
1691 ********************************************************************/
1693 static int net_ads_join_usage(struct net_context
*c
, int argc
, const char **argv
)
1695 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1696 "Valid options:\n"));
1697 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1698 " The default is in the form netbiosname.dnsdomain\n"));
1699 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1700 " The default UPN is in the form host/netbiosname@REALM.\n"));
1701 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1702 " The OU string read from top to bottom without RDNs\n"
1703 " and delimited by a '/'.\n"
1704 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1705 " NB: A backslash '\\' is used as escape at multiple\n"
1706 " levels and may need to be doubled or even\n"
1707 " quadrupled. It is not used as a separator.\n"));
1708 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1709 " the join. The default password is random.\n"));
1710 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1711 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1712 " NB: osName and osVer must be specified together for\n"
1713 " either to take effect. The operatingSystemService\n"
1714 " attribute is then also set along with the two\n"
1715 " other attributes.\n"));
1716 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1717 " during the join.\n"
1718 " NB: If not specified then by default the samba\n"
1719 " version string is used instead.\n"));
1724 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
1726 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1727 struct libnet_JoinCtx
*r
= NULL
;
1728 const char *domain
= lp_realm();
1729 WERROR werr
= WERR_NERR_SETUPNOTJOINED
;
1730 bool createupn
= false;
1731 const char *dnshostname
= NULL
;
1732 const char *machineupn
= NULL
;
1733 const char *machine_password
= NULL
;
1734 const char *create_in_ou
= NULL
;
1736 const char *os_name
= NULL
;
1737 const char *os_version
= NULL
;
1738 const char *os_servicepack
= NULL
;
1739 bool modify_config
= lp_config_backend_is_registry();
1740 enum libnetjoin_JoinDomNameType domain_name_type
= JoinDomNameTypeDNS
;
1743 if (c
->display_usage
) {
1744 TALLOC_FREE(tmp_ctx
);
1745 return net_ads_join_usage(c
, argc
, argv
);
1748 net_warn_member_options();
1750 if (!modify_config
) {
1751 werr
= check_ads_config();
1752 if (!W_ERROR_IS_OK(werr
)) {
1753 d_fprintf(stderr
, _("Invalid configuration. Exiting....\n"));
1758 if (!c
->opt_kerberos
) {
1759 use_in_memory_ccache();
1762 werr
= libnet_init_JoinCtx(tmp_ctx
, &r
);
1763 if (!W_ERROR_IS_OK(werr
)) {
1767 /* process additional command line args */
1769 for ( i
=0; i
<argc
; i
++ ) {
1770 if ( !strncasecmp_m(argv
[i
], "dnshostname", strlen("dnshostname")) ) {
1771 dnshostname
= get_string_param(argv
[i
]);
1773 else if ( !strncasecmp_m(argv
[i
], "createupn", strlen("createupn")) ) {
1775 machineupn
= get_string_param(argv
[i
]);
1777 else if ( !strncasecmp_m(argv
[i
], "createcomputer", strlen("createcomputer")) ) {
1778 if ( (create_in_ou
= get_string_param(argv
[i
])) == NULL
) {
1779 d_fprintf(stderr
, _("Please supply a valid OU path.\n"));
1780 werr
= WERR_INVALID_PARAMETER
;
1784 else if ( !strncasecmp_m(argv
[i
], "osName", strlen("osName")) ) {
1785 if ( (os_name
= get_string_param(argv
[i
])) == NULL
) {
1786 d_fprintf(stderr
, _("Please supply a operating system name.\n"));
1787 werr
= WERR_INVALID_PARAMETER
;
1791 else if ( !strncasecmp_m(argv
[i
], "osVer", strlen("osVer")) ) {
1792 if ( (os_version
= get_string_param(argv
[i
])) == NULL
) {
1793 d_fprintf(stderr
, _("Please supply a valid operating system version.\n"));
1794 werr
= WERR_INVALID_PARAMETER
;
1798 else if ( !strncasecmp_m(argv
[i
], "osServicePack", strlen("osServicePack")) ) {
1799 if ( (os_servicepack
= get_string_param(argv
[i
])) == NULL
) {
1800 d_fprintf(stderr
, _("Please supply a valid servicepack identifier.\n"));
1801 werr
= WERR_INVALID_PARAMETER
;
1805 else if ( !strncasecmp_m(argv
[i
], "machinepass", strlen("machinepass")) ) {
1806 if ( (machine_password
= get_string_param(argv
[i
])) == NULL
) {
1807 d_fprintf(stderr
, _("Please supply a valid password to set as trust account password.\n"));
1808 werr
= WERR_INVALID_PARAMETER
;
1813 if (strchr(domain
, '.') == NULL
) {
1814 domain_name_type
= JoinDomNameTypeUnknown
;
1816 domain_name_type
= JoinDomNameTypeDNS
;
1822 d_fprintf(stderr
, _("Please supply a valid domain name\n"));
1823 werr
= WERR_INVALID_PARAMETER
;
1828 d_fprintf(stderr
, _("Could not initialise message context. "
1829 "Try running as root\n"));
1830 werr
= WERR_ACCESS_DENIED
;
1834 /* Do the domain join here */
1836 r
->in
.domain_name
= domain
;
1837 r
->in
.domain_name_type
= domain_name_type
;
1838 r
->in
.create_upn
= createupn
;
1839 r
->in
.upn
= machineupn
;
1840 r
->in
.dnshostname
= dnshostname
;
1841 r
->in
.account_ou
= create_in_ou
;
1842 r
->in
.os_name
= os_name
;
1843 r
->in
.os_version
= os_version
;
1844 r
->in
.os_servicepack
= os_servicepack
;
1845 r
->in
.dc_name
= c
->opt_host
;
1846 r
->in
.admin_credentials
= c
->creds
;
1847 r
->in
.machine_password
= machine_password
;
1849 r
->in
.modify_config
= modify_config
;
1850 r
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1851 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
|
1852 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
;
1853 r
->in
.msg_ctx
= c
->msg_ctx
;
1855 werr
= libnet_Join(tmp_ctx
, r
);
1856 if (W_ERROR_EQUAL(werr
, WERR_NERR_DCNOTFOUND
) &&
1857 strequal(domain
, lp_realm())) {
1858 r
->in
.domain_name
= lp_workgroup();
1859 r
->in
.domain_name_type
= JoinDomNameTypeNBT
;
1860 werr
= libnet_Join(tmp_ctx
, r
);
1862 if (!W_ERROR_IS_OK(werr
)) {
1866 /* Check the short name of the domain */
1868 if (!modify_config
&& !strequal(lp_workgroup(), r
->out
.netbios_domain_name
)) {
1869 d_printf(_("The workgroup in %s does not match the short\n"
1870 "domain name obtained from the server.\n"
1871 "Using the name [%s] from the server.\n"
1872 "You should set \"workgroup = %s\" in %s.\n"),
1873 get_dyn_CONFIGFILE(), r
->out
.netbios_domain_name
,
1874 r
->out
.netbios_domain_name
, get_dyn_CONFIGFILE());
1877 d_printf(_("Using short domain name -- %s\n"), r
->out
.netbios_domain_name
);
1879 if (r
->out
.dns_domain_name
) {
1880 d_printf(_("Joined '%s' to dns domain '%s'\n"), r
->in
.machine_name
,
1881 r
->out
.dns_domain_name
);
1883 d_printf(_("Joined '%s' to domain '%s'\n"), r
->in
.machine_name
,
1884 r
->out
.netbios_domain_name
);
1887 /* print out informative error string in case there is one */
1888 if (r
->out
.error_string
!= NULL
) {
1889 d_printf("%s\n", r
->out
.error_string
);
1893 * We try doing the dns update (if it was compiled in
1894 * and if it was not disabled on the command line).
1895 * If the dns update fails, we still consider the join
1896 * operation as succeeded if we came this far.
1898 if (!c
->opt_no_dns_updates
) {
1899 net_ads_join_dns_updates(c
, tmp_ctx
, r
);
1906 /* issue an overall failure message at the end. */
1907 d_printf(_("Failed to join domain: %s\n"),
1908 r
&& r
->out
.error_string
? r
->out
.error_string
:
1909 get_friendly_werror_msg(werr
));
1912 TALLOC_FREE(tmp_ctx
);
1917 /*******************************************************************
1918 ********************************************************************/
1920 static int net_ads_dns_register(struct net_context
*c
, int argc
, const char **argv
)
1922 #if defined(HAVE_KRB5)
1923 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1924 ADS_STRUCT
*ads
= NULL
;
1927 const char *hostname
= NULL
;
1928 const char **addrs_list
= NULL
;
1929 struct sockaddr_storage
*addrs
= NULL
;
1935 talloc_enable_leak_report();
1938 if (argc
<= 1 && lp_clustering() && lp_cluster_addresses() == NULL
) {
1939 d_fprintf(stderr
, _("Refusing DNS updates with automatic "
1940 "detection of addresses in a clustered "
1942 c
->display_usage
= true;
1945 if (c
->display_usage
) {
1947 "net ads dns register [hostname [IP [IP...]]] "
1948 "[--force] [--dns-ttl TTL]\n"
1951 _("Register hostname with DNS\n"));
1952 TALLOC_FREE(tmp_ctx
);
1961 num_addrs
= argc
- 1;
1962 addrs_list
= &argv
[1];
1963 } else if (lp_clustering()) {
1964 addrs_list
= lp_cluster_addresses();
1965 num_addrs
= str_list_length(addrs_list
);
1968 if (num_addrs
> 0) {
1969 addrs
= talloc_zero_array(tmp_ctx
,
1970 struct sockaddr_storage
,
1972 if (addrs
== NULL
) {
1973 d_fprintf(stderr
, _("Error allocating memory!\n"));
1978 for (count
= 0; count
< num_addrs
; count
++) {
1979 if (!interpret_string_addr(&addrs
[count
], addrs_list
[count
], 0)) {
1980 d_fprintf(stderr
, "%s '%s'.\n",
1981 _("Cannot interpret address"),
1987 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1988 if ( !ADS_ERR_OK(status
) ) {
1989 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
1993 ntstatus
= net_update_dns_ext(c
,
2001 if (!NT_STATUS_IS_OK(ntstatus
)) {
2002 d_fprintf( stderr
, _("DNS update failed!\n") );
2006 d_fprintf( stderr
, _("Successfully registered hostname with DNS\n") );
2010 TALLOC_FREE(tmp_ctx
);
2015 _("DNS update support not enabled at compile time!\n"));
2020 static int net_ads_dns_unregister(struct net_context
*c
,
2024 #if defined(HAVE_KRB5)
2025 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2026 ADS_STRUCT
*ads
= NULL
;
2029 const char *hostname
= NULL
;
2033 talloc_enable_leak_report();
2037 c
->display_usage
= true;
2040 if (c
->display_usage
) {
2042 "net ads dns unregister [hostname]\n"
2045 _("Remove all IP Address entries for a given\n"
2046 " hostname from the Active Directory server.\n"));
2047 TALLOC_FREE(tmp_ctx
);
2051 /* Get the hostname for un-registering */
2054 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2055 if ( !ADS_ERR_OK(status
) ) {
2056 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
2060 ntstatus
= net_update_dns_ext(c
,
2068 if (!NT_STATUS_IS_OK(ntstatus
)) {
2069 d_fprintf( stderr
, _("DNS update failed!\n") );
2073 d_fprintf( stderr
, _("Successfully un-registered hostname from DNS\n"));
2077 TALLOC_FREE(tmp_ctx
);
2082 _("DNS update support not enabled at compile time!\n"));
2088 static int net_ads_dns_async(struct net_context
*c
, int argc
, const char **argv
)
2090 size_t num_names
= 0;
2091 char **hostnames
= NULL
;
2093 struct samba_sockaddr
*addrs
= NULL
;
2096 if (argc
!= 1 || c
->display_usage
) {
2101 _("net ads dns async <name>\n"),
2102 _(" Async look up hostname from the DNS server\n"
2103 " hostname\tName to look up\n"));
2107 status
= ads_dns_lookup_a(talloc_tos(),
2112 if (!NT_STATUS_IS_OK(status
)) {
2113 d_printf("Looking up A record for %s got error %s\n",
2118 d_printf("Async A record lookup - got %u names for %s\n",
2119 (unsigned int)num_names
,
2121 for (i
= 0; i
< num_names
; i
++) {
2122 char addr_buf
[INET6_ADDRSTRLEN
];
2123 print_sockaddr(addr_buf
,
2126 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2132 #if defined(HAVE_IPV6)
2133 status
= ads_dns_lookup_aaaa(talloc_tos(),
2138 if (!NT_STATUS_IS_OK(status
)) {
2139 d_printf("Looking up AAAA record for %s got error %s\n",
2144 d_printf("Async AAAA record lookup - got %u names for %s\n",
2145 (unsigned int)num_names
,
2147 for (i
= 0; i
< num_names
; i
++) {
2148 char addr_buf
[INET6_ADDRSTRLEN
];
2149 print_sockaddr(addr_buf
,
2152 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2162 static int net_ads_dns(struct net_context
*c
, int argc
, const char *argv
[])
2164 struct functable func
[] = {
2167 net_ads_dns_register
,
2169 N_("Add host dns entry to AD"),
2170 N_("net ads dns register\n"
2171 " Add host dns entry to AD")
2175 net_ads_dns_unregister
,
2177 N_("Remove host dns entry from AD"),
2178 N_("net ads dns unregister\n"
2179 " Remove host dns entry from AD")
2186 N_("net ads dns async\n"
2187 " Look up host using async DNS")
2189 {NULL
, NULL
, 0, NULL
, NULL
}
2192 return net_run_function(c
, argc
, argv
, "net ads dns", func
);
2195 /*******************************************************************
2196 ********************************************************************/
2198 int net_ads_printer_usage(struct net_context
*c
, int argc
, const char **argv
)
2201 "\nnet ads printer search <printer>"
2202 "\n\tsearch for a printer in the directory\n"
2203 "\nnet ads printer info <printer> <server>"
2204 "\n\tlookup info in directory for printer on server"
2205 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2206 "\nnet ads printer publish <printername>"
2207 "\n\tpublish printer in directory"
2208 "\n\t(note: printer name is required)\n"
2209 "\nnet ads printer remove <printername>"
2210 "\n\tremove printer from directory"
2211 "\n\t(note: printer name is required)\n"));
2215 /*******************************************************************
2216 ********************************************************************/
2218 static int net_ads_printer_search(struct net_context
*c
,
2222 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2223 ADS_STRUCT
*ads
= NULL
;
2225 LDAPMessage
*res
= NULL
;
2228 if (c
->display_usage
) {
2230 "net ads printer search\n"
2233 _("List printers in the AD"));
2234 TALLOC_FREE(tmp_ctx
);
2238 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2239 if (!ADS_ERR_OK(status
)) {
2243 status
= ads_find_printers(ads
, &res
);
2244 if (!ADS_ERR_OK(status
)) {
2245 d_fprintf(stderr
, _("ads_find_printer: %s\n"),
2246 ads_errstr(status
));
2250 if (ads_count_replies(ads
, res
) == 0) {
2251 d_fprintf(stderr
, _("No results found\n"));
2259 ads_msgfree(ads
, res
);
2260 TALLOC_FREE(tmp_ctx
);
2264 static int net_ads_printer_info(struct net_context
*c
,
2268 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2269 ADS_STRUCT
*ads
= NULL
;
2271 const char *servername
= NULL
;
2272 const char *printername
= NULL
;
2273 LDAPMessage
*res
= NULL
;
2276 if (c
->display_usage
) {
2279 _("net ads printer info [printername [servername]]\n"
2280 " Display printer info from AD\n"
2281 " printername\tPrinter name or wildcard\n"
2282 " servername\tName of the print server\n"));
2283 TALLOC_FREE(tmp_ctx
);
2287 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2288 if (!ADS_ERR_OK(status
)) {
2293 printername
= argv
[0];
2299 servername
= argv
[1];
2301 servername
= lp_netbios_name();
2304 status
= ads_find_printer_on_server(ads
, &res
, printername
, servername
);
2305 if (!ADS_ERR_OK(status
)) {
2306 d_fprintf(stderr
, _("Server '%s' not found: %s\n"),
2307 servername
, ads_errstr(status
));
2311 if (ads_count_replies(ads
, res
) == 0) {
2312 d_fprintf(stderr
, _("Printer '%s' not found\n"), printername
);
2320 ads_msgfree(ads
, res
);
2321 TALLOC_FREE(tmp_ctx
);
2325 static int net_ads_printer_publish(struct net_context
*c
,
2329 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2330 ADS_STRUCT
*ads
= NULL
;
2332 const char *servername
= NULL
;
2333 const char *printername
= NULL
;
2334 struct cli_state
*cli
= NULL
;
2335 struct rpc_pipe_client
*pipe_hnd
= NULL
;
2336 struct sockaddr_storage server_ss
= { 0 };
2338 ADS_MODLIST mods
= NULL
;
2339 char *prt_dn
= NULL
;
2340 char *srv_dn
= NULL
;
2341 char **srv_cn
= NULL
;
2342 char *srv_cn_escaped
= NULL
;
2343 char *printername_escaped
= NULL
;
2344 LDAPMessage
*res
= NULL
;
2348 if (argc
< 1 || c
->display_usage
) {
2351 _("net ads printer publish <printername> [servername]\n"
2352 " Publish printer in AD\n"
2353 " printername\tName of the printer\n"
2354 " servername\tName of the print server\n"));
2355 TALLOC_FREE(tmp_ctx
);
2359 mods
= ads_init_mods(tmp_ctx
);
2361 d_fprintf(stderr
, _("Out of memory\n"));
2365 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2366 if (!ADS_ERR_OK(status
)) {
2370 printername
= argv
[0];
2373 servername
= argv
[1];
2375 servername
= lp_netbios_name();
2378 /* Get printer data from SPOOLSS */
2380 ok
= resolve_name(servername
, &server_ss
, 0x20, false);
2382 d_fprintf(stderr
, _("Could not find server %s\n"),
2387 cli_credentials_set_kerberos_state(c
->creds
,
2388 CRED_USE_KERBEROS_REQUIRED
,
2391 nt_status
= cli_full_connection_creds(c
,
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 */
2654 ads
->auth
.flags
|= ADS_AUTH_GENERATE_KRB5_CONFIG
;
2655 ads_connect_cldap_only(ads
);
2657 if (!ads
->config
.realm
) {
2658 d_fprintf(stderr
, _("Didn't find the kerberos server!\n"));
2662 if (argv
[1] != NULL
) {
2663 new_password
= talloc_strdup(tmp_ctx
, argv
[1]);
2667 prompt
= talloc_asprintf(tmp_ctx
, _("Enter new password for %s:"), user
);
2668 if (prompt
== NULL
) {
2669 d_fprintf(stderr
, _("Out of memory\n"));
2673 rc
= samba_getpass(prompt
, pwd
, sizeof(pwd
), false, true);
2677 new_password
= talloc_strdup(tmp_ctx
, pwd
);
2678 memset(pwd
, '\0', sizeof(pwd
));
2681 if (new_password
== NULL
) {
2682 d_fprintf(stderr
, _("Out of memory\n"));
2686 status
= kerberos_set_password(ads
->auth
.kdc_server
,
2692 memset(new_password
, '\0', strlen(new_password
));
2693 if (!ADS_ERR_OK(status
)) {
2694 d_fprintf(stderr
, _("Password change failed: %s\n"),
2695 ads_errstr(status
));
2699 d_printf(_("Password change for %s completed.\n"), user
);
2703 TALLOC_FREE(tmp_ctx
);
2707 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
2709 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2710 ADS_STRUCT
*ads
= NULL
;
2711 char *host_principal
= NULL
;
2712 char *my_name
= NULL
;
2716 if (c
->display_usage
) {
2718 "net ads changetrustpw\n"
2721 _("Change the machine account's trust password"));
2722 TALLOC_FREE(tmp_ctx
);
2726 if (!secrets_init()) {
2727 DEBUG(1,("Failed to initialise secrets database\n"));
2731 net_warn_member_options();
2733 net_use_krb_machine_account(c
);
2735 use_in_memory_ccache();
2737 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2738 if (!ADS_ERR_OK(status
)) {
2742 my_name
= talloc_asprintf_strlower_m(tmp_ctx
, "%s", lp_netbios_name());
2743 if (my_name
== NULL
) {
2744 d_fprintf(stderr
, _("Out of memory\n"));
2748 host_principal
= talloc_asprintf(tmp_ctx
, "%s$@%s", my_name
, ads
->config
.realm
);
2749 if (host_principal
== NULL
) {
2750 d_fprintf(stderr
, _("Out of memory\n"));
2754 d_printf(_("Changing password for principal: %s\n"), host_principal
);
2756 status
= ads_change_trust_account_password(ads
, host_principal
);
2757 if (!ADS_ERR_OK(status
)) {
2758 d_fprintf(stderr
, _("Password change failed: %s\n"), ads_errstr(status
));
2762 d_printf(_("Password change for principal %s succeeded.\n"), host_principal
);
2764 if (USE_SYSTEM_KEYTAB
) {
2765 d_printf(_("Attempting to update system keytab with new password.\n"));
2766 if (ads_keytab_create_default(ads
)) {
2767 d_printf(_("Failed to update system keytab.\n"));
2773 TALLOC_FREE(tmp_ctx
);
2779 help for net ads search
2781 static int net_ads_search_usage(struct net_context
*c
, int argc
, const char **argv
)
2784 "\nnet ads search <expression> <attributes...>\n"
2785 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2786 "The expression is a standard LDAP search expression, and the\n"
2787 "attributes are a list of LDAP fields to show in the results.\n\n"
2788 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2790 net_common_flags_usage(c
, argc
, argv
);
2796 general ADS search function. Useful in diagnosing problems in ADS
2798 static int net_ads_search(struct net_context
*c
, int argc
, const char **argv
)
2800 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2801 ADS_STRUCT
*ads
= NULL
;
2803 const char *ldap_exp
= NULL
;
2804 const char **attrs
= NULL
;
2805 LDAPMessage
*res
= NULL
;
2808 if (argc
< 1 || c
->display_usage
) {
2809 TALLOC_FREE(tmp_ctx
);
2810 return net_ads_search_usage(c
, argc
, argv
);
2813 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2814 if (!ADS_ERR_OK(status
)) {
2821 status
= ads_do_search_retry(ads
,
2822 ads
->config
.bind_path
,
2827 if (!ADS_ERR_OK(status
)) {
2828 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2832 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2834 /* dump the results */
2839 ads_msgfree(ads
, res
);
2840 TALLOC_FREE(tmp_ctx
);
2846 help for net ads search
2848 static int net_ads_dn_usage(struct net_context
*c
, int argc
, const char **argv
)
2851 "\nnet ads dn <dn> <attributes...>\n"
2852 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2853 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2854 "to show in the results\n\n"
2855 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2856 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2858 net_common_flags_usage(c
, argc
, argv
);
2864 general ADS search function. Useful in diagnosing problems in ADS
2866 static int net_ads_dn(struct net_context
*c
, int argc
, const char **argv
)
2868 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2869 ADS_STRUCT
*ads
= NULL
;
2871 const char *dn
= NULL
;
2872 const char **attrs
= NULL
;
2873 LDAPMessage
*res
= NULL
;
2876 if (argc
< 1 || c
->display_usage
) {
2877 TALLOC_FREE(tmp_ctx
);
2878 return net_ads_dn_usage(c
, argc
, argv
);
2881 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2882 if (!ADS_ERR_OK(status
)) {
2889 status
= ads_do_search_all(ads
,
2895 if (!ADS_ERR_OK(status
)) {
2896 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2900 d_printf("Got %d replies\n\n", ads_count_replies(ads
, res
));
2902 /* dump the results */
2907 ads_msgfree(ads
, res
);
2908 TALLOC_FREE(tmp_ctx
);
2913 help for net ads sid search
2915 static int net_ads_sid_usage(struct net_context
*c
, int argc
, const char **argv
)
2918 "\nnet ads sid <sid> <attributes...>\n"
2919 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2920 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2921 "to show in the results\n\n"
2922 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2924 net_common_flags_usage(c
, argc
, argv
);
2930 general ADS search function. Useful in diagnosing problems in ADS
2932 static int net_ads_sid(struct net_context
*c
, int argc
, const char **argv
)
2934 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2935 ADS_STRUCT
*ads
= NULL
;
2937 const char *sid_string
= NULL
;
2938 const char **attrs
= NULL
;
2939 LDAPMessage
*res
= NULL
;
2940 struct dom_sid sid
= { 0 };
2943 if (argc
< 1 || c
->display_usage
) {
2944 TALLOC_FREE(tmp_ctx
);
2945 return net_ads_sid_usage(c
, argc
, argv
);
2948 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2949 if (!ADS_ERR_OK(status
)) {
2953 sid_string
= argv
[0];
2956 if (!string_to_sid(&sid
, sid_string
)) {
2957 d_fprintf(stderr
, _("could not convert sid\n"));
2961 status
= ads_search_retry_sid(ads
, &res
, &sid
, attrs
);
2962 if (!ADS_ERR_OK(status
)) {
2963 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2967 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2969 /* dump the results */
2974 ads_msgfree(ads
, res
);
2975 TALLOC_FREE(tmp_ctx
);
2979 static int net_ads_keytab_flush(struct net_context
*c
,
2983 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2984 ADS_STRUCT
*ads
= NULL
;
2988 if (c
->display_usage
) {
2990 "net ads keytab flush\n"
2993 _("Delete the whole keytab"));
2994 TALLOC_FREE(tmp_ctx
);
2998 if (!c
->explicit_credentials
) {
2999 net_use_krb_machine_account(c
);
3002 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3003 if (!ADS_ERR_OK(status
)) {
3007 ret
= ads_keytab_flush(ads
);
3009 TALLOC_FREE(tmp_ctx
);
3013 static int net_ads_keytab_add(struct net_context
*c
,
3018 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3019 ADS_STRUCT
*ads
= NULL
;
3024 if (c
->display_usage
) {
3027 _("net ads keytab add <principal> [principal ...]\n"
3028 " Add principals to local keytab\n"
3029 " principal\tKerberos principal to add to "
3031 TALLOC_FREE(tmp_ctx
);
3035 net_warn_member_options();
3037 d_printf(_("Processing principals to add...\n"));
3039 if (!c
->explicit_credentials
) {
3040 net_use_krb_machine_account(c
);
3043 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3044 if (!ADS_ERR_OK(status
)) {
3048 for (ret
= 0, i
= 0; i
< argc
; i
++) {
3049 ret
|= ads_keytab_add_entry(ads
, argv
[i
], update_ads
);
3052 TALLOC_FREE(tmp_ctx
);
3056 static int net_ads_keytab_add_default(struct net_context
*c
,
3060 return net_ads_keytab_add(c
, argc
, argv
, false);
3063 static int net_ads_keytab_add_update_ads(struct net_context
*c
,
3067 return net_ads_keytab_add(c
, argc
, argv
, true);
3070 static int net_ads_keytab_delete(struct net_context
*c
,
3074 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3075 ADS_STRUCT
*ads
= NULL
;
3080 if (c
->display_usage
) {
3083 _("net ads keytab delete <principal> [principal ...]\n"
3084 " Remove entries for service principal, "
3085 " from the keytab file only."
3086 " Remove principals from local keytab\n"
3087 " principal\tKerberos principal to remove from "
3089 TALLOC_FREE(tmp_ctx
);
3093 d_printf(_("Processing principals to delete...\n"));
3095 if (!c
->explicit_credentials
) {
3096 net_use_krb_machine_account(c
);
3099 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3100 if (!ADS_ERR_OK(status
)) {
3104 for (ret
= 0, i
= 0; i
< argc
; i
++) {
3105 ret
|= ads_keytab_delete_entry(ads
, argv
[i
]);
3108 TALLOC_FREE(tmp_ctx
);
3112 static int net_ads_keytab_create(struct net_context
*c
, int argc
, const char **argv
)
3114 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3115 ADS_STRUCT
*ads
= NULL
;
3119 if (c
->display_usage
) {
3121 "net ads keytab create\n"
3124 _("Create new default keytab"));
3125 TALLOC_FREE(tmp_ctx
);
3129 net_warn_member_options();
3131 if (!c
->explicit_credentials
) {
3132 net_use_krb_machine_account(c
);
3135 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3136 if (!ADS_ERR_OK(status
)) {
3140 ret
= ads_keytab_create_default(ads
);
3142 TALLOC_FREE(tmp_ctx
);
3146 static int net_ads_keytab_list(struct net_context
*c
, int argc
, const char **argv
)
3148 const char *keytab
= NULL
;
3150 if (c
->display_usage
) {
3153 _("net ads keytab list [keytab]\n"
3154 " List a local keytab\n"
3155 " keytab\tKeytab to list\n"));
3163 return ads_keytab_list(keytab
);
3167 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
3169 struct functable func
[] = {
3172 net_ads_keytab_add_default
,
3174 N_("Add a service principal"),
3175 N_("net ads keytab add\n"
3176 " Add a service principal, updates keytab file only.")
3180 net_ads_keytab_delete
,
3182 N_("Delete a service principal"),
3183 N_("net ads keytab delete\n"
3184 " Remove entries for service principal, from the keytab file only.")
3188 net_ads_keytab_add_update_ads
,
3190 N_("Add a service principal"),
3191 N_("net ads keytab add_update_ads\n"
3192 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3196 net_ads_keytab_create
,
3198 N_("Create a fresh keytab"),
3199 N_("net ads keytab create\n"
3200 " Create a fresh keytab or update existing one.")
3204 net_ads_keytab_flush
,
3206 N_("Remove all keytab entries"),
3207 N_("net ads keytab flush\n"
3208 " Remove all keytab entries")
3212 net_ads_keytab_list
,
3214 N_("List a keytab"),
3215 N_("net ads keytab list\n"
3218 {NULL
, NULL
, 0, NULL
, NULL
}
3221 if (!USE_KERBEROS_KEYTAB
) {
3222 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3223 "keytab method to use keytab functions.\n"));
3226 return net_run_function(c
, argc
, argv
, "net ads keytab", func
);
3229 static int net_ads_kerberos_renew(struct net_context
*c
, int argc
, const char **argv
)
3233 if (c
->display_usage
) {
3235 "net ads kerberos renew\n"
3238 _("Renew TGT from existing credential cache"));
3242 ret
= smb_krb5_renew_ticket(NULL
, NULL
, NULL
, NULL
);
3244 d_printf(_("failed to renew kerberos ticket: %s\n"),
3245 error_message(ret
));
3250 static int net_ads_kerberos_pac_common(struct net_context
*c
, int argc
, const char **argv
,
3251 struct PAC_DATA_CTR
**pac_data_ctr
)
3255 const char *impersonate_princ_s
= NULL
;
3256 const char *local_service
= NULL
;
3257 const char *password
= NULL
;
3260 for (i
=0; i
<argc
; i
++) {
3261 if (strnequal(argv
[i
], "impersonate", strlen("impersonate"))) {
3262 impersonate_princ_s
= get_string_param(argv
[i
]);
3263 if (impersonate_princ_s
== NULL
) {
3267 if (strnequal(argv
[i
], "local_service", strlen("local_service"))) {
3268 local_service
= get_string_param(argv
[i
]);
3269 if (local_service
== NULL
) {
3275 if (local_service
== NULL
) {
3276 local_service
= talloc_asprintf(c
, "%s$@%s",
3277 lp_netbios_name(), lp_realm());
3278 if (local_service
== NULL
) {
3283 password
= cli_credentials_get_password(c
->creds
);
3285 status
= kerberos_return_pac(c
,
3294 2592000, /* one month */
3295 impersonate_princ_s
,
3300 if (!NT_STATUS_IS_OK(status
)) {
3301 d_printf(_("failed to query kerberos PAC: %s\n"),
3311 static int net_ads_kerberos_pac_dump(struct net_context
*c
, int argc
, const char **argv
)
3313 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3316 enum PAC_TYPE type
= 0;
3318 if (c
->display_usage
) {
3320 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3323 _("Dump the Kerberos PAC"));
3327 for (i
=0; i
<argc
; i
++) {
3328 if (strnequal(argv
[i
], "pac_buffer_type", strlen("pac_buffer_type"))) {
3329 type
= get_int_param(argv
[i
]);
3333 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3342 s
= NDR_PRINT_STRUCT_STRING(c
, PAC_DATA
,
3343 pac_data_ctr
->pac_data
);
3345 d_printf(_("The Pac: %s\n"), s
);
3352 num_buffers
= pac_data_ctr
->pac_data
->num_buffers
;
3354 for (i
=0; i
<num_buffers
; i
++) {
3358 if (pac_data_ctr
->pac_data
->buffers
[i
].type
!= type
) {
3362 s
= NDR_PRINT_UNION_STRING(c
, PAC_INFO
, type
,
3363 pac_data_ctr
->pac_data
->buffers
[i
].info
);
3365 d_printf(_("The Pac: %s\n"), s
);
3374 static int net_ads_kerberos_pac_save(struct net_context
*c
, int argc
, const char **argv
)
3376 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3377 char *filename
= NULL
;
3381 if (c
->display_usage
) {
3383 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3386 _("Save the Kerberos PAC"));
3390 for (i
=0; i
<argc
; i
++) {
3391 if (strnequal(argv
[i
], "filename", strlen("filename"))) {
3392 filename
= get_string_param(argv
[i
]);
3393 if (filename
== NULL
) {
3399 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3404 if (filename
== NULL
) {
3405 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3409 /* save the raw format */
3410 if (!file_save(filename
, pac_data_ctr
->pac_blob
.data
, pac_data_ctr
->pac_blob
.length
)) {
3411 d_printf(_("failed to save PAC in %s\n"), filename
);
3418 static int net_ads_kerberos_pac(struct net_context
*c
, int argc
, const char **argv
)
3420 struct functable func
[] = {
3423 net_ads_kerberos_pac_dump
,
3425 N_("Dump Kerberos PAC"),
3426 N_("net ads kerberos pac dump\n"
3427 " Dump a Kerberos PAC to stdout")
3431 net_ads_kerberos_pac_save
,
3433 N_("Save Kerberos PAC"),
3434 N_("net ads kerberos pac save\n"
3435 " Save a Kerberos PAC in a file")
3438 {NULL
, NULL
, 0, NULL
, NULL
}
3441 return net_run_function(c
, argc
, argv
, "net ads kerberos pac", func
);
3444 static int net_ads_kerberos_kinit(struct net_context
*c
, int argc
, const char **argv
)
3448 const char *password
= NULL
;
3450 if (c
->display_usage
) {
3452 "net ads kerberos kinit\n"
3455 _("Get Ticket Granting Ticket (TGT) for the user"));
3459 password
= cli_credentials_get_password(c
->creds
);
3461 ret
= kerberos_kinit_password_ext(c
->opt_user_name
,
3469 2592000, /* one month */
3475 d_printf(_("failed to kinit password: %s\n"),
3481 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
3483 struct functable func
[] = {
3486 net_ads_kerberos_kinit
,
3488 N_("Retrieve Ticket Granting Ticket (TGT)"),
3489 N_("net ads kerberos kinit\n"
3490 " Receive Ticket Granting Ticket (TGT)")
3494 net_ads_kerberos_renew
,
3496 N_("Renew Ticket Granting Ticket from credential cache"),
3497 N_("net ads kerberos renew\n"
3498 " Renew Ticket Granting Ticket (TGT) from "
3503 net_ads_kerberos_pac
,
3505 N_("Dump Kerberos PAC"),
3506 N_("net ads kerberos pac\n"
3507 " Dump Kerberos PAC")
3509 {NULL
, NULL
, 0, NULL
, NULL
}
3512 return net_run_function(c
, argc
, argv
, "net ads kerberos", func
);
3515 static int net_ads_setspn_list(struct net_context
*c
,
3519 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3520 ADS_STRUCT
*ads
= NULL
;
3525 if (c
->display_usage
) {
3528 _("net ads setspn list <machinename>\n"));
3529 TALLOC_FREE(tmp_ctx
);
3533 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3534 if (!ADS_ERR_OK(status
)) {
3539 ok
= ads_setspn_list(ads
, argv
[0]);
3541 ok
= ads_setspn_list(ads
, lp_netbios_name());
3546 TALLOC_FREE(tmp_ctx
);
3550 static int net_ads_setspn_add(struct net_context
*c
, int argc
, const char **argv
)
3552 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3553 ADS_STRUCT
*ads
= NULL
;
3558 if (c
->display_usage
|| argc
< 1) {
3561 _("net ads setspn add <machinename> SPN\n"));
3562 TALLOC_FREE(tmp_ctx
);
3566 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3567 if (!ADS_ERR_OK(status
)) {
3572 ok
= ads_setspn_add(ads
, argv
[0], argv
[1]);
3574 ok
= ads_setspn_add(ads
, lp_netbios_name(), argv
[0]);
3579 TALLOC_FREE(tmp_ctx
);
3583 static int net_ads_setspn_delete(struct net_context
*c
, int argc
, const char **argv
)
3585 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3586 ADS_STRUCT
*ads
= NULL
;
3591 if (c
->display_usage
|| argc
< 1) {
3594 _("net ads setspn delete <machinename> SPN\n"));
3595 TALLOC_FREE(tmp_ctx
);
3599 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3600 if (!ADS_ERR_OK(status
)) {
3605 ok
= ads_setspn_delete(ads
, argv
[0], argv
[1]);
3607 ok
= ads_setspn_delete(ads
, lp_netbios_name(), argv
[0]);
3612 TALLOC_FREE(tmp_ctx
);
3616 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
3618 struct functable func
[] = {
3621 net_ads_setspn_list
,
3623 N_("List Service Principal Names (SPN)"),
3624 N_("net ads setspn list machine\n"
3625 " List Service Principal Names (SPN)")
3631 N_("Add Service Principal Names (SPN)"),
3632 N_("net ads setspn add machine spn\n"
3633 " Add Service Principal Names (SPN)")
3637 net_ads_setspn_delete
,
3639 N_("Delete Service Principal Names (SPN)"),
3640 N_("net ads setspn delete machine spn\n"
3641 " Delete Service Principal Names (SPN)")
3643 {NULL
, NULL
, 0, NULL
, NULL
}
3646 return net_run_function(c
, argc
, argv
, "net ads setspn", func
);
3649 static int net_ads_enctype_lookup_account(struct net_context
*c
,
3651 const char *account
,
3653 const char **enctype_str
)
3656 const char *attrs
[] = {
3657 "msDS-SupportedEncryptionTypes",
3664 filter
= talloc_asprintf(c
, "(&(objectclass=user)(sAMAccountName=%s))",
3666 if (filter
== NULL
) {
3670 status
= ads_search(ads
, res
, filter
, attrs
);
3671 if (!ADS_ERR_OK(status
)) {
3672 d_printf(_("no account found with filter: %s\n"), filter
);
3676 count
= ads_count_replies(ads
, *res
);
3681 d_printf(_("no account found with filter: %s\n"), filter
);
3684 d_printf(_("multiple accounts found with filter: %s\n"), filter
);
3689 *enctype_str
= ads_pull_string(ads
, c
, *res
,
3690 "msDS-SupportedEncryptionTypes");
3691 if (*enctype_str
== NULL
) {
3692 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3702 static void net_ads_enctype_dump_enctypes(const char *username
,
3703 const char *enctype_str
)
3705 int enctypes
= atoi(enctype_str
);
3707 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3708 username
, enctypes
, enctypes
);
3710 printf("[%s] 0x%08x DES-CBC-CRC\n",
3711 enctypes
& ENC_CRC32
? "X" : " ",
3713 printf("[%s] 0x%08x DES-CBC-MD5\n",
3714 enctypes
& ENC_RSA_MD5
? "X" : " ",
3716 printf("[%s] 0x%08x RC4-HMAC\n",
3717 enctypes
& ENC_RC4_HMAC_MD5
? "X" : " ",
3719 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3720 enctypes
& ENC_HMAC_SHA1_96_AES128
? "X" : " ",
3721 ENC_HMAC_SHA1_96_AES128
);
3722 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3723 enctypes
& ENC_HMAC_SHA1_96_AES256
? "X" : " ",
3724 ENC_HMAC_SHA1_96_AES256
);
3725 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3726 enctypes
& ENC_HMAC_SHA1_96_AES256_SK
? "X" : " ",
3727 ENC_HMAC_SHA1_96_AES256_SK
);
3728 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3729 enctypes
& KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
? "X" : " ",
3730 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
);
3733 static int net_ads_enctypes_list(struct net_context
*c
, int argc
, const char **argv
)
3735 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3737 ADS_STRUCT
*ads
= NULL
;
3738 LDAPMessage
*res
= NULL
;
3739 const char *str
= NULL
;
3742 if (c
->display_usage
|| (argc
< 1)) {
3744 "net ads enctypes list\n"
3747 _("List supported enctypes"));
3748 TALLOC_FREE(tmp_ctx
);
3752 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3753 if (!ADS_ERR_OK(status
)) {
3757 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3762 net_ads_enctype_dump_enctypes(argv
[0], str
);
3766 ads_msgfree(ads
, res
);
3767 TALLOC_FREE(tmp_ctx
);
3771 static int net_ads_enctypes_set(struct net_context
*c
, int argc
, const char **argv
)
3773 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3776 ADS_STRUCT
*ads
= NULL
;
3777 LDAPMessage
*res
= NULL
;
3778 const char *etype_list_str
= NULL
;
3779 const char *dn
= NULL
;
3780 ADS_MODLIST mods
= NULL
;
3781 uint32_t etype_list
;
3782 const char *str
= NULL
;
3784 if (c
->display_usage
|| argc
< 1) {
3786 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3789 _("Set supported enctypes"));
3790 TALLOC_FREE(tmp_ctx
);
3794 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3795 if (!ADS_ERR_OK(status
)) {
3799 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3804 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3810 etype_list
|= ENC_RC4_HMAC_MD5
;
3811 etype_list
|= ENC_HMAC_SHA1_96_AES128
;
3812 etype_list
|= ENC_HMAC_SHA1_96_AES256
;
3814 if (argv
[1] != NULL
) {
3815 sscanf(argv
[1], "%i", &etype_list
);
3818 etype_list_str
= talloc_asprintf(tmp_ctx
, "%d", etype_list
);
3819 if (!etype_list_str
) {
3823 mods
= ads_init_mods(tmp_ctx
);
3828 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes",
3830 if (!ADS_ERR_OK(status
)) {
3834 status
= ads_gen_mod(ads
, dn
, mods
);
3835 if (!ADS_ERR_OK(status
)) {
3836 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3837 ads_errstr(status
));
3841 ads_msgfree(ads
, res
);
3844 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3849 net_ads_enctype_dump_enctypes(argv
[0], str
);
3853 ads_msgfree(ads
, res
);
3854 TALLOC_FREE(tmp_ctx
);
3858 static int net_ads_enctypes_delete(struct net_context
*c
, int argc
, const char **argv
)
3860 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3863 ADS_STRUCT
*ads
= NULL
;
3864 LDAPMessage
*res
= NULL
;
3865 const char *dn
= NULL
;
3866 ADS_MODLIST mods
= NULL
;
3868 if (c
->display_usage
|| argc
< 1) {
3870 "net ads enctypes delete <sAMAccountName>\n"
3873 _("Delete supported enctypes"));
3874 TALLOC_FREE(tmp_ctx
);
3878 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3879 if (!ADS_ERR_OK(status
)) {
3883 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3888 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3893 mods
= ads_init_mods(tmp_ctx
);
3898 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes", NULL
);
3899 if (!ADS_ERR_OK(status
)) {
3903 status
= ads_gen_mod(ads
, dn
, mods
);
3904 if (!ADS_ERR_OK(status
)) {
3905 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3906 ads_errstr(status
));
3913 ads_msgfree(ads
, res
);
3914 TALLOC_FREE(tmp_ctx
);
3918 static int net_ads_enctypes(struct net_context
*c
, int argc
, const char **argv
)
3920 struct functable func
[] = {
3923 net_ads_enctypes_list
,
3925 N_("List the supported encryption types"),
3926 N_("net ads enctypes list\n"
3927 " List the supported encryption types")
3931 net_ads_enctypes_set
,
3933 N_("Set the supported encryption types"),
3934 N_("net ads enctypes set\n"
3935 " Set the supported encryption types")
3939 net_ads_enctypes_delete
,
3941 N_("Delete the supported encryption types"),
3942 N_("net ads enctypes delete\n"
3943 " Delete the supported encryption types")
3946 {NULL
, NULL
, 0, NULL
, NULL
}
3949 return net_run_function(c
, argc
, argv
, "net ads enctypes", func
);
3953 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
3955 struct functable func
[] = {
3960 N_("Display details on remote ADS server"),
3962 " Display details on remote ADS server")
3968 N_("Join the local machine to ADS realm"),
3970 " Join the local machine to ADS realm")
3976 N_("Validate machine account"),
3977 N_("net ads testjoin\n"
3978 " Validate machine account")
3984 N_("Remove the local machine from ADS"),
3985 N_("net ads leave\n"
3986 " Remove the local machine from ADS")
3992 N_("Display machine account details"),
3993 N_("net ads status\n"
3994 " Display machine account details")
4000 N_("List/modify users"),
4002 " List/modify users")
4008 N_("List/modify groups"),
4009 N_("net ads group\n"
4010 " List/modify groups")
4016 N_("Issue dynamic DNS update"),
4018 " Issue dynamic DNS update")
4024 N_("Change user passwords"),
4025 N_("net ads password\n"
4026 " Change user passwords")
4030 net_ads_changetrustpw
,
4032 N_("Change trust account password"),
4033 N_("net ads changetrustpw\n"
4034 " Change trust account password")
4040 N_("List/modify printer entries"),
4041 N_("net ads printer\n"
4042 " List/modify printer entries")
4048 N_("Issue LDAP search using filter"),
4049 N_("net ads search\n"
4050 " Issue LDAP search using filter")
4056 N_("Issue LDAP search by DN"),
4058 " Issue LDAP search by DN")
4064 N_("Issue LDAP search by SID"),
4066 " Issue LDAP search by SID")
4072 N_("Display workgroup name"),
4073 N_("net ads workgroup\n"
4074 " Display the workgroup name")
4080 N_("Perform CLDAP query on DC"),
4081 N_("net ads lookup\n"
4082 " Find the ADS DC using CLDAP lookups")
4088 N_("Manage local keytab file"),
4089 N_("net ads keytab\n"
4090 " Manage local keytab file")
4096 N_("Manage Service Principal Names (SPN)s"),
4097 N_("net ads spnset\n"
4098 " Manage Service Principal Names (SPN)s")
4104 N_("Manage group policy objects"),
4106 " Manage group policy objects")
4112 N_("Manage kerberos keytab"),
4113 N_("net ads kerberos\n"
4114 " Manage kerberos keytab")
4120 N_("List/modify supported encryption types"),
4121 N_("net ads enctypes\n"
4122 " List/modify enctypes")
4124 {NULL
, NULL
, 0, NULL
, NULL
}
4127 return net_run_function(c
, argc
, argv
, "net ads", func
);
4132 static int net_ads_noads(void)
4134 d_fprintf(stderr
, _("ADS support not compiled in\n"));
4138 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
4140 return net_ads_noads();
4143 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
4145 return net_ads_noads();
4148 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
4150 return net_ads_noads();
4153 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
4155 return net_ads_noads();
4158 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
4160 return net_ads_noads();
4163 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
4165 return net_ads_noads();
4168 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
4170 return net_ads_noads();
4173 int net_ads_gpo(struct net_context
*c
, int argc
, const char **argv
)
4175 return net_ads_noads();
4178 /* this one shouldn't display a message */
4179 int net_ads_check(struct net_context
*c
)
4184 int net_ads_check_our_domain(struct net_context
*c
)
4189 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
4191 return net_ads_noads();
4194 #endif /* HAVE_ADS */