2 Samba Unix/Linux SMB client library
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "utils/net.h"
25 #include "libsmb/namequery.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "librpc/gen_ndr/ndr_krb5pac.h"
28 #include "../librpc/gen_ndr/ndr_spoolss.h"
29 #include "nsswitch/libwbclient/wbclient.h"
31 #include "libads/cldap.h"
32 #include "../lib/addns/dnsquery.h"
33 #include "../libds/common/flags.h"
34 #include "librpc/gen_ndr/libnet_join.h"
35 #include "libnet/libnet_join.h"
39 #include "../libcli/security/security.h"
40 #include "libsmb/libsmb.h"
41 #include "lib/param/loadparm.h"
42 #include "utils/net_dns.h"
43 #include "auth/kerberos/pac_utils.h"
44 #include "lib/util/string_wrappers.h"
48 #include "audit_logging.h" /* various JSON helpers */
49 #include "auth/common_auth.h"
50 #endif /* [HAVE_JANSSON] */
54 /* when we do not have sufficient input parameters to contact a remote domain
55 * we always fall back to our own realm - Guenther*/
57 static const char *assume_own_realm(struct net_context
*c
)
59 if (!c
->opt_host
&& strequal(lp_workgroup(), c
->opt_target_workgroup
)) {
69 * note: JSON output deliberately bypasses gettext so as to provide the same
70 * output irrespective of the locale.
73 static int output_json(const struct json_object
*jsobj
)
75 TALLOC_CTX
*ctx
= NULL
;
78 if (json_is_invalid(jsobj
)) {
82 ctx
= talloc_new(NULL
);
84 d_fprintf(stderr
, _("Out of memory\n"));
88 json
= json_to_string(ctx
, jsobj
);
90 d_fprintf(stderr
, _("error encoding to JSON\n"));
94 d_printf("%s\n", json
);
100 static int net_ads_cldap_netlogon_json
103 const struct NETLOGON_SAM_LOGON_RESPONSE_EX
*reply
)
105 struct json_object jsobj
= json_new_object();
106 struct json_object flagsobj
= json_new_object();
107 char response_type
[32] = { '\0' };
110 if (json_is_invalid(&jsobj
) || json_is_invalid(&flagsobj
)) {
111 d_fprintf(stderr
, _("error setting up JSON value\n"));
116 switch (reply
->command
) {
117 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
118 strncpy(response_type
,
119 "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
120 sizeof(response_type
));
122 case LOGON_SAM_LOGON_RESPONSE_EX
:
123 strncpy(response_type
, "LOGON_SAM_LOGON_RESPONSE_EX",
124 sizeof(response_type
));
127 snprintf(response_type
, sizeof(response_type
), "0x%x",
132 ret
= json_add_string(&jsobj
, "Information for Domain Controller",
138 ret
= json_add_string(&jsobj
, "Response Type", response_type
);
143 ret
= json_add_guid(&jsobj
, "GUID", &reply
->domain_uuid
);
148 ret
= json_add_bool(&flagsobj
, "Is a PDC",
149 reply
->server_type
& NBT_SERVER_PDC
);
154 ret
= json_add_bool(&flagsobj
, "Is a GC of the forest",
155 reply
->server_type
& NBT_SERVER_GC
);
160 ret
= json_add_bool(&flagsobj
, "Is an LDAP server",
161 reply
->server_type
& NBT_SERVER_LDAP
);
166 ret
= json_add_bool(&flagsobj
, "Supports DS",
167 reply
->server_type
& NBT_SERVER_DS
);
172 ret
= json_add_bool(&flagsobj
, "Is running a KDC",
173 reply
->server_type
& NBT_SERVER_KDC
);
178 ret
= json_add_bool(&flagsobj
, "Is running time services",
179 reply
->server_type
& NBT_SERVER_TIMESERV
);
184 ret
= json_add_bool(&flagsobj
, "Is the closest DC",
185 reply
->server_type
& NBT_SERVER_CLOSEST
);
190 ret
= json_add_bool(&flagsobj
, "Is writable",
191 reply
->server_type
& NBT_SERVER_WRITABLE
);
196 ret
= json_add_bool(&flagsobj
, "Has a hardware clock",
197 reply
->server_type
& NBT_SERVER_GOOD_TIMESERV
);
202 ret
= json_add_bool(&flagsobj
,
203 "Is a non-domain NC serviced by LDAP server",
204 reply
->server_type
& NBT_SERVER_NDNC
);
210 (&flagsobj
, "Is NT6 DC that has some secrets",
211 reply
->server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
);
217 (&flagsobj
, "Is NT6 DC that has all secrets",
218 reply
->server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
);
223 ret
= json_add_bool(&flagsobj
, "Runs Active Directory Web Services",
224 reply
->server_type
& NBT_SERVER_ADS_WEB_SERVICE
);
229 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2012 or later",
230 reply
->server_type
& NBT_SERVER_DS_8
);
235 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2012R2 or later",
236 reply
->server_type
& NBT_SERVER_DS_9
);
241 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2016 or later",
242 reply
->server_type
& NBT_SERVER_DS_10
);
247 ret
= json_add_bool(&flagsobj
, "Has a DNS name",
248 reply
->server_type
& NBT_SERVER_HAS_DNS_NAME
);
253 ret
= json_add_bool(&flagsobj
, "Is a default NC",
254 reply
->server_type
& NBT_SERVER_IS_DEFAULT_NC
);
259 ret
= json_add_bool(&flagsobj
, "Is the forest root",
260 reply
->server_type
& NBT_SERVER_FOREST_ROOT
);
265 ret
= json_add_string(&jsobj
, "Forest", reply
->forest
);
270 ret
= json_add_string(&jsobj
, "Domain", reply
->dns_domain
);
275 ret
= json_add_string(&jsobj
, "Domain Controller", reply
->pdc_dns_name
);
281 ret
= json_add_string(&jsobj
, "Pre-Win2k Domain", reply
->domain_name
);
286 ret
= json_add_string(&jsobj
, "Pre-Win2k Hostname", reply
->pdc_name
);
291 if (*reply
->user_name
) {
292 ret
= json_add_string(&jsobj
, "User name", reply
->user_name
);
298 ret
= json_add_string(&jsobj
, "Server Site Name", reply
->server_site
);
303 ret
= json_add_string(&jsobj
, "Client Site Name", reply
->client_site
);
308 ret
= json_add_int(&jsobj
, "NT Version", reply
->nt_version
);
313 ret
= json_add_int(&jsobj
, "LMNT Token", reply
->lmnt_token
);
318 ret
= json_add_int(&jsobj
, "LM20 Token", reply
->lm20_token
);
323 ret
= json_add_object(&jsobj
, "Flags", &flagsobj
);
328 ret
= output_json(&jsobj
);
329 json_free(&jsobj
); /* frees flagsobj recursively */
334 json_free(&flagsobj
);
340 #else /* [HAVE_JANSSON] */
342 static int net_ads_cldap_netlogon_json
345 const struct NETLOGON_SAM_LOGON_RESPONSE_EX
* reply
)
347 d_fprintf(stderr
, _("JSON support not available\n"));
352 #endif /* [HAVE_JANSSON] */
355 do a cldap netlogon query
357 static int net_ads_cldap_netlogon(struct net_context
*c
, ADS_STRUCT
*ads
)
359 char addr
[INET6_ADDRSTRLEN
];
360 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
362 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
364 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads
->ldap
.ss
, ads
->server
.realm
, &reply
) ) {
365 d_fprintf(stderr
, _("CLDAP query failed!\n"));
370 return net_ads_cldap_netlogon_json(ads
, addr
, &reply
);
373 d_printf(_("Information for Domain Controller: %s\n\n"),
376 d_printf(_("Response Type: "));
377 switch (reply
.command
) {
378 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
379 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
381 case LOGON_SAM_LOGON_RESPONSE_EX
:
382 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
385 d_printf("0x%x\n", reply
.command
);
389 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply
.domain_uuid
));
391 d_printf(_("Flags:\n"
393 "\tIs a GC of the forest: %s\n"
394 "\tIs an LDAP server: %s\n"
395 "\tSupports DS: %s\n"
396 "\tIs running a KDC: %s\n"
397 "\tIs running time services: %s\n"
398 "\tIs the closest DC: %s\n"
399 "\tIs writable: %s\n"
400 "\tHas a hardware clock: %s\n"
401 "\tIs a non-domain NC serviced by LDAP server: %s\n"
402 "\tIs NT6 DC that has some secrets: %s\n"
403 "\tIs NT6 DC that has all secrets: %s\n"
404 "\tRuns Active Directory Web Services: %s\n"
405 "\tRuns on Windows 2012 or later: %s\n"
406 "\tRuns on Windows 2012R2 or later: %s\n"
407 "\tRuns on Windows 2016 or later: %s\n"
408 "\tHas a DNS name: %s\n"
409 "\tIs a default NC: %s\n"
410 "\tIs the forest root: %s\n"),
411 (reply
.server_type
& NBT_SERVER_PDC
) ? _("yes") : _("no"),
412 (reply
.server_type
& NBT_SERVER_GC
) ? _("yes") : _("no"),
413 (reply
.server_type
& NBT_SERVER_LDAP
) ? _("yes") : _("no"),
414 (reply
.server_type
& NBT_SERVER_DS
) ? _("yes") : _("no"),
415 (reply
.server_type
& NBT_SERVER_KDC
) ? _("yes") : _("no"),
416 (reply
.server_type
& NBT_SERVER_TIMESERV
) ? _("yes") : _("no"),
417 (reply
.server_type
& NBT_SERVER_CLOSEST
) ? _("yes") : _("no"),
418 (reply
.server_type
& NBT_SERVER_WRITABLE
) ? _("yes") : _("no"),
419 (reply
.server_type
& NBT_SERVER_GOOD_TIMESERV
) ? _("yes") : _("no"),
420 (reply
.server_type
& NBT_SERVER_NDNC
) ? _("yes") : _("no"),
421 (reply
.server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
422 (reply
.server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
423 (reply
.server_type
& NBT_SERVER_ADS_WEB_SERVICE
) ? _("yes") : _("no"),
424 (reply
.server_type
& NBT_SERVER_DS_8
) ? _("yes") : _("no"),
425 (reply
.server_type
& NBT_SERVER_DS_9
) ? _("yes") : _("no"),
426 (reply
.server_type
& NBT_SERVER_DS_10
) ? _("yes") : _("no"),
427 (reply
.server_type
& NBT_SERVER_HAS_DNS_NAME
) ? _("yes") : _("no"),
428 (reply
.server_type
& NBT_SERVER_IS_DEFAULT_NC
) ? _("yes") : _("no"),
429 (reply
.server_type
& NBT_SERVER_FOREST_ROOT
) ? _("yes") : _("no"));
432 printf(_("Forest: %s\n"), reply
.forest
);
433 printf(_("Domain: %s\n"), reply
.dns_domain
);
434 printf(_("Domain Controller: %s\n"), reply
.pdc_dns_name
);
436 printf(_("Pre-Win2k Domain: %s\n"), reply
.domain_name
);
437 printf(_("Pre-Win2k Hostname: %s\n"), reply
.pdc_name
);
439 if (*reply
.user_name
) printf(_("User name: %s\n"), reply
.user_name
);
441 printf(_("Server Site Name: %s\n"), reply
.server_site
);
442 printf(_("Client Site Name: %s\n"), reply
.client_site
);
444 d_printf(_("NT Version: %d\n"), reply
.nt_version
);
445 d_printf(_("LMNT Token: %.2x\n"), reply
.lmnt_token
);
446 d_printf(_("LM20 Token: %.2x\n"), reply
.lm20_token
);
452 this implements the CLDAP based netlogon lookup requests
453 for finding the domain controller of a ADS domain
455 static int net_ads_lookup(struct net_context
*c
, int argc
, const char **argv
)
457 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
458 ADS_STRUCT
*ads
= NULL
;
462 if (c
->display_usage
) {
467 _("Find the ADS DC using CLDAP lookup.\n"));
468 TALLOC_FREE(tmp_ctx
);
472 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
473 if (!ADS_ERR_OK(status
)) {
474 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
478 if (!ads
->config
.realm
) {
479 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
480 if (ads
->config
.realm
== NULL
) {
481 d_fprintf(stderr
, _("Out of memory\n"));
484 ads
->ldap
.port
= 389;
487 ret
= net_ads_cldap_netlogon(c
, ads
);
489 TALLOC_FREE(tmp_ctx
);
496 static int net_ads_info_json(ADS_STRUCT
*ads
)
499 char addr
[INET6_ADDRSTRLEN
];
501 struct json_object jsobj
= json_new_object();
503 if (json_is_invalid(&jsobj
)) {
504 d_fprintf(stderr
, _("error setting up JSON value\n"));
509 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
511 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
513 ret
= json_add_string (&jsobj
, "LDAP server", addr
);
518 ret
= json_add_string (&jsobj
, "LDAP server name",
519 ads
->config
.ldap_server_name
);
524 ret
= json_add_string (&jsobj
, "Realm", ads
->config
.realm
);
529 ret
= json_add_string (&jsobj
, "Bind Path", ads
->config
.bind_path
);
534 ret
= json_add_int (&jsobj
, "LDAP port", ads
->ldap
.port
);
539 ret
= json_add_int (&jsobj
, "Server time", ads
->config
.current_time
);
544 ret
= json_add_string (&jsobj
, "KDC server", ads
->auth
.kdc_server
);
549 ret
= json_add_int (&jsobj
, "Server time offset",
550 ads
->auth
.time_offset
);
555 ret
= json_add_int (&jsobj
, "Last machine account password change",
561 ret
= output_json(&jsobj
);
568 #else /* [HAVE_JANSSON] */
570 static int net_ads_info_json(ADS_STRUCT
*ads
)
572 d_fprintf(stderr
, _("JSON support not available\n"));
577 #endif /* [HAVE_JANSSON] */
581 static int net_ads_info(struct net_context
*c
, int argc
, const char **argv
)
583 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
584 ADS_STRUCT
*ads
= NULL
;
586 char addr
[INET6_ADDRSTRLEN
];
590 if (c
->display_usage
) {
595 _("Display information about an Active Directory "
597 TALLOC_FREE(tmp_ctx
);
601 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
602 if (!ADS_ERR_OK(status
)) {
603 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
607 if (!ads
|| !ads
->config
.realm
) {
608 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
612 /* Try to set the server's current time since we didn't do a full
613 TCP LDAP session initially */
615 if ( !ADS_ERR_OK(ads_current_time( ads
)) ) {
616 d_fprintf( stderr
, _("Failed to get server's current time!\n"));
620 ret
= net_ads_info_json(ads
);
624 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
626 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
628 d_printf(_("LDAP server: %s\n"), addr
);
629 d_printf(_("LDAP server name: %s\n"), ads
->config
.ldap_server_name
);
630 d_printf(_("Realm: %s\n"), ads
->config
.realm
);
631 d_printf(_("Bind Path: %s\n"), ads
->config
.bind_path
);
632 d_printf(_("LDAP port: %d\n"), ads
->ldap
.port
);
633 d_printf(_("Server time: %s\n"),
634 http_timestring(tmp_ctx
, ads
->config
.current_time
));
636 d_printf(_("KDC server: %s\n"), ads
->auth
.kdc_server
);
637 d_printf(_("Server time offset: %d\n"), ads
->auth
.time_offset
);
639 d_printf(_("Last machine account password change: %s\n"),
640 http_timestring(tmp_ctx
, pass_time
));
644 TALLOC_FREE(tmp_ctx
);
648 static ADS_STATUS
ads_startup_int(struct net_context
*c
,
649 bool only_own_domain
,
652 ADS_STRUCT
**ads_ret
)
654 ADS_STRUCT
*ads
= NULL
;
656 bool need_password
= false;
657 bool second_time
= false;
659 const char *realm
= NULL
;
660 bool tried_closest_dc
= false;
661 enum credentials_use_kerberos krb5_state
=
662 CRED_USE_KERBEROS_DISABLED
;
664 /* lp_realm() should be handled by a command line param,
665 However, the join requires that realm be set in smb.conf
666 and compares our realm with the remote server's so this is
667 ok until someone needs more flexibility */
672 if (only_own_domain
) {
675 realm
= assume_own_realm(c
);
678 ads
= ads_init(mem_ctx
,
680 c
->opt_target_workgroup
,
684 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
687 if (!c
->opt_user_name
) {
688 c
->opt_user_name
= "administrator";
691 if (c
->opt_user_specified
) {
692 need_password
= true;
696 if (!c
->opt_password
&& need_password
&& !c
->opt_machine_pass
) {
697 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
698 if (!c
->opt_password
) {
700 return ADS_ERROR(LDAP_NO_MEMORY
);
704 if (c
->opt_password
) {
705 use_in_memory_ccache();
706 ADS_TALLOC_CONST_FREE(ads
->auth
.password
);
707 ads
->auth
.password
= talloc_strdup(ads
, c
->opt_password
);
708 if (ads
->auth
.password
== NULL
) {
710 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
714 ADS_TALLOC_CONST_FREE(ads
->auth
.user_name
);
715 ads
->auth
.user_name
= talloc_strdup(ads
, c
->opt_user_name
);
716 if (ads
->auth
.user_name
== NULL
) {
718 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
721 ads
->auth
.flags
|= auth_flags
;
723 /* The ADS code will handle FIPS mode */
724 krb5_state
= cli_credentials_get_kerberos_state(c
->creds
);
725 switch (krb5_state
) {
726 case CRED_USE_KERBEROS_REQUIRED
:
727 ads
->auth
.flags
&= ~ADS_AUTH_DISABLE_KERBEROS
;
728 ads
->auth
.flags
&= ~ADS_AUTH_ALLOW_NTLMSSP
;
730 case CRED_USE_KERBEROS_DESIRED
:
731 ads
->auth
.flags
&= ~ADS_AUTH_DISABLE_KERBEROS
;
732 ads
->auth
.flags
|= ADS_AUTH_ALLOW_NTLMSSP
;
734 case CRED_USE_KERBEROS_DISABLED
:
735 ads
->auth
.flags
|= ADS_AUTH_DISABLE_KERBEROS
;
736 ads
->auth
.flags
|= ADS_AUTH_ALLOW_NTLMSSP
;
741 * If the username is of the form "name@realm",
742 * extract the realm and convert to upper case.
743 * This is only used to establish the connection.
745 if ((cp
= strchr_m(ads
->auth
.user_name
, '@'))!=0) {
747 ADS_TALLOC_CONST_FREE(ads
->auth
.realm
);
748 ads
->auth
.realm
= talloc_asprintf_strupper_m(ads
, "%s", cp
);
749 if (ads
->auth
.realm
== NULL
) {
751 return ADS_ERROR(LDAP_NO_MEMORY
);
753 } else if (ads
->auth
.realm
== NULL
) {
754 const char *c_realm
= cli_credentials_get_realm(c
->creds
);
756 if (c_realm
!= NULL
) {
757 ads
->auth
.realm
= talloc_strdup(ads
, c_realm
);
758 if (ads
->auth
.realm
== NULL
) {
760 return ADS_ERROR(LDAP_NO_MEMORY
);
765 status
= ads_connect(ads
);
767 if (!ADS_ERR_OK(status
)) {
769 if (NT_STATUS_EQUAL(ads_ntstatus(status
),
770 NT_STATUS_NO_LOGON_SERVERS
)) {
771 DEBUG(0,("ads_connect: %s\n", ads_errstr(status
)));
776 if (!need_password
&& !second_time
&& !(auth_flags
& ADS_AUTH_NO_BIND
)) {
777 need_password
= true;
786 /* when contacting our own domain, make sure we use the closest DC.
787 * This is done by reconnecting to ADS because only the first call to
788 * ads_connect will give us our own sitename */
790 if ((only_own_domain
|| !c
->opt_host
) && !tried_closest_dc
) {
792 tried_closest_dc
= true; /* avoid loop */
794 if (!ads_closest_dc(ads
)) {
796 namecache_delete(ads
->server
.realm
, 0x1C);
797 namecache_delete(ads
->server
.workgroup
, 0x1C);
805 *ads_ret
= talloc_move(mem_ctx
, &ads
);
809 ADS_STATUS
ads_startup(struct net_context
*c
,
810 bool only_own_domain
,
814 return ads_startup_int(c
, only_own_domain
, 0, mem_ctx
, ads
);
817 ADS_STATUS
ads_startup_nobind(struct net_context
*c
,
818 bool only_own_domain
,
822 return ads_startup_int(c
,
830 Check to see if connection can be made via ads.
831 ads_startup() stores the password in opt_password if it needs to so
832 that rpc or rap can use it without re-prompting.
834 static int net_ads_check_int(struct net_context
*c
,
836 const char *workgroup
,
839 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
844 ads
= ads_init(tmp_ctx
, realm
, workgroup
, host
, ADS_SASL_PLAIN
);
849 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
851 status
= ads_connect(ads
);
852 if ( !ADS_ERR_OK(status
) ) {
858 TALLOC_FREE(tmp_ctx
);
862 int net_ads_check_our_domain(struct net_context
*c
)
864 return net_ads_check_int(c
, lp_realm(), lp_workgroup(), NULL
);
867 int net_ads_check(struct net_context
*c
)
869 return net_ads_check_int(c
, NULL
, c
->opt_workgroup
, c
->opt_host
);
873 determine the netbios workgroup name for a domain
875 static int net_ads_workgroup(struct net_context
*c
, int argc
, const char **argv
)
877 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
878 ADS_STRUCT
*ads
= NULL
;
880 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
884 if (c
->display_usage
) {
886 "net ads workgroup\n"
889 _("Print the workgroup name"));
890 TALLOC_FREE(tmp_ctx
);
894 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
895 if (!ADS_ERR_OK(status
)) {
896 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
900 if (!ads
->config
.realm
) {
901 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
902 if (ads
->config
.realm
== NULL
) {
903 d_fprintf(stderr
, _("Out of memory\n"));
906 ads
->ldap
.port
= 389;
909 ok
= ads_cldap_netlogon_5(tmp_ctx
,
910 &ads
->ldap
.ss
, ads
->server
.realm
, &reply
);
912 d_fprintf(stderr
, _("CLDAP query failed!\n"));
916 d_printf(_("Workgroup: %s\n"), reply
.domain_name
);
920 TALLOC_FREE(tmp_ctx
);
927 static bool usergrp_display(ADS_STRUCT
*ads
, char *field
, void **values
, void *data_area
)
929 char **disp_fields
= (char **) data_area
;
931 if (!field
) { /* must be end of record */
932 if (disp_fields
[0]) {
933 if (!strchr_m(disp_fields
[0], '$')) {
935 d_printf("%-21.21s %s\n",
936 disp_fields
[0], disp_fields
[1]);
938 d_printf("%s\n", disp_fields
[0]);
941 SAFE_FREE(disp_fields
[0]);
942 SAFE_FREE(disp_fields
[1]);
945 if (!values
) /* must be new field, indicate string field */
947 if (strcasecmp_m(field
, "sAMAccountName") == 0) {
948 disp_fields
[0] = SMB_STRDUP((char *) values
[0]);
950 if (strcasecmp_m(field
, "description") == 0)
951 disp_fields
[1] = SMB_STRDUP((char *) values
[0]);
955 static int net_ads_user_usage(struct net_context
*c
, int argc
, const char **argv
)
957 return net_user_usage(c
, argc
, argv
);
960 static int ads_user_add(struct net_context
*c
, int argc
, const char **argv
)
962 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
963 ADS_STRUCT
*ads
= NULL
;
966 LDAPMessage
*res
=NULL
;
970 if (argc
< 1 || c
->display_usage
) {
971 TALLOC_FREE(tmp_ctx
);
972 return net_ads_user_usage(c
, argc
, argv
);
975 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
976 if (!ADS_ERR_OK(status
)) {
980 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
981 if (!ADS_ERR_OK(status
)) {
982 d_fprintf(stderr
, _("ads_user_add: %s\n"), ads_errstr(status
));
986 if (ads_count_replies(ads
, res
)) {
987 d_fprintf(stderr
, _("ads_user_add: User %s already exists\n"),
992 if (c
->opt_container
) {
993 ou_str
= SMB_STRDUP(c
->opt_container
);
995 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
998 status
= ads_add_user_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
999 if (!ADS_ERR_OK(status
)) {
1000 d_fprintf(stderr
, _("Could not add user %s: %s\n"), argv
[0],
1001 ads_errstr(status
));
1005 /* if no password is to be set, we're done */
1007 d_printf(_("User %s added\n"), argv
[0]);
1012 /* try setting the password */
1013 upn
= talloc_asprintf(tmp_ctx
,
1021 status
= ads_krb5_set_password(ads
->auth
.kdc_server
, upn
, argv
[1],
1022 ads
->auth
.time_offset
);
1023 if (ADS_ERR_OK(status
)) {
1024 d_printf(_("User %s added\n"), argv
[0]);
1030 /* password didn't set, delete account */
1031 d_fprintf(stderr
, _("Could not add user %s. "
1032 "Error setting password %s\n"),
1033 argv
[0], ads_errstr(status
));
1035 ads_msgfree(ads
, res
);
1038 status
=ads_find_user_acct(ads
, &res
, argv
[0]);
1039 if (ADS_ERR_OK(status
)) {
1040 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1041 ads_del_dn(ads
, userdn
);
1042 TALLOC_FREE(userdn
);
1046 ads_msgfree(ads
, res
);
1048 TALLOC_FREE(tmp_ctx
);
1052 static int ads_user_info(struct net_context
*c
, int argc
, const char **argv
)
1054 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1055 ADS_STRUCT
*ads
= NULL
;
1057 LDAPMessage
*res
= NULL
;
1060 const char *attrs
[] = {"memberOf", "primaryGroupID", NULL
};
1061 char *searchstring
= NULL
;
1062 char **grouplist
= NULL
;
1063 char *primary_group
= NULL
;
1064 char *escaped_user
= NULL
;
1065 struct dom_sid primary_group_sid
;
1067 enum wbcSidType type
;
1069 if (argc
< 1 || c
->display_usage
) {
1070 TALLOC_FREE(tmp_ctx
);
1071 return net_ads_user_usage(c
, argc
, argv
);
1074 escaped_user
= escape_ldap_string(tmp_ctx
, argv
[0]);
1075 if (!escaped_user
) {
1077 _("ads_user_info: failed to escape user %s\n"),
1082 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1083 if (!ADS_ERR_OK(status
)) {
1087 searchstring
= talloc_asprintf(tmp_ctx
,
1088 "(sAMAccountName=%s)",
1090 if (searchstring
== NULL
) {
1094 status
= ads_search(ads
, &res
, searchstring
, attrs
);
1095 if (!ADS_ERR_OK(status
)) {
1096 d_fprintf(stderr
, _("ads_search: %s\n"), ads_errstr(status
));
1100 if (!ads_pull_uint32(ads
, res
, "primaryGroupID", &group_rid
)) {
1101 d_fprintf(stderr
, _("ads_pull_uint32 failed\n"));
1105 status
= ads_domain_sid(ads
, &primary_group_sid
);
1106 if (!ADS_ERR_OK(status
)) {
1107 d_fprintf(stderr
, _("ads_domain_sid: %s\n"), ads_errstr(status
));
1111 sid_append_rid(&primary_group_sid
, group_rid
);
1113 wbc_status
= wbcLookupSid((struct wbcDomainSid
*)&primary_group_sid
,
1114 NULL
, /* don't look up domain */
1117 if (!WBC_ERROR_IS_OK(wbc_status
)) {
1118 d_fprintf(stderr
, "wbcLookupSid: %s\n",
1119 wbcErrorString(wbc_status
));
1123 d_printf("%s\n", primary_group
);
1125 wbcFreeMemory(primary_group
);
1127 grouplist
= ldap_get_values((LDAP
*)ads
->ldap
.ld
,
1128 (LDAPMessage
*)res
, "memberOf");
1133 for (i
=0;grouplist
[i
];i
++) {
1134 groupname
= ldap_explode_dn(grouplist
[i
], 1);
1135 d_printf("%s\n", groupname
[0]);
1136 ldap_value_free(groupname
);
1138 ldap_value_free(grouplist
);
1143 ads_msgfree(ads
, res
);
1144 TALLOC_FREE(tmp_ctx
);
1148 static int ads_user_delete(struct net_context
*c
, int argc
, const char **argv
)
1150 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1151 ADS_STRUCT
*ads
= NULL
;
1153 LDAPMessage
*res
= NULL
;
1154 char *userdn
= NULL
;
1158 TALLOC_FREE(tmp_ctx
);
1159 return net_ads_user_usage(c
, argc
, argv
);
1162 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1163 if (!ADS_ERR_OK(status
)) {
1167 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1168 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1169 d_printf(_("User %s does not exist.\n"), argv
[0]);
1173 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1174 if (userdn
== NULL
) {
1178 status
= ads_del_dn(ads
, userdn
);
1179 if (!ADS_ERR_OK(status
)) {
1180 d_fprintf(stderr
, _("Error deleting user %s: %s\n"), argv
[0],
1181 ads_errstr(status
));
1185 d_printf(_("User %s deleted\n"), argv
[0]);
1189 ads_msgfree(ads
, res
);
1190 TALLOC_FREE(tmp_ctx
);
1194 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
1196 struct functable func
[] = {
1201 N_("Add an AD user"),
1202 N_("net ads user add\n"
1209 N_("Display information about an AD user"),
1210 N_("net ads user info\n"
1211 " Display information about an AD user")
1217 N_("Delete an AD user"),
1218 N_("net ads user delete\n"
1219 " Delete an AD user")
1221 {NULL
, NULL
, 0, NULL
, NULL
}
1223 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1224 ADS_STRUCT
*ads
= NULL
;
1226 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1227 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1228 char *disp_fields
[2] = {NULL
, NULL
};
1232 TALLOC_FREE(tmp_ctx
);
1233 return net_run_function(c
, argc
, argv
, "net ads user", func
);
1236 if (c
->display_usage
) {
1241 _("List AD users"));
1242 net_display_usage_from_functable(func
);
1243 TALLOC_FREE(tmp_ctx
);
1247 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1248 if (!ADS_ERR_OK(status
)) {
1252 if (c
->opt_long_list_entries
)
1253 d_printf(_("\nUser name Comment"
1254 "\n-----------------------------\n"));
1256 status
= ads_do_search_all_fn(ads
,
1257 ads
->config
.bind_path
,
1259 "(objectCategory=user)",
1260 c
->opt_long_list_entries
?
1261 longattrs
: shortattrs
,
1264 if (!ADS_ERR_OK(status
)) {
1270 TALLOC_FREE(tmp_ctx
);
1274 static int net_ads_group_usage(struct net_context
*c
, int argc
, const char **argv
)
1276 return net_group_usage(c
, argc
, argv
);
1279 static int ads_group_add(struct net_context
*c
, int argc
, const char **argv
)
1281 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1282 ADS_STRUCT
*ads
= NULL
;
1284 LDAPMessage
*res
= NULL
;
1286 char *ou_str
= NULL
;
1288 if (argc
< 1 || c
->display_usage
) {
1289 TALLOC_FREE(tmp_ctx
);
1290 return net_ads_group_usage(c
, argc
, argv
);
1293 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1294 if (!ADS_ERR_OK(status
)) {
1298 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1299 if (!ADS_ERR_OK(status
)) {
1300 d_fprintf(stderr
, _("ads_group_add: %s\n"), ads_errstr(status
));
1304 if (ads_count_replies(ads
, res
)) {
1305 d_fprintf(stderr
, _("ads_group_add: Group %s already exists\n"), argv
[0]);
1309 if (c
->opt_container
) {
1310 ou_str
= SMB_STRDUP(c
->opt_container
);
1312 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
1315 status
= ads_add_group_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
1316 if (!ADS_ERR_OK(status
)) {
1317 d_fprintf(stderr
, _("Could not add group %s: %s\n"), argv
[0],
1318 ads_errstr(status
));
1322 d_printf(_("Group %s added\n"), argv
[0]);
1326 ads_msgfree(ads
, res
);
1328 TALLOC_FREE(tmp_ctx
);
1332 static int ads_group_delete(struct net_context
*c
, int argc
, const char **argv
)
1334 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1335 ADS_STRUCT
*ads
= NULL
;
1337 LDAPMessage
*res
= NULL
;
1338 char *groupdn
= NULL
;
1341 if (argc
< 1 || c
->display_usage
) {
1342 TALLOC_FREE(tmp_ctx
);
1343 return net_ads_group_usage(c
, argc
, argv
);
1346 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1347 if (!ADS_ERR_OK(status
)) {
1351 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1352 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1353 d_printf(_("Group %s does not exist.\n"), argv
[0]);
1357 groupdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1358 if (groupdn
== NULL
) {
1362 status
= ads_del_dn(ads
, groupdn
);
1363 if (!ADS_ERR_OK(status
)) {
1364 d_fprintf(stderr
, _("Error deleting group %s: %s\n"), argv
[0],
1365 ads_errstr(status
));
1368 d_printf(_("Group %s deleted\n"), argv
[0]);
1372 ads_msgfree(ads
, res
);
1373 TALLOC_FREE(tmp_ctx
);
1377 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
1379 struct functable func
[] = {
1384 N_("Add an AD group"),
1385 N_("net ads group add\n"
1392 N_("Delete an AD group"),
1393 N_("net ads group delete\n"
1394 " Delete an AD group")
1396 {NULL
, NULL
, 0, NULL
, NULL
}
1398 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1399 ADS_STRUCT
*ads
= NULL
;
1401 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1402 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1403 char *disp_fields
[2] = {NULL
, NULL
};
1407 TALLOC_FREE(tmp_ctx
);
1408 return net_run_function(c
, argc
, argv
, "net ads group", func
);
1411 if (c
->display_usage
) {
1416 _("List AD groups"));
1417 net_display_usage_from_functable(func
);
1418 TALLOC_FREE(tmp_ctx
);
1422 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1423 if (!ADS_ERR_OK(status
)) {
1427 if (c
->opt_long_list_entries
)
1428 d_printf(_("\nGroup name Comment"
1429 "\n-----------------------------\n"));
1431 status
= ads_do_search_all_fn(ads
,
1432 ads
->config
.bind_path
,
1434 "(objectCategory=group)",
1435 c
->opt_long_list_entries
?
1436 longattrs
: shortattrs
,
1439 if (!ADS_ERR_OK(status
)) {
1445 TALLOC_FREE(tmp_ctx
);
1449 static int net_ads_status(struct net_context
*c
, int argc
, const char **argv
)
1451 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1452 ADS_STRUCT
*ads
= NULL
;
1454 LDAPMessage
*res
= NULL
;
1457 if (c
->display_usage
) {
1462 _("Display machine account details"));
1463 TALLOC_FREE(tmp_ctx
);
1467 net_warn_member_options();
1469 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1470 if (!ADS_ERR_OK(status
)) {
1474 status
= ads_find_machine_acct(ads
, &res
, lp_netbios_name());
1475 if (!ADS_ERR_OK(status
)) {
1476 d_fprintf(stderr
, _("ads_find_machine_acct: %s\n"),
1477 ads_errstr(status
));
1481 if (ads_count_replies(ads
, res
) == 0) {
1482 d_fprintf(stderr
, _("No machine account for '%s' found\n"),
1491 ads_msgfree(ads
, res
);
1492 TALLOC_FREE(tmp_ctx
);
1496 /*******************************************************************
1497 Leave an AD domain. Windows XP disables the machine account.
1498 We'll try the same. The old code would do an LDAP delete.
1499 That only worked using the machine creds because added the machine
1500 with full control to the computer object's ACL.
1501 *******************************************************************/
1503 static int net_ads_leave(struct net_context
*c
, int argc
, const char **argv
)
1505 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1506 struct libnet_UnjoinCtx
*r
= NULL
;
1510 if (c
->display_usage
) {
1512 "net ads leave [--keep-account]\n"
1515 _("Leave an AD domain"));
1516 TALLOC_FREE(tmp_ctx
);
1521 d_fprintf(stderr
, _("No realm set, are we joined ?\n"));
1522 TALLOC_FREE(tmp_ctx
);
1526 if (!c
->opt_kerberos
) {
1527 use_in_memory_ccache();
1531 d_fprintf(stderr
, _("Could not initialise message context. "
1532 "Try running as root\n"));
1536 werr
= libnet_init_UnjoinCtx(tmp_ctx
, &r
);
1537 if (!W_ERROR_IS_OK(werr
)) {
1538 d_fprintf(stderr
, _("Could not initialise unjoin context.\n"));
1543 r
->in
.use_kerberos
= c
->opt_kerberos
;
1544 r
->in
.dc_name
= c
->opt_host
;
1545 r
->in
.domain_name
= lp_realm();
1546 r
->in
.admin_account
= c
->opt_user_name
;
1547 r
->in
.admin_password
= net_prompt_pass(c
, c
->opt_user_name
);
1548 r
->in
.modify_config
= lp_config_backend_is_registry();
1550 /* Try to delete it, but if that fails, disable it. The
1551 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1552 r
->in
.unjoin_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1553 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
;
1554 if (c
->opt_keep_account
) {
1555 r
->in
.delete_machine_account
= false;
1557 r
->in
.delete_machine_account
= true;
1560 r
->in
.msg_ctx
= c
->msg_ctx
;
1562 werr
= libnet_Unjoin(tmp_ctx
, r
);
1563 if (!W_ERROR_IS_OK(werr
)) {
1564 d_printf(_("Failed to leave domain: %s\n"),
1565 r
->out
.error_string
? r
->out
.error_string
:
1566 get_friendly_werror_msg(werr
));
1570 if (r
->out
.deleted_machine_account
) {
1571 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1572 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1577 /* We couldn't delete it - see if the disable succeeded. */
1578 if (r
->out
.disabled_machine_account
) {
1579 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1580 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1585 /* Based on what we requested, we shouldn't get here, but if
1586 we did, it means the secrets were removed, and therefore
1587 we have left the domain */
1588 d_fprintf(stderr
, _("Machine '%s' Left domain '%s'\n"),
1589 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1593 TALLOC_FREE(tmp_ctx
);
1597 static ADS_STATUS
net_ads_join_ok(struct net_context
*c
)
1599 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1600 ADS_STRUCT
*ads
= NULL
;
1603 struct sockaddr_storage dcip
;
1605 if (!secrets_init()) {
1606 DEBUG(1,("Failed to initialise secrets database\n"));
1607 TALLOC_FREE(tmp_ctx
);
1608 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
1611 net_warn_member_options();
1613 net_use_krb_machine_account(c
);
1615 get_dc_name(lp_workgroup(), lp_realm(), dc_name
, &dcip
);
1617 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1618 if (!ADS_ERR_OK(status
)) {
1622 status
= ADS_ERROR_NT(NT_STATUS_OK
);
1624 TALLOC_FREE(tmp_ctx
);
1629 check that an existing join is OK
1631 int net_ads_testjoin(struct net_context
*c
, int argc
, const char **argv
)
1634 use_in_memory_ccache();
1636 if (c
->display_usage
) {
1638 "net ads testjoin\n"
1641 _("Test if the existing join is ok"));
1645 net_warn_member_options();
1647 /* Display success or failure */
1648 status
= net_ads_join_ok(c
);
1649 if (!ADS_ERR_OK(status
)) {
1650 fprintf(stderr
, _("Join to domain is not valid: %s\n"),
1651 get_friendly_nt_error_msg(ads_ntstatus(status
)));
1655 printf(_("Join is OK\n"));
1659 /*******************************************************************
1660 Simple config checks before beginning the join
1661 ********************************************************************/
1663 static WERROR
check_ads_config( void )
1665 if (lp_server_role() != ROLE_DOMAIN_MEMBER
) {
1666 d_printf(_("Host is not configured as a member server.\n"));
1667 return WERR_INVALID_DOMAIN_ROLE
;
1670 if (strlen(lp_netbios_name()) > 15) {
1671 d_printf(_("Our netbios name can be at most 15 chars long, "
1672 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1673 (unsigned int)strlen(lp_netbios_name()));
1674 return WERR_INVALID_COMPUTERNAME
;
1677 if ( lp_security() == SEC_ADS
&& !*lp_realm()) {
1678 d_fprintf(stderr
, _("realm must be set in in %s for ADS "
1679 "join to succeed.\n"), get_dyn_CONFIGFILE());
1680 return WERR_INVALID_PARAMETER
;
1686 /*******************************************************************
1687 ********************************************************************/
1689 static int net_ads_join_usage(struct net_context
*c
, int argc
, const char **argv
)
1691 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1692 "Valid options:\n"));
1693 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1694 " The default is in the form netbiosname.dnsdomain\n"));
1695 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1696 " The default UPN is in the form host/netbiosname@REALM.\n"));
1697 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1698 " The OU string read from top to bottom without RDNs\n"
1699 " and delimited by a '/'.\n"
1700 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1701 " NB: A backslash '\\' is used as escape at multiple\n"
1702 " levels and may need to be doubled or even\n"
1703 " quadrupled. It is not used as a separator.\n"));
1704 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1705 " the join. The default password is random.\n"));
1706 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1707 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1708 " NB: osName and osVer must be specified together for\n"
1709 " either to take effect. The operatingSystemService\n"
1710 " attribute is then also set along with the two\n"
1711 " other attributes.\n"));
1712 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1713 " during the join.\n"
1714 " NB: If not specified then by default the samba\n"
1715 " version string is used instead.\n"));
1720 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
1722 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1723 struct libnet_JoinCtx
*r
= NULL
;
1724 const char *domain
= lp_realm();
1725 WERROR werr
= WERR_NERR_SETUPNOTJOINED
;
1726 bool createupn
= false;
1727 const char *dnshostname
= NULL
;
1728 const char *machineupn
= NULL
;
1729 const char *machine_password
= NULL
;
1730 const char *create_in_ou
= NULL
;
1732 const char *os_name
= NULL
;
1733 const char *os_version
= NULL
;
1734 const char *os_servicepack
= NULL
;
1735 bool modify_config
= lp_config_backend_is_registry();
1736 enum libnetjoin_JoinDomNameType domain_name_type
= JoinDomNameTypeDNS
;
1739 if (c
->display_usage
) {
1740 TALLOC_FREE(tmp_ctx
);
1741 return net_ads_join_usage(c
, argc
, argv
);
1744 net_warn_member_options();
1746 if (!modify_config
) {
1747 werr
= check_ads_config();
1748 if (!W_ERROR_IS_OK(werr
)) {
1749 d_fprintf(stderr
, _("Invalid configuration. Exiting....\n"));
1754 if (!c
->opt_kerberos
) {
1755 use_in_memory_ccache();
1758 werr
= libnet_init_JoinCtx(tmp_ctx
, &r
);
1759 if (!W_ERROR_IS_OK(werr
)) {
1763 /* process additional command line args */
1765 for ( i
=0; i
<argc
; i
++ ) {
1766 if ( !strncasecmp_m(argv
[i
], "dnshostname", strlen("dnshostname")) ) {
1767 dnshostname
= get_string_param(argv
[i
]);
1769 else if ( !strncasecmp_m(argv
[i
], "createupn", strlen("createupn")) ) {
1771 machineupn
= get_string_param(argv
[i
]);
1773 else if ( !strncasecmp_m(argv
[i
], "createcomputer", strlen("createcomputer")) ) {
1774 if ( (create_in_ou
= get_string_param(argv
[i
])) == NULL
) {
1775 d_fprintf(stderr
, _("Please supply a valid OU path.\n"));
1776 werr
= WERR_INVALID_PARAMETER
;
1780 else if ( !strncasecmp_m(argv
[i
], "osName", strlen("osName")) ) {
1781 if ( (os_name
= get_string_param(argv
[i
])) == NULL
) {
1782 d_fprintf(stderr
, _("Please supply a operating system name.\n"));
1783 werr
= WERR_INVALID_PARAMETER
;
1787 else if ( !strncasecmp_m(argv
[i
], "osVer", strlen("osVer")) ) {
1788 if ( (os_version
= get_string_param(argv
[i
])) == NULL
) {
1789 d_fprintf(stderr
, _("Please supply a valid operating system version.\n"));
1790 werr
= WERR_INVALID_PARAMETER
;
1794 else if ( !strncasecmp_m(argv
[i
], "osServicePack", strlen("osServicePack")) ) {
1795 if ( (os_servicepack
= get_string_param(argv
[i
])) == NULL
) {
1796 d_fprintf(stderr
, _("Please supply a valid servicepack identifier.\n"));
1797 werr
= WERR_INVALID_PARAMETER
;
1801 else if ( !strncasecmp_m(argv
[i
], "machinepass", strlen("machinepass")) ) {
1802 if ( (machine_password
= get_string_param(argv
[i
])) == NULL
) {
1803 d_fprintf(stderr
, _("Please supply a valid password to set as trust account password.\n"));
1804 werr
= WERR_INVALID_PARAMETER
;
1809 if (strchr(domain
, '.') == NULL
) {
1810 domain_name_type
= JoinDomNameTypeUnknown
;
1812 domain_name_type
= JoinDomNameTypeDNS
;
1818 d_fprintf(stderr
, _("Please supply a valid domain name\n"));
1819 werr
= WERR_INVALID_PARAMETER
;
1824 d_fprintf(stderr
, _("Could not initialise message context. "
1825 "Try running as root\n"));
1826 werr
= WERR_ACCESS_DENIED
;
1830 /* Do the domain join here */
1832 r
->in
.domain_name
= domain
;
1833 r
->in
.domain_name_type
= domain_name_type
;
1834 r
->in
.create_upn
= createupn
;
1835 r
->in
.upn
= machineupn
;
1836 r
->in
.dnshostname
= dnshostname
;
1837 r
->in
.account_ou
= create_in_ou
;
1838 r
->in
.os_name
= os_name
;
1839 r
->in
.os_version
= os_version
;
1840 r
->in
.os_servicepack
= os_servicepack
;
1841 r
->in
.dc_name
= c
->opt_host
;
1842 r
->in
.admin_account
= c
->opt_user_name
;
1843 r
->in
.admin_password
= net_prompt_pass(c
, c
->opt_user_name
);
1844 r
->in
.machine_password
= machine_password
;
1846 r
->in
.use_kerberos
= c
->opt_kerberos
;
1847 r
->in
.modify_config
= modify_config
;
1848 r
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1849 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
|
1850 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
;
1851 r
->in
.msg_ctx
= c
->msg_ctx
;
1853 werr
= libnet_Join(tmp_ctx
, r
);
1854 if (W_ERROR_EQUAL(werr
, WERR_NERR_DCNOTFOUND
) &&
1855 strequal(domain
, lp_realm())) {
1856 r
->in
.domain_name
= lp_workgroup();
1857 r
->in
.domain_name_type
= JoinDomNameTypeNBT
;
1858 werr
= libnet_Join(tmp_ctx
, r
);
1860 if (!W_ERROR_IS_OK(werr
)) {
1864 /* Check the short name of the domain */
1866 if (!modify_config
&& !strequal(lp_workgroup(), r
->out
.netbios_domain_name
)) {
1867 d_printf(_("The workgroup in %s does not match the short\n"
1868 "domain name obtained from the server.\n"
1869 "Using the name [%s] from the server.\n"
1870 "You should set \"workgroup = %s\" in %s.\n"),
1871 get_dyn_CONFIGFILE(), r
->out
.netbios_domain_name
,
1872 r
->out
.netbios_domain_name
, get_dyn_CONFIGFILE());
1875 d_printf(_("Using short domain name -- %s\n"), r
->out
.netbios_domain_name
);
1877 if (r
->out
.dns_domain_name
) {
1878 d_printf(_("Joined '%s' to dns domain '%s'\n"), r
->in
.machine_name
,
1879 r
->out
.dns_domain_name
);
1881 d_printf(_("Joined '%s' to domain '%s'\n"), r
->in
.machine_name
,
1882 r
->out
.netbios_domain_name
);
1885 /* print out informative error string in case there is one */
1886 if (r
->out
.error_string
!= NULL
) {
1887 d_printf("%s\n", r
->out
.error_string
);
1891 * We try doing the dns update (if it was compiled in
1892 * and if it was not disabled on the command line).
1893 * If the dns update fails, we still consider the join
1894 * operation as succeeded if we came this far.
1896 if (!c
->opt_no_dns_updates
) {
1897 net_ads_join_dns_updates(c
, tmp_ctx
, r
);
1904 /* issue an overall failure message at the end. */
1905 d_printf(_("Failed to join domain: %s\n"),
1906 r
&& r
->out
.error_string
? r
->out
.error_string
:
1907 get_friendly_werror_msg(werr
));
1910 TALLOC_FREE(tmp_ctx
);
1915 /*******************************************************************
1916 ********************************************************************/
1918 static int net_ads_dns_register(struct net_context
*c
, int argc
, const char **argv
)
1920 #if defined(HAVE_KRB5)
1921 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1922 ADS_STRUCT
*ads
= NULL
;
1925 const char *hostname
= NULL
;
1926 const char **addrs_list
= NULL
;
1927 struct sockaddr_storage
*addrs
= NULL
;
1933 talloc_enable_leak_report();
1936 if (argc
<= 1 && lp_clustering() && lp_cluster_addresses() == NULL
) {
1937 d_fprintf(stderr
, _("Refusing DNS updates with automatic "
1938 "detection of addresses in a clustered "
1940 c
->display_usage
= true;
1943 if (c
->display_usage
) {
1945 "net ads dns register [hostname [IP [IP...]]] "
1946 "[--force] [--dns-ttl TTL]\n"
1949 _("Register hostname with DNS\n"));
1950 TALLOC_FREE(tmp_ctx
);
1959 num_addrs
= argc
- 1;
1960 addrs_list
= &argv
[1];
1961 } else if (lp_clustering()) {
1962 addrs_list
= lp_cluster_addresses();
1963 num_addrs
= str_list_length(addrs_list
);
1966 if (num_addrs
> 0) {
1967 addrs
= talloc_zero_array(tmp_ctx
,
1968 struct sockaddr_storage
,
1970 if (addrs
== NULL
) {
1971 d_fprintf(stderr
, _("Error allocating memory!\n"));
1976 for (count
= 0; count
< num_addrs
; count
++) {
1977 if (!interpret_string_addr(&addrs
[count
], addrs_list
[count
], 0)) {
1978 d_fprintf(stderr
, "%s '%s'.\n",
1979 _("Cannot interpret address"),
1985 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1986 if ( !ADS_ERR_OK(status
) ) {
1987 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
1991 ntstatus
= net_update_dns_ext(c
,
1998 if (!NT_STATUS_IS_OK(ntstatus
)) {
1999 d_fprintf( stderr
, _("DNS update failed!\n") );
2003 d_fprintf( stderr
, _("Successfully registered hostname with DNS\n") );
2007 TALLOC_FREE(tmp_ctx
);
2012 _("DNS update support not enabled at compile time!\n"));
2017 static int net_ads_dns_unregister(struct net_context
*c
,
2021 #if defined(HAVE_KRB5)
2022 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2023 ADS_STRUCT
*ads
= NULL
;
2026 const char *hostname
= NULL
;
2030 talloc_enable_leak_report();
2034 c
->display_usage
= true;
2037 if (c
->display_usage
) {
2039 "net ads dns unregister [hostname]\n"
2042 _("Remove all IP Address entries for a given\n"
2043 " hostname from the Active Directory server.\n"));
2044 TALLOC_FREE(tmp_ctx
);
2048 /* Get the hostname for un-registering */
2051 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2052 if ( !ADS_ERR_OK(status
) ) {
2053 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
2057 ntstatus
= net_update_dns_ext(c
,
2064 if (!NT_STATUS_IS_OK(ntstatus
)) {
2065 d_fprintf( stderr
, _("DNS update failed!\n") );
2069 d_fprintf( stderr
, _("Successfully un-registered hostname from DNS\n"));
2073 TALLOC_FREE(tmp_ctx
);
2078 _("DNS update support not enabled at compile time!\n"));
2084 static int net_ads_dns_async(struct net_context
*c
, int argc
, const char **argv
)
2086 size_t num_names
= 0;
2087 char **hostnames
= NULL
;
2089 struct samba_sockaddr
*addrs
= NULL
;
2092 if (argc
!= 1 || c
->display_usage
) {
2097 _("net ads dns async <name>\n"),
2098 _(" Async look up hostname from the DNS server\n"
2099 " hostname\tName to look up\n"));
2103 status
= ads_dns_lookup_a(talloc_tos(),
2108 if (!NT_STATUS_IS_OK(status
)) {
2109 d_printf("Looking up A record for %s got error %s\n",
2114 d_printf("Async A record lookup - got %u names for %s\n",
2115 (unsigned int)num_names
,
2117 for (i
= 0; i
< num_names
; i
++) {
2118 char addr_buf
[INET6_ADDRSTRLEN
];
2119 print_sockaddr(addr_buf
,
2122 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2128 #if defined(HAVE_IPV6)
2129 status
= ads_dns_lookup_aaaa(talloc_tos(),
2134 if (!NT_STATUS_IS_OK(status
)) {
2135 d_printf("Looking up AAAA record for %s got error %s\n",
2140 d_printf("Async AAAA record lookup - got %u names for %s\n",
2141 (unsigned int)num_names
,
2143 for (i
= 0; i
< num_names
; i
++) {
2144 char addr_buf
[INET6_ADDRSTRLEN
];
2145 print_sockaddr(addr_buf
,
2148 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2158 static int net_ads_dns(struct net_context
*c
, int argc
, const char *argv
[])
2160 struct functable func
[] = {
2163 net_ads_dns_register
,
2165 N_("Add host dns entry to AD"),
2166 N_("net ads dns register\n"
2167 " Add host dns entry to AD")
2171 net_ads_dns_unregister
,
2173 N_("Remove host dns entry from AD"),
2174 N_("net ads dns unregister\n"
2175 " Remove host dns entry from AD")
2182 N_("net ads dns async\n"
2183 " Look up host using async DNS")
2185 {NULL
, NULL
, 0, NULL
, NULL
}
2188 return net_run_function(c
, argc
, argv
, "net ads dns", func
);
2191 /*******************************************************************
2192 ********************************************************************/
2194 int net_ads_printer_usage(struct net_context
*c
, int argc
, const char **argv
)
2197 "\nnet ads printer search <printer>"
2198 "\n\tsearch for a printer in the directory\n"
2199 "\nnet ads printer info <printer> <server>"
2200 "\n\tlookup info in directory for printer on server"
2201 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2202 "\nnet ads printer publish <printername>"
2203 "\n\tpublish printer in directory"
2204 "\n\t(note: printer name is required)\n"
2205 "\nnet ads printer remove <printername>"
2206 "\n\tremove printer from directory"
2207 "\n\t(note: printer name is required)\n"));
2211 /*******************************************************************
2212 ********************************************************************/
2214 static int net_ads_printer_search(struct net_context
*c
,
2218 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2219 ADS_STRUCT
*ads
= NULL
;
2221 LDAPMessage
*res
= NULL
;
2224 if (c
->display_usage
) {
2226 "net ads printer search\n"
2229 _("List printers in the AD"));
2230 TALLOC_FREE(tmp_ctx
);
2234 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2235 if (!ADS_ERR_OK(status
)) {
2239 status
= ads_find_printers(ads
, &res
);
2240 if (!ADS_ERR_OK(status
)) {
2241 d_fprintf(stderr
, _("ads_find_printer: %s\n"),
2242 ads_errstr(status
));
2246 if (ads_count_replies(ads
, res
) == 0) {
2247 d_fprintf(stderr
, _("No results found\n"));
2255 ads_msgfree(ads
, res
);
2256 TALLOC_FREE(tmp_ctx
);
2260 static int net_ads_printer_info(struct net_context
*c
,
2264 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2265 ADS_STRUCT
*ads
= NULL
;
2267 const char *servername
= NULL
;
2268 const char *printername
= NULL
;
2269 LDAPMessage
*res
= NULL
;
2272 if (c
->display_usage
) {
2275 _("net ads printer info [printername [servername]]\n"
2276 " Display printer info from AD\n"
2277 " printername\tPrinter name or wildcard\n"
2278 " servername\tName of the print server\n"));
2279 TALLOC_FREE(tmp_ctx
);
2283 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2284 if (!ADS_ERR_OK(status
)) {
2289 printername
= argv
[0];
2295 servername
= argv
[1];
2297 servername
= lp_netbios_name();
2300 status
= ads_find_printer_on_server(ads
, &res
, printername
, servername
);
2301 if (!ADS_ERR_OK(status
)) {
2302 d_fprintf(stderr
, _("Server '%s' not found: %s\n"),
2303 servername
, ads_errstr(status
));
2307 if (ads_count_replies(ads
, res
) == 0) {
2308 d_fprintf(stderr
, _("Printer '%s' not found\n"), printername
);
2316 ads_msgfree(ads
, res
);
2317 TALLOC_FREE(tmp_ctx
);
2321 static int net_ads_printer_publish(struct net_context
*c
,
2325 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2326 ADS_STRUCT
*ads
= NULL
;
2328 const char *servername
= NULL
;
2329 const char *printername
= NULL
;
2330 struct cli_state
*cli
= NULL
;
2331 struct rpc_pipe_client
*pipe_hnd
= NULL
;
2332 struct sockaddr_storage server_ss
= { 0 };
2334 ADS_MODLIST mods
= NULL
;
2335 char *prt_dn
= NULL
;
2336 char *srv_dn
= NULL
;
2337 char **srv_cn
= NULL
;
2338 char *srv_cn_escaped
= NULL
;
2339 char *printername_escaped
= NULL
;
2340 LDAPMessage
*res
= NULL
;
2344 if (argc
< 1 || c
->display_usage
) {
2347 _("net ads printer publish <printername> [servername]\n"
2348 " Publish printer in AD\n"
2349 " printername\tName of the printer\n"
2350 " servername\tName of the print server\n"));
2351 TALLOC_FREE(tmp_ctx
);
2355 mods
= ads_init_mods(tmp_ctx
);
2357 d_fprintf(stderr
, _("Out of memory\n"));
2361 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2362 if (!ADS_ERR_OK(status
)) {
2366 printername
= argv
[0];
2369 servername
= argv
[1];
2371 servername
= lp_netbios_name();
2374 /* Get printer data from SPOOLSS */
2376 ok
= resolve_name(servername
, &server_ss
, 0x20, false);
2378 d_fprintf(stderr
, _("Could not find server %s\n"),
2383 cli_credentials_set_kerberos_state(c
->creds
,
2384 CRED_USE_KERBEROS_REQUIRED
,
2387 nt_status
= cli_full_connection_creds(&cli
, lp_netbios_name(), servername
,
2391 CLI_FULL_CONNECTION_IPC
);
2393 if (NT_STATUS_IS_ERR(nt_status
)) {
2394 d_fprintf(stderr
, _("Unable to open a connection to %s to "
2395 "obtain data for %s\n"),
2396 servername
, printername
);
2400 /* Publish on AD server */
2402 ads_find_machine_acct(ads
, &res
, servername
);
2404 if (ads_count_replies(ads
, res
) == 0) {
2405 d_fprintf(stderr
, _("Could not find machine account for server "
2411 srv_dn
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
2412 srv_cn
= ldap_explode_dn(srv_dn
, 1);
2414 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn
[0]);
2415 printername_escaped
= escape_rdn_val_string_alloc(printername
);
2416 if (!srv_cn_escaped
|| !printername_escaped
) {
2417 SAFE_FREE(srv_cn_escaped
);
2418 SAFE_FREE(printername_escaped
);
2419 d_fprintf(stderr
, _("Internal error, out of memory!"));
2423 prt_dn
= talloc_asprintf(tmp_ctx
,
2426 printername_escaped
,
2428 if (prt_dn
== NULL
) {
2429 SAFE_FREE(srv_cn_escaped
);
2430 SAFE_FREE(printername_escaped
);
2431 d_fprintf(stderr
, _("Internal error, out of memory!"));
2435 SAFE_FREE(srv_cn_escaped
);
2436 SAFE_FREE(printername_escaped
);
2438 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_spoolss
, &pipe_hnd
);
2439 if (!NT_STATUS_IS_OK(nt_status
)) {
2440 d_fprintf(stderr
, _("Unable to open a connection to the spoolss pipe on %s\n"),
2445 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd
,
2452 status
= ads_add_printer_entry(ads
, prt_dn
, tmp_ctx
, &mods
);
2453 if (!ADS_ERR_OK(status
)) {
2454 d_fprintf(stderr
, "ads_publish_printer: %s\n",
2455 ads_errstr(status
));
2459 d_printf("published printer\n");
2463 talloc_destroy(tmp_ctx
);
2468 static int net_ads_printer_remove(struct net_context
*c
,
2472 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2473 ADS_STRUCT
*ads
= NULL
;
2475 const char *servername
= NULL
;
2476 char *prt_dn
= NULL
;
2477 LDAPMessage
*res
= NULL
;
2480 if (argc
< 1 || c
->display_usage
) {
2483 _("net ads printer remove <printername> [servername]\n"
2484 " Remove a printer from the AD\n"
2485 " printername\tName of the printer\n"
2486 " servername\tName of the print server\n"));
2487 TALLOC_FREE(tmp_ctx
);
2491 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2492 if (!ADS_ERR_OK(status
)) {
2497 servername
= argv
[1];
2499 servername
= lp_netbios_name();
2502 status
= ads_find_printer_on_server(ads
, &res
, argv
[0], servername
);
2503 if (!ADS_ERR_OK(status
)) {
2504 d_fprintf(stderr
, _("ads_find_printer_on_server: %s\n"),
2505 ads_errstr(status
));
2509 if (ads_count_replies(ads
, res
) == 0) {
2510 d_fprintf(stderr
, _("Printer '%s' not found\n"), argv
[1]);
2514 prt_dn
= ads_get_dn(ads
, tmp_ctx
, res
);
2515 if (prt_dn
== NULL
) {
2516 d_fprintf(stderr
, _("Out of memory\n"));
2520 status
= ads_del_dn(ads
, prt_dn
);
2521 if (!ADS_ERR_OK(status
)) {
2522 d_fprintf(stderr
, _("ads_del_dn: %s\n"), ads_errstr(status
));
2528 ads_msgfree(ads
, res
);
2529 TALLOC_FREE(tmp_ctx
);
2533 static int net_ads_printer(struct net_context
*c
, int argc
, const char **argv
)
2535 struct functable func
[] = {
2538 net_ads_printer_search
,
2540 N_("Search for a printer"),
2541 N_("net ads printer search\n"
2542 " Search for a printer")
2546 net_ads_printer_info
,
2548 N_("Display printer information"),
2549 N_("net ads printer info\n"
2550 " Display printer information")
2554 net_ads_printer_publish
,
2556 N_("Publish a printer"),
2557 N_("net ads printer publish\n"
2558 " Publish a printer")
2562 net_ads_printer_remove
,
2564 N_("Delete a printer"),
2565 N_("net ads printer remove\n"
2566 " Delete a printer")
2568 {NULL
, NULL
, 0, NULL
, NULL
}
2571 return net_run_function(c
, argc
, argv
, "net ads printer", func
);
2575 static int net_ads_password(struct net_context
*c
, int argc
, const char **argv
)
2577 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2578 ADS_STRUCT
*ads
= NULL
;
2579 const char *auth_principal
= cli_credentials_get_username(c
->creds
);
2580 const char *auth_password
= cli_credentials_get_password(c
->creds
);
2581 const char *realm
= NULL
;
2582 char *new_password
= NULL
;
2584 char *prompt
= NULL
;
2585 const char *user
= NULL
;
2586 char pwd
[256] = {0};
2590 if (c
->display_usage
) {
2593 _("net ads password <username>\n"
2594 " Change password for user\n"
2595 " username\tName of user to change password for\n"));
2596 TALLOC_FREE(tmp_ctx
);
2600 if (auth_principal
== NULL
|| auth_password
== NULL
) {
2601 d_fprintf(stderr
, _("You must supply an administrator "
2602 "username/password\n"));
2603 TALLOC_FREE(tmp_ctx
);
2608 d_fprintf(stderr
, _("ERROR: You must say which username to "
2609 "change password for\n"));
2610 TALLOC_FREE(tmp_ctx
);
2614 if (strchr_m(argv
[0], '@')) {
2615 user
= talloc_strdup(tmp_ctx
, argv
[0]);
2617 user
= talloc_asprintf(tmp_ctx
, "%s@%s", argv
[0], lp_realm());
2620 d_fprintf(stderr
, _("Out of memory\n"));
2624 use_in_memory_ccache();
2625 chr
= strchr_m(auth_principal
, '@');
2632 /* use the realm so we can eventually change passwords for users
2633 in realms other than default */
2634 ads
= ads_init(tmp_ctx
,
2643 /* we don't actually need a full connect, but it's the easy way to
2644 fill in the KDC's address */
2647 if (!ads
->config
.realm
) {
2648 d_fprintf(stderr
, _("Didn't find the kerberos server!\n"));
2652 if (argv
[1] != NULL
) {
2653 new_password
= talloc_strdup(tmp_ctx
, argv
[1]);
2657 prompt
= talloc_asprintf(tmp_ctx
, _("Enter new password for %s:"), user
);
2658 if (prompt
== NULL
) {
2659 d_fprintf(stderr
, _("Out of memory\n"));
2663 rc
= samba_getpass(prompt
, pwd
, sizeof(pwd
), false, true);
2667 new_password
= talloc_strdup(tmp_ctx
, pwd
);
2668 memset(pwd
, '\0', sizeof(pwd
));
2671 if (new_password
== NULL
) {
2672 d_fprintf(stderr
, _("Out of memory\n"));
2676 status
= kerberos_set_password(ads
->auth
.kdc_server
,
2681 ads
->auth
.time_offset
);
2682 memset(new_password
, '\0', strlen(new_password
));
2683 if (!ADS_ERR_OK(status
)) {
2684 d_fprintf(stderr
, _("Password change failed: %s\n"),
2685 ads_errstr(status
));
2689 d_printf(_("Password change for %s completed.\n"), user
);
2693 TALLOC_FREE(tmp_ctx
);
2697 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
2699 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2700 ADS_STRUCT
*ads
= NULL
;
2701 char *host_principal
= NULL
;
2702 char *my_name
= NULL
;
2706 if (c
->display_usage
) {
2708 "net ads changetrustpw\n"
2711 _("Change the machine account's trust password"));
2712 TALLOC_FREE(tmp_ctx
);
2716 if (!secrets_init()) {
2717 DEBUG(1,("Failed to initialise secrets database\n"));
2721 net_warn_member_options();
2723 net_use_krb_machine_account(c
);
2725 use_in_memory_ccache();
2727 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2728 if (!ADS_ERR_OK(status
)) {
2732 my_name
= talloc_asprintf_strlower_m(tmp_ctx
, "%s", lp_netbios_name());
2733 if (my_name
== NULL
) {
2734 d_fprintf(stderr
, _("Out of memory\n"));
2738 host_principal
= talloc_asprintf(tmp_ctx
, "%s$@%s", my_name
, ads
->config
.realm
);
2739 if (host_principal
== NULL
) {
2740 d_fprintf(stderr
, _("Out of memory\n"));
2744 d_printf(_("Changing password for principal: %s\n"), host_principal
);
2746 status
= ads_change_trust_account_password(ads
, host_principal
);
2747 if (!ADS_ERR_OK(status
)) {
2748 d_fprintf(stderr
, _("Password change failed: %s\n"), ads_errstr(status
));
2752 d_printf(_("Password change for principal %s succeeded.\n"), host_principal
);
2754 if (USE_SYSTEM_KEYTAB
) {
2755 d_printf(_("Attempting to update system keytab with new password.\n"));
2756 if (ads_keytab_create_default(ads
)) {
2757 d_printf(_("Failed to update system keytab.\n"));
2763 TALLOC_FREE(tmp_ctx
);
2769 help for net ads search
2771 static int net_ads_search_usage(struct net_context
*c
, int argc
, const char **argv
)
2774 "\nnet ads search <expression> <attributes...>\n"
2775 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2776 "The expression is a standard LDAP search expression, and the\n"
2777 "attributes are a list of LDAP fields to show in the results.\n\n"
2778 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2780 net_common_flags_usage(c
, argc
, argv
);
2786 general ADS search function. Useful in diagnosing problems in ADS
2788 static int net_ads_search(struct net_context
*c
, int argc
, const char **argv
)
2790 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2791 ADS_STRUCT
*ads
= NULL
;
2793 const char *ldap_exp
= NULL
;
2794 const char **attrs
= NULL
;
2795 LDAPMessage
*res
= NULL
;
2798 if (argc
< 1 || c
->display_usage
) {
2799 TALLOC_FREE(tmp_ctx
);
2800 return net_ads_search_usage(c
, argc
, argv
);
2803 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2804 if (!ADS_ERR_OK(status
)) {
2811 status
= ads_do_search_retry(ads
,
2812 ads
->config
.bind_path
,
2817 if (!ADS_ERR_OK(status
)) {
2818 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2822 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2824 /* dump the results */
2829 ads_msgfree(ads
, res
);
2830 TALLOC_FREE(tmp_ctx
);
2836 help for net ads search
2838 static int net_ads_dn_usage(struct net_context
*c
, int argc
, const char **argv
)
2841 "\nnet ads dn <dn> <attributes...>\n"
2842 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2843 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2844 "to show in the results\n\n"
2845 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2846 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2848 net_common_flags_usage(c
, argc
, argv
);
2854 general ADS search function. Useful in diagnosing problems in ADS
2856 static int net_ads_dn(struct net_context
*c
, int argc
, const char **argv
)
2858 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2859 ADS_STRUCT
*ads
= NULL
;
2861 const char *dn
= NULL
;
2862 const char **attrs
= NULL
;
2863 LDAPMessage
*res
= NULL
;
2866 if (argc
< 1 || c
->display_usage
) {
2867 TALLOC_FREE(tmp_ctx
);
2868 return net_ads_dn_usage(c
, argc
, argv
);
2871 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2872 if (!ADS_ERR_OK(status
)) {
2879 status
= ads_do_search_all(ads
,
2885 if (!ADS_ERR_OK(status
)) {
2886 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2890 d_printf("Got %d replies\n\n", ads_count_replies(ads
, res
));
2892 /* dump the results */
2897 ads_msgfree(ads
, res
);
2898 TALLOC_FREE(tmp_ctx
);
2903 help for net ads sid search
2905 static int net_ads_sid_usage(struct net_context
*c
, int argc
, const char **argv
)
2908 "\nnet ads sid <sid> <attributes...>\n"
2909 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2910 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2911 "to show in the results\n\n"
2912 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2914 net_common_flags_usage(c
, argc
, argv
);
2920 general ADS search function. Useful in diagnosing problems in ADS
2922 static int net_ads_sid(struct net_context
*c
, int argc
, const char **argv
)
2924 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2925 ADS_STRUCT
*ads
= NULL
;
2927 const char *sid_string
= NULL
;
2928 const char **attrs
= NULL
;
2929 LDAPMessage
*res
= NULL
;
2930 struct dom_sid sid
= { 0 };
2933 if (argc
< 1 || c
->display_usage
) {
2934 TALLOC_FREE(tmp_ctx
);
2935 return net_ads_sid_usage(c
, argc
, argv
);
2938 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2939 if (!ADS_ERR_OK(status
)) {
2943 sid_string
= argv
[0];
2946 if (!string_to_sid(&sid
, sid_string
)) {
2947 d_fprintf(stderr
, _("could not convert sid\n"));
2951 status
= ads_search_retry_sid(ads
, &res
, &sid
, attrs
);
2952 if (!ADS_ERR_OK(status
)) {
2953 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2957 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2959 /* dump the results */
2964 ads_msgfree(ads
, res
);
2965 TALLOC_FREE(tmp_ctx
);
2969 static int net_ads_keytab_flush(struct net_context
*c
,
2973 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2974 ADS_STRUCT
*ads
= NULL
;
2978 if (c
->display_usage
) {
2980 "net ads keytab flush\n"
2983 _("Delete the whole keytab"));
2984 TALLOC_FREE(tmp_ctx
);
2988 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
2989 net_use_krb_machine_account(c
);
2992 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2993 if (!ADS_ERR_OK(status
)) {
2997 ret
= ads_keytab_flush(ads
);
2999 TALLOC_FREE(tmp_ctx
);
3003 static int net_ads_keytab_add(struct net_context
*c
,
3008 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3009 ADS_STRUCT
*ads
= NULL
;
3014 if (c
->display_usage
) {
3017 _("net ads keytab add <principal> [principal ...]\n"
3018 " Add principals to local keytab\n"
3019 " principal\tKerberos principal to add to "
3021 TALLOC_FREE(tmp_ctx
);
3025 net_warn_member_options();
3027 d_printf(_("Processing principals to add...\n"));
3029 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
3030 net_use_krb_machine_account(c
);
3033 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3034 if (!ADS_ERR_OK(status
)) {
3038 for (ret
= 0, i
= 0; i
< argc
; i
++) {
3039 ret
|= ads_keytab_add_entry(ads
, argv
[i
], update_ads
);
3042 TALLOC_FREE(tmp_ctx
);
3046 static int net_ads_keytab_add_default(struct net_context
*c
,
3050 return net_ads_keytab_add(c
, argc
, argv
, false);
3053 static int net_ads_keytab_add_update_ads(struct net_context
*c
,
3057 return net_ads_keytab_add(c
, argc
, argv
, true);
3060 static int net_ads_keytab_delete(struct net_context
*c
,
3064 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3065 ADS_STRUCT
*ads
= NULL
;
3070 if (c
->display_usage
) {
3073 _("net ads keytab delete <principal> [principal ...]\n"
3074 " Remove entries for service principal, "
3075 " from the keytab file only."
3076 " Remove principals from local keytab\n"
3077 " principal\tKerberos principal to remove from "
3079 TALLOC_FREE(tmp_ctx
);
3083 d_printf(_("Processing principals to delete...\n"));
3085 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
3086 net_use_krb_machine_account(c
);
3089 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3090 if (!ADS_ERR_OK(status
)) {
3094 for (ret
= 0, i
= 0; i
< argc
; i
++) {
3095 ret
|= ads_keytab_delete_entry(ads
, argv
[i
]);
3098 TALLOC_FREE(tmp_ctx
);
3102 static int net_ads_keytab_create(struct net_context
*c
, int argc
, const char **argv
)
3104 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3105 ADS_STRUCT
*ads
= NULL
;
3109 if (c
->display_usage
) {
3111 "net ads keytab create\n"
3114 _("Create new default keytab"));
3115 TALLOC_FREE(tmp_ctx
);
3119 net_warn_member_options();
3121 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
3122 net_use_krb_machine_account(c
);
3125 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3126 if (!ADS_ERR_OK(status
)) {
3130 ret
= ads_keytab_create_default(ads
);
3132 TALLOC_FREE(tmp_ctx
);
3136 static int net_ads_keytab_list(struct net_context
*c
, int argc
, const char **argv
)
3138 const char *keytab
= NULL
;
3140 if (c
->display_usage
) {
3143 _("net ads keytab list [keytab]\n"
3144 " List a local keytab\n"
3145 " keytab\tKeytab to list\n"));
3153 return ads_keytab_list(keytab
);
3157 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
3159 struct functable func
[] = {
3162 net_ads_keytab_add_default
,
3164 N_("Add a service principal"),
3165 N_("net ads keytab add\n"
3166 " Add a service principal, updates keytab file only.")
3170 net_ads_keytab_delete
,
3172 N_("Delete a service principal"),
3173 N_("net ads keytab delete\n"
3174 " Remove entries for service principal, from the keytab file only.")
3178 net_ads_keytab_add_update_ads
,
3180 N_("Add a service principal"),
3181 N_("net ads keytab add_update_ads\n"
3182 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3186 net_ads_keytab_create
,
3188 N_("Create a fresh keytab"),
3189 N_("net ads keytab create\n"
3190 " Create a fresh keytab or update existing one.")
3194 net_ads_keytab_flush
,
3196 N_("Remove all keytab entries"),
3197 N_("net ads keytab flush\n"
3198 " Remove all keytab entries")
3202 net_ads_keytab_list
,
3204 N_("List a keytab"),
3205 N_("net ads keytab list\n"
3208 {NULL
, NULL
, 0, NULL
, NULL
}
3211 if (!USE_KERBEROS_KEYTAB
) {
3212 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3213 "keytab method to use keytab functions.\n"));
3216 return net_run_function(c
, argc
, argv
, "net ads keytab", func
);
3219 static int net_ads_kerberos_renew(struct net_context
*c
, int argc
, const char **argv
)
3223 if (c
->display_usage
) {
3225 "net ads kerberos renew\n"
3228 _("Renew TGT from existing credential cache"));
3232 ret
= smb_krb5_renew_ticket(NULL
, NULL
, NULL
, NULL
);
3234 d_printf(_("failed to renew kerberos ticket: %s\n"),
3235 error_message(ret
));
3240 static int net_ads_kerberos_pac_common(struct net_context
*c
, int argc
, const char **argv
,
3241 struct PAC_DATA_CTR
**pac_data_ctr
)
3245 const char *impersonate_princ_s
= NULL
;
3246 const char *local_service
= NULL
;
3249 for (i
=0; i
<argc
; i
++) {
3250 if (strnequal(argv
[i
], "impersonate", strlen("impersonate"))) {
3251 impersonate_princ_s
= get_string_param(argv
[i
]);
3252 if (impersonate_princ_s
== NULL
) {
3256 if (strnequal(argv
[i
], "local_service", strlen("local_service"))) {
3257 local_service
= get_string_param(argv
[i
]);
3258 if (local_service
== NULL
) {
3264 if (local_service
== NULL
) {
3265 local_service
= talloc_asprintf(c
, "%s$@%s",
3266 lp_netbios_name(), lp_realm());
3267 if (local_service
== NULL
) {
3272 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
3274 status
= kerberos_return_pac(c
,
3283 2592000, /* one month */
3284 impersonate_princ_s
,
3289 if (!NT_STATUS_IS_OK(status
)) {
3290 d_printf(_("failed to query kerberos PAC: %s\n"),
3300 static int net_ads_kerberos_pac_dump(struct net_context
*c
, int argc
, const char **argv
)
3302 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3305 enum PAC_TYPE type
= 0;
3307 if (c
->display_usage
) {
3309 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3312 _("Dump the Kerberos PAC"));
3316 for (i
=0; i
<argc
; i
++) {
3317 if (strnequal(argv
[i
], "pac_buffer_type", strlen("pac_buffer_type"))) {
3318 type
= get_int_param(argv
[i
]);
3322 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3331 s
= NDR_PRINT_STRUCT_STRING(c
, PAC_DATA
,
3332 pac_data_ctr
->pac_data
);
3334 d_printf(_("The Pac: %s\n"), s
);
3341 num_buffers
= pac_data_ctr
->pac_data
->num_buffers
;
3343 for (i
=0; i
<num_buffers
; i
++) {
3347 if (pac_data_ctr
->pac_data
->buffers
[i
].type
!= type
) {
3351 s
= NDR_PRINT_UNION_STRING(c
, PAC_INFO
, type
,
3352 pac_data_ctr
->pac_data
->buffers
[i
].info
);
3354 d_printf(_("The Pac: %s\n"), s
);
3363 static int net_ads_kerberos_pac_save(struct net_context
*c
, int argc
, const char **argv
)
3365 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3366 char *filename
= NULL
;
3370 if (c
->display_usage
) {
3372 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3375 _("Save the Kerberos PAC"));
3379 for (i
=0; i
<argc
; i
++) {
3380 if (strnequal(argv
[i
], "filename", strlen("filename"))) {
3381 filename
= get_string_param(argv
[i
]);
3382 if (filename
== NULL
) {
3388 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3393 if (filename
== NULL
) {
3394 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3398 /* save the raw format */
3399 if (!file_save(filename
, pac_data_ctr
->pac_blob
.data
, pac_data_ctr
->pac_blob
.length
)) {
3400 d_printf(_("failed to save PAC in %s\n"), filename
);
3407 static int net_ads_kerberos_pac(struct net_context
*c
, int argc
, const char **argv
)
3409 struct functable func
[] = {
3412 net_ads_kerberos_pac_dump
,
3414 N_("Dump Kerberos PAC"),
3415 N_("net ads kerberos pac dump\n"
3416 " Dump a Kerberos PAC to stdout")
3420 net_ads_kerberos_pac_save
,
3422 N_("Save Kerberos PAC"),
3423 N_("net ads kerberos pac save\n"
3424 " Save a Kerberos PAC in a file")
3427 {NULL
, NULL
, 0, NULL
, NULL
}
3430 return net_run_function(c
, argc
, argv
, "net ads kerberos pac", func
);
3433 static int net_ads_kerberos_kinit(struct net_context
*c
, int argc
, const char **argv
)
3438 if (c
->display_usage
) {
3440 "net ads kerberos kinit\n"
3443 _("Get Ticket Granting Ticket (TGT) for the user"));
3447 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
3449 ret
= kerberos_kinit_password_ext(c
->opt_user_name
,
3457 2592000, /* one month */
3463 d_printf(_("failed to kinit password: %s\n"),
3469 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
3471 struct functable func
[] = {
3474 net_ads_kerberos_kinit
,
3476 N_("Retrieve Ticket Granting Ticket (TGT)"),
3477 N_("net ads kerberos kinit\n"
3478 " Receive Ticket Granting Ticket (TGT)")
3482 net_ads_kerberos_renew
,
3484 N_("Renew Ticket Granting Ticket from credential cache"),
3485 N_("net ads kerberos renew\n"
3486 " Renew Ticket Granting Ticket (TGT) from "
3491 net_ads_kerberos_pac
,
3493 N_("Dump Kerberos PAC"),
3494 N_("net ads kerberos pac\n"
3495 " Dump Kerberos PAC")
3497 {NULL
, NULL
, 0, NULL
, NULL
}
3500 return net_run_function(c
, argc
, argv
, "net ads kerberos", func
);
3503 static int net_ads_setspn_list(struct net_context
*c
,
3507 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3508 ADS_STRUCT
*ads
= NULL
;
3513 if (c
->display_usage
) {
3516 _("net ads setspn list <machinename>\n"));
3517 TALLOC_FREE(tmp_ctx
);
3521 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3522 if (!ADS_ERR_OK(status
)) {
3527 ok
= ads_setspn_list(ads
, argv
[0]);
3529 ok
= ads_setspn_list(ads
, lp_netbios_name());
3534 TALLOC_FREE(tmp_ctx
);
3538 static int net_ads_setspn_add(struct net_context
*c
, int argc
, const char **argv
)
3540 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3541 ADS_STRUCT
*ads
= NULL
;
3546 if (c
->display_usage
|| argc
< 1) {
3549 _("net ads setspn add <machinename> SPN\n"));
3550 TALLOC_FREE(tmp_ctx
);
3554 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3555 if (!ADS_ERR_OK(status
)) {
3560 ok
= ads_setspn_add(ads
, argv
[0], argv
[1]);
3562 ok
= ads_setspn_add(ads
, lp_netbios_name(), argv
[0]);
3567 TALLOC_FREE(tmp_ctx
);
3571 static int net_ads_setspn_delete(struct net_context
*c
, int argc
, const char **argv
)
3573 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3574 ADS_STRUCT
*ads
= NULL
;
3579 if (c
->display_usage
|| argc
< 1) {
3582 _("net ads setspn delete <machinename> SPN\n"));
3583 TALLOC_FREE(tmp_ctx
);
3587 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3588 if (!ADS_ERR_OK(status
)) {
3593 ok
= ads_setspn_delete(ads
, argv
[0], argv
[1]);
3595 ok
= ads_setspn_delete(ads
, lp_netbios_name(), argv
[0]);
3600 TALLOC_FREE(tmp_ctx
);
3604 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
3606 struct functable func
[] = {
3609 net_ads_setspn_list
,
3611 N_("List Service Principal Names (SPN)"),
3612 N_("net ads setspn list machine\n"
3613 " List Service Principal Names (SPN)")
3619 N_("Add Service Principal Names (SPN)"),
3620 N_("net ads setspn add machine spn\n"
3621 " Add Service Principal Names (SPN)")
3625 net_ads_setspn_delete
,
3627 N_("Delete Service Principal Names (SPN)"),
3628 N_("net ads setspn delete machine spn\n"
3629 " Delete Service Principal Names (SPN)")
3631 {NULL
, NULL
, 0, NULL
, NULL
}
3634 return net_run_function(c
, argc
, argv
, "net ads setspn", func
);
3637 static int net_ads_enctype_lookup_account(struct net_context
*c
,
3639 const char *account
,
3641 const char **enctype_str
)
3644 const char *attrs
[] = {
3645 "msDS-SupportedEncryptionTypes",
3652 filter
= talloc_asprintf(c
, "(&(objectclass=user)(sAMAccountName=%s))",
3654 if (filter
== NULL
) {
3658 status
= ads_search(ads
, res
, filter
, attrs
);
3659 if (!ADS_ERR_OK(status
)) {
3660 d_printf(_("no account found with filter: %s\n"), filter
);
3664 count
= ads_count_replies(ads
, *res
);
3669 d_printf(_("no account found with filter: %s\n"), filter
);
3672 d_printf(_("multiple accounts found with filter: %s\n"), filter
);
3677 *enctype_str
= ads_pull_string(ads
, c
, *res
,
3678 "msDS-SupportedEncryptionTypes");
3679 if (*enctype_str
== NULL
) {
3680 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3690 static void net_ads_enctype_dump_enctypes(const char *username
,
3691 const char *enctype_str
)
3693 int enctypes
= atoi(enctype_str
);
3695 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3696 username
, enctypes
, enctypes
);
3698 printf("[%s] 0x%08x DES-CBC-CRC\n",
3699 enctypes
& ENC_CRC32
? "X" : " ",
3701 printf("[%s] 0x%08x DES-CBC-MD5\n",
3702 enctypes
& ENC_RSA_MD5
? "X" : " ",
3704 printf("[%s] 0x%08x RC4-HMAC\n",
3705 enctypes
& ENC_RC4_HMAC_MD5
? "X" : " ",
3707 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3708 enctypes
& ENC_HMAC_SHA1_96_AES128
? "X" : " ",
3709 ENC_HMAC_SHA1_96_AES128
);
3710 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3711 enctypes
& ENC_HMAC_SHA1_96_AES256
? "X" : " ",
3712 ENC_HMAC_SHA1_96_AES256
);
3713 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3714 enctypes
& ENC_HMAC_SHA1_96_AES256_SK
? "X" : " ",
3715 ENC_HMAC_SHA1_96_AES256_SK
);
3716 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3717 enctypes
& KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
? "X" : " ",
3718 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
);
3721 static int net_ads_enctypes_list(struct net_context
*c
, int argc
, const char **argv
)
3723 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3725 ADS_STRUCT
*ads
= NULL
;
3726 LDAPMessage
*res
= NULL
;
3727 const char *str
= NULL
;
3730 if (c
->display_usage
|| (argc
< 1)) {
3732 "net ads enctypes list\n"
3735 _("List supported enctypes"));
3736 TALLOC_FREE(tmp_ctx
);
3740 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3741 if (!ADS_ERR_OK(status
)) {
3745 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3750 net_ads_enctype_dump_enctypes(argv
[0], str
);
3754 ads_msgfree(ads
, res
);
3755 TALLOC_FREE(tmp_ctx
);
3759 static int net_ads_enctypes_set(struct net_context
*c
, int argc
, const char **argv
)
3761 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3764 ADS_STRUCT
*ads
= NULL
;
3765 LDAPMessage
*res
= NULL
;
3766 const char *etype_list_str
= NULL
;
3767 const char *dn
= NULL
;
3768 ADS_MODLIST mods
= NULL
;
3769 uint32_t etype_list
;
3770 const char *str
= NULL
;
3772 if (c
->display_usage
|| argc
< 1) {
3774 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3777 _("Set supported enctypes"));
3778 TALLOC_FREE(tmp_ctx
);
3782 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3783 if (!ADS_ERR_OK(status
)) {
3787 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3792 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3798 etype_list
|= ENC_RC4_HMAC_MD5
;
3799 etype_list
|= ENC_HMAC_SHA1_96_AES128
;
3800 etype_list
|= ENC_HMAC_SHA1_96_AES256
;
3802 if (argv
[1] != NULL
) {
3803 sscanf(argv
[1], "%i", &etype_list
);
3806 etype_list_str
= talloc_asprintf(tmp_ctx
, "%d", etype_list
);
3807 if (!etype_list_str
) {
3811 mods
= ads_init_mods(tmp_ctx
);
3816 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes",
3818 if (!ADS_ERR_OK(status
)) {
3822 status
= ads_gen_mod(ads
, dn
, mods
);
3823 if (!ADS_ERR_OK(status
)) {
3824 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3825 ads_errstr(status
));
3829 ads_msgfree(ads
, res
);
3832 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3837 net_ads_enctype_dump_enctypes(argv
[0], str
);
3841 ads_msgfree(ads
, res
);
3842 TALLOC_FREE(tmp_ctx
);
3846 static int net_ads_enctypes_delete(struct net_context
*c
, int argc
, const char **argv
)
3848 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3851 ADS_STRUCT
*ads
= NULL
;
3852 LDAPMessage
*res
= NULL
;
3853 const char *dn
= NULL
;
3854 ADS_MODLIST mods
= NULL
;
3856 if (c
->display_usage
|| argc
< 1) {
3858 "net ads enctypes delete <sAMAccountName>\n"
3861 _("Delete supported enctypes"));
3862 TALLOC_FREE(tmp_ctx
);
3866 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3867 if (!ADS_ERR_OK(status
)) {
3871 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3876 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3881 mods
= ads_init_mods(tmp_ctx
);
3886 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes", NULL
);
3887 if (!ADS_ERR_OK(status
)) {
3891 status
= ads_gen_mod(ads
, dn
, mods
);
3892 if (!ADS_ERR_OK(status
)) {
3893 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3894 ads_errstr(status
));
3901 ads_msgfree(ads
, res
);
3902 TALLOC_FREE(tmp_ctx
);
3906 static int net_ads_enctypes(struct net_context
*c
, int argc
, const char **argv
)
3908 struct functable func
[] = {
3911 net_ads_enctypes_list
,
3913 N_("List the supported encryption types"),
3914 N_("net ads enctypes list\n"
3915 " List the supported encryption types")
3919 net_ads_enctypes_set
,
3921 N_("Set the supported encryption types"),
3922 N_("net ads enctypes set\n"
3923 " Set the supported encryption types")
3927 net_ads_enctypes_delete
,
3929 N_("Delete the supported encryption types"),
3930 N_("net ads enctypes delete\n"
3931 " Delete the supported encryption types")
3934 {NULL
, NULL
, 0, NULL
, NULL
}
3937 return net_run_function(c
, argc
, argv
, "net ads enctypes", func
);
3941 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
3943 struct functable func
[] = {
3948 N_("Display details on remote ADS server"),
3950 " Display details on remote ADS server")
3956 N_("Join the local machine to ADS realm"),
3958 " Join the local machine to ADS realm")
3964 N_("Validate machine account"),
3965 N_("net ads testjoin\n"
3966 " Validate machine account")
3972 N_("Remove the local machine from ADS"),
3973 N_("net ads leave\n"
3974 " Remove the local machine from ADS")
3980 N_("Display machine account details"),
3981 N_("net ads status\n"
3982 " Display machine account details")
3988 N_("List/modify users"),
3990 " List/modify users")
3996 N_("List/modify groups"),
3997 N_("net ads group\n"
3998 " List/modify groups")
4004 N_("Issue dynamic DNS update"),
4006 " Issue dynamic DNS update")
4012 N_("Change user passwords"),
4013 N_("net ads password\n"
4014 " Change user passwords")
4018 net_ads_changetrustpw
,
4020 N_("Change trust account password"),
4021 N_("net ads changetrustpw\n"
4022 " Change trust account password")
4028 N_("List/modify printer entries"),
4029 N_("net ads printer\n"
4030 " List/modify printer entries")
4036 N_("Issue LDAP search using filter"),
4037 N_("net ads search\n"
4038 " Issue LDAP search using filter")
4044 N_("Issue LDAP search by DN"),
4046 " Issue LDAP search by DN")
4052 N_("Issue LDAP search by SID"),
4054 " Issue LDAP search by SID")
4060 N_("Display workgroup name"),
4061 N_("net ads workgroup\n"
4062 " Display the workgroup name")
4068 N_("Perform CLDAP query on DC"),
4069 N_("net ads lookup\n"
4070 " Find the ADS DC using CLDAP lookups")
4076 N_("Manage local keytab file"),
4077 N_("net ads keytab\n"
4078 " Manage local keytab file")
4084 N_("Manage Service Principal Names (SPN)s"),
4085 N_("net ads spnset\n"
4086 " Manage Service Principal Names (SPN)s")
4092 N_("Manage group policy objects"),
4094 " Manage group policy objects")
4100 N_("Manage kerberos keytab"),
4101 N_("net ads kerberos\n"
4102 " Manage kerberos keytab")
4108 N_("List/modify supported encryption types"),
4109 N_("net ads enctypes\n"
4110 " List/modify enctypes")
4112 {NULL
, NULL
, 0, NULL
, NULL
}
4115 return net_run_function(c
, argc
, argv
, "net ads", func
);
4120 static int net_ads_noads(void)
4122 d_fprintf(stderr
, _("ADS support not compiled in\n"));
4126 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
4128 return net_ads_noads();
4131 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
4133 return net_ads_noads();
4136 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
4138 return net_ads_noads();
4141 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
4143 return net_ads_noads();
4146 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
4148 return net_ads_noads();
4151 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
4153 return net_ads_noads();
4156 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
4158 return net_ads_noads();
4161 int net_ads_gpo(struct net_context
*c
, int argc
, const char **argv
)
4163 return net_ads_noads();
4166 /* this one shouldn't display a message */
4167 int net_ads_check(struct net_context
*c
)
4172 int net_ads_check_our_domain(struct net_context
*c
)
4177 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
4179 return net_ads_noads();
4182 #endif /* HAVE_ADS */