2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Gerald (Jerry) Carter 2006
5 * Copyright (C) Guenther Deschner 2007-2008
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "librpc/gen_ndr/ndr_libnet_join.h"
24 #include "libnet/libnet_join.h"
25 #include "libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/ndr_samr_c.h"
27 #include "rpc_client/init_samr.h"
28 #include "../librpc/gen_ndr/ndr_lsa_c.h"
29 #include "rpc_client/cli_lsarpc.h"
30 #include "../librpc/gen_ndr/ndr_netlogon.h"
31 #include "rpc_client/cli_netlogon.h"
32 #include "lib/smbconf/smbconf.h"
33 #include "lib/smbconf/smbconf_reg.h"
34 #include "../libds/common/flags.h"
36 #include "rpc_client/init_lsa.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
40 #include "libsmb/libsmb.h"
41 #include "../libcli/smb/smbXcli_base.h"
42 #include "lib/param/loadparm.h"
43 #include "libcli/auth/netlogon_creds_cli.h"
44 #include "auth/credentials/credentials.h"
46 /****************************************************************
47 ****************************************************************/
49 #define LIBNET_JOIN_DUMP_CTX(ctx, r, f) \
52 str = NDR_PRINT_FUNCTION_STRING(ctx, libnet_JoinCtx, f, r); \
53 DEBUG(1,("libnet_Join:\n%s", str)); \
57 #define LIBNET_JOIN_IN_DUMP_CTX(ctx, r) \
58 LIBNET_JOIN_DUMP_CTX(ctx, r, NDR_IN | NDR_SET_VALUES)
59 #define LIBNET_JOIN_OUT_DUMP_CTX(ctx, r) \
60 LIBNET_JOIN_DUMP_CTX(ctx, r, NDR_OUT)
62 #define LIBNET_UNJOIN_DUMP_CTX(ctx, r, f) \
65 str = NDR_PRINT_FUNCTION_STRING(ctx, libnet_UnjoinCtx, f, r); \
66 DEBUG(1,("libnet_Unjoin:\n%s", str)); \
70 #define LIBNET_UNJOIN_IN_DUMP_CTX(ctx, r) \
71 LIBNET_UNJOIN_DUMP_CTX(ctx, r, NDR_IN | NDR_SET_VALUES)
72 #define LIBNET_UNJOIN_OUT_DUMP_CTX(ctx, r) \
73 LIBNET_UNJOIN_DUMP_CTX(ctx, r, NDR_OUT)
75 /****************************************************************
76 ****************************************************************/
78 static void libnet_join_set_error_string(TALLOC_CTX
*mem_ctx
,
79 struct libnet_JoinCtx
*r
,
80 const char *format
, ...)
84 if (r
->out
.error_string
) {
88 va_start(args
, format
);
89 r
->out
.error_string
= talloc_vasprintf(mem_ctx
, format
, args
);
93 /****************************************************************
94 ****************************************************************/
96 static void libnet_unjoin_set_error_string(TALLOC_CTX
*mem_ctx
,
97 struct libnet_UnjoinCtx
*r
,
98 const char *format
, ...)
102 if (r
->out
.error_string
) {
106 va_start(args
, format
);
107 r
->out
.error_string
= talloc_vasprintf(mem_ctx
, format
, args
);
113 /****************************************************************
114 ****************************************************************/
116 static ADS_STATUS
libnet_connect_ads(const char *dns_domain_name
,
117 const char *netbios_domain_name
,
119 const char *user_name
,
120 const char *password
,
124 ADS_STRUCT
*my_ads
= NULL
;
127 my_ads
= ads_init(dns_domain_name
,
131 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
135 SAFE_FREE(my_ads
->auth
.user_name
);
136 my_ads
->auth
.user_name
= SMB_STRDUP(user_name
);
137 if ((cp
= strchr_m(my_ads
->auth
.user_name
, '@'))!=0) {
139 SAFE_FREE(my_ads
->auth
.realm
);
140 my_ads
->auth
.realm
= smb_xstrdup(cp
);
141 if (!strupper_m(my_ads
->auth
.realm
)) {
142 ads_destroy(&my_ads
);
143 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
149 SAFE_FREE(my_ads
->auth
.password
);
150 my_ads
->auth
.password
= SMB_STRDUP(password
);
153 status
= ads_connect_user_creds(my_ads
);
154 if (!ADS_ERR_OK(status
)) {
155 ads_destroy(&my_ads
);
163 /****************************************************************
164 ****************************************************************/
166 static ADS_STATUS
libnet_join_connect_ads(TALLOC_CTX
*mem_ctx
,
167 struct libnet_JoinCtx
*r
)
171 status
= libnet_connect_ads(r
->out
.dns_domain_name
,
172 r
->out
.netbios_domain_name
,
175 r
->in
.admin_password
,
177 if (!ADS_ERR_OK(status
)) {
178 libnet_join_set_error_string(mem_ctx
, r
,
179 "failed to connect to AD: %s",
184 if (!r
->out
.netbios_domain_name
) {
185 r
->out
.netbios_domain_name
= talloc_strdup(mem_ctx
,
186 r
->in
.ads
->server
.workgroup
);
187 ADS_ERROR_HAVE_NO_MEMORY(r
->out
.netbios_domain_name
);
190 if (!r
->out
.dns_domain_name
) {
191 r
->out
.dns_domain_name
= talloc_strdup(mem_ctx
,
192 r
->in
.ads
->config
.realm
);
193 ADS_ERROR_HAVE_NO_MEMORY(r
->out
.dns_domain_name
);
196 r
->out
.domain_is_ad
= true;
201 /****************************************************************
202 ****************************************************************/
204 static ADS_STATUS
libnet_unjoin_connect_ads(TALLOC_CTX
*mem_ctx
,
205 struct libnet_UnjoinCtx
*r
)
209 status
= libnet_connect_ads(r
->in
.domain_name
,
213 r
->in
.admin_password
,
215 if (!ADS_ERR_OK(status
)) {
216 libnet_unjoin_set_error_string(mem_ctx
, r
,
217 "failed to connect to AD: %s",
224 /****************************************************************
225 join a domain using ADS (LDAP mods)
226 ****************************************************************/
228 static ADS_STATUS
libnet_join_precreate_machine_acct(TALLOC_CTX
*mem_ctx
,
229 struct libnet_JoinCtx
*r
)
232 LDAPMessage
*res
= NULL
;
233 const char *attrs
[] = { "dn", NULL
};
236 status
= ads_check_ou_dn(mem_ctx
, r
->in
.ads
, &r
->in
.account_ou
);
237 if (!ADS_ERR_OK(status
)) {
241 status
= ads_search_dn(r
->in
.ads
, &res
, r
->in
.account_ou
, attrs
);
242 if (!ADS_ERR_OK(status
)) {
246 if (ads_count_replies(r
->in
.ads
, res
) != 1) {
247 ads_msgfree(r
->in
.ads
, res
);
248 return ADS_ERROR_LDAP(LDAP_NO_SUCH_OBJECT
);
251 ads_msgfree(r
->in
.ads
, res
);
253 /* Attempt to create the machine account and bail if this fails.
254 Assume that the admin wants exactly what they requested */
256 status
= ads_create_machine_acct(r
->in
.ads
,
260 if (ADS_ERR_OK(status
)) {
261 DEBUG(1,("machine account creation created\n"));
263 } else if ((status
.error_type
== ENUM_ADS_ERROR_LDAP
) &&
264 (status
.err
.rc
== LDAP_ALREADY_EXISTS
)) {
265 status
= ADS_SUCCESS
;
268 if (!ADS_ERR_OK(status
)) {
269 DEBUG(1,("machine account creation failed\n"));
273 status
= ads_move_machine_acct(r
->in
.ads
,
277 if (!ADS_ERR_OK(status
)) {
278 DEBUG(1,("failure to locate/move pre-existing "
279 "machine account\n"));
283 DEBUG(1,("The machine account %s the specified OU.\n",
284 moved
? "was moved into" : "already exists in"));
289 /****************************************************************
290 ****************************************************************/
292 static ADS_STATUS
libnet_unjoin_remove_machine_acct(TALLOC_CTX
*mem_ctx
,
293 struct libnet_UnjoinCtx
*r
)
298 status
= libnet_unjoin_connect_ads(mem_ctx
, r
);
299 if (!ADS_ERR_OK(status
)) {
300 libnet_unjoin_set_error_string(mem_ctx
, r
,
301 "failed to connect to AD: %s",
307 status
= ads_leave_realm(r
->in
.ads
, r
->in
.machine_name
);
308 if (!ADS_ERR_OK(status
)) {
309 libnet_unjoin_set_error_string(mem_ctx
, r
,
310 "failed to leave realm: %s",
318 /****************************************************************
319 ****************************************************************/
321 static ADS_STATUS
libnet_join_find_machine_acct(TALLOC_CTX
*mem_ctx
,
322 struct libnet_JoinCtx
*r
)
325 LDAPMessage
*res
= NULL
;
328 if (!r
->in
.machine_name
) {
329 return ADS_ERROR(LDAP_NO_MEMORY
);
332 status
= ads_find_machine_acct(r
->in
.ads
,
335 if (!ADS_ERR_OK(status
)) {
339 if (ads_count_replies(r
->in
.ads
, res
) != 1) {
340 status
= ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
344 dn
= ads_get_dn(r
->in
.ads
, mem_ctx
, res
);
346 status
= ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
350 r
->out
.dn
= talloc_strdup(mem_ctx
, dn
);
352 status
= ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
357 ads_msgfree(r
->in
.ads
, res
);
363 /****************************************************************
364 Set a machines dNSHostName and servicePrincipalName attributes
365 ****************************************************************/
367 static ADS_STATUS
libnet_join_set_machine_spn(TALLOC_CTX
*mem_ctx
,
368 struct libnet_JoinCtx
*r
)
373 const char *spn_array
[3] = {NULL
, NULL
, NULL
};
378 status
= libnet_join_find_machine_acct(mem_ctx
, r
);
379 if (!ADS_ERR_OK(status
)) {
383 /* Windows only creates HOST/shortname & HOST/fqdn. */
385 spn
= talloc_asprintf(mem_ctx
, "HOST/%s", r
->in
.machine_name
);
387 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
389 if (!strupper_m(spn
)) {
390 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
394 if (!name_to_fqdn(my_fqdn
, r
->in
.machine_name
)
395 || (strchr(my_fqdn
, '.') == NULL
)) {
396 fstr_sprintf(my_fqdn
, "%s.%s", r
->in
.machine_name
,
397 r
->out
.dns_domain_name
);
400 if (!strlower_m(my_fqdn
)) {
401 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
404 if (!strequal(my_fqdn
, r
->in
.machine_name
)) {
405 spn
= talloc_asprintf(mem_ctx
, "HOST/%s", my_fqdn
);
407 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
412 mods
= ads_init_mods(mem_ctx
);
414 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
417 /* fields of primary importance */
419 status
= ads_mod_str(mem_ctx
, &mods
, "dNSHostName", my_fqdn
);
420 if (!ADS_ERR_OK(status
)) {
421 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
424 status
= ads_mod_strlist(mem_ctx
, &mods
, "servicePrincipalName",
426 if (!ADS_ERR_OK(status
)) {
427 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
430 return ads_gen_mod(r
->in
.ads
, r
->out
.dn
, mods
);
433 /****************************************************************
434 ****************************************************************/
436 static ADS_STATUS
libnet_join_set_machine_upn(TALLOC_CTX
*mem_ctx
,
437 struct libnet_JoinCtx
*r
)
442 if (!r
->in
.create_upn
) {
448 status
= libnet_join_find_machine_acct(mem_ctx
, r
);
449 if (!ADS_ERR_OK(status
)) {
454 const char *realm
= r
->out
.dns_domain_name
;
456 /* in case we are about to generate a keytab during the join
457 * make sure the default upn we create is usable with kinit -k.
460 if (USE_KERBEROS_KEYTAB
) {
461 realm
= talloc_strdup_upper(mem_ctx
,
462 r
->out
.dns_domain_name
);
466 return ADS_ERROR(LDAP_NO_MEMORY
);
469 r
->in
.upn
= talloc_asprintf(mem_ctx
,
474 return ADS_ERROR(LDAP_NO_MEMORY
);
478 /* now do the mods */
480 mods
= ads_init_mods(mem_ctx
);
482 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
485 /* fields of primary importance */
487 status
= ads_mod_str(mem_ctx
, &mods
, "userPrincipalName", r
->in
.upn
);
488 if (!ADS_ERR_OK(status
)) {
489 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
492 return ads_gen_mod(r
->in
.ads
, r
->out
.dn
, mods
);
496 /****************************************************************
497 ****************************************************************/
499 static ADS_STATUS
libnet_join_set_os_attributes(TALLOC_CTX
*mem_ctx
,
500 struct libnet_JoinCtx
*r
)
506 if (!r
->in
.os_name
|| !r
->in
.os_version
) {
512 status
= libnet_join_find_machine_acct(mem_ctx
, r
);
513 if (!ADS_ERR_OK(status
)) {
517 /* now do the mods */
519 mods
= ads_init_mods(mem_ctx
);
521 return ADS_ERROR(LDAP_NO_MEMORY
);
524 os_sp
= talloc_asprintf(mem_ctx
, "Samba %s", samba_version_string());
526 return ADS_ERROR(LDAP_NO_MEMORY
);
529 /* fields of primary importance */
531 status
= ads_mod_str(mem_ctx
, &mods
, "operatingSystem",
533 if (!ADS_ERR_OK(status
)) {
537 status
= ads_mod_str(mem_ctx
, &mods
, "operatingSystemVersion",
539 if (!ADS_ERR_OK(status
)) {
543 status
= ads_mod_str(mem_ctx
, &mods
, "operatingSystemServicePack",
545 if (!ADS_ERR_OK(status
)) {
549 return ads_gen_mod(r
->in
.ads
, r
->out
.dn
, mods
);
552 /****************************************************************
553 ****************************************************************/
555 static bool libnet_join_create_keytab(TALLOC_CTX
*mem_ctx
,
556 struct libnet_JoinCtx
*r
)
558 if (!USE_SYSTEM_KEYTAB
) {
562 if (ads_keytab_create_default(r
->in
.ads
) != 0) {
569 /****************************************************************
570 ****************************************************************/
572 static bool libnet_join_derive_salting_principal(TALLOC_CTX
*mem_ctx
,
573 struct libnet_JoinCtx
*r
)
575 uint32_t domain_func
;
577 const char *salt
= NULL
;
578 char *std_salt
= NULL
;
580 status
= ads_domain_func_level(r
->in
.ads
, &domain_func
);
581 if (!ADS_ERR_OK(status
)) {
582 libnet_join_set_error_string(mem_ctx
, r
,
583 "failed to determine domain functional level: %s",
588 /* go ahead and setup the default salt */
590 std_salt
= kerberos_standard_des_salt();
592 libnet_join_set_error_string(mem_ctx
, r
,
593 "failed to obtain standard DES salt");
597 salt
= talloc_strdup(mem_ctx
, std_salt
);
604 /* if it's a Windows functional domain, we have to look for the UPN */
606 if (domain_func
== DS_DOMAIN_FUNCTION_2000
) {
609 upn
= ads_get_upn(r
->in
.ads
, mem_ctx
,
612 salt
= talloc_strdup(mem_ctx
, upn
);
619 return kerberos_secrets_store_des_salt(salt
);
622 /****************************************************************
623 ****************************************************************/
625 static ADS_STATUS
libnet_join_post_processing_ads(TALLOC_CTX
*mem_ctx
,
626 struct libnet_JoinCtx
*r
)
631 status
= libnet_join_connect_ads(mem_ctx
, r
);
632 if (!ADS_ERR_OK(status
)) {
637 status
= libnet_join_set_machine_spn(mem_ctx
, r
);
638 if (!ADS_ERR_OK(status
)) {
639 libnet_join_set_error_string(mem_ctx
, r
,
640 "Failed to set machine spn: %s\n"
641 "Do you have sufficient permissions to create machine "
647 status
= libnet_join_set_os_attributes(mem_ctx
, r
);
648 if (!ADS_ERR_OK(status
)) {
649 libnet_join_set_error_string(mem_ctx
, r
,
650 "failed to set machine os attributes: %s",
655 status
= libnet_join_set_machine_upn(mem_ctx
, r
);
656 if (!ADS_ERR_OK(status
)) {
657 libnet_join_set_error_string(mem_ctx
, r
,
658 "failed to set machine upn: %s",
663 if (!libnet_join_derive_salting_principal(mem_ctx
, r
)) {
664 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
667 if (!libnet_join_create_keytab(mem_ctx
, r
)) {
668 libnet_join_set_error_string(mem_ctx
, r
,
669 "failed to create kerberos keytab");
670 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
675 #endif /* HAVE_ADS */
677 /****************************************************************
678 Store the machine password and domain SID
679 ****************************************************************/
681 static bool libnet_join_joindomain_store_secrets(TALLOC_CTX
*mem_ctx
,
682 struct libnet_JoinCtx
*r
)
684 if (!secrets_store_domain_sid(r
->out
.netbios_domain_name
,
687 DEBUG(1,("Failed to save domain sid\n"));
691 if (!secrets_store_machine_password(r
->in
.machine_password
,
692 r
->out
.netbios_domain_name
,
693 r
->in
.secure_channel_type
))
695 DEBUG(1,("Failed to save machine password\n"));
702 /****************************************************************
703 Connect dc's IPC$ share
704 ****************************************************************/
706 static NTSTATUS
libnet_join_connect_dc_ipc(const char *dc
,
711 struct cli_state
**cli
)
716 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
719 if (use_kerberos
&& pass
) {
720 flags
|= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
;
723 return cli_full_connection(cli
, NULL
,
731 SMB_SIGNING_DEFAULT
);
734 /****************************************************************
735 Lookup domain dc's info
736 ****************************************************************/
738 static NTSTATUS
libnet_join_lookup_dc_rpc(TALLOC_CTX
*mem_ctx
,
739 struct libnet_JoinCtx
*r
,
740 struct cli_state
**cli
)
742 struct rpc_pipe_client
*pipe_hnd
= NULL
;
743 struct policy_handle lsa_pol
;
744 NTSTATUS status
, result
;
745 union lsa_PolicyInformation
*info
= NULL
;
746 struct dcerpc_binding_handle
*b
;
748 status
= libnet_join_connect_dc_ipc(r
->in
.dc_name
,
751 r
->in
.admin_password
,
754 if (!NT_STATUS_IS_OK(status
)) {
758 status
= cli_rpc_pipe_open_noauth(*cli
, &ndr_table_lsarpc
,
760 if (!NT_STATUS_IS_OK(status
)) {
761 DEBUG(0,("Error connecting to LSA pipe. Error was %s\n",
766 b
= pipe_hnd
->binding_handle
;
768 status
= rpccli_lsa_open_policy(pipe_hnd
, mem_ctx
, true,
769 SEC_FLAG_MAXIMUM_ALLOWED
, &lsa_pol
);
770 if (!NT_STATUS_IS_OK(status
)) {
774 status
= dcerpc_lsa_QueryInfoPolicy2(b
, mem_ctx
,
779 if (NT_STATUS_IS_OK(status
) && NT_STATUS_IS_OK(result
)) {
780 r
->out
.domain_is_ad
= true;
781 r
->out
.netbios_domain_name
= info
->dns
.name
.string
;
782 r
->out
.dns_domain_name
= info
->dns
.dns_domain
.string
;
783 r
->out
.forest_name
= info
->dns
.dns_forest
.string
;
784 r
->out
.domain_sid
= dom_sid_dup(mem_ctx
, info
->dns
.sid
);
785 NT_STATUS_HAVE_NO_MEMORY(r
->out
.domain_sid
);
788 if (!NT_STATUS_IS_OK(status
)) {
789 status
= dcerpc_lsa_QueryInfoPolicy(b
, mem_ctx
,
791 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
794 if (!NT_STATUS_IS_OK(status
)) {
797 if (!NT_STATUS_IS_OK(result
)) {
802 r
->out
.netbios_domain_name
= info
->account_domain
.name
.string
;
803 r
->out
.domain_sid
= dom_sid_dup(mem_ctx
, info
->account_domain
.sid
);
804 NT_STATUS_HAVE_NO_MEMORY(r
->out
.domain_sid
);
807 dcerpc_lsa_Close(b
, mem_ctx
, &lsa_pol
, &result
);
808 TALLOC_FREE(pipe_hnd
);
814 /****************************************************************
815 Do the domain join unsecure
816 ****************************************************************/
818 static NTSTATUS
libnet_join_joindomain_rpc_unsecure(TALLOC_CTX
*mem_ctx
,
819 struct libnet_JoinCtx
*r
,
820 struct cli_state
*cli
)
822 TALLOC_CTX
*frame
= talloc_stackframe();
823 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
824 struct netlogon_creds_cli_context
*netlogon_creds
= NULL
;
825 struct samr_Password current_nt_hash
;
826 const char *account_name
= NULL
;
829 status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_netlogon
,
831 if (!NT_STATUS_IS_OK(status
)) {
836 if (!r
->in
.machine_password
) {
837 r
->in
.machine_password
= generate_random_password(mem_ctx
,
838 DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
,
839 DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
);
840 if (r
->in
.machine_password
== NULL
) {
842 return NT_STATUS_NO_MEMORY
;
846 /* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */
847 E_md4hash(r
->in
.admin_password
, current_nt_hash
.hash
);
849 account_name
= talloc_asprintf(frame
, "%s$",
851 if (account_name
== NULL
) {
853 return NT_STATUS_NO_MEMORY
;
856 status
= rpccli_create_netlogon_creds(netlogon_pipe
->desthost
,
859 r
->in
.secure_channel_type
,
863 if (!NT_STATUS_IS_OK(status
)) {
868 status
= rpccli_setup_netlogon_creds(cli
,
870 true, /* force_reauth */
872 NULL
); /* previous_nt_hash */
873 if (!NT_STATUS_IS_OK(status
)) {
878 status
= netlogon_creds_cli_ServerPasswordSet(netlogon_creds
,
879 netlogon_pipe
->binding_handle
,
880 r
->in
.machine_password
,
881 NULL
); /* new_version */
882 if (!NT_STATUS_IS_OK(status
)) {
891 /****************************************************************
893 ****************************************************************/
895 static NTSTATUS
libnet_join_joindomain_rpc(TALLOC_CTX
*mem_ctx
,
896 struct libnet_JoinCtx
*r
,
897 struct cli_state
*cli
)
899 struct rpc_pipe_client
*pipe_hnd
= NULL
;
900 struct policy_handle sam_pol
, domain_pol
, user_pol
;
901 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
, result
;
903 struct lsa_String lsa_acct_name
;
905 uint32_t acct_flags
= ACB_WSTRUST
;
906 struct samr_Ids user_rids
;
907 struct samr_Ids name_types
;
908 union samr_UserInfo user_info
;
909 struct dcerpc_binding_handle
*b
= NULL
;
910 unsigned int old_timeout
= 0;
912 DATA_BLOB session_key
= data_blob_null
;
913 struct samr_CryptPassword crypt_pwd
;
914 struct samr_CryptPasswordEx crypt_pwd_ex
;
916 ZERO_STRUCT(sam_pol
);
917 ZERO_STRUCT(domain_pol
);
918 ZERO_STRUCT(user_pol
);
920 switch (r
->in
.secure_channel_type
) {
922 acct_flags
= ACB_WSTRUST
;
925 acct_flags
= ACB_SVRTRUST
;
928 return NT_STATUS_INVALID_PARAMETER
;
931 if (!r
->in
.machine_password
) {
932 r
->in
.machine_password
= generate_random_password(mem_ctx
,
933 DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
,
934 DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
);
935 NT_STATUS_HAVE_NO_MEMORY(r
->in
.machine_password
);
938 /* Open the domain */
940 status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_samr
,
942 if (!NT_STATUS_IS_OK(status
)) {
943 DEBUG(0,("Error connecting to SAM pipe. Error was %s\n",
948 b
= pipe_hnd
->binding_handle
;
950 status
= cli_get_session_key(mem_ctx
, pipe_hnd
, &session_key
);
951 if (!NT_STATUS_IS_OK(status
)) {
952 DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
957 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
959 SAMR_ACCESS_ENUM_DOMAINS
960 | SAMR_ACCESS_LOOKUP_DOMAIN
,
963 if (!NT_STATUS_IS_OK(status
)) {
966 if (!NT_STATUS_IS_OK(result
)) {
971 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
973 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
974 | SAMR_DOMAIN_ACCESS_CREATE_USER
975 | SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
979 if (!NT_STATUS_IS_OK(status
)) {
982 if (!NT_STATUS_IS_OK(result
)) {
987 /* Create domain user */
989 acct_name
= talloc_asprintf(mem_ctx
, "%s$", r
->in
.machine_name
);
990 if (!strlower_m(acct_name
)) {
991 status
= NT_STATUS_INVALID_PARAMETER
;
995 init_lsa_String(&lsa_acct_name
, acct_name
);
997 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
) {
998 uint32_t access_desired
=
999 SEC_GENERIC_READ
| SEC_GENERIC_WRITE
| SEC_GENERIC_EXECUTE
|
1000 SEC_STD_WRITE_DAC
| SEC_STD_DELETE
|
1001 SAMR_USER_ACCESS_SET_PASSWORD
|
1002 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
1003 SAMR_USER_ACCESS_SET_ATTRIBUTES
;
1004 uint32_t access_granted
= 0;
1006 DEBUG(10,("Creating account with desired access mask: %d\n",
1009 status
= dcerpc_samr_CreateUser2(b
, mem_ctx
,
1018 if (!NT_STATUS_IS_OK(status
)) {
1023 if (!NT_STATUS_IS_OK(status
) &&
1024 !NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
1026 DEBUG(10,("Creation of workstation account failed: %s\n",
1027 nt_errstr(status
)));
1029 /* If NT_STATUS_ACCESS_DENIED then we have a valid
1030 username/password combo but the user does not have
1031 administrator access. */
1033 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCESS_DENIED
)) {
1034 libnet_join_set_error_string(mem_ctx
, r
,
1035 "User specified does not have "
1036 "administrator privileges");
1042 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
1043 if (!(r
->in
.join_flags
&
1044 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
)) {
1049 /* We *must* do this.... don't ask... */
1051 if (NT_STATUS_IS_OK(status
)) {
1052 dcerpc_samr_Close(b
, mem_ctx
, &user_pol
, &result
);
1056 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
1063 if (!NT_STATUS_IS_OK(status
)) {
1066 if (!NT_STATUS_IS_OK(result
)) {
1070 if (user_rids
.count
!= 1) {
1071 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
1074 if (name_types
.count
!= 1) {
1075 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
1079 if (name_types
.ids
[0] != SID_NAME_USER
) {
1080 DEBUG(0,("%s is not a user account (type=%d)\n",
1081 acct_name
, name_types
.ids
[0]));
1082 status
= NT_STATUS_INVALID_WORKSTATION
;
1086 user_rid
= user_rids
.ids
[0];
1088 /* Open handle on user */
1090 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
1092 SEC_FLAG_MAXIMUM_ALLOWED
,
1096 if (!NT_STATUS_IS_OK(status
)) {
1099 if (!NT_STATUS_IS_OK(result
)) {
1104 /* Fill in the additional account flags now */
1106 acct_flags
|= ACB_PWNOEXP
;
1108 /* Set account flags on machine account */
1109 ZERO_STRUCT(user_info
.info16
);
1110 user_info
.info16
.acct_flags
= acct_flags
;
1112 status
= dcerpc_samr_SetUserInfo(b
, mem_ctx
,
1117 if (!NT_STATUS_IS_OK(status
)) {
1118 dcerpc_samr_DeleteUser(b
, mem_ctx
,
1122 libnet_join_set_error_string(mem_ctx
, r
,
1123 "Failed to set account flags for machine account (%s)\n",
1128 if (!NT_STATUS_IS_OK(result
)) {
1131 dcerpc_samr_DeleteUser(b
, mem_ctx
,
1135 libnet_join_set_error_string(mem_ctx
, r
,
1136 "Failed to set account flags for machine account (%s)\n",
1141 /* Set password on machine account - first try level 26 */
1144 * increase the timeout as password filter modules on the DC
1145 * might delay the operation for a significant amount of time
1147 old_timeout
= rpccli_set_timeout(pipe_hnd
, 600000);
1149 init_samr_CryptPasswordEx(r
->in
.machine_password
,
1153 user_info
.info26
.password
= crypt_pwd_ex
;
1154 user_info
.info26
.password_expired
= PASS_DONT_CHANGE_AT_NEXT_LOGON
;
1156 status
= dcerpc_samr_SetUserInfo2(b
, mem_ctx
,
1162 if (NT_STATUS_EQUAL(status
, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE
)) {
1164 /* retry with level 24 */
1166 init_samr_CryptPassword(r
->in
.machine_password
,
1170 user_info
.info24
.password
= crypt_pwd
;
1171 user_info
.info24
.password_expired
= PASS_DONT_CHANGE_AT_NEXT_LOGON
;
1173 status
= dcerpc_samr_SetUserInfo2(b
, mem_ctx
,
1180 old_timeout
= rpccli_set_timeout(pipe_hnd
, old_timeout
);
1182 if (!NT_STATUS_IS_OK(status
)) {
1184 dcerpc_samr_DeleteUser(b
, mem_ctx
,
1188 libnet_join_set_error_string(mem_ctx
, r
,
1189 "Failed to set password for machine account (%s)\n",
1193 if (!NT_STATUS_IS_OK(result
)) {
1196 dcerpc_samr_DeleteUser(b
, mem_ctx
,
1200 libnet_join_set_error_string(mem_ctx
, r
,
1201 "Failed to set password for machine account (%s)\n",
1206 status
= NT_STATUS_OK
;
1213 data_blob_clear_free(&session_key
);
1215 if (is_valid_policy_hnd(&sam_pol
)) {
1216 dcerpc_samr_Close(b
, mem_ctx
, &sam_pol
, &result
);
1218 if (is_valid_policy_hnd(&domain_pol
)) {
1219 dcerpc_samr_Close(b
, mem_ctx
, &domain_pol
, &result
);
1221 if (is_valid_policy_hnd(&user_pol
)) {
1222 dcerpc_samr_Close(b
, mem_ctx
, &user_pol
, &result
);
1224 TALLOC_FREE(pipe_hnd
);
1229 /****************************************************************
1230 ****************************************************************/
1232 NTSTATUS
libnet_join_ok(struct messaging_context
*msg_ctx
,
1233 const char *netbios_domain_name
,
1234 const char *dc_name
,
1235 const bool use_kerberos
)
1237 TALLOC_CTX
*frame
= talloc_stackframe();
1238 struct cli_state
*cli
= NULL
;
1239 struct rpc_pipe_client
*netlogon_pipe
= NULL
;
1240 struct netlogon_creds_cli_context
*netlogon_creds
= NULL
;
1241 struct netlogon_creds_CredentialState
*creds
= NULL
;
1242 uint32_t netlogon_flags
= 0;
1243 enum netr_SchannelType sec_chan_type
= 0;
1245 char *machine_password
= NULL
;
1246 const char *machine_name
= NULL
;
1247 const char *machine_account
= NULL
;
1249 struct samr_Password current_nt_hash
;
1250 struct samr_Password
*previous_nt_hash
= NULL
;
1255 return NT_STATUS_INVALID_PARAMETER
;
1258 if (!secrets_init()) {
1260 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1263 ok
= get_trust_pw_clear(netbios_domain_name
,
1269 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1272 machine_account
= talloc_asprintf(frame
, "%s$", machine_name
);
1273 if (machine_account
== NULL
) {
1274 SAFE_FREE(machine_password
);
1275 SAFE_FREE(previous_nt_hash
);
1277 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
1281 flags
|= CLI_FULL_CONNECTION_USE_KERBEROS
;
1284 status
= cli_full_connection(&cli
, NULL
,
1289 netbios_domain_name
,
1292 SMB_SIGNING_DEFAULT
);
1294 E_md4hash(machine_password
, current_nt_hash
.hash
);
1295 SAFE_FREE(machine_password
);
1297 if (!NT_STATUS_IS_OK(status
)) {
1298 status
= cli_full_connection(&cli
, NULL
,
1306 SMB_SIGNING_DEFAULT
);
1309 if (!NT_STATUS_IS_OK(status
)) {
1310 SAFE_FREE(previous_nt_hash
);
1315 status
= rpccli_create_netlogon_creds(dc_name
,
1316 netbios_domain_name
,
1322 if (!NT_STATUS_IS_OK(status
)) {
1323 SAFE_FREE(previous_nt_hash
);
1329 status
= rpccli_setup_netlogon_creds(cli
,
1331 true, /* force_reauth */
1334 SAFE_FREE(previous_nt_hash
);
1335 if (!NT_STATUS_IS_OK(status
)) {
1336 DEBUG(0,("connect_to_domain_password_server: "
1337 "unable to open the domain client session to "
1338 "machine %s. Flags[0x%08X] Error was : %s.\n",
1339 dc_name
, (unsigned)netlogon_flags
,
1340 nt_errstr(status
)));
1346 status
= netlogon_creds_cli_get(netlogon_creds
,
1349 if (!NT_STATUS_IS_OK(status
)) {
1354 netlogon_flags
= creds
->negotiate_flags
;
1357 if (!(netlogon_flags
& NETLOGON_NEG_AUTHENTICATED_RPC
)) {
1360 return NT_STATUS_OK
;
1363 status
= cli_rpc_pipe_open_schannel_with_key(
1364 cli
, &ndr_table_netlogon
, NCACN_NP
,
1365 netbios_domain_name
,
1366 netlogon_creds
, &netlogon_pipe
);
1368 TALLOC_FREE(netlogon_pipe
);
1370 if (!NT_STATUS_IS_OK(status
)) {
1371 DEBUG(0,("libnet_join_ok: failed to open schannel session "
1372 "on netlogon pipe to server %s for domain %s. "
1374 smbXcli_conn_remote_name(cli
->conn
),
1375 netbios_domain_name
, nt_errstr(status
)));
1383 return NT_STATUS_OK
;
1386 /****************************************************************
1387 ****************************************************************/
1389 static WERROR
libnet_join_post_verify(TALLOC_CTX
*mem_ctx
,
1390 struct libnet_JoinCtx
*r
)
1394 status
= libnet_join_ok(r
->in
.msg_ctx
,
1395 r
->out
.netbios_domain_name
,
1397 r
->in
.use_kerberos
);
1398 if (!NT_STATUS_IS_OK(status
)) {
1399 libnet_join_set_error_string(mem_ctx
, r
,
1400 "failed to verify domain membership after joining: %s",
1401 get_friendly_nt_error_msg(status
));
1402 return WERR_SETUP_NOT_JOINED
;
1408 /****************************************************************
1409 ****************************************************************/
1411 static bool libnet_join_unjoindomain_remove_secrets(TALLOC_CTX
*mem_ctx
,
1412 struct libnet_UnjoinCtx
*r
)
1414 if (!secrets_delete_machine_password_ex(lp_workgroup())) {
1418 if (!secrets_delete_domain_sid(lp_workgroup())) {
1425 /****************************************************************
1426 ****************************************************************/
1428 static NTSTATUS
libnet_join_unjoindomain_rpc(TALLOC_CTX
*mem_ctx
,
1429 struct libnet_UnjoinCtx
*r
)
1431 struct cli_state
*cli
= NULL
;
1432 struct rpc_pipe_client
*pipe_hnd
= NULL
;
1433 struct policy_handle sam_pol
, domain_pol
, user_pol
;
1434 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
, result
;
1437 struct lsa_String lsa_acct_name
;
1438 struct samr_Ids user_rids
;
1439 struct samr_Ids name_types
;
1440 union samr_UserInfo
*info
= NULL
;
1441 struct dcerpc_binding_handle
*b
= NULL
;
1443 ZERO_STRUCT(sam_pol
);
1444 ZERO_STRUCT(domain_pol
);
1445 ZERO_STRUCT(user_pol
);
1447 status
= libnet_join_connect_dc_ipc(r
->in
.dc_name
,
1448 r
->in
.admin_account
,
1450 r
->in
.admin_password
,
1453 if (!NT_STATUS_IS_OK(status
)) {
1457 /* Open the domain */
1459 status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_samr
,
1461 if (!NT_STATUS_IS_OK(status
)) {
1462 DEBUG(0,("Error connecting to SAM pipe. Error was %s\n",
1463 nt_errstr(status
)));
1467 b
= pipe_hnd
->binding_handle
;
1469 status
= dcerpc_samr_Connect2(b
, mem_ctx
,
1471 SEC_FLAG_MAXIMUM_ALLOWED
,
1474 if (!NT_STATUS_IS_OK(status
)) {
1477 if (!NT_STATUS_IS_OK(result
)) {
1482 status
= dcerpc_samr_OpenDomain(b
, mem_ctx
,
1484 SEC_FLAG_MAXIMUM_ALLOWED
,
1488 if (!NT_STATUS_IS_OK(status
)) {
1491 if (!NT_STATUS_IS_OK(result
)) {
1496 /* Create domain user */
1498 acct_name
= talloc_asprintf(mem_ctx
, "%s$", r
->in
.machine_name
);
1499 if (!strlower_m(acct_name
)) {
1500 status
= NT_STATUS_INVALID_PARAMETER
;
1504 init_lsa_String(&lsa_acct_name
, acct_name
);
1506 status
= dcerpc_samr_LookupNames(b
, mem_ctx
,
1514 if (!NT_STATUS_IS_OK(status
)) {
1517 if (!NT_STATUS_IS_OK(result
)) {
1521 if (user_rids
.count
!= 1) {
1522 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
1525 if (name_types
.count
!= 1) {
1526 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
1530 if (name_types
.ids
[0] != SID_NAME_USER
) {
1531 DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name
,
1532 name_types
.ids
[0]));
1533 status
= NT_STATUS_INVALID_WORKSTATION
;
1537 user_rid
= user_rids
.ids
[0];
1539 /* Open handle on user */
1541 status
= dcerpc_samr_OpenUser(b
, mem_ctx
,
1543 SEC_FLAG_MAXIMUM_ALLOWED
,
1547 if (!NT_STATUS_IS_OK(status
)) {
1550 if (!NT_STATUS_IS_OK(result
)) {
1557 status
= dcerpc_samr_QueryUserInfo(b
, mem_ctx
,
1562 if (!NT_STATUS_IS_OK(status
)) {
1563 dcerpc_samr_Close(b
, mem_ctx
, &user_pol
, &result
);
1566 if (!NT_STATUS_IS_OK(result
)) {
1568 dcerpc_samr_Close(b
, mem_ctx
, &user_pol
, &result
);
1572 /* now disable and setuser info */
1574 info
->info16
.acct_flags
|= ACB_DISABLED
;
1576 status
= dcerpc_samr_SetUserInfo(b
, mem_ctx
,
1581 if (!NT_STATUS_IS_OK(status
)) {
1582 dcerpc_samr_Close(b
, mem_ctx
, &user_pol
, &result
);
1585 if (!NT_STATUS_IS_OK(result
)) {
1587 dcerpc_samr_Close(b
, mem_ctx
, &user_pol
, &result
);
1591 dcerpc_samr_Close(b
, mem_ctx
, &user_pol
, &result
);
1594 if (pipe_hnd
&& b
) {
1595 if (is_valid_policy_hnd(&domain_pol
)) {
1596 dcerpc_samr_Close(b
, mem_ctx
, &domain_pol
, &result
);
1598 if (is_valid_policy_hnd(&sam_pol
)) {
1599 dcerpc_samr_Close(b
, mem_ctx
, &sam_pol
, &result
);
1601 TALLOC_FREE(pipe_hnd
);
1611 /****************************************************************
1612 ****************************************************************/
1614 static WERROR
do_join_modify_vals_config(struct libnet_JoinCtx
*r
)
1616 WERROR werr
= WERR_OK
;
1618 struct smbconf_ctx
*ctx
;
1620 err
= smbconf_init_reg(r
, &ctx
, NULL
);
1621 if (!SBC_ERROR_IS_OK(err
)) {
1622 werr
= WERR_NO_SUCH_SERVICE
;
1626 if (!(r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
)) {
1628 err
= smbconf_set_global_parameter(ctx
, "security", "user");
1629 if (!SBC_ERROR_IS_OK(err
)) {
1630 werr
= WERR_NO_SUCH_SERVICE
;
1634 err
= smbconf_set_global_parameter(ctx
, "workgroup",
1636 if (!SBC_ERROR_IS_OK(err
)) {
1637 werr
= WERR_NO_SUCH_SERVICE
;
1641 smbconf_delete_global_parameter(ctx
, "realm");
1645 err
= smbconf_set_global_parameter(ctx
, "security", "domain");
1646 if (!SBC_ERROR_IS_OK(err
)) {
1647 werr
= WERR_NO_SUCH_SERVICE
;
1651 err
= smbconf_set_global_parameter(ctx
, "workgroup",
1652 r
->out
.netbios_domain_name
);
1653 if (!SBC_ERROR_IS_OK(err
)) {
1654 werr
= WERR_NO_SUCH_SERVICE
;
1658 if (r
->out
.domain_is_ad
) {
1659 err
= smbconf_set_global_parameter(ctx
, "security", "ads");
1660 if (!SBC_ERROR_IS_OK(err
)) {
1661 werr
= WERR_NO_SUCH_SERVICE
;
1665 err
= smbconf_set_global_parameter(ctx
, "realm",
1666 r
->out
.dns_domain_name
);
1667 if (!SBC_ERROR_IS_OK(err
)) {
1668 werr
= WERR_NO_SUCH_SERVICE
;
1674 smbconf_shutdown(ctx
);
1678 /****************************************************************
1679 ****************************************************************/
1681 static WERROR
do_unjoin_modify_vals_config(struct libnet_UnjoinCtx
*r
)
1683 WERROR werr
= WERR_OK
;
1685 struct smbconf_ctx
*ctx
;
1687 err
= smbconf_init_reg(r
, &ctx
, NULL
);
1688 if (!SBC_ERROR_IS_OK(err
)) {
1689 werr
= WERR_NO_SUCH_SERVICE
;
1693 if (r
->in
.unjoin_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
1695 err
= smbconf_set_global_parameter(ctx
, "security", "user");
1696 if (!SBC_ERROR_IS_OK(err
)) {
1697 werr
= WERR_NO_SUCH_SERVICE
;
1701 err
= smbconf_delete_global_parameter(ctx
, "workgroup");
1702 if (!SBC_ERROR_IS_OK(err
)) {
1703 werr
= WERR_NO_SUCH_SERVICE
;
1707 smbconf_delete_global_parameter(ctx
, "realm");
1711 smbconf_shutdown(ctx
);
1715 /****************************************************************
1716 ****************************************************************/
1718 static WERROR
do_JoinConfig(struct libnet_JoinCtx
*r
)
1722 if (!W_ERROR_IS_OK(r
->out
.result
)) {
1723 return r
->out
.result
;
1726 if (!r
->in
.modify_config
) {
1730 werr
= do_join_modify_vals_config(r
);
1731 if (!W_ERROR_IS_OK(werr
)) {
1735 lp_load_global(get_dyn_CONFIGFILE());
1737 r
->out
.modified_config
= true;
1738 r
->out
.result
= werr
;
1743 /****************************************************************
1744 ****************************************************************/
1746 static WERROR
libnet_unjoin_config(struct libnet_UnjoinCtx
*r
)
1750 if (!W_ERROR_IS_OK(r
->out
.result
)) {
1751 return r
->out
.result
;
1754 if (!r
->in
.modify_config
) {
1758 werr
= do_unjoin_modify_vals_config(r
);
1759 if (!W_ERROR_IS_OK(werr
)) {
1763 lp_load_global(get_dyn_CONFIGFILE());
1765 r
->out
.modified_config
= true;
1766 r
->out
.result
= werr
;
1771 /****************************************************************
1772 ****************************************************************/
1774 static bool libnet_parse_domain_dc(TALLOC_CTX
*mem_ctx
,
1775 const char *domain_str
,
1776 const char **domain_p
,
1779 char *domain
= NULL
;
1781 const char *p
= NULL
;
1783 if (!domain_str
|| !domain_p
|| !dc_p
) {
1787 p
= strchr_m(domain_str
, '\\');
1790 domain
= talloc_strndup(mem_ctx
, domain_str
,
1791 PTR_DIFF(p
, domain_str
));
1792 dc
= talloc_strdup(mem_ctx
, p
+1);
1797 domain
= talloc_strdup(mem_ctx
, domain_str
);
1813 /****************************************************************
1814 ****************************************************************/
1816 static WERROR
libnet_join_pre_processing(TALLOC_CTX
*mem_ctx
,
1817 struct libnet_JoinCtx
*r
)
1819 if (!r
->in
.domain_name
) {
1820 libnet_join_set_error_string(mem_ctx
, r
,
1821 "No domain name defined");
1822 return WERR_INVALID_PARAM
;
1825 if (strlen(r
->in
.machine_name
) > 15) {
1826 libnet_join_set_error_string(mem_ctx
, r
,
1827 "Our netbios name can be at most 15 chars long, "
1828 "\"%s\" is %u chars long\n",
1830 (unsigned int)strlen(r
->in
.machine_name
));
1831 return WERR_INVALID_PARAM
;
1834 if (!libnet_parse_domain_dc(mem_ctx
, r
->in
.domain_name
,
1837 libnet_join_set_error_string(mem_ctx
, r
,
1838 "Failed to parse domain name");
1839 return WERR_INVALID_PARAM
;
1843 return WERR_SETUP_DOMAIN_CONTROLLER
;
1846 if (!r
->in
.admin_domain
) {
1847 char *admin_domain
= NULL
;
1848 char *admin_account
= NULL
;
1849 split_domain_user(mem_ctx
,
1850 r
->in
.admin_account
,
1853 r
->in
.admin_domain
= admin_domain
;
1854 r
->in
.admin_account
= admin_account
;
1857 if (!secrets_init()) {
1858 libnet_join_set_error_string(mem_ctx
, r
,
1859 "Unable to open secrets database");
1860 return WERR_CAN_NOT_COMPLETE
;
1866 /****************************************************************
1867 ****************************************************************/
1869 static void libnet_join_add_dom_rids_to_builtins(struct dom_sid
*domain_sid
)
1873 /* Try adding dom admins to builtin\admins. Only log failures. */
1874 status
= create_builtin_administrators(domain_sid
);
1875 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROTOCOL_UNREACHABLE
)) {
1876 DEBUG(10,("Unable to auto-add domain administrators to "
1877 "BUILTIN\\Administrators during join because "
1878 "winbindd must be running.\n"));
1879 } else if (!NT_STATUS_IS_OK(status
)) {
1880 DEBUG(5, ("Failed to auto-add domain administrators to "
1881 "BUILTIN\\Administrators during join: %s\n",
1882 nt_errstr(status
)));
1885 /* Try adding dom users to builtin\users. Only log failures. */
1886 status
= create_builtin_users(domain_sid
);
1887 if (NT_STATUS_EQUAL(status
, NT_STATUS_PROTOCOL_UNREACHABLE
)) {
1888 DEBUG(10,("Unable to auto-add domain users to BUILTIN\\users "
1889 "during join because winbindd must be running.\n"));
1890 } else if (!NT_STATUS_IS_OK(status
)) {
1891 DEBUG(5, ("Failed to auto-add domain administrators to "
1892 "BUILTIN\\Administrators during join: %s\n",
1893 nt_errstr(status
)));
1897 /****************************************************************
1898 ****************************************************************/
1900 static WERROR
libnet_join_post_processing(TALLOC_CTX
*mem_ctx
,
1901 struct libnet_JoinCtx
*r
)
1905 if (!W_ERROR_IS_OK(r
->out
.result
)) {
1906 return r
->out
.result
;
1909 werr
= do_JoinConfig(r
);
1910 if (!W_ERROR_IS_OK(werr
)) {
1914 if (!(r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
)) {
1918 saf_join_store(r
->out
.netbios_domain_name
, r
->in
.dc_name
);
1919 if (r
->out
.dns_domain_name
) {
1920 saf_join_store(r
->out
.dns_domain_name
, r
->in
.dc_name
);
1924 if (r
->out
.domain_is_ad
&&
1925 !(r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_UNSECURE
)) {
1926 ADS_STATUS ads_status
;
1928 ads_status
= libnet_join_post_processing_ads(mem_ctx
, r
);
1929 if (!ADS_ERR_OK(ads_status
)) {
1930 return WERR_GENERAL_FAILURE
;
1933 #endif /* HAVE_ADS */
1935 libnet_join_add_dom_rids_to_builtins(r
->out
.domain_sid
);
1940 /****************************************************************
1941 ****************************************************************/
1943 static int libnet_destroy_JoinCtx(struct libnet_JoinCtx
*r
)
1946 ads_destroy(&r
->in
.ads
);
1952 /****************************************************************
1953 ****************************************************************/
1955 static int libnet_destroy_UnjoinCtx(struct libnet_UnjoinCtx
*r
)
1958 ads_destroy(&r
->in
.ads
);
1964 /****************************************************************
1965 ****************************************************************/
1967 WERROR
libnet_init_JoinCtx(TALLOC_CTX
*mem_ctx
,
1968 struct libnet_JoinCtx
**r
)
1970 struct libnet_JoinCtx
*ctx
;
1972 ctx
= talloc_zero(mem_ctx
, struct libnet_JoinCtx
);
1977 talloc_set_destructor(ctx
, libnet_destroy_JoinCtx
);
1979 ctx
->in
.machine_name
= talloc_strdup(mem_ctx
, lp_netbios_name());
1980 W_ERROR_HAVE_NO_MEMORY(ctx
->in
.machine_name
);
1982 ctx
->in
.secure_channel_type
= SEC_CHAN_WKSTA
;
1989 /****************************************************************
1990 ****************************************************************/
1992 WERROR
libnet_init_UnjoinCtx(TALLOC_CTX
*mem_ctx
,
1993 struct libnet_UnjoinCtx
**r
)
1995 struct libnet_UnjoinCtx
*ctx
;
1997 ctx
= talloc_zero(mem_ctx
, struct libnet_UnjoinCtx
);
2002 talloc_set_destructor(ctx
, libnet_destroy_UnjoinCtx
);
2004 ctx
->in
.machine_name
= talloc_strdup(mem_ctx
, lp_netbios_name());
2005 W_ERROR_HAVE_NO_MEMORY(ctx
->in
.machine_name
);
2012 /****************************************************************
2013 ****************************************************************/
2015 static WERROR
libnet_join_check_config(TALLOC_CTX
*mem_ctx
,
2016 struct libnet_JoinCtx
*r
)
2018 bool valid_security
= false;
2019 bool valid_workgroup
= false;
2020 bool valid_realm
= false;
2022 /* check if configuration is already set correctly */
2024 valid_workgroup
= strequal(lp_workgroup(), r
->out
.netbios_domain_name
);
2026 switch (r
->out
.domain_is_ad
) {
2028 valid_security
= (lp_security() == SEC_DOMAIN
);
2029 if (valid_workgroup
&& valid_security
) {
2030 /* nothing to be done */
2035 valid_realm
= strequal(lp_realm(), r
->out
.dns_domain_name
);
2036 switch (lp_security()) {
2039 valid_security
= true;
2042 if (valid_workgroup
&& valid_realm
&& valid_security
) {
2043 /* nothing to be done */
2049 /* check if we are supposed to manipulate configuration */
2051 if (!r
->in
.modify_config
) {
2053 char *wrong_conf
= talloc_strdup(mem_ctx
, "");
2055 if (!valid_workgroup
) {
2056 wrong_conf
= talloc_asprintf_append(wrong_conf
,
2057 "\"workgroup\" set to '%s', should be '%s'",
2058 lp_workgroup(), r
->out
.netbios_domain_name
);
2059 W_ERROR_HAVE_NO_MEMORY(wrong_conf
);
2063 wrong_conf
= talloc_asprintf_append(wrong_conf
,
2064 "\"realm\" set to '%s', should be '%s'",
2065 lp_realm(), r
->out
.dns_domain_name
);
2066 W_ERROR_HAVE_NO_MEMORY(wrong_conf
);
2069 if (!valid_security
) {
2070 const char *sec
= NULL
;
2071 switch (lp_security()) {
2072 case SEC_USER
: sec
= "user"; break;
2073 case SEC_DOMAIN
: sec
= "domain"; break;
2074 case SEC_ADS
: sec
= "ads"; break;
2076 wrong_conf
= talloc_asprintf_append(wrong_conf
,
2077 "\"security\" set to '%s', should be %s",
2078 sec
, r
->out
.domain_is_ad
?
2079 "either 'domain' or 'ads'" : "'domain'");
2080 W_ERROR_HAVE_NO_MEMORY(wrong_conf
);
2083 libnet_join_set_error_string(mem_ctx
, r
,
2084 "Invalid configuration (%s) and configuration modification "
2085 "was not requested", wrong_conf
);
2086 return WERR_CAN_NOT_COMPLETE
;
2089 /* check if we are able to manipulate configuration */
2091 if (!lp_config_backend_is_registry()) {
2092 libnet_join_set_error_string(mem_ctx
, r
,
2093 "Configuration manipulation requested but not "
2094 "supported by backend");
2095 return WERR_NOT_SUPPORTED
;
2101 /****************************************************************
2102 ****************************************************************/
2104 static WERROR
libnet_DomainJoin(TALLOC_CTX
*mem_ctx
,
2105 struct libnet_JoinCtx
*r
)
2109 struct cli_state
*cli
= NULL
;
2111 ADS_STATUS ads_status
;
2112 #endif /* HAVE_ADS */
2114 if (!r
->in
.dc_name
) {
2115 struct netr_DsRGetDCNameInfo
*info
;
2117 status
= dsgetdcname(mem_ctx
,
2122 DS_FORCE_REDISCOVERY
|
2123 DS_DIRECTORY_SERVICE_REQUIRED
|
2124 DS_WRITABLE_REQUIRED
|
2127 if (!NT_STATUS_IS_OK(status
)) {
2128 libnet_join_set_error_string(mem_ctx
, r
,
2129 "failed to find DC for domain %s",
2131 get_friendly_nt_error_msg(status
));
2132 return WERR_DCNOTFOUND
;
2135 dc
= strip_hostname(info
->dc_unc
);
2136 r
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
2137 W_ERROR_HAVE_NO_MEMORY(r
->in
.dc_name
);
2140 status
= libnet_join_lookup_dc_rpc(mem_ctx
, r
, &cli
);
2141 if (!NT_STATUS_IS_OK(status
)) {
2142 libnet_join_set_error_string(mem_ctx
, r
,
2143 "failed to lookup DC info for domain '%s' over rpc: %s",
2144 r
->in
.domain_name
, get_friendly_nt_error_msg(status
));
2145 return ntstatus_to_werror(status
);
2148 werr
= libnet_join_check_config(mem_ctx
, r
);
2149 if (!W_ERROR_IS_OK(werr
)) {
2155 create_local_private_krb5_conf_for_domain(
2156 r
->out
.dns_domain_name
, r
->out
.netbios_domain_name
,
2157 NULL
, smbXcli_conn_remote_sockaddr(cli
->conn
));
2159 if (r
->out
.domain_is_ad
&& r
->in
.account_ou
&&
2160 !(r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_UNSECURE
)) {
2162 ads_status
= libnet_join_connect_ads(mem_ctx
, r
);
2163 if (!ADS_ERR_OK(ads_status
)) {
2164 return WERR_DEFAULT_JOIN_REQUIRED
;
2167 ads_status
= libnet_join_precreate_machine_acct(mem_ctx
, r
);
2168 if (!ADS_ERR_OK(ads_status
)) {
2169 libnet_join_set_error_string(mem_ctx
, r
,
2170 "failed to precreate account in ou %s: %s",
2172 ads_errstr(ads_status
));
2173 return WERR_DEFAULT_JOIN_REQUIRED
;
2176 r
->in
.join_flags
&= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
;
2178 #endif /* HAVE_ADS */
2180 if ((r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_UNSECURE
) &&
2181 (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED
)) {
2182 status
= libnet_join_joindomain_rpc_unsecure(mem_ctx
, r
, cli
);
2184 status
= libnet_join_joindomain_rpc(mem_ctx
, r
, cli
);
2186 if (!NT_STATUS_IS_OK(status
)) {
2187 libnet_join_set_error_string(mem_ctx
, r
,
2188 "failed to join domain '%s' over rpc: %s",
2189 r
->in
.domain_name
, get_friendly_nt_error_msg(status
));
2190 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
2191 return WERR_SETUP_ALREADY_JOINED
;
2193 werr
= ntstatus_to_werror(status
);
2197 if (!libnet_join_joindomain_store_secrets(mem_ctx
, r
)) {
2198 werr
= WERR_SETUP_NOT_JOINED
;
2212 /****************************************************************
2213 ****************************************************************/
2215 static WERROR
libnet_join_rollback(TALLOC_CTX
*mem_ctx
,
2216 struct libnet_JoinCtx
*r
)
2219 struct libnet_UnjoinCtx
*u
= NULL
;
2221 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
2222 if (!W_ERROR_IS_OK(werr
)) {
2226 u
->in
.debug
= r
->in
.debug
;
2227 u
->in
.dc_name
= r
->in
.dc_name
;
2228 u
->in
.domain_name
= r
->in
.domain_name
;
2229 u
->in
.admin_account
= r
->in
.admin_account
;
2230 u
->in
.admin_password
= r
->in
.admin_password
;
2231 u
->in
.modify_config
= r
->in
.modify_config
;
2232 u
->in
.use_kerberos
= r
->in
.use_kerberos
;
2233 u
->in
.unjoin_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
2234 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
;
2236 werr
= libnet_Unjoin(mem_ctx
, u
);
2242 /****************************************************************
2243 ****************************************************************/
2245 WERROR
libnet_Join(TALLOC_CTX
*mem_ctx
,
2246 struct libnet_JoinCtx
*r
)
2251 LIBNET_JOIN_IN_DUMP_CTX(mem_ctx
, r
);
2254 ZERO_STRUCT(r
->out
);
2256 werr
= libnet_join_pre_processing(mem_ctx
, r
);
2257 if (!W_ERROR_IS_OK(werr
)) {
2261 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
2262 werr
= libnet_DomainJoin(mem_ctx
, r
);
2263 if (!W_ERROR_IS_OK(werr
)) {
2268 werr
= libnet_join_post_processing(mem_ctx
, r
);
2269 if (!W_ERROR_IS_OK(werr
)) {
2273 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
2274 werr
= libnet_join_post_verify(mem_ctx
, r
);
2275 if (!W_ERROR_IS_OK(werr
)) {
2276 libnet_join_rollback(mem_ctx
, r
);
2281 r
->out
.result
= werr
;
2284 LIBNET_JOIN_OUT_DUMP_CTX(mem_ctx
, r
);
2289 /****************************************************************
2290 ****************************************************************/
2292 static WERROR
libnet_DomainUnjoin(TALLOC_CTX
*mem_ctx
,
2293 struct libnet_UnjoinCtx
*r
)
2297 if (!r
->in
.domain_sid
) {
2299 if (!secrets_fetch_domain_sid(lp_workgroup(), &sid
)) {
2300 libnet_unjoin_set_error_string(mem_ctx
, r
,
2301 "Unable to fetch domain sid: are we joined?");
2302 return WERR_SETUP_NOT_JOINED
;
2304 r
->in
.domain_sid
= dom_sid_dup(mem_ctx
, &sid
);
2305 W_ERROR_HAVE_NO_MEMORY(r
->in
.domain_sid
);
2308 if (!(r
->in
.unjoin_flags
& WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
) &&
2309 !r
->in
.delete_machine_account
) {
2310 libnet_join_unjoindomain_remove_secrets(mem_ctx
, r
);
2314 if (!r
->in
.dc_name
) {
2315 struct netr_DsRGetDCNameInfo
*info
;
2317 status
= dsgetdcname(mem_ctx
,
2322 DS_DIRECTORY_SERVICE_REQUIRED
|
2323 DS_WRITABLE_REQUIRED
|
2326 if (!NT_STATUS_IS_OK(status
)) {
2327 libnet_unjoin_set_error_string(mem_ctx
, r
,
2328 "failed to find DC for domain %s",
2330 get_friendly_nt_error_msg(status
));
2331 return WERR_DCNOTFOUND
;
2334 dc
= strip_hostname(info
->dc_unc
);
2335 r
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
2336 W_ERROR_HAVE_NO_MEMORY(r
->in
.dc_name
);
2340 /* for net ads leave, try to delete the account. If it works,
2341 no sense in disabling. If it fails, we can still try to
2344 if (r
->in
.delete_machine_account
) {
2345 ADS_STATUS ads_status
;
2346 ads_status
= libnet_unjoin_connect_ads(mem_ctx
, r
);
2347 if (ADS_ERR_OK(ads_status
)) {
2349 r
->out
.dns_domain_name
=
2350 talloc_strdup(mem_ctx
,
2351 r
->in
.ads
->server
.realm
);
2353 libnet_unjoin_remove_machine_acct(mem_ctx
, r
);
2355 if (!ADS_ERR_OK(ads_status
)) {
2356 libnet_unjoin_set_error_string(mem_ctx
, r
,
2357 "failed to remove machine account from AD: %s",
2358 ads_errstr(ads_status
));
2360 r
->out
.deleted_machine_account
= true;
2361 W_ERROR_HAVE_NO_MEMORY(r
->out
.dns_domain_name
);
2362 libnet_join_unjoindomain_remove_secrets(mem_ctx
, r
);
2366 #endif /* HAVE_ADS */
2368 /* The WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE flag really means
2370 if (r
->in
.unjoin_flags
& WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
) {
2371 status
= libnet_join_unjoindomain_rpc(mem_ctx
, r
);
2372 if (!NT_STATUS_IS_OK(status
)) {
2373 libnet_unjoin_set_error_string(mem_ctx
, r
,
2374 "failed to disable machine account via rpc: %s",
2375 get_friendly_nt_error_msg(status
));
2376 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
2377 return WERR_SETUP_NOT_JOINED
;
2379 return ntstatus_to_werror(status
);
2382 r
->out
.disabled_machine_account
= true;
2385 /* If disable succeeded or was not requested at all, we
2386 should be getting rid of our end of things */
2388 libnet_join_unjoindomain_remove_secrets(mem_ctx
, r
);
2393 /****************************************************************
2394 ****************************************************************/
2396 static WERROR
libnet_unjoin_pre_processing(TALLOC_CTX
*mem_ctx
,
2397 struct libnet_UnjoinCtx
*r
)
2399 if (!r
->in
.domain_name
) {
2400 libnet_unjoin_set_error_string(mem_ctx
, r
,
2401 "No domain name defined");
2402 return WERR_INVALID_PARAM
;
2405 if (!libnet_parse_domain_dc(mem_ctx
, r
->in
.domain_name
,
2408 libnet_unjoin_set_error_string(mem_ctx
, r
,
2409 "Failed to parse domain name");
2410 return WERR_INVALID_PARAM
;
2414 return WERR_SETUP_DOMAIN_CONTROLLER
;
2417 if (!r
->in
.admin_domain
) {
2418 char *admin_domain
= NULL
;
2419 char *admin_account
= NULL
;
2420 split_domain_user(mem_ctx
,
2421 r
->in
.admin_account
,
2424 r
->in
.admin_domain
= admin_domain
;
2425 r
->in
.admin_account
= admin_account
;
2428 if (!secrets_init()) {
2429 libnet_unjoin_set_error_string(mem_ctx
, r
,
2430 "Unable to open secrets database");
2431 return WERR_CAN_NOT_COMPLETE
;
2437 /****************************************************************
2438 ****************************************************************/
2440 static WERROR
libnet_unjoin_post_processing(TALLOC_CTX
*mem_ctx
,
2441 struct libnet_UnjoinCtx
*r
)
2443 saf_delete(r
->out
.netbios_domain_name
);
2444 saf_delete(r
->out
.dns_domain_name
);
2446 return libnet_unjoin_config(r
);
2449 /****************************************************************
2450 ****************************************************************/
2452 WERROR
libnet_Unjoin(TALLOC_CTX
*mem_ctx
,
2453 struct libnet_UnjoinCtx
*r
)
2458 LIBNET_UNJOIN_IN_DUMP_CTX(mem_ctx
, r
);
2461 werr
= libnet_unjoin_pre_processing(mem_ctx
, r
);
2462 if (!W_ERROR_IS_OK(werr
)) {
2466 if (r
->in
.unjoin_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
2467 werr
= libnet_DomainUnjoin(mem_ctx
, r
);
2468 if (!W_ERROR_IS_OK(werr
)) {
2469 libnet_unjoin_config(r
);
2474 werr
= libnet_unjoin_post_processing(mem_ctx
, r
);
2475 if (!W_ERROR_IS_OK(werr
)) {
2480 r
->out
.result
= werr
;
2483 LIBNET_UNJOIN_OUT_DUMP_CTX(mem_ctx
, r
);