2 Samba Unix/Linux SMB client library
4 Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5 Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7 Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "utils/net.h"
25 #include "libsmb/namequery.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "librpc/gen_ndr/ndr_krb5pac.h"
28 #include "../librpc/gen_ndr/ndr_spoolss.h"
29 #include "nsswitch/libwbclient/wbclient.h"
31 #include "libads/cldap.h"
32 #include "../lib/addns/dnsquery.h"
33 #include "../libds/common/flags.h"
34 #include "librpc/gen_ndr/libnet_join.h"
35 #include "libnet/libnet_join.h"
39 #include "../libcli/security/security.h"
40 #include "libsmb/libsmb.h"
41 #include "lib/param/loadparm.h"
42 #include "utils/net_dns.h"
43 #include "auth/kerberos/pac_utils.h"
44 #include "lib/util/string_wrappers.h"
48 #include "audit_logging.h" /* various JSON helpers */
49 #include "auth/common_auth.h"
50 #endif /* [HAVE_JANSSON] */
54 /* when we do not have sufficient input parameters to contact a remote domain
55 * we always fall back to our own realm - Guenther*/
57 static const char *assume_own_realm(struct net_context
*c
)
59 if (!c
->opt_host
&& strequal(lp_workgroup(), c
->opt_target_workgroup
)) {
69 * note: JSON output deliberately bypasses gettext so as to provide the same
70 * output irrespective of the locale.
73 static int output_json(const struct json_object
*jsobj
)
75 TALLOC_CTX
*ctx
= NULL
;
78 if (json_is_invalid(jsobj
)) {
82 ctx
= talloc_new(NULL
);
84 d_fprintf(stderr
, _("Out of memory\n"));
88 json
= json_to_string(ctx
, jsobj
);
90 d_fprintf(stderr
, _("error encoding to JSON\n"));
94 d_printf("%s\n", json
);
100 static int net_ads_cldap_netlogon_json
103 const struct NETLOGON_SAM_LOGON_RESPONSE_EX
*reply
)
105 struct json_object jsobj
= json_new_object();
106 struct json_object flagsobj
= json_new_object();
107 char response_type
[32] = { '\0' };
110 if (json_is_invalid(&jsobj
) || json_is_invalid(&flagsobj
)) {
111 d_fprintf(stderr
, _("error setting up JSON value\n"));
116 switch (reply
->command
) {
117 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
118 strncpy(response_type
,
119 "LOGON_SAM_LOGON_USER_UNKNOWN_EX",
120 sizeof(response_type
));
122 case LOGON_SAM_LOGON_RESPONSE_EX
:
123 strncpy(response_type
, "LOGON_SAM_LOGON_RESPONSE_EX",
124 sizeof(response_type
));
127 snprintf(response_type
, sizeof(response_type
), "0x%x",
132 ret
= json_add_string(&jsobj
, "Information for Domain Controller",
138 ret
= json_add_string(&jsobj
, "Response Type", response_type
);
143 ret
= json_add_guid(&jsobj
, "GUID", &reply
->domain_uuid
);
148 ret
= json_add_bool(&flagsobj
, "Is a PDC",
149 reply
->server_type
& NBT_SERVER_PDC
);
154 ret
= json_add_bool(&flagsobj
, "Is a GC of the forest",
155 reply
->server_type
& NBT_SERVER_GC
);
160 ret
= json_add_bool(&flagsobj
, "Is an LDAP server",
161 reply
->server_type
& NBT_SERVER_LDAP
);
166 ret
= json_add_bool(&flagsobj
, "Supports DS",
167 reply
->server_type
& NBT_SERVER_DS
);
172 ret
= json_add_bool(&flagsobj
, "Is running a KDC",
173 reply
->server_type
& NBT_SERVER_KDC
);
178 ret
= json_add_bool(&flagsobj
, "Is running time services",
179 reply
->server_type
& NBT_SERVER_TIMESERV
);
184 ret
= json_add_bool(&flagsobj
, "Is the closest DC",
185 reply
->server_type
& NBT_SERVER_CLOSEST
);
190 ret
= json_add_bool(&flagsobj
, "Is writable",
191 reply
->server_type
& NBT_SERVER_WRITABLE
);
196 ret
= json_add_bool(&flagsobj
, "Has a hardware clock",
197 reply
->server_type
& NBT_SERVER_GOOD_TIMESERV
);
202 ret
= json_add_bool(&flagsobj
,
203 "Is a non-domain NC serviced by LDAP server",
204 reply
->server_type
& NBT_SERVER_NDNC
);
210 (&flagsobj
, "Is NT6 DC that has some secrets",
211 reply
->server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
);
217 (&flagsobj
, "Is NT6 DC that has all secrets",
218 reply
->server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
);
223 ret
= json_add_bool(&flagsobj
, "Runs Active Directory Web Services",
224 reply
->server_type
& NBT_SERVER_ADS_WEB_SERVICE
);
229 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2012 or later",
230 reply
->server_type
& NBT_SERVER_DS_8
);
235 ret
= json_add_string(&jsobj
, "Forest", reply
->forest
);
240 ret
= json_add_string(&jsobj
, "Domain", reply
->dns_domain
);
245 ret
= json_add_string(&jsobj
, "Domain Controller", reply
->pdc_dns_name
);
251 ret
= json_add_string(&jsobj
, "Pre-Win2k Domain", reply
->domain_name
);
256 ret
= json_add_string(&jsobj
, "Pre-Win2k Hostname", reply
->pdc_name
);
261 if (*reply
->user_name
) {
262 ret
= json_add_string(&jsobj
, "User name", reply
->user_name
);
268 ret
= json_add_string(&jsobj
, "Server Site Name", reply
->server_site
);
273 ret
= json_add_string(&jsobj
, "Client Site Name", reply
->client_site
);
278 ret
= json_add_int(&jsobj
, "NT Version", reply
->nt_version
);
283 ret
= json_add_int(&jsobj
, "LMNT Token", reply
->lmnt_token
);
288 ret
= json_add_int(&jsobj
, "LM20 Token", reply
->lm20_token
);
293 ret
= json_add_object(&jsobj
, "Flags", &flagsobj
);
298 ret
= output_json(&jsobj
);
299 json_free(&jsobj
); /* frees flagsobj recursively */
304 json_free(&flagsobj
);
310 #else /* [HAVE_JANSSON] */
312 static int net_ads_cldap_netlogon_json
315 const struct NETLOGON_SAM_LOGON_RESPONSE_EX
* reply
)
317 d_fprintf(stderr
, _("JSON support not available\n"));
322 #endif /* [HAVE_JANSSON] */
325 do a cldap netlogon query
327 static int net_ads_cldap_netlogon(struct net_context
*c
, ADS_STRUCT
*ads
)
329 char addr
[INET6_ADDRSTRLEN
];
330 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
332 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
334 if ( !ads_cldap_netlogon_5(talloc_tos(), &ads
->ldap
.ss
, ads
->server
.realm
, &reply
) ) {
335 d_fprintf(stderr
, _("CLDAP query failed!\n"));
340 return net_ads_cldap_netlogon_json(ads
, addr
, &reply
);
343 d_printf(_("Information for Domain Controller: %s\n\n"),
346 d_printf(_("Response Type: "));
347 switch (reply
.command
) {
348 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
349 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
351 case LOGON_SAM_LOGON_RESPONSE_EX
:
352 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
355 d_printf("0x%x\n", reply
.command
);
359 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply
.domain_uuid
));
361 d_printf(_("Flags:\n"
363 "\tIs a GC of the forest: %s\n"
364 "\tIs an LDAP server: %s\n"
365 "\tSupports DS: %s\n"
366 "\tIs running a KDC: %s\n"
367 "\tIs running time services: %s\n"
368 "\tIs the closest DC: %s\n"
369 "\tIs writable: %s\n"
370 "\tHas a hardware clock: %s\n"
371 "\tIs a non-domain NC serviced by LDAP server: %s\n"
372 "\tIs NT6 DC that has some secrets: %s\n"
373 "\tIs NT6 DC that has all secrets: %s\n"
374 "\tRuns Active Directory Web Services: %s\n"
375 "\tRuns on Windows 2012 or later: %s\n"),
376 (reply
.server_type
& NBT_SERVER_PDC
) ? _("yes") : _("no"),
377 (reply
.server_type
& NBT_SERVER_GC
) ? _("yes") : _("no"),
378 (reply
.server_type
& NBT_SERVER_LDAP
) ? _("yes") : _("no"),
379 (reply
.server_type
& NBT_SERVER_DS
) ? _("yes") : _("no"),
380 (reply
.server_type
& NBT_SERVER_KDC
) ? _("yes") : _("no"),
381 (reply
.server_type
& NBT_SERVER_TIMESERV
) ? _("yes") : _("no"),
382 (reply
.server_type
& NBT_SERVER_CLOSEST
) ? _("yes") : _("no"),
383 (reply
.server_type
& NBT_SERVER_WRITABLE
) ? _("yes") : _("no"),
384 (reply
.server_type
& NBT_SERVER_GOOD_TIMESERV
) ? _("yes") : _("no"),
385 (reply
.server_type
& NBT_SERVER_NDNC
) ? _("yes") : _("no"),
386 (reply
.server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
387 (reply
.server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
388 (reply
.server_type
& NBT_SERVER_ADS_WEB_SERVICE
) ? _("yes") : _("no"),
389 (reply
.server_type
& NBT_SERVER_DS_8
) ? _("yes") : _("no"));
392 printf(_("Forest: %s\n"), reply
.forest
);
393 printf(_("Domain: %s\n"), reply
.dns_domain
);
394 printf(_("Domain Controller: %s\n"), reply
.pdc_dns_name
);
396 printf(_("Pre-Win2k Domain: %s\n"), reply
.domain_name
);
397 printf(_("Pre-Win2k Hostname: %s\n"), reply
.pdc_name
);
399 if (*reply
.user_name
) printf(_("User name: %s\n"), reply
.user_name
);
401 printf(_("Server Site Name: %s\n"), reply
.server_site
);
402 printf(_("Client Site Name: %s\n"), reply
.client_site
);
404 d_printf(_("NT Version: %d\n"), reply
.nt_version
);
405 d_printf(_("LMNT Token: %.2x\n"), reply
.lmnt_token
);
406 d_printf(_("LM20 Token: %.2x\n"), reply
.lm20_token
);
412 this implements the CLDAP based netlogon lookup requests
413 for finding the domain controller of a ADS domain
415 static int net_ads_lookup(struct net_context
*c
, int argc
, const char **argv
)
417 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
418 ADS_STRUCT
*ads
= NULL
;
422 if (c
->display_usage
) {
427 _("Find the ADS DC using CLDAP lookup.\n"));
428 TALLOC_FREE(tmp_ctx
);
432 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
433 if (!ADS_ERR_OK(status
)) {
434 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
438 if (!ads
->config
.realm
) {
439 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
440 if (ads
->config
.realm
== NULL
) {
441 d_fprintf(stderr
, _("Out of memory\n"));
444 ads
->ldap
.port
= 389;
447 ret
= net_ads_cldap_netlogon(c
, ads
);
449 TALLOC_FREE(tmp_ctx
);
456 static int net_ads_info_json(ADS_STRUCT
*ads
)
459 char addr
[INET6_ADDRSTRLEN
];
461 struct json_object jsobj
= json_new_object();
463 if (json_is_invalid(&jsobj
)) {
464 d_fprintf(stderr
, _("error setting up JSON value\n"));
469 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
471 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
473 ret
= json_add_string (&jsobj
, "LDAP server", addr
);
478 ret
= json_add_string (&jsobj
, "LDAP server name",
479 ads
->config
.ldap_server_name
);
484 ret
= json_add_string (&jsobj
, "Realm", ads
->config
.realm
);
489 ret
= json_add_string (&jsobj
, "Bind Path", ads
->config
.bind_path
);
494 ret
= json_add_int (&jsobj
, "LDAP port", ads
->ldap
.port
);
499 ret
= json_add_int (&jsobj
, "Server time", ads
->config
.current_time
);
504 ret
= json_add_string (&jsobj
, "KDC server", ads
->auth
.kdc_server
);
509 ret
= json_add_int (&jsobj
, "Server time offset",
510 ads
->auth
.time_offset
);
515 ret
= json_add_int (&jsobj
, "Last machine account password change",
521 ret
= output_json(&jsobj
);
528 #else /* [HAVE_JANSSON] */
530 static int net_ads_info_json(ADS_STRUCT
*ads
)
532 d_fprintf(stderr
, _("JSON support not available\n"));
537 #endif /* [HAVE_JANSSON] */
541 static int net_ads_info(struct net_context
*c
, int argc
, const char **argv
)
543 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
544 ADS_STRUCT
*ads
= NULL
;
546 char addr
[INET6_ADDRSTRLEN
];
550 if (c
->display_usage
) {
555 _("Display information about an Active Directory "
557 TALLOC_FREE(tmp_ctx
);
561 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
562 if (!ADS_ERR_OK(status
)) {
563 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
567 if (!ads
|| !ads
->config
.realm
) {
568 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
572 /* Try to set the server's current time since we didn't do a full
573 TCP LDAP session initially */
575 if ( !ADS_ERR_OK(ads_current_time( ads
)) ) {
576 d_fprintf( stderr
, _("Failed to get server's current time!\n"));
580 ret
= net_ads_info_json(ads
);
584 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
586 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
588 d_printf(_("LDAP server: %s\n"), addr
);
589 d_printf(_("LDAP server name: %s\n"), ads
->config
.ldap_server_name
);
590 d_printf(_("Realm: %s\n"), ads
->config
.realm
);
591 d_printf(_("Bind Path: %s\n"), ads
->config
.bind_path
);
592 d_printf(_("LDAP port: %d\n"), ads
->ldap
.port
);
593 d_printf(_("Server time: %s\n"),
594 http_timestring(tmp_ctx
, ads
->config
.current_time
));
596 d_printf(_("KDC server: %s\n"), ads
->auth
.kdc_server
);
597 d_printf(_("Server time offset: %d\n"), ads
->auth
.time_offset
);
599 d_printf(_("Last machine account password change: %s\n"),
600 http_timestring(tmp_ctx
, pass_time
));
604 TALLOC_FREE(tmp_ctx
);
608 static ADS_STATUS
ads_startup_int(struct net_context
*c
,
609 bool only_own_domain
,
612 ADS_STRUCT
**ads_ret
)
614 ADS_STRUCT
*ads
= NULL
;
616 bool need_password
= false;
617 bool second_time
= false;
619 const char *realm
= NULL
;
620 bool tried_closest_dc
= false;
621 enum credentials_use_kerberos krb5_state
=
622 CRED_USE_KERBEROS_DISABLED
;
624 /* lp_realm() should be handled by a command line param,
625 However, the join requires that realm be set in smb.conf
626 and compares our realm with the remote server's so this is
627 ok until someone needs more flexibility */
632 if (only_own_domain
) {
635 realm
= assume_own_realm(c
);
638 ads
= ads_init(mem_ctx
,
640 c
->opt_target_workgroup
,
644 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
647 if (!c
->opt_user_name
) {
648 c
->opt_user_name
= "administrator";
651 if (c
->opt_user_specified
) {
652 need_password
= true;
656 if (!c
->opt_password
&& need_password
&& !c
->opt_machine_pass
) {
657 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
658 if (!c
->opt_password
) {
660 return ADS_ERROR(LDAP_NO_MEMORY
);
664 if (c
->opt_password
) {
665 use_in_memory_ccache();
666 TALLOC_FREE(ads
->auth
.password
);
667 ads
->auth
.password
= talloc_strdup(ads
, c
->opt_password
);
668 if (ads
->auth
.password
== NULL
) {
670 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
674 TALLOC_FREE(ads
->auth
.user_name
);
675 ads
->auth
.user_name
= talloc_strdup(ads
, c
->opt_user_name
);
676 if (ads
->auth
.user_name
== NULL
) {
678 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
681 ads
->auth
.flags
|= auth_flags
;
683 /* The ADS code will handle FIPS mode */
684 krb5_state
= cli_credentials_get_kerberos_state(c
->creds
);
685 switch (krb5_state
) {
686 case CRED_USE_KERBEROS_REQUIRED
:
687 ads
->auth
.flags
&= ~ADS_AUTH_DISABLE_KERBEROS
;
688 ads
->auth
.flags
&= ~ADS_AUTH_ALLOW_NTLMSSP
;
690 case CRED_USE_KERBEROS_DESIRED
:
691 ads
->auth
.flags
&= ~ADS_AUTH_DISABLE_KERBEROS
;
692 ads
->auth
.flags
|= ADS_AUTH_ALLOW_NTLMSSP
;
694 case CRED_USE_KERBEROS_DISABLED
:
695 ads
->auth
.flags
|= ADS_AUTH_DISABLE_KERBEROS
;
696 ads
->auth
.flags
|= ADS_AUTH_ALLOW_NTLMSSP
;
701 * If the username is of the form "name@realm",
702 * extract the realm and convert to upper case.
703 * This is only used to establish the connection.
705 if ((cp
= strchr_m(ads
->auth
.user_name
, '@'))!=0) {
707 TALLOC_FREE(ads
->auth
.realm
);
708 ads
->auth
.realm
= talloc_asprintf_strupper_m(ads
, "%s", cp
);
709 if (ads
->auth
.realm
== NULL
) {
711 return ADS_ERROR(LDAP_NO_MEMORY
);
715 status
= ads_connect(ads
);
717 if (!ADS_ERR_OK(status
)) {
719 if (NT_STATUS_EQUAL(ads_ntstatus(status
),
720 NT_STATUS_NO_LOGON_SERVERS
)) {
721 DEBUG(0,("ads_connect: %s\n", ads_errstr(status
)));
726 if (!need_password
&& !second_time
&& !(auth_flags
& ADS_AUTH_NO_BIND
)) {
727 need_password
= true;
736 /* when contacting our own domain, make sure we use the closest DC.
737 * This is done by reconnecting to ADS because only the first call to
738 * ads_connect will give us our own sitename */
740 if ((only_own_domain
|| !c
->opt_host
) && !tried_closest_dc
) {
742 tried_closest_dc
= true; /* avoid loop */
744 if (!ads_closest_dc(ads
)) {
746 namecache_delete(ads
->server
.realm
, 0x1C);
747 namecache_delete(ads
->server
.workgroup
, 0x1C);
755 *ads_ret
= talloc_move(mem_ctx
, &ads
);
759 ADS_STATUS
ads_startup(struct net_context
*c
,
760 bool only_own_domain
,
764 return ads_startup_int(c
, only_own_domain
, 0, mem_ctx
, ads
);
767 ADS_STATUS
ads_startup_nobind(struct net_context
*c
,
768 bool only_own_domain
,
772 return ads_startup_int(c
,
780 Check to see if connection can be made via ads.
781 ads_startup() stores the password in opt_password if it needs to so
782 that rpc or rap can use it without re-prompting.
784 static int net_ads_check_int(struct net_context
*c
,
786 const char *workgroup
,
789 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
794 ads
= ads_init(tmp_ctx
, realm
, workgroup
, host
, ADS_SASL_PLAIN
);
799 ads
->auth
.flags
|= ADS_AUTH_NO_BIND
;
801 status
= ads_connect(ads
);
802 if ( !ADS_ERR_OK(status
) ) {
808 TALLOC_FREE(tmp_ctx
);
812 int net_ads_check_our_domain(struct net_context
*c
)
814 return net_ads_check_int(c
, lp_realm(), lp_workgroup(), NULL
);
817 int net_ads_check(struct net_context
*c
)
819 return net_ads_check_int(c
, NULL
, c
->opt_workgroup
, c
->opt_host
);
823 determine the netbios workgroup name for a domain
825 static int net_ads_workgroup(struct net_context
*c
, int argc
, const char **argv
)
827 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
828 ADS_STRUCT
*ads
= NULL
;
830 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
834 if (c
->display_usage
) {
836 "net ads workgroup\n"
839 _("Print the workgroup name"));
840 TALLOC_FREE(tmp_ctx
);
844 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
845 if (!ADS_ERR_OK(status
)) {
846 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
850 if (!ads
->config
.realm
) {
851 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
852 if (ads
->config
.realm
== NULL
) {
853 d_fprintf(stderr
, _("Out of memory\n"));
856 ads
->ldap
.port
= 389;
859 ok
= ads_cldap_netlogon_5(tmp_ctx
,
860 &ads
->ldap
.ss
, ads
->server
.realm
, &reply
);
862 d_fprintf(stderr
, _("CLDAP query failed!\n"));
866 d_printf(_("Workgroup: %s\n"), reply
.domain_name
);
870 TALLOC_FREE(tmp_ctx
);
877 static bool usergrp_display(ADS_STRUCT
*ads
, char *field
, void **values
, void *data_area
)
879 char **disp_fields
= (char **) data_area
;
881 if (!field
) { /* must be end of record */
882 if (disp_fields
[0]) {
883 if (!strchr_m(disp_fields
[0], '$')) {
885 d_printf("%-21.21s %s\n",
886 disp_fields
[0], disp_fields
[1]);
888 d_printf("%s\n", disp_fields
[0]);
891 SAFE_FREE(disp_fields
[0]);
892 SAFE_FREE(disp_fields
[1]);
895 if (!values
) /* must be new field, indicate string field */
897 if (strcasecmp_m(field
, "sAMAccountName") == 0) {
898 disp_fields
[0] = SMB_STRDUP((char *) values
[0]);
900 if (strcasecmp_m(field
, "description") == 0)
901 disp_fields
[1] = SMB_STRDUP((char *) values
[0]);
905 static int net_ads_user_usage(struct net_context
*c
, int argc
, const char **argv
)
907 return net_user_usage(c
, argc
, argv
);
910 static int ads_user_add(struct net_context
*c
, int argc
, const char **argv
)
912 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
913 ADS_STRUCT
*ads
= NULL
;
916 LDAPMessage
*res
=NULL
;
920 if (argc
< 1 || c
->display_usage
) {
921 TALLOC_FREE(tmp_ctx
);
922 return net_ads_user_usage(c
, argc
, argv
);
925 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
926 if (!ADS_ERR_OK(status
)) {
930 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
931 if (!ADS_ERR_OK(status
)) {
932 d_fprintf(stderr
, _("ads_user_add: %s\n"), ads_errstr(status
));
936 if (ads_count_replies(ads
, res
)) {
937 d_fprintf(stderr
, _("ads_user_add: User %s already exists\n"),
942 if (c
->opt_container
) {
943 ou_str
= SMB_STRDUP(c
->opt_container
);
945 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
948 status
= ads_add_user_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
949 if (!ADS_ERR_OK(status
)) {
950 d_fprintf(stderr
, _("Could not add user %s: %s\n"), argv
[0],
955 /* if no password is to be set, we're done */
957 d_printf(_("User %s added\n"), argv
[0]);
962 /* try setting the password */
963 upn
= talloc_asprintf(tmp_ctx
,
971 status
= ads_krb5_set_password(ads
->auth
.kdc_server
, upn
, argv
[1],
972 ads
->auth
.time_offset
);
973 if (ADS_ERR_OK(status
)) {
974 d_printf(_("User %s added\n"), argv
[0]);
980 /* password didn't set, delete account */
981 d_fprintf(stderr
, _("Could not add user %s. "
982 "Error setting password %s\n"),
983 argv
[0], ads_errstr(status
));
985 ads_msgfree(ads
, res
);
988 status
=ads_find_user_acct(ads
, &res
, argv
[0]);
989 if (ADS_ERR_OK(status
)) {
990 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
991 ads_del_dn(ads
, userdn
);
996 ads_msgfree(ads
, res
);
998 TALLOC_FREE(tmp_ctx
);
1002 static int ads_user_info(struct net_context
*c
, int argc
, const char **argv
)
1004 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1005 ADS_STRUCT
*ads
= NULL
;
1007 LDAPMessage
*res
= NULL
;
1010 const char *attrs
[] = {"memberOf", "primaryGroupID", NULL
};
1011 char *searchstring
= NULL
;
1012 char **grouplist
= NULL
;
1013 char *primary_group
= NULL
;
1014 char *escaped_user
= NULL
;
1015 struct dom_sid primary_group_sid
;
1017 enum wbcSidType type
;
1019 if (argc
< 1 || c
->display_usage
) {
1020 TALLOC_FREE(tmp_ctx
);
1021 return net_ads_user_usage(c
, argc
, argv
);
1024 escaped_user
= escape_ldap_string(tmp_ctx
, argv
[0]);
1025 if (!escaped_user
) {
1027 _("ads_user_info: failed to escape user %s\n"),
1032 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1033 if (!ADS_ERR_OK(status
)) {
1037 searchstring
= talloc_asprintf(tmp_ctx
,
1038 "(sAMAccountName=%s)",
1040 if (searchstring
== NULL
) {
1044 status
= ads_search(ads
, &res
, searchstring
, attrs
);
1045 if (!ADS_ERR_OK(status
)) {
1046 d_fprintf(stderr
, _("ads_search: %s\n"), ads_errstr(status
));
1050 if (!ads_pull_uint32(ads
, res
, "primaryGroupID", &group_rid
)) {
1051 d_fprintf(stderr
, _("ads_pull_uint32 failed\n"));
1055 status
= ads_domain_sid(ads
, &primary_group_sid
);
1056 if (!ADS_ERR_OK(status
)) {
1057 d_fprintf(stderr
, _("ads_domain_sid: %s\n"), ads_errstr(status
));
1061 sid_append_rid(&primary_group_sid
, group_rid
);
1063 wbc_status
= wbcLookupSid((struct wbcDomainSid
*)&primary_group_sid
,
1064 NULL
, /* don't look up domain */
1067 if (!WBC_ERROR_IS_OK(wbc_status
)) {
1068 d_fprintf(stderr
, "wbcLookupSid: %s\n",
1069 wbcErrorString(wbc_status
));
1073 d_printf("%s\n", primary_group
);
1075 wbcFreeMemory(primary_group
);
1077 grouplist
= ldap_get_values((LDAP
*)ads
->ldap
.ld
,
1078 (LDAPMessage
*)res
, "memberOf");
1083 for (i
=0;grouplist
[i
];i
++) {
1084 groupname
= ldap_explode_dn(grouplist
[i
], 1);
1085 d_printf("%s\n", groupname
[0]);
1086 ldap_value_free(groupname
);
1088 ldap_value_free(grouplist
);
1093 ads_msgfree(ads
, res
);
1094 TALLOC_FREE(tmp_ctx
);
1098 static int ads_user_delete(struct net_context
*c
, int argc
, const char **argv
)
1100 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1101 ADS_STRUCT
*ads
= NULL
;
1103 LDAPMessage
*res
= NULL
;
1104 char *userdn
= NULL
;
1108 TALLOC_FREE(tmp_ctx
);
1109 return net_ads_user_usage(c
, argc
, argv
);
1112 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1113 if (!ADS_ERR_OK(status
)) {
1117 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1118 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1119 d_printf(_("User %s does not exist.\n"), argv
[0]);
1123 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1124 if (userdn
== NULL
) {
1128 status
= ads_del_dn(ads
, userdn
);
1129 if (!ADS_ERR_OK(status
)) {
1130 d_fprintf(stderr
, _("Error deleting user %s: %s\n"), argv
[0],
1131 ads_errstr(status
));
1135 d_printf(_("User %s deleted\n"), argv
[0]);
1139 ads_msgfree(ads
, res
);
1140 TALLOC_FREE(tmp_ctx
);
1144 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
1146 struct functable func
[] = {
1151 N_("Add an AD user"),
1152 N_("net ads user add\n"
1159 N_("Display information about an AD user"),
1160 N_("net ads user info\n"
1161 " Display information about an AD user")
1167 N_("Delete an AD user"),
1168 N_("net ads user delete\n"
1169 " Delete an AD user")
1171 {NULL
, NULL
, 0, NULL
, NULL
}
1173 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1174 ADS_STRUCT
*ads
= NULL
;
1176 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1177 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1178 char *disp_fields
[2] = {NULL
, NULL
};
1182 TALLOC_FREE(tmp_ctx
);
1183 return net_run_function(c
, argc
, argv
, "net ads user", func
);
1186 if (c
->display_usage
) {
1191 _("List AD users"));
1192 net_display_usage_from_functable(func
);
1193 TALLOC_FREE(tmp_ctx
);
1197 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1198 if (!ADS_ERR_OK(status
)) {
1202 if (c
->opt_long_list_entries
)
1203 d_printf(_("\nUser name Comment"
1204 "\n-----------------------------\n"));
1206 status
= ads_do_search_all_fn(ads
,
1207 ads
->config
.bind_path
,
1209 "(objectCategory=user)",
1210 c
->opt_long_list_entries
?
1211 longattrs
: shortattrs
,
1214 if (!ADS_ERR_OK(status
)) {
1220 TALLOC_FREE(tmp_ctx
);
1224 static int net_ads_group_usage(struct net_context
*c
, int argc
, const char **argv
)
1226 return net_group_usage(c
, argc
, argv
);
1229 static int ads_group_add(struct net_context
*c
, int argc
, const char **argv
)
1231 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1232 ADS_STRUCT
*ads
= NULL
;
1234 LDAPMessage
*res
= NULL
;
1236 char *ou_str
= NULL
;
1238 if (argc
< 1 || c
->display_usage
) {
1239 TALLOC_FREE(tmp_ctx
);
1240 return net_ads_group_usage(c
, argc
, argv
);
1243 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1244 if (!ADS_ERR_OK(status
)) {
1248 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1249 if (!ADS_ERR_OK(status
)) {
1250 d_fprintf(stderr
, _("ads_group_add: %s\n"), ads_errstr(status
));
1254 if (ads_count_replies(ads
, res
)) {
1255 d_fprintf(stderr
, _("ads_group_add: Group %s already exists\n"), argv
[0]);
1259 if (c
->opt_container
) {
1260 ou_str
= SMB_STRDUP(c
->opt_container
);
1262 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
1265 status
= ads_add_group_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
1266 if (!ADS_ERR_OK(status
)) {
1267 d_fprintf(stderr
, _("Could not add group %s: %s\n"), argv
[0],
1268 ads_errstr(status
));
1272 d_printf(_("Group %s added\n"), argv
[0]);
1276 ads_msgfree(ads
, res
);
1278 TALLOC_FREE(tmp_ctx
);
1282 static int ads_group_delete(struct net_context
*c
, int argc
, const char **argv
)
1284 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1285 ADS_STRUCT
*ads
= NULL
;
1287 LDAPMessage
*res
= NULL
;
1288 char *groupdn
= NULL
;
1291 if (argc
< 1 || c
->display_usage
) {
1292 TALLOC_FREE(tmp_ctx
);
1293 return net_ads_group_usage(c
, argc
, argv
);
1296 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1297 if (!ADS_ERR_OK(status
)) {
1301 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1302 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1303 d_printf(_("Group %s does not exist.\n"), argv
[0]);
1307 groupdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1308 if (groupdn
== NULL
) {
1312 status
= ads_del_dn(ads
, groupdn
);
1313 if (!ADS_ERR_OK(status
)) {
1314 d_fprintf(stderr
, _("Error deleting group %s: %s\n"), argv
[0],
1315 ads_errstr(status
));
1318 d_printf(_("Group %s deleted\n"), argv
[0]);
1322 ads_msgfree(ads
, res
);
1323 TALLOC_FREE(tmp_ctx
);
1327 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
1329 struct functable func
[] = {
1334 N_("Add an AD group"),
1335 N_("net ads group add\n"
1342 N_("Delete an AD group"),
1343 N_("net ads group delete\n"
1344 " Delete an AD group")
1346 {NULL
, NULL
, 0, NULL
, NULL
}
1348 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1349 ADS_STRUCT
*ads
= NULL
;
1351 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1352 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1353 char *disp_fields
[2] = {NULL
, NULL
};
1357 TALLOC_FREE(tmp_ctx
);
1358 return net_run_function(c
, argc
, argv
, "net ads group", func
);
1361 if (c
->display_usage
) {
1366 _("List AD groups"));
1367 net_display_usage_from_functable(func
);
1368 TALLOC_FREE(tmp_ctx
);
1372 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1373 if (!ADS_ERR_OK(status
)) {
1377 if (c
->opt_long_list_entries
)
1378 d_printf(_("\nGroup name Comment"
1379 "\n-----------------------------\n"));
1381 status
= ads_do_search_all_fn(ads
,
1382 ads
->config
.bind_path
,
1384 "(objectCategory=group)",
1385 c
->opt_long_list_entries
?
1386 longattrs
: shortattrs
,
1389 if (!ADS_ERR_OK(status
)) {
1395 TALLOC_FREE(tmp_ctx
);
1399 static int net_ads_status(struct net_context
*c
, int argc
, const char **argv
)
1401 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1402 ADS_STRUCT
*ads
= NULL
;
1404 LDAPMessage
*res
= NULL
;
1407 if (c
->display_usage
) {
1412 _("Display machine account details"));
1413 TALLOC_FREE(tmp_ctx
);
1417 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1418 if (!ADS_ERR_OK(status
)) {
1422 status
= ads_find_machine_acct(ads
, &res
, lp_netbios_name());
1423 if (!ADS_ERR_OK(status
)) {
1424 d_fprintf(stderr
, _("ads_find_machine_acct: %s\n"),
1425 ads_errstr(status
));
1429 if (ads_count_replies(ads
, res
) == 0) {
1430 d_fprintf(stderr
, _("No machine account for '%s' found\n"),
1439 ads_msgfree(ads
, res
);
1440 TALLOC_FREE(tmp_ctx
);
1444 /*******************************************************************
1445 Leave an AD domain. Windows XP disables the machine account.
1446 We'll try the same. The old code would do an LDAP delete.
1447 That only worked using the machine creds because added the machine
1448 with full control to the computer object's ACL.
1449 *******************************************************************/
1451 static int net_ads_leave(struct net_context
*c
, int argc
, const char **argv
)
1453 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1454 struct libnet_UnjoinCtx
*r
= NULL
;
1458 if (c
->display_usage
) {
1460 "net ads leave [--keep-account]\n"
1463 _("Leave an AD domain"));
1464 TALLOC_FREE(tmp_ctx
);
1469 d_fprintf(stderr
, _("No realm set, are we joined ?\n"));
1470 TALLOC_FREE(tmp_ctx
);
1474 if (!c
->opt_kerberos
) {
1475 use_in_memory_ccache();
1479 d_fprintf(stderr
, _("Could not initialise message context. "
1480 "Try running as root\n"));
1484 werr
= libnet_init_UnjoinCtx(tmp_ctx
, &r
);
1485 if (!W_ERROR_IS_OK(werr
)) {
1486 d_fprintf(stderr
, _("Could not initialise unjoin context.\n"));
1491 r
->in
.use_kerberos
= c
->opt_kerberos
;
1492 r
->in
.dc_name
= c
->opt_host
;
1493 r
->in
.domain_name
= lp_realm();
1494 r
->in
.admin_account
= c
->opt_user_name
;
1495 r
->in
.admin_password
= net_prompt_pass(c
, c
->opt_user_name
);
1496 r
->in
.modify_config
= lp_config_backend_is_registry();
1498 /* Try to delete it, but if that fails, disable it. The
1499 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1500 r
->in
.unjoin_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1501 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
;
1502 if (c
->opt_keep_account
) {
1503 r
->in
.delete_machine_account
= false;
1505 r
->in
.delete_machine_account
= true;
1508 r
->in
.msg_ctx
= c
->msg_ctx
;
1510 werr
= libnet_Unjoin(tmp_ctx
, r
);
1511 if (!W_ERROR_IS_OK(werr
)) {
1512 d_printf(_("Failed to leave domain: %s\n"),
1513 r
->out
.error_string
? r
->out
.error_string
:
1514 get_friendly_werror_msg(werr
));
1518 if (r
->out
.deleted_machine_account
) {
1519 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1520 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1525 /* We couldn't delete it - see if the disable succeeded. */
1526 if (r
->out
.disabled_machine_account
) {
1527 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1528 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1533 /* Based on what we requested, we shouldn't get here, but if
1534 we did, it means the secrets were removed, and therefore
1535 we have left the domain */
1536 d_fprintf(stderr
, _("Machine '%s' Left domain '%s'\n"),
1537 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1541 TALLOC_FREE(tmp_ctx
);
1545 static ADS_STATUS
net_ads_join_ok(struct net_context
*c
)
1547 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1548 ADS_STRUCT
*ads
= NULL
;
1551 struct sockaddr_storage dcip
;
1553 if (!secrets_init()) {
1554 DEBUG(1,("Failed to initialise secrets database\n"));
1555 TALLOC_FREE(tmp_ctx
);
1556 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
1559 net_use_krb_machine_account(c
);
1561 get_dc_name(lp_workgroup(), lp_realm(), dc_name
, &dcip
);
1563 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1564 if (!ADS_ERR_OK(status
)) {
1568 status
= ADS_ERROR_NT(NT_STATUS_OK
);
1570 TALLOC_FREE(tmp_ctx
);
1575 check that an existing join is OK
1577 int net_ads_testjoin(struct net_context
*c
, int argc
, const char **argv
)
1580 use_in_memory_ccache();
1582 if (c
->display_usage
) {
1584 "net ads testjoin\n"
1587 _("Test if the existing join is ok"));
1591 /* Display success or failure */
1592 status
= net_ads_join_ok(c
);
1593 if (!ADS_ERR_OK(status
)) {
1594 fprintf(stderr
, _("Join to domain is not valid: %s\n"),
1595 get_friendly_nt_error_msg(ads_ntstatus(status
)));
1599 printf(_("Join is OK\n"));
1603 /*******************************************************************
1604 Simple config checks before beginning the join
1605 ********************************************************************/
1607 static WERROR
check_ads_config( void )
1609 if (lp_server_role() != ROLE_DOMAIN_MEMBER
) {
1610 d_printf(_("Host is not configured as a member server.\n"));
1611 return WERR_INVALID_DOMAIN_ROLE
;
1614 if (strlen(lp_netbios_name()) > 15) {
1615 d_printf(_("Our netbios name can be at most 15 chars long, "
1616 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1617 (unsigned int)strlen(lp_netbios_name()));
1618 return WERR_INVALID_COMPUTERNAME
;
1621 if ( lp_security() == SEC_ADS
&& !*lp_realm()) {
1622 d_fprintf(stderr
, _("realm must be set in in %s for ADS "
1623 "join to succeed.\n"), get_dyn_CONFIGFILE());
1624 return WERR_INVALID_PARAMETER
;
1630 /*******************************************************************
1631 ********************************************************************/
1633 static int net_ads_join_usage(struct net_context
*c
, int argc
, const char **argv
)
1635 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1636 "Valid options:\n"));
1637 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1638 " The default is in the form netbiosname.dnsdomain\n"));
1639 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1640 " The default UPN is in the form host/netbiosname@REALM.\n"));
1641 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1642 " The OU string read from top to bottom without RDNs\n"
1643 " and delimited by a '/'.\n"
1644 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1645 " NB: A backslash '\\' is used as escape at multiple\n"
1646 " levels and may need to be doubled or even\n"
1647 " quadrupled. It is not used as a separator.\n"));
1648 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1649 " the join. The default password is random.\n"));
1650 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1651 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1652 " NB: osName and osVer must be specified together for\n"
1653 " either to take effect. The operatingSystemService\n"
1654 " attribute is then also set along with the two\n"
1655 " other attributes.\n"));
1656 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1657 " during the join.\n"
1658 " NB: If not specified then by default the samba\n"
1659 " version string is used instead.\n"));
1664 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
1666 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1667 struct libnet_JoinCtx
*r
= NULL
;
1668 const char *domain
= lp_realm();
1669 WERROR werr
= WERR_NERR_SETUPNOTJOINED
;
1670 bool createupn
= false;
1671 const char *dnshostname
= NULL
;
1672 const char *machineupn
= NULL
;
1673 const char *machine_password
= NULL
;
1674 const char *create_in_ou
= NULL
;
1676 const char *os_name
= NULL
;
1677 const char *os_version
= NULL
;
1678 const char *os_servicepack
= NULL
;
1679 bool modify_config
= lp_config_backend_is_registry();
1680 enum libnetjoin_JoinDomNameType domain_name_type
= JoinDomNameTypeDNS
;
1683 if (c
->display_usage
) {
1684 TALLOC_FREE(tmp_ctx
);
1685 return net_ads_join_usage(c
, argc
, argv
);
1688 if (!modify_config
) {
1689 werr
= check_ads_config();
1690 if (!W_ERROR_IS_OK(werr
)) {
1691 d_fprintf(stderr
, _("Invalid configuration. Exiting....\n"));
1696 if (!c
->opt_kerberos
) {
1697 use_in_memory_ccache();
1700 werr
= libnet_init_JoinCtx(tmp_ctx
, &r
);
1701 if (!W_ERROR_IS_OK(werr
)) {
1705 /* process additional command line args */
1707 for ( i
=0; i
<argc
; i
++ ) {
1708 if ( !strncasecmp_m(argv
[i
], "dnshostname", strlen("dnshostname")) ) {
1709 dnshostname
= get_string_param(argv
[i
]);
1711 else if ( !strncasecmp_m(argv
[i
], "createupn", strlen("createupn")) ) {
1713 machineupn
= get_string_param(argv
[i
]);
1715 else if ( !strncasecmp_m(argv
[i
], "createcomputer", strlen("createcomputer")) ) {
1716 if ( (create_in_ou
= get_string_param(argv
[i
])) == NULL
) {
1717 d_fprintf(stderr
, _("Please supply a valid OU path.\n"));
1718 werr
= WERR_INVALID_PARAMETER
;
1722 else if ( !strncasecmp_m(argv
[i
], "osName", strlen("osName")) ) {
1723 if ( (os_name
= get_string_param(argv
[i
])) == NULL
) {
1724 d_fprintf(stderr
, _("Please supply a operating system name.\n"));
1725 werr
= WERR_INVALID_PARAMETER
;
1729 else if ( !strncasecmp_m(argv
[i
], "osVer", strlen("osVer")) ) {
1730 if ( (os_version
= get_string_param(argv
[i
])) == NULL
) {
1731 d_fprintf(stderr
, _("Please supply a valid operating system version.\n"));
1732 werr
= WERR_INVALID_PARAMETER
;
1736 else if ( !strncasecmp_m(argv
[i
], "osServicePack", strlen("osServicePack")) ) {
1737 if ( (os_servicepack
= get_string_param(argv
[i
])) == NULL
) {
1738 d_fprintf(stderr
, _("Please supply a valid servicepack identifier.\n"));
1739 werr
= WERR_INVALID_PARAMETER
;
1743 else if ( !strncasecmp_m(argv
[i
], "machinepass", strlen("machinepass")) ) {
1744 if ( (machine_password
= get_string_param(argv
[i
])) == NULL
) {
1745 d_fprintf(stderr
, _("Please supply a valid password to set as trust account password.\n"));
1746 werr
= WERR_INVALID_PARAMETER
;
1751 if (strchr(domain
, '.') == NULL
) {
1752 domain_name_type
= JoinDomNameTypeUnknown
;
1754 domain_name_type
= JoinDomNameTypeDNS
;
1760 d_fprintf(stderr
, _("Please supply a valid domain name\n"));
1761 werr
= WERR_INVALID_PARAMETER
;
1766 d_fprintf(stderr
, _("Could not initialise message context. "
1767 "Try running as root\n"));
1768 werr
= WERR_ACCESS_DENIED
;
1772 /* Do the domain join here */
1774 r
->in
.domain_name
= domain
;
1775 r
->in
.domain_name_type
= domain_name_type
;
1776 r
->in
.create_upn
= createupn
;
1777 r
->in
.upn
= machineupn
;
1778 r
->in
.dnshostname
= dnshostname
;
1779 r
->in
.account_ou
= create_in_ou
;
1780 r
->in
.os_name
= os_name
;
1781 r
->in
.os_version
= os_version
;
1782 r
->in
.os_servicepack
= os_servicepack
;
1783 r
->in
.dc_name
= c
->opt_host
;
1784 r
->in
.admin_account
= c
->opt_user_name
;
1785 r
->in
.admin_password
= net_prompt_pass(c
, c
->opt_user_name
);
1786 r
->in
.machine_password
= machine_password
;
1788 r
->in
.use_kerberos
= c
->opt_kerberos
;
1789 r
->in
.modify_config
= modify_config
;
1790 r
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1791 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
|
1792 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
;
1793 r
->in
.msg_ctx
= c
->msg_ctx
;
1795 werr
= libnet_Join(tmp_ctx
, r
);
1796 if (W_ERROR_EQUAL(werr
, WERR_NERR_DCNOTFOUND
) &&
1797 strequal(domain
, lp_realm())) {
1798 r
->in
.domain_name
= lp_workgroup();
1799 r
->in
.domain_name_type
= JoinDomNameTypeNBT
;
1800 werr
= libnet_Join(tmp_ctx
, r
);
1802 if (!W_ERROR_IS_OK(werr
)) {
1806 /* Check the short name of the domain */
1808 if (!modify_config
&& !strequal(lp_workgroup(), r
->out
.netbios_domain_name
)) {
1809 d_printf(_("The workgroup in %s does not match the short\n"
1810 "domain name obtained from the server.\n"
1811 "Using the name [%s] from the server.\n"
1812 "You should set \"workgroup = %s\" in %s.\n"),
1813 get_dyn_CONFIGFILE(), r
->out
.netbios_domain_name
,
1814 r
->out
.netbios_domain_name
, get_dyn_CONFIGFILE());
1817 d_printf(_("Using short domain name -- %s\n"), r
->out
.netbios_domain_name
);
1819 if (r
->out
.dns_domain_name
) {
1820 d_printf(_("Joined '%s' to dns domain '%s'\n"), r
->in
.machine_name
,
1821 r
->out
.dns_domain_name
);
1823 d_printf(_("Joined '%s' to domain '%s'\n"), r
->in
.machine_name
,
1824 r
->out
.netbios_domain_name
);
1827 /* print out informative error string in case there is one */
1828 if (r
->out
.error_string
!= NULL
) {
1829 d_printf("%s\n", r
->out
.error_string
);
1833 * We try doing the dns update (if it was compiled in
1834 * and if it was not disabled on the command line).
1835 * If the dns update fails, we still consider the join
1836 * operation as succeeded if we came this far.
1838 if (!c
->opt_no_dns_updates
) {
1839 net_ads_join_dns_updates(c
, tmp_ctx
, r
);
1846 /* issue an overall failure message at the end. */
1847 d_printf(_("Failed to join domain: %s\n"),
1848 r
&& r
->out
.error_string
? r
->out
.error_string
:
1849 get_friendly_werror_msg(werr
));
1852 TALLOC_FREE(tmp_ctx
);
1857 /*******************************************************************
1858 ********************************************************************/
1860 static int net_ads_dns_register(struct net_context
*c
, int argc
, const char **argv
)
1862 #if defined(HAVE_KRB5)
1863 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1864 ADS_STRUCT
*ads
= NULL
;
1867 const char *hostname
= NULL
;
1868 const char **addrs_list
= NULL
;
1869 struct sockaddr_storage
*addrs
= NULL
;
1875 talloc_enable_leak_report();
1878 if (argc
<= 1 && lp_clustering() && lp_cluster_addresses() == NULL
) {
1879 d_fprintf(stderr
, _("Refusing DNS updates with automatic "
1880 "detection of addresses in a clustered "
1882 c
->display_usage
= true;
1885 if (c
->display_usage
) {
1887 "net ads dns register [hostname [IP [IP...]]]\n"
1890 _("Register hostname with DNS\n"));
1891 TALLOC_FREE(tmp_ctx
);
1900 num_addrs
= argc
- 1;
1901 addrs_list
= &argv
[1];
1902 } else if (lp_clustering()) {
1903 addrs_list
= lp_cluster_addresses();
1904 num_addrs
= str_list_length(addrs_list
);
1907 if (num_addrs
> 0) {
1908 addrs
= talloc_zero_array(tmp_ctx
,
1909 struct sockaddr_storage
,
1911 if (addrs
== NULL
) {
1912 d_fprintf(stderr
, _("Error allocating memory!\n"));
1917 for (count
= 0; count
< num_addrs
; count
++) {
1918 if (!interpret_string_addr(&addrs
[count
], addrs_list
[count
], 0)) {
1919 d_fprintf(stderr
, "%s '%s'.\n",
1920 _("Cannot interpret address"),
1926 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1927 if ( !ADS_ERR_OK(status
) ) {
1928 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
1932 ntstatus
= net_update_dns_ext(c
,
1939 if (!NT_STATUS_IS_OK(ntstatus
)) {
1940 d_fprintf( stderr
, _("DNS update failed!\n") );
1944 d_fprintf( stderr
, _("Successfully registered hostname with DNS\n") );
1948 TALLOC_FREE(tmp_ctx
);
1953 _("DNS update support not enabled at compile time!\n"));
1958 static int net_ads_dns_unregister(struct net_context
*c
,
1962 #if defined(HAVE_KRB5)
1963 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1964 ADS_STRUCT
*ads
= NULL
;
1967 const char *hostname
= NULL
;
1971 talloc_enable_leak_report();
1975 c
->display_usage
= true;
1978 if (c
->display_usage
) {
1980 "net ads dns unregister [hostname]\n"
1983 _("Remove all IP Address entires for a given\n"
1984 " hostname from the Active Directory server.\n"));
1985 TALLOC_FREE(tmp_ctx
);
1989 /* Get the hostname for un-registering */
1992 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1993 if ( !ADS_ERR_OK(status
) ) {
1994 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
1998 ntstatus
= net_update_dns_ext(c
,
2005 if (!NT_STATUS_IS_OK(ntstatus
)) {
2006 d_fprintf( stderr
, _("DNS update failed!\n") );
2010 d_fprintf( stderr
, _("Successfully un-registered hostname from DNS\n"));
2014 TALLOC_FREE(tmp_ctx
);
2019 _("DNS update support not enabled at compile time!\n"));
2025 static int net_ads_dns_async(struct net_context
*c
, int argc
, const char **argv
)
2027 size_t num_names
= 0;
2028 char **hostnames
= NULL
;
2030 struct samba_sockaddr
*addrs
= NULL
;
2033 if (argc
!= 1 || c
->display_usage
) {
2038 _("net ads dns async <name>\n"),
2039 _(" Async look up hostname from the DNS server\n"
2040 " hostname\tName to look up\n"));
2044 status
= ads_dns_lookup_a(talloc_tos(),
2049 if (!NT_STATUS_IS_OK(status
)) {
2050 d_printf("Looking up A record for %s got error %s\n",
2055 d_printf("Async A record lookup - got %u names for %s\n",
2056 (unsigned int)num_names
,
2058 for (i
= 0; i
< num_names
; i
++) {
2059 char addr_buf
[INET6_ADDRSTRLEN
];
2060 print_sockaddr(addr_buf
,
2063 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2069 #if defined(HAVE_IPV6)
2070 status
= ads_dns_lookup_aaaa(talloc_tos(),
2075 if (!NT_STATUS_IS_OK(status
)) {
2076 d_printf("Looking up AAAA record for %s got error %s\n",
2081 d_printf("Async AAAA record lookup - got %u names for %s\n",
2082 (unsigned int)num_names
,
2084 for (i
= 0; i
< num_names
; i
++) {
2085 char addr_buf
[INET6_ADDRSTRLEN
];
2086 print_sockaddr(addr_buf
,
2089 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2099 static int net_ads_dns(struct net_context
*c
, int argc
, const char *argv
[])
2101 struct functable func
[] = {
2104 net_ads_dns_register
,
2106 N_("Add host dns entry to AD"),
2107 N_("net ads dns register\n"
2108 " Add host dns entry to AD")
2112 net_ads_dns_unregister
,
2114 N_("Remove host dns entry from AD"),
2115 N_("net ads dns unregister\n"
2116 " Remove host dns entry from AD")
2123 N_("net ads dns async\n"
2124 " Look up host using async DNS")
2126 {NULL
, NULL
, 0, NULL
, NULL
}
2129 return net_run_function(c
, argc
, argv
, "net ads dns", func
);
2132 /*******************************************************************
2133 ********************************************************************/
2135 int net_ads_printer_usage(struct net_context
*c
, int argc
, const char **argv
)
2138 "\nnet ads printer search <printer>"
2139 "\n\tsearch for a printer in the directory\n"
2140 "\nnet ads printer info <printer> <server>"
2141 "\n\tlookup info in directory for printer on server"
2142 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2143 "\nnet ads printer publish <printername>"
2144 "\n\tpublish printer in directory"
2145 "\n\t(note: printer name is required)\n"
2146 "\nnet ads printer remove <printername>"
2147 "\n\tremove printer from directory"
2148 "\n\t(note: printer name is required)\n"));
2152 /*******************************************************************
2153 ********************************************************************/
2155 static int net_ads_printer_search(struct net_context
*c
,
2159 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2160 ADS_STRUCT
*ads
= NULL
;
2162 LDAPMessage
*res
= NULL
;
2165 if (c
->display_usage
) {
2167 "net ads printer search\n"
2170 _("List printers in the AD"));
2171 TALLOC_FREE(tmp_ctx
);
2175 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2176 if (!ADS_ERR_OK(status
)) {
2180 status
= ads_find_printers(ads
, &res
);
2181 if (!ADS_ERR_OK(status
)) {
2182 d_fprintf(stderr
, _("ads_find_printer: %s\n"),
2183 ads_errstr(status
));
2187 if (ads_count_replies(ads
, res
) == 0) {
2188 d_fprintf(stderr
, _("No results found\n"));
2196 ads_msgfree(ads
, res
);
2197 TALLOC_FREE(tmp_ctx
);
2201 static int net_ads_printer_info(struct net_context
*c
,
2205 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2206 ADS_STRUCT
*ads
= NULL
;
2208 const char *servername
= NULL
;
2209 const char *printername
= NULL
;
2210 LDAPMessage
*res
= NULL
;
2213 if (c
->display_usage
) {
2216 _("net ads printer info [printername [servername]]\n"
2217 " Display printer info from AD\n"
2218 " printername\tPrinter name or wildcard\n"
2219 " servername\tName of the print server\n"));
2220 TALLOC_FREE(tmp_ctx
);
2224 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2225 if (!ADS_ERR_OK(status
)) {
2230 printername
= argv
[0];
2236 servername
= argv
[1];
2238 servername
= lp_netbios_name();
2241 status
= ads_find_printer_on_server(ads
, &res
, printername
, servername
);
2242 if (!ADS_ERR_OK(status
)) {
2243 d_fprintf(stderr
, _("Server '%s' not found: %s\n"),
2244 servername
, ads_errstr(status
));
2248 if (ads_count_replies(ads
, res
) == 0) {
2249 d_fprintf(stderr
, _("Printer '%s' not found\n"), printername
);
2257 ads_msgfree(ads
, res
);
2258 TALLOC_FREE(tmp_ctx
);
2262 static int net_ads_printer_publish(struct net_context
*c
,
2266 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2267 ADS_STRUCT
*ads
= NULL
;
2269 const char *servername
= NULL
;
2270 const char *printername
= NULL
;
2271 struct cli_state
*cli
= NULL
;
2272 struct rpc_pipe_client
*pipe_hnd
= NULL
;
2273 struct sockaddr_storage server_ss
= { 0 };
2275 ADS_MODLIST mods
= NULL
;
2276 char *prt_dn
= NULL
;
2277 char *srv_dn
= NULL
;
2278 char **srv_cn
= NULL
;
2279 char *srv_cn_escaped
= NULL
;
2280 char *printername_escaped
= NULL
;
2281 LDAPMessage
*res
= NULL
;
2285 if (argc
< 1 || c
->display_usage
) {
2288 _("net ads printer publish <printername> [servername]\n"
2289 " Publish printer in AD\n"
2290 " printername\tName of the printer\n"
2291 " servername\tName of the print server\n"));
2292 TALLOC_FREE(tmp_ctx
);
2296 mods
= ads_init_mods(tmp_ctx
);
2298 d_fprintf(stderr
, _("Out of memory\n"));
2302 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2303 if (!ADS_ERR_OK(status
)) {
2307 printername
= argv
[0];
2310 servername
= argv
[1];
2312 servername
= lp_netbios_name();
2315 /* Get printer data from SPOOLSS */
2317 ok
= resolve_name(servername
, &server_ss
, 0x20, false);
2319 d_fprintf(stderr
, _("Could not find server %s\n"),
2324 cli_credentials_set_kerberos_state(c
->creds
,
2325 CRED_USE_KERBEROS_REQUIRED
,
2328 nt_status
= cli_full_connection_creds(&cli
, lp_netbios_name(), servername
,
2332 CLI_FULL_CONNECTION_IPC
);
2334 if (NT_STATUS_IS_ERR(nt_status
)) {
2335 d_fprintf(stderr
, _("Unable to open a connection to %s to "
2336 "obtain data for %s\n"),
2337 servername
, printername
);
2341 /* Publish on AD server */
2343 ads_find_machine_acct(ads
, &res
, servername
);
2345 if (ads_count_replies(ads
, res
) == 0) {
2346 d_fprintf(stderr
, _("Could not find machine account for server "
2352 srv_dn
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
2353 srv_cn
= ldap_explode_dn(srv_dn
, 1);
2355 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn
[0]);
2356 printername_escaped
= escape_rdn_val_string_alloc(printername
);
2357 if (!srv_cn_escaped
|| !printername_escaped
) {
2358 SAFE_FREE(srv_cn_escaped
);
2359 SAFE_FREE(printername_escaped
);
2360 d_fprintf(stderr
, _("Internal error, out of memory!"));
2364 prt_dn
= talloc_asprintf(tmp_ctx
,
2367 printername_escaped
,
2369 if (prt_dn
== NULL
) {
2370 SAFE_FREE(srv_cn_escaped
);
2371 SAFE_FREE(printername_escaped
);
2372 d_fprintf(stderr
, _("Internal error, out of memory!"));
2376 SAFE_FREE(srv_cn_escaped
);
2377 SAFE_FREE(printername_escaped
);
2379 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_spoolss
, &pipe_hnd
);
2380 if (!NT_STATUS_IS_OK(nt_status
)) {
2381 d_fprintf(stderr
, _("Unable to open a connection to the spoolss pipe on %s\n"),
2386 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd
,
2393 status
= ads_add_printer_entry(ads
, prt_dn
, tmp_ctx
, &mods
);
2394 if (!ADS_ERR_OK(status
)) {
2395 d_fprintf(stderr
, "ads_publish_printer: %s\n",
2396 ads_errstr(status
));
2400 d_printf("published printer\n");
2404 talloc_destroy(tmp_ctx
);
2409 static int net_ads_printer_remove(struct net_context
*c
,
2413 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2414 ADS_STRUCT
*ads
= NULL
;
2416 const char *servername
= NULL
;
2417 char *prt_dn
= NULL
;
2418 LDAPMessage
*res
= NULL
;
2421 if (argc
< 1 || c
->display_usage
) {
2424 _("net ads printer remove <printername> [servername]\n"
2425 " Remove a printer from the AD\n"
2426 " printername\tName of the printer\n"
2427 " servername\tName of the print server\n"));
2428 TALLOC_FREE(tmp_ctx
);
2432 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2433 if (!ADS_ERR_OK(status
)) {
2438 servername
= argv
[1];
2440 servername
= lp_netbios_name();
2443 status
= ads_find_printer_on_server(ads
, &res
, argv
[0], servername
);
2444 if (!ADS_ERR_OK(status
)) {
2445 d_fprintf(stderr
, _("ads_find_printer_on_server: %s\n"),
2446 ads_errstr(status
));
2450 if (ads_count_replies(ads
, res
) == 0) {
2451 d_fprintf(stderr
, _("Printer '%s' not found\n"), argv
[1]);
2455 prt_dn
= ads_get_dn(ads
, tmp_ctx
, res
);
2456 if (prt_dn
== NULL
) {
2457 d_fprintf(stderr
, _("Out of memory\n"));
2461 status
= ads_del_dn(ads
, prt_dn
);
2462 if (!ADS_ERR_OK(status
)) {
2463 d_fprintf(stderr
, _("ads_del_dn: %s\n"), ads_errstr(status
));
2469 ads_msgfree(ads
, res
);
2470 TALLOC_FREE(tmp_ctx
);
2474 static int net_ads_printer(struct net_context
*c
, int argc
, const char **argv
)
2476 struct functable func
[] = {
2479 net_ads_printer_search
,
2481 N_("Search for a printer"),
2482 N_("net ads printer search\n"
2483 " Search for a printer")
2487 net_ads_printer_info
,
2489 N_("Display printer information"),
2490 N_("net ads printer info\n"
2491 " Display printer information")
2495 net_ads_printer_publish
,
2497 N_("Publish a printer"),
2498 N_("net ads printer publish\n"
2499 " Publish a printer")
2503 net_ads_printer_remove
,
2505 N_("Delete a printer"),
2506 N_("net ads printer remove\n"
2507 " Delete a printer")
2509 {NULL
, NULL
, 0, NULL
, NULL
}
2512 return net_run_function(c
, argc
, argv
, "net ads printer", func
);
2516 static int net_ads_password(struct net_context
*c
, int argc
, const char **argv
)
2518 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2519 ADS_STRUCT
*ads
= NULL
;
2520 const char *auth_principal
= cli_credentials_get_username(c
->creds
);
2521 const char *auth_password
= cli_credentials_get_password(c
->creds
);
2522 const char *realm
= NULL
;
2523 char *new_password
= NULL
;
2525 char *prompt
= NULL
;
2526 const char *user
= NULL
;
2527 char pwd
[256] = {0};
2531 if (c
->display_usage
) {
2534 _("net ads password <username>\n"
2535 " Change password for user\n"
2536 " username\tName of user to change password for\n"));
2537 TALLOC_FREE(tmp_ctx
);
2541 if (auth_principal
== NULL
|| auth_password
== NULL
) {
2542 d_fprintf(stderr
, _("You must supply an administrator "
2543 "username/password\n"));
2544 TALLOC_FREE(tmp_ctx
);
2549 d_fprintf(stderr
, _("ERROR: You must say which username to "
2550 "change password for\n"));
2551 TALLOC_FREE(tmp_ctx
);
2555 if (strchr_m(argv
[0], '@')) {
2556 user
= talloc_strdup(tmp_ctx
, argv
[0]);
2558 user
= talloc_asprintf(tmp_ctx
, "%s@%s", argv
[0], lp_realm());
2561 d_fprintf(stderr
, _("Out of memory\n"));
2565 use_in_memory_ccache();
2566 chr
= strchr_m(auth_principal
, '@');
2573 /* use the realm so we can eventually change passwords for users
2574 in realms other than default */
2575 ads
= ads_init(tmp_ctx
,
2584 /* we don't actually need a full connect, but it's the easy way to
2585 fill in the KDC's addresss */
2588 if (!ads
->config
.realm
) {
2589 d_fprintf(stderr
, _("Didn't find the kerberos server!\n"));
2593 if (argv
[1] != NULL
) {
2594 new_password
= talloc_strdup(tmp_ctx
, argv
[1]);
2598 prompt
= talloc_asprintf(tmp_ctx
, _("Enter new password for %s:"), user
);
2599 if (prompt
== NULL
) {
2600 d_fprintf(stderr
, _("Out of memory\n"));
2604 rc
= samba_getpass(prompt
, pwd
, sizeof(pwd
), false, true);
2608 new_password
= talloc_strdup(tmp_ctx
, pwd
);
2609 memset(pwd
, '\0', sizeof(pwd
));
2612 if (new_password
== NULL
) {
2613 d_fprintf(stderr
, _("Out of memory\n"));
2617 status
= kerberos_set_password(ads
->auth
.kdc_server
,
2622 ads
->auth
.time_offset
);
2623 memset(new_password
, '\0', strlen(new_password
));
2624 if (!ADS_ERR_OK(status
)) {
2625 d_fprintf(stderr
, _("Password change failed: %s\n"),
2626 ads_errstr(status
));
2630 d_printf(_("Password change for %s completed.\n"), user
);
2634 TALLOC_FREE(tmp_ctx
);
2638 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
2640 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2641 ADS_STRUCT
*ads
= NULL
;
2642 char *host_principal
= NULL
;
2643 char *my_name
= NULL
;
2647 if (c
->display_usage
) {
2649 "net ads changetrustpw\n"
2652 _("Change the machine account's trust password"));
2653 TALLOC_FREE(tmp_ctx
);
2657 if (!secrets_init()) {
2658 DEBUG(1,("Failed to initialise secrets database\n"));
2662 net_use_krb_machine_account(c
);
2664 use_in_memory_ccache();
2666 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2667 if (!ADS_ERR_OK(status
)) {
2671 my_name
= talloc_asprintf_strlower_m(tmp_ctx
, "%s", lp_netbios_name());
2672 if (my_name
== NULL
) {
2673 d_fprintf(stderr
, _("Out of memory\n"));
2677 host_principal
= talloc_asprintf(tmp_ctx
, "%s$@%s", my_name
, ads
->config
.realm
);
2678 if (host_principal
== NULL
) {
2679 d_fprintf(stderr
, _("Out of memory\n"));
2683 d_printf(_("Changing password for principal: %s\n"), host_principal
);
2685 status
= ads_change_trust_account_password(ads
, host_principal
);
2686 if (!ADS_ERR_OK(status
)) {
2687 d_fprintf(stderr
, _("Password change failed: %s\n"), ads_errstr(status
));
2691 d_printf(_("Password change for principal %s succeeded.\n"), host_principal
);
2693 if (USE_SYSTEM_KEYTAB
) {
2694 d_printf(_("Attempting to update system keytab with new password.\n"));
2695 if (ads_keytab_create_default(ads
)) {
2696 d_printf(_("Failed to update system keytab.\n"));
2702 TALLOC_FREE(tmp_ctx
);
2708 help for net ads search
2710 static int net_ads_search_usage(struct net_context
*c
, int argc
, const char **argv
)
2713 "\nnet ads search <expression> <attributes...>\n"
2714 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2715 "The expression is a standard LDAP search expression, and the\n"
2716 "attributes are a list of LDAP fields to show in the results.\n\n"
2717 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2719 net_common_flags_usage(c
, argc
, argv
);
2725 general ADS search function. Useful in diagnosing problems in ADS
2727 static int net_ads_search(struct net_context
*c
, int argc
, const char **argv
)
2729 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2730 ADS_STRUCT
*ads
= NULL
;
2732 const char *ldap_exp
= NULL
;
2733 const char **attrs
= NULL
;
2734 LDAPMessage
*res
= NULL
;
2737 if (argc
< 1 || c
->display_usage
) {
2738 TALLOC_FREE(tmp_ctx
);
2739 return net_ads_search_usage(c
, argc
, argv
);
2742 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2743 if (!ADS_ERR_OK(status
)) {
2750 status
= ads_do_search_retry(ads
,
2751 ads
->config
.bind_path
,
2756 if (!ADS_ERR_OK(status
)) {
2757 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2761 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2763 /* dump the results */
2768 ads_msgfree(ads
, res
);
2769 TALLOC_FREE(tmp_ctx
);
2775 help for net ads search
2777 static int net_ads_dn_usage(struct net_context
*c
, int argc
, const char **argv
)
2780 "\nnet ads dn <dn> <attributes...>\n"
2781 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2782 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2783 "to show in the results\n\n"
2784 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2785 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2787 net_common_flags_usage(c
, argc
, argv
);
2793 general ADS search function. Useful in diagnosing problems in ADS
2795 static int net_ads_dn(struct net_context
*c
, int argc
, const char **argv
)
2797 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2798 ADS_STRUCT
*ads
= NULL
;
2800 const char *dn
= NULL
;
2801 const char **attrs
= NULL
;
2802 LDAPMessage
*res
= NULL
;
2805 if (argc
< 1 || c
->display_usage
) {
2806 TALLOC_FREE(tmp_ctx
);
2807 return net_ads_dn_usage(c
, argc
, argv
);
2810 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2811 if (!ADS_ERR_OK(status
)) {
2818 status
= ads_do_search_all(ads
,
2824 if (!ADS_ERR_OK(status
)) {
2825 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2829 d_printf("Got %d replies\n\n", ads_count_replies(ads
, res
));
2831 /* dump the results */
2836 ads_msgfree(ads
, res
);
2837 TALLOC_FREE(tmp_ctx
);
2842 help for net ads sid search
2844 static int net_ads_sid_usage(struct net_context
*c
, int argc
, const char **argv
)
2847 "\nnet ads sid <sid> <attributes...>\n"
2848 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2849 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2850 "to show in the results\n\n"
2851 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2853 net_common_flags_usage(c
, argc
, argv
);
2859 general ADS search function. Useful in diagnosing problems in ADS
2861 static int net_ads_sid(struct net_context
*c
, int argc
, const char **argv
)
2863 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2864 ADS_STRUCT
*ads
= NULL
;
2866 const char *sid_string
= NULL
;
2867 const char **attrs
= NULL
;
2868 LDAPMessage
*res
= NULL
;
2869 struct dom_sid sid
= { 0 };
2872 if (argc
< 1 || c
->display_usage
) {
2873 TALLOC_FREE(tmp_ctx
);
2874 return net_ads_sid_usage(c
, argc
, argv
);
2877 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2878 if (!ADS_ERR_OK(status
)) {
2882 sid_string
= argv
[0];
2885 if (!string_to_sid(&sid
, sid_string
)) {
2886 d_fprintf(stderr
, _("could not convert sid\n"));
2890 status
= ads_search_retry_sid(ads
, &res
, &sid
, attrs
);
2891 if (!ADS_ERR_OK(status
)) {
2892 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2896 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2898 /* dump the results */
2903 ads_msgfree(ads
, res
);
2904 TALLOC_FREE(tmp_ctx
);
2908 static int net_ads_keytab_flush(struct net_context
*c
,
2912 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2913 ADS_STRUCT
*ads
= NULL
;
2917 if (c
->display_usage
) {
2919 "net ads keytab flush\n"
2922 _("Delete the whole keytab"));
2923 TALLOC_FREE(tmp_ctx
);
2927 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
2928 net_use_krb_machine_account(c
);
2931 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2932 if (!ADS_ERR_OK(status
)) {
2936 ret
= ads_keytab_flush(ads
);
2938 TALLOC_FREE(tmp_ctx
);
2942 static int net_ads_keytab_add(struct net_context
*c
,
2947 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2948 ADS_STRUCT
*ads
= NULL
;
2953 if (c
->display_usage
) {
2956 _("net ads keytab add <principal> [principal ...]\n"
2957 " Add principals to local keytab\n"
2958 " principal\tKerberos principal to add to "
2960 TALLOC_FREE(tmp_ctx
);
2964 d_printf(_("Processing principals to add...\n"));
2966 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
2967 net_use_krb_machine_account(c
);
2970 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2971 if (!ADS_ERR_OK(status
)) {
2975 for (ret
= 0, i
= 0; i
< argc
; i
++) {
2976 ret
|= ads_keytab_add_entry(ads
, argv
[i
], update_ads
);
2979 TALLOC_FREE(tmp_ctx
);
2983 static int net_ads_keytab_add_default(struct net_context
*c
,
2987 return net_ads_keytab_add(c
, argc
, argv
, false);
2990 static int net_ads_keytab_add_update_ads(struct net_context
*c
,
2994 return net_ads_keytab_add(c
, argc
, argv
, true);
2997 static int net_ads_keytab_create(struct net_context
*c
, int argc
, const char **argv
)
2999 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3000 ADS_STRUCT
*ads
= NULL
;
3004 if (c
->display_usage
) {
3006 "net ads keytab create\n"
3009 _("Create new default keytab"));
3010 TALLOC_FREE(tmp_ctx
);
3014 if (!c
->opt_user_specified
&& c
->opt_password
== NULL
) {
3015 net_use_krb_machine_account(c
);
3018 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3019 if (!ADS_ERR_OK(status
)) {
3023 ret
= ads_keytab_create_default(ads
);
3025 TALLOC_FREE(tmp_ctx
);
3029 static int net_ads_keytab_list(struct net_context
*c
, int argc
, const char **argv
)
3031 const char *keytab
= NULL
;
3033 if (c
->display_usage
) {
3036 _("net ads keytab list [keytab]\n"
3037 " List a local keytab\n"
3038 " keytab\tKeytab to list\n"));
3046 return ads_keytab_list(keytab
);
3050 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
3052 struct functable func
[] = {
3055 net_ads_keytab_add_default
,
3057 N_("Add a service principal"),
3058 N_("net ads keytab add\n"
3059 " Add a service principal, updates keytab file only.")
3063 net_ads_keytab_add_update_ads
,
3065 N_("Add a service principal"),
3066 N_("net ads keytab add_update_ads\n"
3067 " Add a service principal, depending on the param passed may update ADS computer object in addition to the keytab file.")
3071 net_ads_keytab_create
,
3073 N_("Create a fresh keytab"),
3074 N_("net ads keytab create\n"
3075 " Create a fresh keytab or update existing one.")
3079 net_ads_keytab_flush
,
3081 N_("Remove all keytab entries"),
3082 N_("net ads keytab flush\n"
3083 " Remove all keytab entries")
3087 net_ads_keytab_list
,
3089 N_("List a keytab"),
3090 N_("net ads keytab list\n"
3093 {NULL
, NULL
, 0, NULL
, NULL
}
3096 if (!USE_KERBEROS_KEYTAB
) {
3097 d_printf(_("\nWarning: \"kerberos method\" must be set to a "
3098 "keytab method to use keytab functions.\n"));
3101 return net_run_function(c
, argc
, argv
, "net ads keytab", func
);
3104 static int net_ads_kerberos_renew(struct net_context
*c
, int argc
, const char **argv
)
3108 if (c
->display_usage
) {
3110 "net ads kerberos renew\n"
3113 _("Renew TGT from existing credential cache"));
3117 ret
= smb_krb5_renew_ticket(NULL
, NULL
, NULL
, NULL
);
3119 d_printf(_("failed to renew kerberos ticket: %s\n"),
3120 error_message(ret
));
3125 static int net_ads_kerberos_pac_common(struct net_context
*c
, int argc
, const char **argv
,
3126 struct PAC_DATA_CTR
**pac_data_ctr
)
3130 const char *impersonate_princ_s
= NULL
;
3131 const char *local_service
= NULL
;
3134 for (i
=0; i
<argc
; i
++) {
3135 if (strnequal(argv
[i
], "impersonate", strlen("impersonate"))) {
3136 impersonate_princ_s
= get_string_param(argv
[i
]);
3137 if (impersonate_princ_s
== NULL
) {
3141 if (strnequal(argv
[i
], "local_service", strlen("local_service"))) {
3142 local_service
= get_string_param(argv
[i
]);
3143 if (local_service
== NULL
) {
3149 if (local_service
== NULL
) {
3150 local_service
= talloc_asprintf(c
, "%s$@%s",
3151 lp_netbios_name(), lp_realm());
3152 if (local_service
== NULL
) {
3157 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
3159 status
= kerberos_return_pac(c
,
3168 2592000, /* one month */
3169 impersonate_princ_s
,
3174 if (!NT_STATUS_IS_OK(status
)) {
3175 d_printf(_("failed to query kerberos PAC: %s\n"),
3185 static int net_ads_kerberos_pac_dump(struct net_context
*c
, int argc
, const char **argv
)
3187 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3190 enum PAC_TYPE type
= 0;
3192 if (c
->display_usage
) {
3194 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3197 _("Dump the Kerberos PAC"));
3201 for (i
=0; i
<argc
; i
++) {
3202 if (strnequal(argv
[i
], "pac_buffer_type", strlen("pac_buffer_type"))) {
3203 type
= get_int_param(argv
[i
]);
3207 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3216 s
= NDR_PRINT_STRUCT_STRING(c
, PAC_DATA
,
3217 pac_data_ctr
->pac_data
);
3219 d_printf(_("The Pac: %s\n"), s
);
3226 num_buffers
= pac_data_ctr
->pac_data
->num_buffers
;
3228 for (i
=0; i
<num_buffers
; i
++) {
3232 if (pac_data_ctr
->pac_data
->buffers
[i
].type
!= type
) {
3236 s
= NDR_PRINT_UNION_STRING(c
, PAC_INFO
, type
,
3237 pac_data_ctr
->pac_data
->buffers
[i
].info
);
3239 d_printf(_("The Pac: %s\n"), s
);
3248 static int net_ads_kerberos_pac_save(struct net_context
*c
, int argc
, const char **argv
)
3250 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3251 char *filename
= NULL
;
3255 if (c
->display_usage
) {
3257 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3260 _("Save the Kerberos PAC"));
3264 for (i
=0; i
<argc
; i
++) {
3265 if (strnequal(argv
[i
], "filename", strlen("filename"))) {
3266 filename
= get_string_param(argv
[i
]);
3267 if (filename
== NULL
) {
3273 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3278 if (filename
== NULL
) {
3279 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3283 /* save the raw format */
3284 if (!file_save(filename
, pac_data_ctr
->pac_blob
.data
, pac_data_ctr
->pac_blob
.length
)) {
3285 d_printf(_("failed to save PAC in %s\n"), filename
);
3292 static int net_ads_kerberos_pac(struct net_context
*c
, int argc
, const char **argv
)
3294 struct functable func
[] = {
3297 net_ads_kerberos_pac_dump
,
3299 N_("Dump Kerberos PAC"),
3300 N_("net ads kerberos pac dump\n"
3301 " Dump a Kerberos PAC to stdout")
3305 net_ads_kerberos_pac_save
,
3307 N_("Save Kerberos PAC"),
3308 N_("net ads kerberos pac save\n"
3309 " Save a Kerberos PAC in a file")
3312 {NULL
, NULL
, 0, NULL
, NULL
}
3315 return net_run_function(c
, argc
, argv
, "net ads kerberos pac", func
);
3318 static int net_ads_kerberos_kinit(struct net_context
*c
, int argc
, const char **argv
)
3323 if (c
->display_usage
) {
3325 "net ads kerberos kinit\n"
3328 _("Get Ticket Granting Ticket (TGT) for the user"));
3332 c
->opt_password
= net_prompt_pass(c
, c
->opt_user_name
);
3334 ret
= kerberos_kinit_password_ext(c
->opt_user_name
,
3342 2592000, /* one month */
3348 d_printf(_("failed to kinit password: %s\n"),
3354 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
3356 struct functable func
[] = {
3359 net_ads_kerberos_kinit
,
3361 N_("Retrieve Ticket Granting Ticket (TGT)"),
3362 N_("net ads kerberos kinit\n"
3363 " Receive Ticket Granting Ticket (TGT)")
3367 net_ads_kerberos_renew
,
3369 N_("Renew Ticket Granting Ticket from credential cache"),
3370 N_("net ads kerberos renew\n"
3371 " Renew Ticket Granting Ticket (TGT) from "
3376 net_ads_kerberos_pac
,
3378 N_("Dump Kerberos PAC"),
3379 N_("net ads kerberos pac\n"
3380 " Dump Kerberos PAC")
3382 {NULL
, NULL
, 0, NULL
, NULL
}
3385 return net_run_function(c
, argc
, argv
, "net ads kerberos", func
);
3388 static int net_ads_setspn_list(struct net_context
*c
,
3392 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3393 ADS_STRUCT
*ads
= NULL
;
3398 if (c
->display_usage
) {
3401 _("net ads setspn list <machinename>\n"));
3402 TALLOC_FREE(tmp_ctx
);
3406 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3407 if (!ADS_ERR_OK(status
)) {
3412 ok
= ads_setspn_list(ads
, argv
[0]);
3414 ok
= ads_setspn_list(ads
, lp_netbios_name());
3419 TALLOC_FREE(tmp_ctx
);
3423 static int net_ads_setspn_add(struct net_context
*c
, int argc
, const char **argv
)
3425 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3426 ADS_STRUCT
*ads
= NULL
;
3431 if (c
->display_usage
|| argc
< 1) {
3434 _("net ads setspn add <machinename> SPN\n"));
3435 TALLOC_FREE(tmp_ctx
);
3439 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3440 if (!ADS_ERR_OK(status
)) {
3445 ok
= ads_setspn_add(ads
, argv
[0], argv
[1]);
3447 ok
= ads_setspn_add(ads
, lp_netbios_name(), argv
[0]);
3452 TALLOC_FREE(tmp_ctx
);
3456 static int net_ads_setspn_delete(struct net_context
*c
, int argc
, const char **argv
)
3458 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3459 ADS_STRUCT
*ads
= NULL
;
3464 if (c
->display_usage
|| argc
< 1) {
3467 _("net ads setspn delete <machinename> SPN\n"));
3468 TALLOC_FREE(tmp_ctx
);
3472 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3473 if (!ADS_ERR_OK(status
)) {
3478 ok
= ads_setspn_delete(ads
, argv
[0], argv
[1]);
3480 ok
= ads_setspn_delete(ads
, lp_netbios_name(), argv
[0]);
3485 TALLOC_FREE(tmp_ctx
);
3489 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
3491 struct functable func
[] = {
3494 net_ads_setspn_list
,
3496 N_("List Service Principal Names (SPN)"),
3497 N_("net ads setspn list machine\n"
3498 " List Service Principal Names (SPN)")
3504 N_("Add Service Principal Names (SPN)"),
3505 N_("net ads setspn add machine spn\n"
3506 " Add Service Principal Names (SPN)")
3510 net_ads_setspn_delete
,
3512 N_("Delete Service Principal Names (SPN)"),
3513 N_("net ads setspn delete machine spn\n"
3514 " Delete Service Principal Names (SPN)")
3516 {NULL
, NULL
, 0, NULL
, NULL
}
3519 return net_run_function(c
, argc
, argv
, "net ads setspn", func
);
3522 static int net_ads_enctype_lookup_account(struct net_context
*c
,
3524 const char *account
,
3526 const char **enctype_str
)
3529 const char *attrs
[] = {
3530 "msDS-SupportedEncryptionTypes",
3537 filter
= talloc_asprintf(c
, "(&(objectclass=user)(sAMAccountName=%s))",
3539 if (filter
== NULL
) {
3543 status
= ads_search(ads
, res
, filter
, attrs
);
3544 if (!ADS_ERR_OK(status
)) {
3545 d_printf(_("no account found with filter: %s\n"), filter
);
3549 count
= ads_count_replies(ads
, *res
);
3554 d_printf(_("no account found with filter: %s\n"), filter
);
3557 d_printf(_("multiple accounts found with filter: %s\n"), filter
);
3562 *enctype_str
= ads_pull_string(ads
, c
, *res
,
3563 "msDS-SupportedEncryptionTypes");
3564 if (*enctype_str
== NULL
) {
3565 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3575 static void net_ads_enctype_dump_enctypes(const char *username
,
3576 const char *enctype_str
)
3578 int enctypes
= atoi(enctype_str
);
3580 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3581 username
, enctypes
, enctypes
);
3583 printf("[%s] 0x%08x DES-CBC-CRC\n",
3584 enctypes
& ENC_CRC32
? "X" : " ",
3586 printf("[%s] 0x%08x DES-CBC-MD5\n",
3587 enctypes
& ENC_RSA_MD5
? "X" : " ",
3589 printf("[%s] 0x%08x RC4-HMAC\n",
3590 enctypes
& ENC_RC4_HMAC_MD5
? "X" : " ",
3592 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3593 enctypes
& ENC_HMAC_SHA1_96_AES128
? "X" : " ",
3594 ENC_HMAC_SHA1_96_AES128
);
3595 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3596 enctypes
& ENC_HMAC_SHA1_96_AES256
? "X" : " ",
3597 ENC_HMAC_SHA1_96_AES256
);
3600 static int net_ads_enctypes_list(struct net_context
*c
, int argc
, const char **argv
)
3602 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3604 ADS_STRUCT
*ads
= NULL
;
3605 LDAPMessage
*res
= NULL
;
3606 const char *str
= NULL
;
3609 if (c
->display_usage
|| (argc
< 1)) {
3611 "net ads enctypes list\n"
3614 _("List supported enctypes"));
3615 TALLOC_FREE(tmp_ctx
);
3619 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3620 if (!ADS_ERR_OK(status
)) {
3624 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3629 net_ads_enctype_dump_enctypes(argv
[0], str
);
3633 ads_msgfree(ads
, res
);
3634 TALLOC_FREE(tmp_ctx
);
3638 static int net_ads_enctypes_set(struct net_context
*c
, int argc
, const char **argv
)
3640 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3643 ADS_STRUCT
*ads
= NULL
;
3644 LDAPMessage
*res
= NULL
;
3645 const char *etype_list_str
= NULL
;
3646 const char *dn
= NULL
;
3647 ADS_MODLIST mods
= NULL
;
3648 uint32_t etype_list
;
3649 const char *str
= NULL
;
3651 if (c
->display_usage
|| argc
< 1) {
3653 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3656 _("Set supported enctypes"));
3657 TALLOC_FREE(tmp_ctx
);
3661 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3662 if (!ADS_ERR_OK(status
)) {
3666 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3671 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3676 etype_list
= ENC_CRC32
| ENC_RSA_MD5
| ENC_RC4_HMAC_MD5
;
3677 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
3678 etype_list
|= ENC_HMAC_SHA1_96_AES128
;
3680 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
3681 etype_list
|= ENC_HMAC_SHA1_96_AES256
;
3684 if (argv
[1] != NULL
) {
3685 sscanf(argv
[1], "%i", &etype_list
);
3688 etype_list_str
= talloc_asprintf(tmp_ctx
, "%d", etype_list
);
3689 if (!etype_list_str
) {
3693 mods
= ads_init_mods(tmp_ctx
);
3698 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes",
3700 if (!ADS_ERR_OK(status
)) {
3704 status
= ads_gen_mod(ads
, dn
, mods
);
3705 if (!ADS_ERR_OK(status
)) {
3706 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3707 ads_errstr(status
));
3711 ads_msgfree(ads
, res
);
3714 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3719 net_ads_enctype_dump_enctypes(argv
[0], str
);
3723 ads_msgfree(ads
, res
);
3724 TALLOC_FREE(tmp_ctx
);
3728 static int net_ads_enctypes_delete(struct net_context
*c
, int argc
, const char **argv
)
3730 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3733 ADS_STRUCT
*ads
= NULL
;
3734 LDAPMessage
*res
= NULL
;
3735 const char *dn
= NULL
;
3736 ADS_MODLIST mods
= NULL
;
3738 if (c
->display_usage
|| argc
< 1) {
3740 "net ads enctypes delete <sAMAccountName>\n"
3743 _("Delete supported enctypes"));
3744 TALLOC_FREE(tmp_ctx
);
3748 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3749 if (!ADS_ERR_OK(status
)) {
3753 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3758 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3763 mods
= ads_init_mods(tmp_ctx
);
3768 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes", NULL
);
3769 if (!ADS_ERR_OK(status
)) {
3773 status
= ads_gen_mod(ads
, dn
, mods
);
3774 if (!ADS_ERR_OK(status
)) {
3775 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3776 ads_errstr(status
));
3783 ads_msgfree(ads
, res
);
3784 TALLOC_FREE(tmp_ctx
);
3788 static int net_ads_enctypes(struct net_context
*c
, int argc
, const char **argv
)
3790 struct functable func
[] = {
3793 net_ads_enctypes_list
,
3795 N_("List the supported encryption types"),
3796 N_("net ads enctypes list\n"
3797 " List the supported encryption types")
3801 net_ads_enctypes_set
,
3803 N_("Set the supported encryption types"),
3804 N_("net ads enctypes set\n"
3805 " Set the supported encryption types")
3809 net_ads_enctypes_delete
,
3811 N_("Delete the supported encryption types"),
3812 N_("net ads enctypes delete\n"
3813 " Delete the supported encryption types")
3816 {NULL
, NULL
, 0, NULL
, NULL
}
3819 return net_run_function(c
, argc
, argv
, "net ads enctypes", func
);
3823 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
3825 struct functable func
[] = {
3830 N_("Display details on remote ADS server"),
3832 " Display details on remote ADS server")
3838 N_("Join the local machine to ADS realm"),
3840 " Join the local machine to ADS realm")
3846 N_("Validate machine account"),
3847 N_("net ads testjoin\n"
3848 " Validate machine account")
3854 N_("Remove the local machine from ADS"),
3855 N_("net ads leave\n"
3856 " Remove the local machine from ADS")
3862 N_("Display machine account details"),
3863 N_("net ads status\n"
3864 " Display machine account details")
3870 N_("List/modify users"),
3872 " List/modify users")
3878 N_("List/modify groups"),
3879 N_("net ads group\n"
3880 " List/modify groups")
3886 N_("Issue dynamic DNS update"),
3888 " Issue dynamic DNS update")
3894 N_("Change user passwords"),
3895 N_("net ads password\n"
3896 " Change user passwords")
3900 net_ads_changetrustpw
,
3902 N_("Change trust account password"),
3903 N_("net ads changetrustpw\n"
3904 " Change trust account password")
3910 N_("List/modify printer entries"),
3911 N_("net ads printer\n"
3912 " List/modify printer entries")
3918 N_("Issue LDAP search using filter"),
3919 N_("net ads search\n"
3920 " Issue LDAP search using filter")
3926 N_("Issue LDAP search by DN"),
3928 " Issue LDAP search by DN")
3934 N_("Issue LDAP search by SID"),
3936 " Issue LDAP search by SID")
3942 N_("Display workgroup name"),
3943 N_("net ads workgroup\n"
3944 " Display the workgroup name")
3950 N_("Perform CLDAP query on DC"),
3951 N_("net ads lookup\n"
3952 " Find the ADS DC using CLDAP lookups")
3958 N_("Manage local keytab file"),
3959 N_("net ads keytab\n"
3960 " Manage local keytab file")
3966 N_("Manage Service Principal Names (SPN)s"),
3967 N_("net ads spnset\n"
3968 " Manage Service Principal Names (SPN)s")
3974 N_("Manage group policy objects"),
3976 " Manage group policy objects")
3982 N_("Manage kerberos keytab"),
3983 N_("net ads kerberos\n"
3984 " Manage kerberos keytab")
3990 N_("List/modify supported encryption types"),
3991 N_("net ads enctypes\n"
3992 " List/modify enctypes")
3994 {NULL
, NULL
, 0, NULL
, NULL
}
3997 return net_run_function(c
, argc
, argv
, "net ads", func
);
4002 static int net_ads_noads(void)
4004 d_fprintf(stderr
, _("ADS support not compiled in\n"));
4008 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
4010 return net_ads_noads();
4013 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
4015 return net_ads_noads();
4018 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
4020 return net_ads_noads();
4023 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
4025 return net_ads_noads();
4028 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
4030 return net_ads_noads();
4033 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
4035 return net_ads_noads();
4038 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
4040 return net_ads_noads();
4043 int net_ads_gpo(struct net_context
*c
, int argc
, const char **argv
)
4045 return net_ads_noads();
4048 /* this one shouldn't display a message */
4049 int net_ads_check(struct net_context
*c
)
4054 int net_ads_check_our_domain(struct net_context
*c
)
4059 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
4061 return net_ads_noads();
4064 #endif /* HAVE_ADS */