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"
38 #include "../libcli/security/security.h"
39 #include "libsmb/libsmb.h"
40 #include "lib/param/loadparm.h"
41 #include "utils/net_dns.h"
42 #include "auth/kerberos/pac_utils.h"
43 #include "lib/util/string_wrappers.h"
44 #include "lib/util/util_file.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
,
124 "LOGON_SAM_LOGON_RESPONSE_EX",
125 sizeof(response_type
));
128 snprintf(response_type
,
129 sizeof(response_type
),
135 ret
= json_add_string(&jsobj
, "Information for Domain Controller",
141 ret
= json_add_string(&jsobj
, "Response Type", response_type
);
146 ret
= json_add_guid(&jsobj
, "GUID", &reply
->domain_uuid
);
151 ret
= json_add_bool(&flagsobj
, "Is a PDC",
152 reply
->server_type
& NBT_SERVER_PDC
);
157 ret
= json_add_bool(&flagsobj
, "Is a GC of the forest",
158 reply
->server_type
& NBT_SERVER_GC
);
163 ret
= json_add_bool(&flagsobj
, "Is an LDAP server",
164 reply
->server_type
& NBT_SERVER_LDAP
);
169 ret
= json_add_bool(&flagsobj
, "Supports DS",
170 reply
->server_type
& NBT_SERVER_DS
);
175 ret
= json_add_bool(&flagsobj
, "Is running a KDC",
176 reply
->server_type
& NBT_SERVER_KDC
);
181 ret
= json_add_bool(&flagsobj
, "Is running time services",
182 reply
->server_type
& NBT_SERVER_TIMESERV
);
187 ret
= json_add_bool(&flagsobj
, "Is the closest DC",
188 reply
->server_type
& NBT_SERVER_CLOSEST
);
193 ret
= json_add_bool(&flagsobj
, "Is writable",
194 reply
->server_type
& NBT_SERVER_WRITABLE
);
199 ret
= json_add_bool(&flagsobj
, "Has a hardware clock",
200 reply
->server_type
& NBT_SERVER_GOOD_TIMESERV
);
205 ret
= json_add_bool(&flagsobj
,
206 "Is a non-domain NC serviced by LDAP server",
207 reply
->server_type
& NBT_SERVER_NDNC
);
213 (&flagsobj
, "Is NT6 DC that has some secrets",
214 reply
->server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
);
220 (&flagsobj
, "Is NT6 DC that has all secrets",
221 reply
->server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
);
226 ret
= json_add_bool(&flagsobj
, "Runs Active Directory Web Services",
227 reply
->server_type
& NBT_SERVER_ADS_WEB_SERVICE
);
232 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2012 or later",
233 reply
->server_type
& NBT_SERVER_DS_8
);
238 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2012R2 or later",
239 reply
->server_type
& NBT_SERVER_DS_9
);
244 ret
= json_add_bool(&flagsobj
, "Runs on Windows 2016 or later",
245 reply
->server_type
& NBT_SERVER_DS_10
);
250 ret
= json_add_bool(&flagsobj
, "Has a DNS name",
251 reply
->server_type
& NBT_SERVER_HAS_DNS_NAME
);
256 ret
= json_add_bool(&flagsobj
, "Is a default NC",
257 reply
->server_type
& NBT_SERVER_IS_DEFAULT_NC
);
262 ret
= json_add_bool(&flagsobj
, "Is the forest root",
263 reply
->server_type
& NBT_SERVER_FOREST_ROOT
);
268 ret
= json_add_string(&jsobj
, "Forest", reply
->forest
);
273 ret
= json_add_string(&jsobj
, "Domain", reply
->dns_domain
);
278 ret
= json_add_string(&jsobj
, "Domain Controller", reply
->pdc_dns_name
);
284 ret
= json_add_string(&jsobj
, "Pre-Win2k Domain", reply
->domain_name
);
289 ret
= json_add_string(&jsobj
, "Pre-Win2k Hostname", reply
->pdc_name
);
294 if (*reply
->user_name
) {
295 ret
= json_add_string(&jsobj
, "User name", reply
->user_name
);
301 ret
= json_add_string(&jsobj
, "Server Site Name", reply
->server_site
);
306 ret
= json_add_string(&jsobj
, "Client Site Name", reply
->client_site
);
311 ret
= json_add_int(&jsobj
, "NT Version", reply
->nt_version
);
316 ret
= json_add_int(&jsobj
, "LMNT Token", reply
->lmnt_token
);
321 ret
= json_add_int(&jsobj
, "LM20 Token", reply
->lm20_token
);
326 ret
= json_add_object(&jsobj
, "Flags", &flagsobj
);
331 ret
= output_json(&jsobj
);
332 json_free(&jsobj
); /* frees flagsobj recursively */
337 json_free(&flagsobj
);
343 #else /* [HAVE_JANSSON] */
345 static int net_ads_cldap_netlogon_json
348 const struct NETLOGON_SAM_LOGON_RESPONSE_EX
* reply
)
350 d_fprintf(stderr
, _("JSON support not available\n"));
355 #endif /* [HAVE_JANSSON] */
358 do a cldap netlogon query
360 static int net_ads_cldap_netlogon(struct net_context
*c
, ADS_STRUCT
*ads
)
362 char addr
[INET6_ADDRSTRLEN
];
363 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
366 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
368 ok
= ads_cldap_netlogon_5(
369 talloc_tos(), &ads
->ldap
.ss
, ads
->server
.realm
, 0, &reply
);
371 d_fprintf(stderr
, _("CLDAP query failed!\n"));
376 return net_ads_cldap_netlogon_json(ads
, addr
, &reply
);
379 d_printf(_("Information for Domain Controller: %s\n\n"),
382 d_printf(_("Response Type: "));
383 switch (reply
.command
) {
384 case LOGON_SAM_LOGON_USER_UNKNOWN_EX
:
385 d_printf("LOGON_SAM_LOGON_USER_UNKNOWN_EX\n");
387 case LOGON_SAM_LOGON_RESPONSE_EX
:
388 d_printf("LOGON_SAM_LOGON_RESPONSE_EX\n");
391 d_printf("0x%x\n", reply
.command
);
395 d_printf(_("GUID: %s\n"), GUID_string(talloc_tos(),&reply
.domain_uuid
));
397 d_printf(_("Flags:\n"
399 "\tIs a GC of the forest: %s\n"
400 "\tIs an LDAP server: %s\n"
401 "\tSupports DS: %s\n"
402 "\tIs running a KDC: %s\n"
403 "\tIs running time services: %s\n"
404 "\tIs the closest DC: %s\n"
405 "\tIs writable: %s\n"
406 "\tHas a hardware clock: %s\n"
407 "\tIs a non-domain NC serviced by LDAP server: %s\n"
408 "\tIs NT6 DC that has some secrets: %s\n"
409 "\tIs NT6 DC that has all secrets: %s\n"
410 "\tRuns Active Directory Web Services: %s\n"
411 "\tRuns on Windows 2012 or later: %s\n"
412 "\tRuns on Windows 2012R2 or later: %s\n"
413 "\tRuns on Windows 2016 or later: %s\n"
414 "\tHas a DNS name: %s\n"
415 "\tIs a default NC: %s\n"
416 "\tIs the forest root: %s\n"),
417 (reply
.server_type
& NBT_SERVER_PDC
) ? _("yes") : _("no"),
418 (reply
.server_type
& NBT_SERVER_GC
) ? _("yes") : _("no"),
419 (reply
.server_type
& NBT_SERVER_LDAP
) ? _("yes") : _("no"),
420 (reply
.server_type
& NBT_SERVER_DS
) ? _("yes") : _("no"),
421 (reply
.server_type
& NBT_SERVER_KDC
) ? _("yes") : _("no"),
422 (reply
.server_type
& NBT_SERVER_TIMESERV
) ? _("yes") : _("no"),
423 (reply
.server_type
& NBT_SERVER_CLOSEST
) ? _("yes") : _("no"),
424 (reply
.server_type
& NBT_SERVER_WRITABLE
) ? _("yes") : _("no"),
425 (reply
.server_type
& NBT_SERVER_GOOD_TIMESERV
) ? _("yes") : _("no"),
426 (reply
.server_type
& NBT_SERVER_NDNC
) ? _("yes") : _("no"),
427 (reply
.server_type
& NBT_SERVER_SELECT_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
428 (reply
.server_type
& NBT_SERVER_FULL_SECRET_DOMAIN_6
) ? _("yes") : _("no"),
429 (reply
.server_type
& NBT_SERVER_ADS_WEB_SERVICE
) ? _("yes") : _("no"),
430 (reply
.server_type
& NBT_SERVER_DS_8
) ? _("yes") : _("no"),
431 (reply
.server_type
& NBT_SERVER_DS_9
) ? _("yes") : _("no"),
432 (reply
.server_type
& NBT_SERVER_DS_10
) ? _("yes") : _("no"),
433 (reply
.server_type
& NBT_SERVER_HAS_DNS_NAME
) ? _("yes") : _("no"),
434 (reply
.server_type
& NBT_SERVER_IS_DEFAULT_NC
) ? _("yes") : _("no"),
435 (reply
.server_type
& NBT_SERVER_FOREST_ROOT
) ? _("yes") : _("no"));
438 printf(_("Forest: %s\n"), reply
.forest
);
439 printf(_("Domain: %s\n"), reply
.dns_domain
);
440 printf(_("Domain Controller: %s\n"), reply
.pdc_dns_name
);
442 printf(_("Pre-Win2k Domain: %s\n"), reply
.domain_name
);
443 printf(_("Pre-Win2k Hostname: %s\n"), reply
.pdc_name
);
445 if (*reply
.user_name
) printf(_("User name: %s\n"), reply
.user_name
);
447 printf(_("Server Site Name: %s\n"), reply
.server_site
);
448 printf(_("Client Site Name: %s\n"), reply
.client_site
);
450 d_printf(_("NT Version: %d\n"), reply
.nt_version
);
451 d_printf(_("LMNT Token: %.2x\n"), reply
.lmnt_token
);
452 d_printf(_("LM20 Token: %.2x\n"), reply
.lm20_token
);
458 this implements the CLDAP based netlogon lookup requests
459 for finding the domain controller of a ADS domain
461 static int net_ads_lookup(struct net_context
*c
, int argc
, const char **argv
)
463 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
464 ADS_STRUCT
*ads
= NULL
;
468 if (c
->display_usage
) {
473 _("Find the ADS DC using CLDAP lookup.\n"));
474 TALLOC_FREE(tmp_ctx
);
478 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
479 if (!ADS_ERR_OK(status
)) {
480 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
484 if (!ads
->config
.realm
) {
485 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
486 if (ads
->config
.realm
== NULL
) {
487 d_fprintf(stderr
, _("Out of memory\n"));
490 ads
->ldap
.port
= 389;
493 ret
= net_ads_cldap_netlogon(c
, ads
);
495 TALLOC_FREE(tmp_ctx
);
502 static int net_ads_info_json(ADS_STRUCT
*ads
)
505 char addr
[INET6_ADDRSTRLEN
];
507 struct json_object jsobj
= json_new_object();
509 if (json_is_invalid(&jsobj
)) {
510 d_fprintf(stderr
, _("error setting up JSON value\n"));
515 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
517 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
519 ret
= json_add_string (&jsobj
, "LDAP server", addr
);
524 ret
= json_add_string (&jsobj
, "LDAP server name",
525 ads
->config
.ldap_server_name
);
530 ret
= json_add_string (&jsobj
, "Workgroup", ads
->config
.workgroup
);
535 ret
= json_add_string (&jsobj
, "Realm", ads
->config
.realm
);
540 ret
= json_add_string (&jsobj
, "Bind Path", ads
->config
.bind_path
);
545 ret
= json_add_int (&jsobj
, "LDAP port", ads
->ldap
.port
);
550 ret
= json_add_int (&jsobj
, "Server time", ads
->config
.current_time
);
555 ret
= json_add_string (&jsobj
, "KDC server", ads
->auth
.kdc_server
);
560 ret
= json_add_int (&jsobj
, "Server time offset",
561 ads
->config
.time_offset
);
566 ret
= json_add_int (&jsobj
, "Last machine account password change",
572 ret
= output_json(&jsobj
);
579 #else /* [HAVE_JANSSON] */
581 static int net_ads_info_json(ADS_STRUCT
*ads
)
583 d_fprintf(stderr
, _("JSON support not available\n"));
588 #endif /* [HAVE_JANSSON] */
592 static int net_ads_info(struct net_context
*c
, int argc
, const char **argv
)
594 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
595 ADS_STRUCT
*ads
= NULL
;
597 char addr
[INET6_ADDRSTRLEN
];
601 if (c
->display_usage
) {
606 _("Display information about an Active Directory "
608 TALLOC_FREE(tmp_ctx
);
612 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
613 if (!ADS_ERR_OK(status
)) {
614 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
618 if (!ads
|| !ads
->config
.realm
) {
619 d_fprintf(stderr
, _("Didn't find the ldap server!\n"));
623 /* Try to set the server's current time since we didn't do a full
624 TCP LDAP session initially */
626 if ( !ADS_ERR_OK(ads_current_time( ads
)) ) {
627 d_fprintf( stderr
, _("Failed to get server's current time!\n"));
631 ret
= net_ads_info_json(ads
);
635 pass_time
= secrets_fetch_pass_last_set_time(ads
->server
.workgroup
);
637 print_sockaddr(addr
, sizeof(addr
), &ads
->ldap
.ss
);
639 d_printf(_("LDAP server: %s\n"), addr
);
640 d_printf(_("LDAP server name: %s\n"), ads
->config
.ldap_server_name
);
641 d_printf(_("Workgroup: %s\n"), ads
->config
.workgroup
);
642 d_printf(_("Realm: %s\n"), ads
->config
.realm
);
643 d_printf(_("Bind Path: %s\n"), ads
->config
.bind_path
);
644 d_printf(_("LDAP port: %d\n"), ads
->ldap
.port
);
645 d_printf(_("Server time: %s\n"),
646 http_timestring(tmp_ctx
, ads
->config
.current_time
));
648 d_printf(_("KDC server: %s\n"), ads
->auth
.kdc_server
);
649 d_printf(_("Server time offset: %d\n"), ads
->config
.time_offset
);
651 d_printf(_("Last machine account password change: %s\n"),
652 http_timestring(tmp_ctx
, pass_time
));
656 TALLOC_FREE(tmp_ctx
);
660 static ADS_STATUS
ads_startup_int(struct net_context
*c
,
661 bool only_own_domain
,
664 ADS_STRUCT
**ads_ret
)
666 ADS_STRUCT
*ads
= NULL
;
668 const char *realm
= NULL
;
669 const char *workgroup
= NULL
;
670 bool tried_closest_dc
= false;
672 /* lp_realm() should be handled by a command line param,
673 However, the join requires that realm be set in smb.conf
674 and compares our realm with the remote server's so this is
675 ok until someone needs more flexibility */
680 if (only_own_domain
) {
682 workgroup
= lp_workgroup();
684 realm
= assume_own_realm(c
);
685 workgroup
= c
->opt_target_workgroup
;
688 ads
= ads_init(mem_ctx
,
694 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY
);
697 ads
->auth
.flags
|= auth_flags
;
699 if (auth_flags
& ADS_AUTH_NO_BIND
) {
700 status
= ads_connect_cldap_only(ads
);
701 if (!ADS_ERR_OK(status
)) {
702 DBG_ERR("ads_connect_cldap_only: %s\n",
708 status
= ads_connect_creds(ads
, c
->creds
);
709 if (!ADS_ERR_OK(status
)) {
710 DBG_ERR("ads_connect_creds: %s\n",
717 /* when contacting our own domain, make sure we use the closest DC.
718 * This is done by reconnecting to ADS because only the first call to
719 * ads_connect will give us our own sitename */
721 if ((only_own_domain
|| !c
->opt_host
) && !tried_closest_dc
) {
723 tried_closest_dc
= true; /* avoid loop */
725 if (!ads_closest_dc(ads
)) {
727 namecache_delete(ads
->server
.realm
, 0x1C);
728 namecache_delete(ads
->server
.workgroup
, 0x1C);
736 *ads_ret
= talloc_move(mem_ctx
, &ads
);
740 ADS_STATUS
ads_startup(struct net_context
*c
,
741 bool only_own_domain
,
745 return ads_startup_int(c
, only_own_domain
, 0, mem_ctx
, ads
);
748 ADS_STATUS
ads_startup_nobind(struct net_context
*c
,
749 bool only_own_domain
,
753 return ads_startup_int(c
,
761 Check to see if connection can be made via ads.
762 ads_startup() stores the password in opt_password if it needs to so
763 that rpc or rap can use it without re-prompting.
765 static int net_ads_check_int(struct net_context
*c
,
767 const char *workgroup
,
770 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
775 ads
= ads_init(tmp_ctx
, realm
, workgroup
, host
, ADS_SASL_PLAIN
);
780 status
= ads_connect_cldap_only(ads
);
781 if (!ADS_ERR_OK(status
)) {
787 TALLOC_FREE(tmp_ctx
);
791 int net_ads_check_our_domain(struct net_context
*c
)
793 return net_ads_check_int(c
, lp_realm(), lp_workgroup(), NULL
);
796 int net_ads_check(struct net_context
*c
)
798 return net_ads_check_int(c
, NULL
, c
->opt_workgroup
, c
->opt_host
);
802 determine the netbios workgroup name for a domain
804 static int net_ads_workgroup(struct net_context
*c
, int argc
, const char **argv
)
806 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
807 ADS_STRUCT
*ads
= NULL
;
809 struct NETLOGON_SAM_LOGON_RESPONSE_EX reply
;
813 if (c
->display_usage
) {
815 "net ads workgroup\n"
818 _("Print the workgroup name"));
819 TALLOC_FREE(tmp_ctx
);
823 status
= ads_startup_nobind(c
, false, tmp_ctx
, &ads
);
824 if (!ADS_ERR_OK(status
)) {
825 d_fprintf(stderr
, _("Didn't find the cldap server!\n"));
829 if (!ads
->config
.realm
) {
830 ads
->config
.realm
= talloc_strdup(ads
, c
->opt_target_workgroup
);
831 if (ads
->config
.realm
== NULL
) {
832 d_fprintf(stderr
, _("Out of memory\n"));
835 ads
->ldap
.port
= 389;
838 ok
= ads_cldap_netlogon_5(
839 tmp_ctx
, &ads
->ldap
.ss
, ads
->server
.realm
, 0, &reply
);
841 d_fprintf(stderr
, _("CLDAP query failed!\n"));
845 d_printf(_("Workgroup: %s\n"), reply
.domain_name
);
849 TALLOC_FREE(tmp_ctx
);
856 static bool usergrp_display(ADS_STRUCT
*ads
, char *field
, void **values
, void *data_area
)
858 char **disp_fields
= (char **) data_area
;
860 if (!field
) { /* must be end of record */
861 if (disp_fields
[0]) {
862 if (!strchr_m(disp_fields
[0], '$')) {
864 d_printf("%-21.21s %s\n",
865 disp_fields
[0], disp_fields
[1]);
867 d_printf("%s\n", disp_fields
[0]);
870 SAFE_FREE(disp_fields
[0]);
871 SAFE_FREE(disp_fields
[1]);
874 if (!values
) /* must be new field, indicate string field */
876 if (strcasecmp_m(field
, "sAMAccountName") == 0) {
877 disp_fields
[0] = SMB_STRDUP((char *) values
[0]);
879 if (strcasecmp_m(field
, "description") == 0)
880 disp_fields
[1] = SMB_STRDUP((char *) values
[0]);
884 static int net_ads_user_usage(struct net_context
*c
, int argc
, const char **argv
)
886 return net_user_usage(c
, argc
, argv
);
889 static int ads_user_add(struct net_context
*c
, int argc
, const char **argv
)
891 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
892 ADS_STRUCT
*ads
= NULL
;
895 LDAPMessage
*res
=NULL
;
896 char *creds_ccname
= NULL
;
901 if (argc
< 1 || c
->display_usage
) {
902 TALLOC_FREE(tmp_ctx
);
903 return net_ads_user_usage(c
, argc
, argv
);
908 * We rely on ads_krb5_set_password() to
909 * set the password below.
911 * We could pass the password to
912 * ads_add_user_acct()
913 * and set the unicodePwd attribute there...
915 cli_credentials_set_kerberos_state(c
->creds
,
916 CRED_USE_KERBEROS_REQUIRED
,
920 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
921 if (!ADS_ERR_OK(status
)) {
925 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
926 if (!ADS_ERR_OK(status
)) {
927 d_fprintf(stderr
, _("ads_user_add: %s\n"), ads_errstr(status
));
931 if (ads_count_replies(ads
, res
)) {
932 d_fprintf(stderr
, _("ads_user_add: User %s already exists\n"),
937 if (c
->opt_container
) {
938 ou_str
= SMB_STRDUP(c
->opt_container
);
940 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
943 status
= ads_add_user_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
944 if (!ADS_ERR_OK(status
)) {
945 d_fprintf(stderr
, _("Could not add user %s: %s\n"), argv
[0],
950 /* if no password is to be set, we're done */
952 d_printf(_("User %s added\n"), argv
[0]);
957 /* try setting the password */
958 upn
= talloc_asprintf(tmp_ctx
,
966 ok
= cli_credentials_get_ccache_name_obtained(c
->creds
,
971 d_printf(_("No valid krb5 ccache for: %s\n"),
972 cli_credentials_get_unparsed_name(c
->creds
, tmp_ctx
));
976 status
= ads_krb5_set_password(upn
, argv
[1], creds_ccname
);
977 if (ADS_ERR_OK(status
)) {
978 d_printf(_("User %s added\n"), argv
[0]);
984 /* password didn't set, delete account */
985 d_fprintf(stderr
, _("Could not add user %s. "
986 "Error setting password %s\n"),
987 argv
[0], ads_errstr(status
));
989 ads_msgfree(ads
, res
);
992 status
=ads_find_user_acct(ads
, &res
, argv
[0]);
993 if (ADS_ERR_OK(status
)) {
994 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
995 ads_del_dn(ads
, userdn
);
1000 ads_msgfree(ads
, res
);
1002 TALLOC_FREE(tmp_ctx
);
1006 static int ads_user_info(struct net_context
*c
, int argc
, const char **argv
)
1008 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1009 ADS_STRUCT
*ads
= NULL
;
1011 LDAPMessage
*res
= NULL
;
1014 const char *attrs
[] = {"memberOf", "primaryGroupID", NULL
};
1015 char *searchstring
= NULL
;
1016 char **grouplist
= NULL
;
1017 char *primary_group
= NULL
;
1018 char *escaped_user
= NULL
;
1019 struct dom_sid primary_group_sid
;
1021 enum wbcSidType type
;
1023 if (argc
< 1 || c
->display_usage
) {
1024 TALLOC_FREE(tmp_ctx
);
1025 return net_ads_user_usage(c
, argc
, argv
);
1028 escaped_user
= escape_ldap_string(tmp_ctx
, argv
[0]);
1029 if (!escaped_user
) {
1031 _("ads_user_info: failed to escape user %s\n"),
1036 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1037 if (!ADS_ERR_OK(status
)) {
1041 searchstring
= talloc_asprintf(tmp_ctx
,
1042 "(sAMAccountName=%s)",
1044 if (searchstring
== NULL
) {
1048 status
= ads_search(ads
, &res
, searchstring
, attrs
);
1049 if (!ADS_ERR_OK(status
)) {
1050 d_fprintf(stderr
, _("ads_search: %s\n"), ads_errstr(status
));
1054 if (!ads_pull_uint32(ads
, res
, "primaryGroupID", &group_rid
)) {
1055 d_fprintf(stderr
, _("ads_pull_uint32 failed\n"));
1059 status
= ads_domain_sid(ads
, &primary_group_sid
);
1060 if (!ADS_ERR_OK(status
)) {
1061 d_fprintf(stderr
, _("ads_domain_sid: %s\n"), ads_errstr(status
));
1065 sid_append_rid(&primary_group_sid
, group_rid
);
1067 wbc_status
= wbcLookupSid((struct wbcDomainSid
*)&primary_group_sid
,
1068 NULL
, /* don't look up domain */
1071 if (!WBC_ERROR_IS_OK(wbc_status
)) {
1072 d_fprintf(stderr
, "wbcLookupSid: %s\n",
1073 wbcErrorString(wbc_status
));
1077 d_printf("%s\n", primary_group
);
1079 wbcFreeMemory(primary_group
);
1081 grouplist
= ldap_get_values((LDAP
*)ads
->ldap
.ld
,
1082 (LDAPMessage
*)res
, "memberOf");
1087 for (i
=0;grouplist
[i
];i
++) {
1088 groupname
= ldap_explode_dn(grouplist
[i
], 1);
1089 d_printf("%s\n", groupname
[0]);
1090 ldap_value_free(groupname
);
1092 ldap_value_free(grouplist
);
1097 TALLOC_FREE(escaped_user
);
1098 TALLOC_FREE(searchstring
);
1099 ads_msgfree(ads
, res
);
1100 TALLOC_FREE(tmp_ctx
);
1104 static int ads_user_delete(struct net_context
*c
, int argc
, const char **argv
)
1106 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1107 ADS_STRUCT
*ads
= NULL
;
1109 LDAPMessage
*res
= NULL
;
1110 char *userdn
= NULL
;
1114 TALLOC_FREE(tmp_ctx
);
1115 return net_ads_user_usage(c
, argc
, argv
);
1118 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1119 if (!ADS_ERR_OK(status
)) {
1123 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1124 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1125 d_printf(_("User %s does not exist.\n"), argv
[0]);
1129 userdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1130 if (userdn
== NULL
) {
1134 status
= ads_del_dn(ads
, userdn
);
1135 if (!ADS_ERR_OK(status
)) {
1136 d_fprintf(stderr
, _("Error deleting user %s: %s\n"), argv
[0],
1137 ads_errstr(status
));
1141 d_printf(_("User %s deleted\n"), argv
[0]);
1145 ads_msgfree(ads
, res
);
1146 TALLOC_FREE(tmp_ctx
);
1150 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
1152 struct functable func
[] = {
1157 N_("Add an AD user"),
1158 N_("net ads user add\n"
1165 N_("Display information about an AD user"),
1166 N_("net ads user info\n"
1167 " Display information about an AD user")
1173 N_("Delete an AD user"),
1174 N_("net ads user delete\n"
1175 " Delete an AD user")
1177 {NULL
, NULL
, 0, NULL
, NULL
}
1179 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1180 ADS_STRUCT
*ads
= NULL
;
1182 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1183 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1184 char *disp_fields
[2] = {NULL
, NULL
};
1188 TALLOC_FREE(tmp_ctx
);
1189 return net_run_function(c
, argc
, argv
, "net ads user", func
);
1192 if (c
->display_usage
) {
1197 _("List AD users"));
1198 net_display_usage_from_functable(func
);
1199 TALLOC_FREE(tmp_ctx
);
1203 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1204 if (!ADS_ERR_OK(status
)) {
1208 if (c
->opt_long_list_entries
)
1209 d_printf(_("\nUser name Comment"
1210 "\n-----------------------------\n"));
1212 status
= ads_do_search_all_fn(ads
,
1213 ads
->config
.bind_path
,
1215 "(objectCategory=user)",
1216 c
->opt_long_list_entries
?
1217 longattrs
: shortattrs
,
1220 if (!ADS_ERR_OK(status
)) {
1226 TALLOC_FREE(tmp_ctx
);
1230 static int net_ads_group_usage(struct net_context
*c
, int argc
, const char **argv
)
1232 return net_group_usage(c
, argc
, argv
);
1235 static int ads_group_add(struct net_context
*c
, int argc
, const char **argv
)
1237 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1238 ADS_STRUCT
*ads
= NULL
;
1240 LDAPMessage
*res
= NULL
;
1242 char *ou_str
= NULL
;
1244 if (argc
< 1 || c
->display_usage
) {
1245 TALLOC_FREE(tmp_ctx
);
1246 return net_ads_group_usage(c
, argc
, argv
);
1249 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1250 if (!ADS_ERR_OK(status
)) {
1254 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1255 if (!ADS_ERR_OK(status
)) {
1256 d_fprintf(stderr
, _("ads_group_add: %s\n"), ads_errstr(status
));
1260 if (ads_count_replies(ads
, res
)) {
1261 d_fprintf(stderr
, _("ads_group_add: Group %s already exists\n"), argv
[0]);
1265 if (c
->opt_container
) {
1266 ou_str
= SMB_STRDUP(c
->opt_container
);
1268 ou_str
= ads_default_ou_string(ads
, DS_GUID_USERS_CONTAINER
);
1271 status
= ads_add_group_acct(ads
, argv
[0], ou_str
, c
->opt_comment
);
1272 if (!ADS_ERR_OK(status
)) {
1273 d_fprintf(stderr
, _("Could not add group %s: %s\n"), argv
[0],
1274 ads_errstr(status
));
1278 d_printf(_("Group %s added\n"), argv
[0]);
1282 ads_msgfree(ads
, res
);
1284 TALLOC_FREE(tmp_ctx
);
1288 static int ads_group_delete(struct net_context
*c
, int argc
, const char **argv
)
1290 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1291 ADS_STRUCT
*ads
= NULL
;
1293 LDAPMessage
*res
= NULL
;
1294 char *groupdn
= NULL
;
1297 if (argc
< 1 || c
->display_usage
) {
1298 TALLOC_FREE(tmp_ctx
);
1299 return net_ads_group_usage(c
, argc
, argv
);
1302 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1303 if (!ADS_ERR_OK(status
)) {
1307 status
= ads_find_user_acct(ads
, &res
, argv
[0]);
1308 if (!ADS_ERR_OK(status
) || ads_count_replies(ads
, res
) != 1) {
1309 d_printf(_("Group %s does not exist.\n"), argv
[0]);
1313 groupdn
= ads_get_dn(ads
, tmp_ctx
, res
);
1314 if (groupdn
== NULL
) {
1318 status
= ads_del_dn(ads
, groupdn
);
1319 if (!ADS_ERR_OK(status
)) {
1320 d_fprintf(stderr
, _("Error deleting group %s: %s\n"), argv
[0],
1321 ads_errstr(status
));
1324 d_printf(_("Group %s deleted\n"), argv
[0]);
1328 ads_msgfree(ads
, res
);
1329 TALLOC_FREE(tmp_ctx
);
1333 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
1335 struct functable func
[] = {
1340 N_("Add an AD group"),
1341 N_("net ads group add\n"
1348 N_("Delete an AD group"),
1349 N_("net ads group delete\n"
1350 " Delete an AD group")
1352 {NULL
, NULL
, 0, NULL
, NULL
}
1354 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1355 ADS_STRUCT
*ads
= NULL
;
1357 const char *shortattrs
[] = {"sAMAccountName", NULL
};
1358 const char *longattrs
[] = {"sAMAccountName", "description", NULL
};
1359 char *disp_fields
[2] = {NULL
, NULL
};
1363 TALLOC_FREE(tmp_ctx
);
1364 return net_run_function(c
, argc
, argv
, "net ads group", func
);
1367 if (c
->display_usage
) {
1372 _("List AD groups"));
1373 net_display_usage_from_functable(func
);
1374 TALLOC_FREE(tmp_ctx
);
1378 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
1379 if (!ADS_ERR_OK(status
)) {
1383 if (c
->opt_long_list_entries
)
1384 d_printf(_("\nGroup name Comment"
1385 "\n-----------------------------\n"));
1387 status
= ads_do_search_all_fn(ads
,
1388 ads
->config
.bind_path
,
1390 "(objectCategory=group)",
1391 c
->opt_long_list_entries
?
1392 longattrs
: shortattrs
,
1395 if (!ADS_ERR_OK(status
)) {
1401 TALLOC_FREE(tmp_ctx
);
1405 static int net_ads_status(struct net_context
*c
, int argc
, const char **argv
)
1407 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1408 ADS_STRUCT
*ads
= NULL
;
1410 LDAPMessage
*res
= NULL
;
1413 if (c
->display_usage
) {
1418 _("Display machine account details"));
1419 TALLOC_FREE(tmp_ctx
);
1423 net_warn_member_options();
1425 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1426 if (!ADS_ERR_OK(status
)) {
1430 status
= ads_find_machine_acct(ads
, &res
, lp_netbios_name());
1431 if (!ADS_ERR_OK(status
)) {
1432 d_fprintf(stderr
, _("ads_find_machine_acct: %s\n"),
1433 ads_errstr(status
));
1437 if (ads_count_replies(ads
, res
) == 0) {
1438 d_fprintf(stderr
, _("No machine account for '%s' found\n"),
1447 ads_msgfree(ads
, res
);
1448 TALLOC_FREE(tmp_ctx
);
1452 /*******************************************************************
1453 Leave an AD domain. Windows XP disables the machine account.
1454 We'll try the same. The old code would do an LDAP delete.
1455 That only worked using the machine creds because added the machine
1456 with full control to the computer object's ACL.
1457 *******************************************************************/
1459 static int net_ads_leave(struct net_context
*c
, int argc
, const char **argv
)
1461 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1462 struct libnet_UnjoinCtx
*r
= NULL
;
1466 if (c
->display_usage
) {
1468 "net ads leave [--keep-account]\n"
1471 _("Leave an AD domain"));
1472 TALLOC_FREE(tmp_ctx
);
1477 d_fprintf(stderr
, _("No realm set, are we joined ?\n"));
1478 TALLOC_FREE(tmp_ctx
);
1483 d_fprintf(stderr
, _("Could not initialise message context. "
1484 "Try running as root\n"));
1488 werr
= libnet_init_UnjoinCtx(tmp_ctx
, &r
);
1489 if (!W_ERROR_IS_OK(werr
)) {
1490 d_fprintf(stderr
, _("Could not initialise unjoin context.\n"));
1495 r
->in
.dc_name
= c
->opt_host
;
1496 r
->in
.domain_name
= lp_dnsdomain();
1497 r
->in
.admin_credentials
= c
->creds
;
1498 r
->in
.modify_config
= lp_config_backend_is_registry();
1500 /* Try to delete it, but if that fails, disable it. The
1501 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE really means "disable */
1502 r
->in
.unjoin_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1503 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
;
1504 if (c
->opt_keep_account
) {
1505 r
->in
.delete_machine_account
= false;
1507 r
->in
.delete_machine_account
= true;
1510 r
->in
.msg_ctx
= c
->msg_ctx
;
1512 werr
= libnet_Unjoin(tmp_ctx
, r
);
1513 if (!W_ERROR_IS_OK(werr
)) {
1514 d_printf(_("Failed to leave domain: %s\n"),
1515 r
->out
.error_string
? r
->out
.error_string
:
1516 get_friendly_werror_msg(werr
));
1520 if (r
->out
.deleted_machine_account
) {
1521 d_printf(_("Deleted account for '%s' in realm '%s'\n"),
1522 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1527 /* We couldn't delete it - see if the disable succeeded. */
1528 if (r
->out
.disabled_machine_account
) {
1529 d_printf(_("Disabled account for '%s' in realm '%s'\n"),
1530 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1535 /* Based on what we requested, we shouldn't get here, but if
1536 we did, it means the secrets were removed, and therefore
1537 we have left the domain */
1538 d_fprintf(stderr
, _("Machine '%s' Left domain '%s'\n"),
1539 r
->in
.machine_name
, r
->out
.dns_domain_name
);
1543 TALLOC_FREE(tmp_ctx
);
1547 static ADS_STATUS
net_ads_join_ok(struct net_context
*c
)
1549 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1550 ADS_STRUCT
*ads
= NULL
;
1553 struct sockaddr_storage dcip
;
1555 if (!secrets_init()) {
1556 DEBUG(1,("Failed to initialise secrets database\n"));
1557 TALLOC_FREE(tmp_ctx
);
1558 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
1561 net_warn_member_options();
1563 net_use_krb_machine_account(c
);
1565 if (!cli_credentials_authentication_requested(c
->creds
)) {
1566 DBG_ERR("Failed to get machine credentials\n");
1567 TALLOC_FREE(tmp_ctx
);
1568 return ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED
);
1571 get_dc_name(lp_workgroup(), lp_realm(), dc_name
, &dcip
);
1573 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1574 if (!ADS_ERR_OK(status
)) {
1578 status
= ADS_ERROR_NT(NT_STATUS_OK
);
1580 TALLOC_FREE(tmp_ctx
);
1585 check that an existing join is OK
1587 int net_ads_testjoin(struct net_context
*c
, int argc
, const char **argv
)
1591 if (c
->display_usage
) {
1593 "net ads testjoin\n"
1596 _("Test if the existing join is ok"));
1600 net_warn_member_options();
1602 /* Display success or failure */
1603 status
= net_ads_join_ok(c
);
1604 if (!ADS_ERR_OK(status
)) {
1605 fprintf(stderr
, _("Join to domain is not valid: %s\n"),
1606 get_friendly_nt_error_msg(ads_ntstatus(status
)));
1610 printf(_("Join is OK\n"));
1614 /*******************************************************************
1615 Simple config checks before beginning the join
1616 ********************************************************************/
1618 static WERROR
check_ads_config( void )
1620 if (lp_server_role() != ROLE_DOMAIN_MEMBER
) {
1621 d_printf(_("Host is not configured as a member server.\n"));
1622 return WERR_INVALID_DOMAIN_ROLE
;
1625 if (strlen(lp_netbios_name()) > 15) {
1626 d_printf(_("Our netbios name can be at most 15 chars long, "
1627 "\"%s\" is %u chars long\n"), lp_netbios_name(),
1628 (unsigned int)strlen(lp_netbios_name()));
1629 return WERR_INVALID_COMPUTERNAME
;
1632 if ( lp_security() == SEC_ADS
&& !*lp_realm()) {
1633 d_fprintf(stderr
, _("realm must be set in %s for ADS "
1634 "join to succeed.\n"), get_dyn_CONFIGFILE());
1635 return WERR_INVALID_PARAMETER
;
1641 /*******************************************************************
1642 ********************************************************************/
1644 static int net_ads_join_usage(struct net_context
*c
, int argc
, const char **argv
)
1646 d_printf(_("net ads join [--no-dns-updates] [options]\n"
1647 "Valid options:\n"));
1648 d_printf(_(" dnshostname=FQDN Set the dnsHostName attribute during the join.\n"
1649 " The default is in the form netbiosname.dnsdomain\n"));
1650 d_printf(_(" createupn[=UPN] Set the userPrincipalName attribute during the join.\n"
1651 " The default UPN is in the form host/netbiosname@REALM.\n"));
1652 d_printf(_(" createcomputer=OU Precreate the computer account in a specific OU.\n"
1653 " The OU string read from top to bottom without RDNs\n"
1654 " and delimited by a '/'.\n"
1655 " E.g. \"createcomputer=Computers/Servers/Unix\"\n"
1656 " NB: A backslash '\\' is used as escape at multiple\n"
1657 " levels and may need to be doubled or even\n"
1658 " quadrupled. It is not used as a separator.\n"));
1659 d_printf(_(" machinepass=PASS Set the machine password to a specific value during\n"
1660 " the join. The default password is random.\n"));
1661 d_printf(_(" osName=string Set the operatingSystem attribute during the join.\n"));
1662 d_printf(_(" osVer=string Set the operatingSystemVersion attribute during join.\n"
1663 " NB: osName and osVer must be specified together for\n"
1664 " either to take effect. The operatingSystemService\n"
1665 " attribute is then also set along with the two\n"
1666 " other attributes.\n"));
1667 d_printf(_(" osServicePack=string Set the operatingSystemServicePack attribute\n"
1668 " during the join.\n"
1669 " NB: If not specified then by default the samba\n"
1670 " version string is used instead.\n"));
1675 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
1677 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1678 struct libnet_JoinCtx
*r
= NULL
;
1679 const char *domain
= lp_realm();
1680 WERROR werr
= WERR_NERR_SETUPNOTJOINED
;
1681 bool createupn
= false;
1682 const char *dnshostname
= NULL
;
1683 const char *machineupn
= NULL
;
1684 const char *machine_password
= NULL
;
1685 const char *create_in_ou
= NULL
;
1687 const char *os_name
= NULL
;
1688 const char *os_version
= NULL
;
1689 const char *os_servicepack
= NULL
;
1690 bool modify_config
= lp_config_backend_is_registry();
1691 enum libnetjoin_JoinDomNameType domain_name_type
= JoinDomNameTypeDNS
;
1694 if (c
->display_usage
) {
1695 TALLOC_FREE(tmp_ctx
);
1696 return net_ads_join_usage(c
, argc
, argv
);
1699 net_warn_member_options();
1701 if (!modify_config
) {
1702 werr
= check_ads_config();
1703 if (!W_ERROR_IS_OK(werr
)) {
1704 d_fprintf(stderr
, _("Invalid configuration. Exiting....\n"));
1709 werr
= libnet_init_JoinCtx(tmp_ctx
, &r
);
1710 if (!W_ERROR_IS_OK(werr
)) {
1714 /* process additional command line args */
1716 for ( i
=0; i
<argc
; i
++ ) {
1717 if ( !strncasecmp_m(argv
[i
], "dnshostname", strlen("dnshostname")) ) {
1718 dnshostname
= get_string_param(argv
[i
]);
1720 else if ( !strncasecmp_m(argv
[i
], "createupn", strlen("createupn")) ) {
1722 machineupn
= get_string_param(argv
[i
]);
1724 else if ( !strncasecmp_m(argv
[i
], "createcomputer", strlen("createcomputer")) ) {
1725 if ( (create_in_ou
= get_string_param(argv
[i
])) == NULL
) {
1726 d_fprintf(stderr
, _("Please supply a valid OU path.\n"));
1727 werr
= WERR_INVALID_PARAMETER
;
1731 else if ( !strncasecmp_m(argv
[i
], "osName", strlen("osName")) ) {
1732 if ( (os_name
= get_string_param(argv
[i
])) == NULL
) {
1733 d_fprintf(stderr
, _("Please supply a operating system name.\n"));
1734 werr
= WERR_INVALID_PARAMETER
;
1738 else if ( !strncasecmp_m(argv
[i
], "osVer", strlen("osVer")) ) {
1739 if ( (os_version
= get_string_param(argv
[i
])) == NULL
) {
1740 d_fprintf(stderr
, _("Please supply a valid operating system version.\n"));
1741 werr
= WERR_INVALID_PARAMETER
;
1745 else if ( !strncasecmp_m(argv
[i
], "osServicePack", strlen("osServicePack")) ) {
1746 if ( (os_servicepack
= get_string_param(argv
[i
])) == NULL
) {
1747 d_fprintf(stderr
, _("Please supply a valid servicepack identifier.\n"));
1748 werr
= WERR_INVALID_PARAMETER
;
1752 else if ( !strncasecmp_m(argv
[i
], "machinepass", strlen("machinepass")) ) {
1753 if ( (machine_password
= get_string_param(argv
[i
])) == NULL
) {
1754 d_fprintf(stderr
, _("Please supply a valid password to set as trust account password.\n"));
1755 werr
= WERR_INVALID_PARAMETER
;
1760 if (strchr(domain
, '.') == NULL
) {
1761 domain_name_type
= JoinDomNameTypeUnknown
;
1763 domain_name_type
= JoinDomNameTypeDNS
;
1769 d_fprintf(stderr
, _("Please supply a valid domain name\n"));
1770 werr
= WERR_INVALID_PARAMETER
;
1775 d_fprintf(stderr
, _("Could not initialise message context. "
1776 "Try running as root\n"));
1777 werr
= WERR_ACCESS_DENIED
;
1781 /* Do the domain join here */
1783 r
->in
.domain_name
= domain
;
1784 r
->in
.domain_name_type
= domain_name_type
;
1785 r
->in
.create_upn
= createupn
;
1786 r
->in
.upn
= machineupn
;
1787 r
->in
.dnshostname
= dnshostname
;
1788 r
->in
.account_ou
= create_in_ou
;
1789 r
->in
.os_name
= os_name
;
1790 r
->in
.os_version
= os_version
;
1791 r
->in
.os_servicepack
= os_servicepack
;
1792 r
->in
.dc_name
= c
->opt_host
;
1793 r
->in
.admin_credentials
= c
->creds
;
1794 r
->in
.machine_password
= machine_password
;
1796 r
->in
.modify_config
= modify_config
;
1797 r
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
1798 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
|
1799 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
;
1800 r
->in
.msg_ctx
= c
->msg_ctx
;
1802 werr
= libnet_Join(tmp_ctx
, r
);
1803 if (W_ERROR_EQUAL(werr
, WERR_NERR_DCNOTFOUND
) &&
1804 strequal(domain
, lp_realm())) {
1805 r
->in
.domain_name
= lp_workgroup();
1806 r
->in
.domain_name_type
= JoinDomNameTypeNBT
;
1807 werr
= libnet_Join(tmp_ctx
, r
);
1809 if (!W_ERROR_IS_OK(werr
)) {
1813 /* Check the short name of the domain */
1815 if (!modify_config
&& !strequal(lp_workgroup(), r
->out
.netbios_domain_name
)) {
1816 d_printf(_("The workgroup in %s does not match the short\n"
1817 "domain name obtained from the server.\n"
1818 "Using the name [%s] from the server.\n"
1819 "You should set \"workgroup = %s\" in %s.\n"),
1820 get_dyn_CONFIGFILE(), r
->out
.netbios_domain_name
,
1821 r
->out
.netbios_domain_name
, get_dyn_CONFIGFILE());
1824 d_printf(_("Using short domain name -- %s\n"), r
->out
.netbios_domain_name
);
1826 if (r
->out
.dns_domain_name
) {
1827 d_printf(_("Joined '%s' to dns domain '%s'\n"), r
->in
.machine_name
,
1828 r
->out
.dns_domain_name
);
1830 d_printf(_("Joined '%s' to domain '%s'\n"), r
->in
.machine_name
,
1831 r
->out
.netbios_domain_name
);
1834 /* print out informative error string in case there is one */
1835 if (r
->out
.error_string
!= NULL
) {
1836 d_printf("%s\n", r
->out
.error_string
);
1840 * We try doing the dns update (if it was compiled in
1841 * and if it was not disabled on the command line).
1842 * If the dns update fails, we still consider the join
1843 * operation as succeeded if we came this far.
1845 if (!c
->opt_no_dns_updates
) {
1846 net_ads_join_dns_updates(c
, tmp_ctx
, r
);
1853 /* issue an overall failure message at the end. */
1854 d_printf(_("Failed to join domain: %s\n"),
1855 r
&& r
->out
.error_string
? r
->out
.error_string
:
1856 get_friendly_werror_msg(werr
));
1859 TALLOC_FREE(tmp_ctx
);
1864 /*******************************************************************
1865 ********************************************************************/
1867 static int net_ads_dns_register(struct net_context
*c
, int argc
, const char **argv
)
1869 #if defined(HAVE_KRB5)
1870 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1871 ADS_STRUCT
*ads
= NULL
;
1874 const char *hostname
= NULL
;
1875 const char **addrs_list
= NULL
;
1876 struct sockaddr_storage
*addrs
= NULL
;
1882 talloc_enable_leak_report();
1885 if (argc
<= 1 && lp_clustering() && lp_cluster_addresses() == NULL
) {
1886 d_fprintf(stderr
, _("Refusing DNS updates with automatic "
1887 "detection of addresses in a clustered "
1889 c
->display_usage
= true;
1892 if (c
->display_usage
) {
1894 "net ads dns register [hostname [IP [IP...]]] "
1895 "[--force] [--dns-ttl TTL]\n"
1898 _("Register hostname with DNS\n"));
1899 TALLOC_FREE(tmp_ctx
);
1908 num_addrs
= argc
- 1;
1909 addrs_list
= &argv
[1];
1910 } else if (lp_clustering()) {
1911 addrs_list
= lp_cluster_addresses();
1912 num_addrs
= str_list_length(addrs_list
);
1915 if (num_addrs
> 0) {
1916 addrs
= talloc_zero_array(tmp_ctx
,
1917 struct sockaddr_storage
,
1919 if (addrs
== NULL
) {
1920 d_fprintf(stderr
, _("Error allocating memory!\n"));
1925 for (count
= 0; count
< num_addrs
; count
++) {
1926 if (!interpret_string_addr(&addrs
[count
], addrs_list
[count
], 0)) {
1927 d_fprintf(stderr
, "%s '%s'.\n",
1928 _("Cannot interpret address"),
1934 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
1935 if ( !ADS_ERR_OK(status
) ) {
1936 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
1940 ntstatus
= net_update_dns_ext(c
,
1948 if (!NT_STATUS_IS_OK(ntstatus
)) {
1949 d_fprintf( stderr
, _("DNS update failed!\n") );
1953 d_fprintf( stderr
, _("Successfully registered hostname with DNS\n") );
1957 TALLOC_FREE(tmp_ctx
);
1962 _("DNS update support not enabled at compile time!\n"));
1967 static int net_ads_dns_unregister(struct net_context
*c
,
1971 #if defined(HAVE_KRB5)
1972 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1973 ADS_STRUCT
*ads
= NULL
;
1976 const char *hostname
= NULL
;
1980 talloc_enable_leak_report();
1984 c
->display_usage
= true;
1987 if (c
->display_usage
) {
1989 "net ads dns unregister [hostname]\n"
1992 _("Remove all IP Address entries for a given\n"
1993 " hostname from the Active Directory server.\n"));
1994 TALLOC_FREE(tmp_ctx
);
1998 /* Get the hostname for un-registering */
2001 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2002 if ( !ADS_ERR_OK(status
) ) {
2003 DEBUG(1, ("error on ads_startup: %s\n", ads_errstr(status
)));
2007 ntstatus
= net_update_dns_ext(c
,
2015 if (!NT_STATUS_IS_OK(ntstatus
)) {
2016 d_fprintf( stderr
, _("DNS update failed!\n") );
2020 d_fprintf( stderr
, _("Successfully un-registered hostname from DNS\n"));
2024 TALLOC_FREE(tmp_ctx
);
2029 _("DNS update support not enabled at compile time!\n"));
2035 static int net_ads_dns_async(struct net_context
*c
, int argc
, const char **argv
)
2037 size_t num_names
= 0;
2038 char **hostnames
= NULL
;
2040 struct samba_sockaddr
*addrs
= NULL
;
2043 if (argc
!= 1 || c
->display_usage
) {
2048 _("net ads dns async <name>\n"),
2049 _(" Async look up hostname from the DNS server\n"
2050 " hostname\tName to look up\n"));
2054 status
= ads_dns_lookup_a(talloc_tos(),
2059 if (!NT_STATUS_IS_OK(status
)) {
2060 d_printf("Looking up A record for %s got error %s\n",
2065 d_printf("Async A record lookup - got %u names for %s\n",
2066 (unsigned int)num_names
,
2068 for (i
= 0; i
< num_names
; i
++) {
2069 char addr_buf
[INET6_ADDRSTRLEN
];
2070 print_sockaddr(addr_buf
,
2073 d_printf("hostname[%u] = %s, IPv4addr = %s\n",
2079 #if defined(HAVE_IPV6)
2080 status
= ads_dns_lookup_aaaa(talloc_tos(),
2085 if (!NT_STATUS_IS_OK(status
)) {
2086 d_printf("Looking up AAAA record for %s got error %s\n",
2091 d_printf("Async AAAA record lookup - got %u names for %s\n",
2092 (unsigned int)num_names
,
2094 for (i
= 0; i
< num_names
; i
++) {
2095 char addr_buf
[INET6_ADDRSTRLEN
];
2096 print_sockaddr(addr_buf
,
2099 d_printf("hostname[%u] = %s, IPv6addr = %s\n",
2109 static int net_ads_dns(struct net_context
*c
, int argc
, const char *argv
[])
2111 struct functable func
[] = {
2114 net_ads_dns_register
,
2116 N_("Add FQDN dns entry to AD"),
2117 N_("net ads dns register [FQDN [IP [IP.....]]]\n"
2118 " Add FQDN dns entry to AD")
2122 net_ads_dns_unregister
,
2124 N_("Remove FQDN dns entry from AD"),
2125 N_("net ads dns unregister <FQDN>\n"
2126 " Remove FQDN dns entry from AD")
2133 N_("net ads dns async\n"
2134 " Look up host using async DNS")
2136 {NULL
, NULL
, 0, NULL
, NULL
}
2139 return net_run_function(c
, argc
, argv
, "net ads dns", func
);
2142 /*******************************************************************
2143 ********************************************************************/
2145 int net_ads_printer_usage(struct net_context
*c
, int argc
, const char **argv
)
2148 "\nnet ads printer search <printer>"
2149 "\n\tsearch for a printer in the directory\n"
2150 "\nnet ads printer info <printer> <server>"
2151 "\n\tlookup info in directory for printer on server"
2152 "\n\t(note: printer defaults to \"*\", server defaults to local)\n"
2153 "\nnet ads printer publish <printername>"
2154 "\n\tpublish printer in directory"
2155 "\n\t(note: printer name is required)\n"
2156 "\nnet ads printer remove <printername>"
2157 "\n\tremove printer from directory"
2158 "\n\t(note: printer name is required)\n"));
2162 /*******************************************************************
2163 ********************************************************************/
2165 static int net_ads_printer_search(struct net_context
*c
,
2169 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2170 ADS_STRUCT
*ads
= NULL
;
2172 LDAPMessage
*res
= NULL
;
2175 if (c
->display_usage
) {
2177 "net ads printer search\n"
2180 _("List printers in the AD"));
2181 TALLOC_FREE(tmp_ctx
);
2185 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2186 if (!ADS_ERR_OK(status
)) {
2190 status
= ads_find_printers(ads
, &res
);
2191 if (!ADS_ERR_OK(status
)) {
2192 d_fprintf(stderr
, _("ads_find_printer: %s\n"),
2193 ads_errstr(status
));
2197 if (ads_count_replies(ads
, res
) == 0) {
2198 d_fprintf(stderr
, _("No results found\n"));
2206 ads_msgfree(ads
, res
);
2207 TALLOC_FREE(tmp_ctx
);
2211 static int net_ads_printer_info(struct net_context
*c
,
2215 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2216 ADS_STRUCT
*ads
= NULL
;
2218 const char *servername
= NULL
;
2219 const char *printername
= NULL
;
2220 LDAPMessage
*res
= NULL
;
2223 if (c
->display_usage
) {
2226 _("net ads printer info [printername [servername]]\n"
2227 " Display printer info from AD\n"
2228 " printername\tPrinter name or wildcard\n"
2229 " servername\tName of the print server\n"));
2230 TALLOC_FREE(tmp_ctx
);
2234 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2235 if (!ADS_ERR_OK(status
)) {
2240 printername
= argv
[0];
2246 servername
= argv
[1];
2248 servername
= lp_netbios_name();
2251 status
= ads_find_printer_on_server(ads
, &res
, printername
, servername
);
2252 if (!ADS_ERR_OK(status
)) {
2253 d_fprintf(stderr
, _("Server '%s' not found: %s\n"),
2254 servername
, ads_errstr(status
));
2258 if (ads_count_replies(ads
, res
) == 0) {
2259 d_fprintf(stderr
, _("Printer '%s' not found\n"), printername
);
2267 ads_msgfree(ads
, res
);
2268 TALLOC_FREE(tmp_ctx
);
2272 static int net_ads_printer_publish(struct net_context
*c
,
2276 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2277 ADS_STRUCT
*ads
= NULL
;
2279 const char *servername
= NULL
;
2280 const char *printername
= NULL
;
2281 struct cli_state
*cli
= NULL
;
2282 struct rpc_pipe_client
*pipe_hnd
= NULL
;
2283 struct sockaddr_storage server_ss
= { 0 };
2285 ADS_MODLIST mods
= NULL
;
2286 char *prt_dn
= NULL
;
2287 char *srv_dn
= NULL
;
2288 char **srv_cn
= NULL
;
2289 char *srv_cn_escaped
= NULL
;
2290 char *printername_escaped
= NULL
;
2291 LDAPMessage
*res
= NULL
;
2295 if (argc
< 1 || c
->display_usage
) {
2298 _("net ads printer publish <printername> [servername]\n"
2299 " Publish printer in AD\n"
2300 " printername\tName of the printer\n"
2301 " servername\tName of the print server\n"));
2302 TALLOC_FREE(tmp_ctx
);
2306 mods
= ads_init_mods(tmp_ctx
);
2308 d_fprintf(stderr
, _("Out of memory\n"));
2312 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2313 if (!ADS_ERR_OK(status
)) {
2317 printername
= argv
[0];
2320 servername
= argv
[1];
2322 servername
= lp_netbios_name();
2325 /* Get printer data from SPOOLSS */
2327 ok
= resolve_name(servername
, &server_ss
, 0x20, false);
2329 d_fprintf(stderr
, _("Could not find server %s\n"),
2334 cli_credentials_set_kerberos_state(c
->creds
,
2335 CRED_USE_KERBEROS_REQUIRED
,
2338 nt_status
= cli_full_connection_creds(c
,
2347 CLI_FULL_CONNECTION_IPC
);
2349 if (NT_STATUS_IS_ERR(nt_status
)) {
2350 d_fprintf(stderr
, _("Unable to open a connection to %s to "
2351 "obtain data for %s\n"),
2352 servername
, printername
);
2356 /* Publish on AD server */
2358 ads_find_machine_acct(ads
, &res
, servername
);
2360 if (ads_count_replies(ads
, res
) == 0) {
2361 d_fprintf(stderr
, _("Could not find machine account for server "
2367 srv_dn
= ldap_get_dn((LDAP
*)ads
->ldap
.ld
, (LDAPMessage
*)res
);
2368 srv_cn
= ldap_explode_dn(srv_dn
, 1);
2370 srv_cn_escaped
= escape_rdn_val_string_alloc(srv_cn
[0]);
2371 printername_escaped
= escape_rdn_val_string_alloc(printername
);
2372 if (!srv_cn_escaped
|| !printername_escaped
) {
2373 SAFE_FREE(srv_cn_escaped
);
2374 SAFE_FREE(printername_escaped
);
2375 d_fprintf(stderr
, _("Internal error, out of memory!"));
2379 prt_dn
= talloc_asprintf(tmp_ctx
,
2382 printername_escaped
,
2384 if (prt_dn
== NULL
) {
2385 SAFE_FREE(srv_cn_escaped
);
2386 SAFE_FREE(printername_escaped
);
2387 d_fprintf(stderr
, _("Internal error, out of memory!"));
2391 SAFE_FREE(srv_cn_escaped
);
2392 SAFE_FREE(printername_escaped
);
2394 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_spoolss
, &pipe_hnd
);
2395 if (!NT_STATUS_IS_OK(nt_status
)) {
2396 d_fprintf(stderr
, _("Unable to open a connection to the spoolss pipe on %s\n"),
2401 if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd
,
2408 status
= ads_add_printer_entry(ads
, prt_dn
, tmp_ctx
, &mods
);
2409 if (!ADS_ERR_OK(status
)) {
2410 d_fprintf(stderr
, "ads_publish_printer: %s\n",
2411 ads_errstr(status
));
2415 d_printf("published printer\n");
2419 talloc_destroy(tmp_ctx
);
2424 static int net_ads_printer_remove(struct net_context
*c
,
2428 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2429 ADS_STRUCT
*ads
= NULL
;
2431 const char *servername
= NULL
;
2432 char *prt_dn
= NULL
;
2433 LDAPMessage
*res
= NULL
;
2436 if (argc
< 1 || c
->display_usage
) {
2439 _("net ads printer remove <printername> [servername]\n"
2440 " Remove a printer from the AD\n"
2441 " printername\tName of the printer\n"
2442 " servername\tName of the print server\n"));
2443 TALLOC_FREE(tmp_ctx
);
2447 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2448 if (!ADS_ERR_OK(status
)) {
2453 servername
= argv
[1];
2455 servername
= lp_netbios_name();
2458 status
= ads_find_printer_on_server(ads
, &res
, argv
[0], servername
);
2459 if (!ADS_ERR_OK(status
)) {
2460 d_fprintf(stderr
, _("ads_find_printer_on_server: %s\n"),
2461 ads_errstr(status
));
2465 if (ads_count_replies(ads
, res
) == 0) {
2466 d_fprintf(stderr
, _("Printer '%s' not found\n"), argv
[1]);
2470 prt_dn
= ads_get_dn(ads
, tmp_ctx
, res
);
2471 if (prt_dn
== NULL
) {
2472 d_fprintf(stderr
, _("Out of memory\n"));
2476 status
= ads_del_dn(ads
, prt_dn
);
2477 if (!ADS_ERR_OK(status
)) {
2478 d_fprintf(stderr
, _("ads_del_dn: %s\n"), ads_errstr(status
));
2484 ads_msgfree(ads
, res
);
2485 TALLOC_FREE(tmp_ctx
);
2489 static int net_ads_printer(struct net_context
*c
, int argc
, const char **argv
)
2491 struct functable func
[] = {
2494 net_ads_printer_search
,
2496 N_("Search for a printer"),
2497 N_("net ads printer search\n"
2498 " Search for a printer")
2502 net_ads_printer_info
,
2504 N_("Display printer information"),
2505 N_("net ads printer info\n"
2506 " Display printer information")
2510 net_ads_printer_publish
,
2512 N_("Publish a printer"),
2513 N_("net ads printer publish\n"
2514 " Publish a printer")
2518 net_ads_printer_remove
,
2520 N_("Delete a printer"),
2521 N_("net ads printer remove\n"
2522 " Delete a printer")
2524 {NULL
, NULL
, 0, NULL
, NULL
}
2527 return net_run_function(c
, argc
, argv
, "net ads printer", func
);
2531 static int net_ads_password(struct net_context
*c
, int argc
, const char **argv
)
2533 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2534 ADS_STRUCT
*ads
= NULL
;
2535 const char *auth_principal
= cli_credentials_get_username(c
->creds
);
2536 const char *auth_password
= cli_credentials_get_password(c
->creds
);
2537 const char *realm
= NULL
;
2538 char *new_password
= NULL
;
2540 char *prompt
= NULL
;
2541 const char *user
= NULL
;
2542 char pwd
[256] = {0};
2546 if (c
->display_usage
) {
2549 _("net ads password <username>\n"
2550 " Change password for user\n"
2551 " username\tName of user to change password for\n"));
2552 TALLOC_FREE(tmp_ctx
);
2556 if (auth_principal
== NULL
|| auth_password
== NULL
) {
2557 d_fprintf(stderr
, _("You must supply an administrator "
2558 "username/password\n"));
2559 TALLOC_FREE(tmp_ctx
);
2564 d_fprintf(stderr
, _("ERROR: You must say which username to "
2565 "change password for\n"));
2566 TALLOC_FREE(tmp_ctx
);
2570 if (strchr_m(argv
[0], '@')) {
2571 user
= talloc_strdup(tmp_ctx
, argv
[0]);
2573 user
= talloc_asprintf(tmp_ctx
, "%s@%s", argv
[0], lp_realm());
2576 d_fprintf(stderr
, _("Out of memory\n"));
2580 chr
= strchr_m(auth_principal
, '@');
2587 /* use the realm so we can eventually change passwords for users
2588 in realms other than default */
2589 ads
= ads_init(tmp_ctx
,
2598 /* we don't actually need a full connect, but it's the easy way to
2599 fill in the KDC's address */
2600 ads
->auth
.flags
|= ADS_AUTH_GENERATE_KRB5_CONFIG
;
2601 ads_connect_cldap_only(ads
);
2603 if (!ads
->config
.realm
) {
2604 d_fprintf(stderr
, _("Didn't find the kerberos server!\n"));
2608 if (argv
[1] != NULL
) {
2609 new_password
= talloc_strdup(tmp_ctx
, argv
[1]);
2613 prompt
= talloc_asprintf(tmp_ctx
, _("Enter new password for %s:"), user
);
2614 if (prompt
== NULL
) {
2615 d_fprintf(stderr
, _("Out of memory\n"));
2619 rc
= samba_getpass(prompt
, pwd
, sizeof(pwd
), false, true);
2623 new_password
= talloc_strdup(tmp_ctx
, pwd
);
2624 memset(pwd
, '\0', sizeof(pwd
));
2627 if (new_password
== NULL
) {
2628 d_fprintf(stderr
, _("Out of memory\n"));
2632 status
= kerberos_set_password(auth_principal
,
2636 memset(new_password
, '\0', strlen(new_password
));
2637 if (!ADS_ERR_OK(status
)) {
2638 d_fprintf(stderr
, _("Password change failed: %s\n"),
2639 ads_errstr(status
));
2643 d_printf(_("Password change for %s completed.\n"), user
);
2647 TALLOC_FREE(tmp_ctx
);
2651 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
2653 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2654 ADS_STRUCT
*ads
= NULL
;
2655 char *host_principal
= NULL
;
2656 char *my_name
= NULL
;
2660 if (c
->display_usage
) {
2662 "net ads changetrustpw\n"
2665 _("Change the machine account's trust password"));
2666 TALLOC_FREE(tmp_ctx
);
2670 if (!secrets_init()) {
2671 DEBUG(1,("Failed to initialise secrets database\n"));
2675 net_warn_member_options();
2677 net_use_krb_machine_account(c
);
2679 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2680 if (!ADS_ERR_OK(status
)) {
2684 my_name
= talloc_asprintf_strlower_m(tmp_ctx
, "%s", lp_netbios_name());
2685 if (my_name
== NULL
) {
2686 d_fprintf(stderr
, _("Out of memory\n"));
2690 host_principal
= talloc_asprintf(tmp_ctx
, "%s$@%s", my_name
, ads
->config
.realm
);
2691 if (host_principal
== NULL
) {
2692 d_fprintf(stderr
, _("Out of memory\n"));
2696 d_printf(_("Changing password for principal: %s\n"), host_principal
);
2698 status
= ads_change_trust_account_password(ads
, host_principal
);
2699 if (!ADS_ERR_OK(status
)) {
2700 d_fprintf(stderr
, _("Password change failed: %s\n"), ads_errstr(status
));
2704 d_printf(_("Password change for principal %s succeeded.\n"), host_principal
);
2708 TALLOC_FREE(tmp_ctx
);
2714 help for net ads search
2716 static int net_ads_search_usage(struct net_context
*c
, int argc
, const char **argv
)
2719 "\nnet ads search <expression> <attributes...>\n"
2720 "\nPerform a raw LDAP search on a ADS server and dump the results.\n"
2721 "The expression is a standard LDAP search expression, and the\n"
2722 "attributes are a list of LDAP fields to show in the results.\n\n"
2723 "Example: net ads search '(objectCategory=group)' sAMAccountName\n\n"
2725 net_common_flags_usage(c
, argc
, argv
);
2731 general ADS search function. Useful in diagnosing problems in ADS
2733 static int net_ads_search(struct net_context
*c
, int argc
, const char **argv
)
2735 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2736 ADS_STRUCT
*ads
= NULL
;
2738 const char *ldap_exp
= NULL
;
2739 const char **attrs
= NULL
;
2740 LDAPMessage
*res
= NULL
;
2743 if (argc
< 1 || c
->display_usage
) {
2744 TALLOC_FREE(tmp_ctx
);
2745 return net_ads_search_usage(c
, argc
, argv
);
2748 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2749 if (!ADS_ERR_OK(status
)) {
2756 status
= ads_do_search_retry(ads
,
2757 ads
->config
.bind_path
,
2762 if (!ADS_ERR_OK(status
)) {
2763 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2767 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2769 /* dump the results */
2774 ads_msgfree(ads
, res
);
2775 TALLOC_FREE(tmp_ctx
);
2781 help for net ads search
2783 static int net_ads_dn_usage(struct net_context
*c
, int argc
, const char **argv
)
2786 "\nnet ads dn <dn> <attributes...>\n"
2787 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2788 "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"
2789 "to show in the results\n\n"
2790 "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
2791 "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
2793 net_common_flags_usage(c
, argc
, argv
);
2799 general ADS search function. Useful in diagnosing problems in ADS
2801 static int net_ads_dn(struct net_context
*c
, int argc
, const char **argv
)
2803 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2804 ADS_STRUCT
*ads
= NULL
;
2806 const char *dn
= NULL
;
2807 const char **attrs
= NULL
;
2808 LDAPMessage
*res
= NULL
;
2811 if (argc
< 1 || c
->display_usage
) {
2812 TALLOC_FREE(tmp_ctx
);
2813 return net_ads_dn_usage(c
, argc
, argv
);
2816 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2817 if (!ADS_ERR_OK(status
)) {
2824 status
= ads_do_search_all(ads
,
2830 if (!ADS_ERR_OK(status
)) {
2831 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2835 d_printf("Got %d replies\n\n", ads_count_replies(ads
, res
));
2837 /* dump the results */
2842 ads_msgfree(ads
, res
);
2843 TALLOC_FREE(tmp_ctx
);
2848 help for net ads sid search
2850 static int net_ads_sid_usage(struct net_context
*c
, int argc
, const char **argv
)
2853 "\nnet ads sid <sid> <attributes...>\n"
2854 "\nperform a raw LDAP search on a ADS server and dump the results\n"
2855 "The SID is in string format, and the attributes are a list of LDAP fields \n"
2856 "to show in the results\n\n"
2857 "Example: net ads sid 'S-1-5-32' distinguishedName\n\n"
2859 net_common_flags_usage(c
, argc
, argv
);
2865 general ADS search function. Useful in diagnosing problems in ADS
2867 static int net_ads_sid(struct net_context
*c
, int argc
, const char **argv
)
2869 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2870 ADS_STRUCT
*ads
= NULL
;
2872 const char *sid_string
= NULL
;
2873 const char **attrs
= NULL
;
2874 LDAPMessage
*res
= NULL
;
2875 struct dom_sid sid
= { 0 };
2878 if (argc
< 1 || c
->display_usage
) {
2879 TALLOC_FREE(tmp_ctx
);
2880 return net_ads_sid_usage(c
, argc
, argv
);
2883 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
2884 if (!ADS_ERR_OK(status
)) {
2888 sid_string
= argv
[0];
2891 if (!string_to_sid(&sid
, sid_string
)) {
2892 d_fprintf(stderr
, _("could not convert sid\n"));
2896 status
= ads_search_retry_sid(ads
, &res
, &sid
, attrs
);
2897 if (!ADS_ERR_OK(status
)) {
2898 d_fprintf(stderr
, _("search failed: %s\n"), ads_errstr(status
));
2902 d_printf(_("Got %d replies\n\n"), ads_count_replies(ads
, res
));
2904 /* dump the results */
2909 ads_msgfree(ads
, res
);
2910 TALLOC_FREE(tmp_ctx
);
2914 static int net_ads_keytab_flush(struct net_context
*c
,
2918 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2919 ADS_STRUCT
*ads
= NULL
;
2923 if (c
->display_usage
) {
2925 "net ads keytab flush\n"
2928 _("Delete the whole keytab"));
2929 TALLOC_FREE(tmp_ctx
);
2933 if (!c
->explicit_credentials
) {
2934 net_use_krb_machine_account(c
);
2937 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2938 if (!ADS_ERR_OK(status
)) {
2942 ret
= ads_keytab_flush(ads
);
2944 TALLOC_FREE(tmp_ctx
);
2948 static int net_ads_keytab_create(struct net_context
*c
, int argc
, const char **argv
)
2950 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
2951 ADS_STRUCT
*ads
= NULL
;
2956 if (c
->display_usage
) {
2958 "net ads keytab create\n"
2961 _("Create (sync) new default keytab"));
2962 TALLOC_FREE(tmp_ctx
);
2966 net_warn_member_options();
2968 if (!c
->explicit_credentials
) {
2969 net_use_krb_machine_account(c
);
2972 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
2973 if (!ADS_ERR_OK(status
)) {
2977 ntstatus
= sync_pw2keytabs();
2978 ret
= NT_STATUS_IS_OK(ntstatus
) ? 0 : 1;
2980 TALLOC_FREE(tmp_ctx
);
2984 static int net_ads_keytab_list(struct net_context
*c
, int argc
, const char **argv
)
2986 const char *keytab
= NULL
;
2988 if (c
->display_usage
) {
2991 _("net ads keytab list [keytab]\n"
2992 " List a local keytab\n"
2993 " keytab\tKeytab to list\n"));
3001 return ads_keytab_list(keytab
);
3004 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
3006 struct functable func
[] = {
3009 net_ads_keytab_create
,
3011 N_("Create (sync) a fresh keytab"),
3012 N_("net ads keytab create\n"
3013 " Create (sync) a fresh keytab or update existing one (see also smb.conf 'sync machine password to keytab'.")
3017 net_ads_keytab_flush
,
3019 N_("Remove all keytab entries"),
3020 N_("net ads keytab flush\n"
3021 " Remove all keytab entries")
3025 net_ads_keytab_list
,
3027 N_("List a keytab"),
3028 N_("net ads keytab list\n"
3031 {NULL
, NULL
, 0, NULL
, NULL
}
3034 return net_run_function(c
, argc
, argv
, "net ads keytab", func
);
3037 static int net_ads_kerberos_renew(struct net_context
*c
, int argc
, const char **argv
)
3041 if (c
->display_usage
) {
3043 "net ads kerberos renew\n"
3046 _("Renew TGT from existing credential cache"));
3050 ret
= smb_krb5_renew_ticket(NULL
, NULL
, NULL
, NULL
);
3052 d_printf(_("failed to renew kerberos ticket: %s\n"),
3053 error_message(ret
));
3058 static int net_ads_kerberos_pac_common(struct net_context
*c
, int argc
, const char **argv
,
3059 struct PAC_DATA_CTR
**pac_data_ctr
)
3063 const char *impersonate_princ_s
= NULL
;
3064 const char *local_service
= NULL
;
3065 const char *principal
= NULL
;
3066 const char *password
= NULL
;
3069 for (i
=0; i
<argc
; i
++) {
3070 if (strnequal(argv
[i
], "impersonate", strlen("impersonate"))) {
3071 impersonate_princ_s
= get_string_param(argv
[i
]);
3072 if (impersonate_princ_s
== NULL
) {
3076 if (strnequal(argv
[i
], "local_service", strlen("local_service"))) {
3077 local_service
= get_string_param(argv
[i
]);
3078 if (local_service
== NULL
) {
3084 if (local_service
== NULL
) {
3085 local_service
= talloc_asprintf(c
, "%s$@%s",
3086 lp_netbios_name(), lp_realm());
3087 if (local_service
== NULL
) {
3092 principal
= cli_credentials_get_principal(c
->creds
, c
);
3093 if (principal
== NULL
) {
3094 d_printf("cli_credentials_get_principal() failed\n");
3097 password
= cli_credentials_get_password(c
->creds
);
3099 status
= kerberos_return_pac(c
,
3108 2592000, /* one month */
3109 impersonate_princ_s
,
3114 if (!NT_STATUS_IS_OK(status
)) {
3115 d_printf(_("failed to query kerberos PAC: %s\n"),
3125 static int net_ads_kerberos_pac_dump(struct net_context
*c
, int argc
, const char **argv
)
3127 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3130 enum PAC_TYPE type
= 0;
3132 if (c
->display_usage
) {
3134 "net ads kerberos pac dump [impersonate=string] [local_service=string] [pac_buffer_type=int]\n"
3137 _("Dump the Kerberos PAC"));
3141 for (i
=0; i
<argc
; i
++) {
3142 if (strnequal(argv
[i
], "pac_buffer_type", strlen("pac_buffer_type"))) {
3143 type
= get_int_param(argv
[i
]);
3147 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3156 s
= NDR_PRINT_STRUCT_STRING(c
, PAC_DATA
,
3157 pac_data_ctr
->pac_data
);
3159 d_printf(_("The Pac: %s\n"), s
);
3166 num_buffers
= pac_data_ctr
->pac_data
->num_buffers
;
3168 for (i
=0; i
<num_buffers
; i
++) {
3172 if (pac_data_ctr
->pac_data
->buffers
[i
].type
!= type
) {
3176 s
= NDR_PRINT_UNION_STRING(c
, PAC_INFO
, type
,
3177 pac_data_ctr
->pac_data
->buffers
[i
].info
);
3179 d_printf(_("The Pac: %s\n"), s
);
3188 static int net_ads_kerberos_pac_save(struct net_context
*c
, int argc
, const char **argv
)
3190 struct PAC_DATA_CTR
*pac_data_ctr
= NULL
;
3191 char *filename
= NULL
;
3195 if (c
->display_usage
) {
3197 "net ads kerberos pac save [impersonate=string] [local_service=string] [filename=string]\n"
3200 _("Save the Kerberos PAC"));
3204 for (i
=0; i
<argc
; i
++) {
3205 if (strnequal(argv
[i
], "filename", strlen("filename"))) {
3206 filename
= get_string_param(argv
[i
]);
3207 if (filename
== NULL
) {
3213 ret
= net_ads_kerberos_pac_common(c
, argc
, argv
, &pac_data_ctr
);
3218 if (filename
== NULL
) {
3219 d_printf(_("please define \"filename=<filename>\" to save the PAC\n"));
3223 /* save the raw format */
3224 if (!file_save(filename
, pac_data_ctr
->pac_blob
.data
, pac_data_ctr
->pac_blob
.length
)) {
3225 d_printf(_("failed to save PAC in %s\n"), filename
);
3232 static int net_ads_kerberos_pac(struct net_context
*c
, int argc
, const char **argv
)
3234 struct functable func
[] = {
3237 net_ads_kerberos_pac_dump
,
3239 N_("Dump Kerberos PAC"),
3240 N_("net ads kerberos pac dump\n"
3241 " Dump a Kerberos PAC to stdout")
3245 net_ads_kerberos_pac_save
,
3247 N_("Save Kerberos PAC"),
3248 N_("net ads kerberos pac save\n"
3249 " Save a Kerberos PAC in a file")
3252 {NULL
, NULL
, 0, NULL
, NULL
}
3255 return net_run_function(c
, argc
, argv
, "net ads kerberos pac", func
);
3258 static int net_ads_kerberos_kinit(struct net_context
*c
, int argc
, const char **argv
)
3262 const char *principal
= NULL
;
3263 const char *password
= NULL
;
3265 if (c
->display_usage
) {
3267 "net ads kerberos kinit\n"
3270 _("Get Ticket Granting Ticket (TGT) for the user"));
3274 principal
= cli_credentials_get_principal(c
->creds
, c
);
3275 if (principal
== NULL
) {
3276 d_printf("cli_credentials_get_principal() failed\n");
3279 password
= cli_credentials_get_password(c
->creds
);
3281 ret
= kerberos_kinit_password_ext(principal
,
3289 2592000, /* one month */
3295 d_printf(_("failed to kinit password: %s\n"),
3301 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
3303 struct functable func
[] = {
3306 net_ads_kerberos_kinit
,
3308 N_("Retrieve Ticket Granting Ticket (TGT)"),
3309 N_("net ads kerberos kinit\n"
3310 " Receive Ticket Granting Ticket (TGT)")
3314 net_ads_kerberos_renew
,
3316 N_("Renew Ticket Granting Ticket from credential cache"),
3317 N_("net ads kerberos renew\n"
3318 " Renew Ticket Granting Ticket (TGT) from "
3323 net_ads_kerberos_pac
,
3325 N_("Dump Kerberos PAC"),
3326 N_("net ads kerberos pac\n"
3327 " Dump Kerberos PAC")
3329 {NULL
, NULL
, 0, NULL
, NULL
}
3332 return net_run_function(c
, argc
, argv
, "net ads kerberos", func
);
3335 static int net_ads_setspn_list(struct net_context
*c
,
3339 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3340 ADS_STRUCT
*ads
= NULL
;
3345 if (c
->display_usage
) {
3348 _("net ads setspn list [machinename]\n"));
3349 TALLOC_FREE(tmp_ctx
);
3353 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3354 if (!ADS_ERR_OK(status
)) {
3359 ok
= ads_setspn_list(ads
, argv
[0]);
3361 ok
= ads_setspn_list(ads
, lp_netbios_name());
3366 TALLOC_FREE(tmp_ctx
);
3370 static int net_ads_setspn_add(struct net_context
*c
, int argc
, const char **argv
)
3372 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3373 ADS_STRUCT
*ads
= NULL
;
3378 if (c
->display_usage
|| argc
< 1) {
3381 _("net ads setspn add [machinename] spn\n"));
3382 TALLOC_FREE(tmp_ctx
);
3386 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3387 if (!ADS_ERR_OK(status
)) {
3392 ok
= ads_setspn_add(ads
, argv
[0], argv
[1]);
3394 ok
= ads_setspn_add(ads
, lp_netbios_name(), argv
[0]);
3399 TALLOC_FREE(tmp_ctx
);
3403 static int net_ads_setspn_delete(struct net_context
*c
, int argc
, const char **argv
)
3405 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3406 ADS_STRUCT
*ads
= NULL
;
3411 if (c
->display_usage
|| argc
< 1) {
3414 _("net ads setspn delete [machinename] spn\n"));
3415 TALLOC_FREE(tmp_ctx
);
3419 status
= ads_startup(c
, true, tmp_ctx
, &ads
);
3420 if (!ADS_ERR_OK(status
)) {
3425 ok
= ads_setspn_delete(ads
, argv
[0], argv
[1]);
3427 ok
= ads_setspn_delete(ads
, lp_netbios_name(), argv
[0]);
3432 TALLOC_FREE(tmp_ctx
);
3436 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
3438 struct functable func
[] = {
3441 net_ads_setspn_list
,
3443 N_("List Service Principal Names (SPN)"),
3444 N_("net ads setspn list [machine]\n"
3445 " List Service Principal Names (SPN)")
3451 N_("Add Service Principal Names (SPN)"),
3452 N_("net ads setspn add [machine] spn\n"
3453 " Add Service Principal Names (SPN)")
3457 net_ads_setspn_delete
,
3459 N_("Delete Service Principal Names (SPN)"),
3460 N_("net ads setspn delete [machine] spn\n"
3461 " Delete Service Principal Names (SPN)")
3463 {NULL
, NULL
, 0, NULL
, NULL
}
3466 return net_run_function(c
, argc
, argv
, "net ads setspn", func
);
3469 static int net_ads_enctype_lookup_account(struct net_context
*c
,
3471 const char *account
,
3473 const char **enctype_str
)
3476 const char *attrs
[] = {
3477 "msDS-SupportedEncryptionTypes",
3484 filter
= talloc_asprintf(c
, "(&(objectclass=user)(sAMAccountName=%s))",
3486 if (filter
== NULL
) {
3490 status
= ads_search(ads
, res
, filter
, attrs
);
3491 if (!ADS_ERR_OK(status
)) {
3492 d_printf(_("no account found with filter: %s\n"), filter
);
3496 count
= ads_count_replies(ads
, *res
);
3501 d_printf(_("no account found with filter: %s\n"), filter
);
3504 d_printf(_("multiple accounts found with filter: %s\n"), filter
);
3509 *enctype_str
= ads_pull_string(ads
, c
, *res
,
3510 "msDS-SupportedEncryptionTypes");
3511 if (*enctype_str
== NULL
) {
3512 d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n"));
3522 static void net_ads_enctype_dump_enctypes(const char *username
,
3523 const char *enctype_str
)
3525 int enctypes
= atoi(enctype_str
);
3527 d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\": %d (0x%08x)\n"),
3528 username
, enctypes
, enctypes
);
3530 printf("[%s] 0x%08x DES-CBC-CRC\n",
3531 enctypes
& ENC_CRC32
? "X" : " ",
3533 printf("[%s] 0x%08x DES-CBC-MD5\n",
3534 enctypes
& ENC_RSA_MD5
? "X" : " ",
3536 printf("[%s] 0x%08x RC4-HMAC\n",
3537 enctypes
& ENC_RC4_HMAC_MD5
? "X" : " ",
3539 printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n",
3540 enctypes
& ENC_HMAC_SHA1_96_AES128
? "X" : " ",
3541 ENC_HMAC_SHA1_96_AES128
);
3542 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n",
3543 enctypes
& ENC_HMAC_SHA1_96_AES256
? "X" : " ",
3544 ENC_HMAC_SHA1_96_AES256
);
3545 printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96-SK\n",
3546 enctypes
& ENC_HMAC_SHA1_96_AES256_SK
? "X" : " ",
3547 ENC_HMAC_SHA1_96_AES256_SK
);
3548 printf("[%s] 0x%08x RESOURCE-SID-COMPRESSION-DISABLED\n",
3549 enctypes
& KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
? "X" : " ",
3550 KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
);
3553 static int net_ads_enctypes_list(struct net_context
*c
, int argc
, const char **argv
)
3555 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3557 ADS_STRUCT
*ads
= NULL
;
3558 LDAPMessage
*res
= NULL
;
3559 const char *str
= NULL
;
3562 if (c
->display_usage
|| (argc
< 1)) {
3564 "net ads enctypes list <account_name>\n"
3567 _("List supported enctypes"));
3568 TALLOC_FREE(tmp_ctx
);
3572 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3573 if (!ADS_ERR_OK(status
)) {
3577 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3582 net_ads_enctype_dump_enctypes(argv
[0], str
);
3586 ads_msgfree(ads
, res
);
3587 TALLOC_FREE(tmp_ctx
);
3591 static int net_ads_enctypes_set(struct net_context
*c
, int argc
, const char **argv
)
3593 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3596 ADS_STRUCT
*ads
= NULL
;
3597 LDAPMessage
*res
= NULL
;
3598 const char *etype_list_str
= NULL
;
3599 const char *dn
= NULL
;
3600 ADS_MODLIST mods
= NULL
;
3601 uint32_t etype_list
;
3602 const char *str
= NULL
;
3604 if (c
->display_usage
|| argc
< 1) {
3606 "net ads enctypes set <sAMAccountName> [enctypes]\n"
3609 _("Set supported enctypes"));
3610 TALLOC_FREE(tmp_ctx
);
3614 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3615 if (!ADS_ERR_OK(status
)) {
3619 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3624 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3630 etype_list
|= ENC_RC4_HMAC_MD5
;
3631 etype_list
|= ENC_HMAC_SHA1_96_AES128
;
3632 etype_list
|= ENC_HMAC_SHA1_96_AES256
;
3634 if (argv
[1] != NULL
) {
3635 sscanf(argv
[1], "%i", &etype_list
);
3638 etype_list_str
= talloc_asprintf(tmp_ctx
, "%d", etype_list
);
3639 if (!etype_list_str
) {
3643 mods
= ads_init_mods(tmp_ctx
);
3648 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes",
3650 if (!ADS_ERR_OK(status
)) {
3654 status
= ads_gen_mod(ads
, dn
, mods
);
3655 if (!ADS_ERR_OK(status
)) {
3656 d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"),
3657 ads_errstr(status
));
3661 ads_msgfree(ads
, res
);
3664 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, &str
);
3669 net_ads_enctype_dump_enctypes(argv
[0], str
);
3673 ads_msgfree(ads
, res
);
3674 TALLOC_FREE(tmp_ctx
);
3678 static int net_ads_enctypes_delete(struct net_context
*c
, int argc
, const char **argv
)
3680 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
3683 ADS_STRUCT
*ads
= NULL
;
3684 LDAPMessage
*res
= NULL
;
3685 const char *dn
= NULL
;
3686 ADS_MODLIST mods
= NULL
;
3688 if (c
->display_usage
|| argc
< 1) {
3690 "net ads enctypes delete <sAMAccountName>\n"
3693 _("Delete supported enctypes"));
3694 TALLOC_FREE(tmp_ctx
);
3698 status
= ads_startup(c
, false, tmp_ctx
, &ads
);
3699 if (!ADS_ERR_OK(status
)) {
3703 ret
= net_ads_enctype_lookup_account(c
, ads
, argv
[0], &res
, NULL
);
3708 dn
= ads_get_dn(ads
, tmp_ctx
, res
);
3713 mods
= ads_init_mods(tmp_ctx
);
3718 status
= ads_mod_str(tmp_ctx
, &mods
, "msDS-SupportedEncryptionTypes", NULL
);
3719 if (!ADS_ERR_OK(status
)) {
3723 status
= ads_gen_mod(ads
, dn
, mods
);
3724 if (!ADS_ERR_OK(status
)) {
3725 d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"),
3726 ads_errstr(status
));
3733 ads_msgfree(ads
, res
);
3734 TALLOC_FREE(tmp_ctx
);
3738 static int net_ads_enctypes(struct net_context
*c
, int argc
, const char **argv
)
3740 struct functable func
[] = {
3743 net_ads_enctypes_list
,
3745 N_("List the supported encryption types"),
3746 N_("net ads enctypes list <account_name>\n"
3747 " List the supported encryption types")
3751 net_ads_enctypes_set
,
3753 N_("Set the supported encryption types"),
3754 N_("net ads enctypes set <account_name> [enctypes]\n"
3755 " Set the supported encryption types")
3759 net_ads_enctypes_delete
,
3761 N_("Delete the msDS-SupportedEncryptionTypes attribute"),
3762 N_("net ads enctypes delete <account_name>\n"
3763 " Delete the LDAP attribute")
3766 {NULL
, NULL
, 0, NULL
, NULL
}
3769 return net_run_function(c
, argc
, argv
, "net ads enctypes", func
);
3773 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
3775 struct functable func
[] = {
3780 N_("Display details on remote ADS server"),
3782 " Display details on remote ADS server")
3788 N_("Join the local machine to ADS realm"),
3790 " Join the local machine to ADS realm")
3796 N_("Validate machine account"),
3797 N_("net ads testjoin\n"
3798 " Validate machine account")
3804 N_("Remove the local machine from ADS"),
3805 N_("net ads leave\n"
3806 " Remove the local machine from ADS")
3812 N_("Display machine account details"),
3813 N_("net ads status\n"
3814 " Display machine account details")
3820 N_("List/modify users"),
3822 " List/modify users")
3828 N_("List/modify groups"),
3829 N_("net ads group\n"
3830 " List/modify groups")
3836 N_("Issue dynamic DNS update"),
3838 " Issue dynamic DNS update")
3844 N_("Change user passwords"),
3845 N_("net ads password\n"
3846 " Change user passwords")
3850 net_ads_changetrustpw
,
3852 N_("Change trust account password"),
3853 N_("net ads changetrustpw\n"
3854 " Change trust account password")
3860 N_("List/modify printer entries"),
3861 N_("net ads printer\n"
3862 " List/modify printer entries")
3868 N_("Issue LDAP search using filter"),
3869 N_("net ads search\n"
3870 " Issue LDAP search using filter")
3876 N_("Issue LDAP search by DN"),
3878 " Issue LDAP search by DN")
3884 N_("Issue LDAP search by SID"),
3886 " Issue LDAP search by SID")
3892 N_("Display workgroup name"),
3893 N_("net ads workgroup\n"
3894 " Display the workgroup name")
3900 N_("Perform CLDAP query on DC"),
3901 N_("net ads lookup\n"
3902 " Find the ADS DC using CLDAP lookups")
3908 N_("Manage local keytab file"),
3909 N_("net ads keytab\n"
3910 " Manage local keytab file")
3916 N_("Manage Service Principal Names (SPN)s"),
3917 N_("net ads spnset\n"
3918 " Manage Service Principal Names (SPN)s")
3924 N_("Manage group policy objects"),
3926 " Manage group policy objects")
3932 N_("Manage kerberos keytab"),
3933 N_("net ads kerberos\n"
3934 " Manage kerberos keytab")
3940 N_("List/modify supported encryption types"),
3941 N_("net ads enctypes\n"
3942 " List/modify enctypes")
3944 {NULL
, NULL
, 0, NULL
, NULL
}
3947 return net_run_function(c
, argc
, argv
, "net ads", func
);
3952 static int net_ads_noads(void)
3954 d_fprintf(stderr
, _("ADS support not compiled in\n"));
3958 int net_ads_keytab(struct net_context
*c
, int argc
, const char **argv
)
3960 return net_ads_noads();
3963 int net_ads_kerberos(struct net_context
*c
, int argc
, const char **argv
)
3965 return net_ads_noads();
3968 int net_ads_setspn(struct net_context
*c
, int argc
, const char **argv
)
3970 return net_ads_noads();
3973 int net_ads_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
3975 return net_ads_noads();
3978 int net_ads_join(struct net_context
*c
, int argc
, const char **argv
)
3980 return net_ads_noads();
3983 int net_ads_user(struct net_context
*c
, int argc
, const char **argv
)
3985 return net_ads_noads();
3988 int net_ads_group(struct net_context
*c
, int argc
, const char **argv
)
3990 return net_ads_noads();
3993 int net_ads_gpo(struct net_context
*c
, int argc
, const char **argv
)
3995 return net_ads_noads();
3998 /* this one shouldn't display a message */
3999 int net_ads_check(struct net_context
*c
)
4004 int net_ads_check_our_domain(struct net_context
*c
)
4009 int net_ads(struct net_context
*c
, int argc
, const char **argv
)
4011 return net_ads_noads();
4014 #endif /* HAVE_ADS */