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/>.
22 #include "libnet/libnet_join.h"
23 #include "libnet/libnet_proto.h"
25 /****************************************************************
26 ****************************************************************/
28 static void libnet_join_set_error_string(TALLOC_CTX
*mem_ctx
,
29 struct libnet_JoinCtx
*r
,
30 const char *format
, ...)
34 if (r
->out
.error_string
) {
38 va_start(args
, format
);
39 r
->out
.error_string
= talloc_vasprintf(mem_ctx
, format
, args
);
43 /****************************************************************
44 ****************************************************************/
46 static void libnet_unjoin_set_error_string(TALLOC_CTX
*mem_ctx
,
47 struct libnet_UnjoinCtx
*r
,
48 const char *format
, ...)
52 if (r
->out
.error_string
) {
56 va_start(args
, format
);
57 r
->out
.error_string
= talloc_vasprintf(mem_ctx
, format
, args
);
63 /****************************************************************
64 ****************************************************************/
66 static ADS_STATUS
libnet_connect_ads(const char *dns_domain_name
,
67 const char *netbios_domain_name
,
69 const char *user_name
,
74 ADS_STRUCT
*my_ads
= NULL
;
76 my_ads
= ads_init(dns_domain_name
,
80 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
84 SAFE_FREE(my_ads
->auth
.user_name
);
85 my_ads
->auth
.user_name
= SMB_STRDUP(user_name
);
89 SAFE_FREE(my_ads
->auth
.password
);
90 my_ads
->auth
.password
= SMB_STRDUP(password
);
93 status
= ads_connect(my_ads
);
94 if (!ADS_ERR_OK(status
)) {
103 /****************************************************************
104 ****************************************************************/
106 static ADS_STATUS
libnet_join_connect_ads(TALLOC_CTX
*mem_ctx
,
107 struct libnet_JoinCtx
*r
)
112 ads_destroy(&r
->in
.ads
);
115 status
= libnet_connect_ads(r
->in
.domain_name
,
119 r
->in
.admin_password
,
121 if (!ADS_ERR_OK(status
)) {
122 libnet_join_set_error_string(mem_ctx
, r
,
123 "failed to connect to AD: %s",
130 /****************************************************************
131 ****************************************************************/
133 static ADS_STATUS
libnet_unjoin_connect_ads(TALLOC_CTX
*mem_ctx
,
134 struct libnet_UnjoinCtx
*r
)
139 ads_destroy(&r
->in
.ads
);
142 status
= libnet_connect_ads(r
->in
.domain_name
,
146 r
->in
.admin_password
,
148 if (!ADS_ERR_OK(status
)) {
149 libnet_unjoin_set_error_string(mem_ctx
, r
,
150 "failed to connect to AD: %s",
157 /****************************************************************
158 ****************************************************************/
160 static ADS_STATUS
libnet_join_precreate_machine_acct(TALLOC_CTX
*mem_ctx
,
161 struct libnet_JoinCtx
*r
)
164 LDAPMessage
*res
= NULL
;
165 const char *attrs
[] = { "dn", NULL
};
167 status
= ads_search_dn(r
->in
.ads
, &res
, r
->in
.account_ou
, attrs
);
168 if (!ADS_ERR_OK(status
)) {
172 if (ads_count_replies(r
->in
.ads
, res
) != 1) {
173 ads_msgfree(r
->in
.ads
, res
);
174 return ADS_ERROR_LDAP(LDAP_NO_SUCH_OBJECT
);
177 status
= ads_create_machine_acct(r
->in
.ads
,
180 ads_msgfree(r
->in
.ads
, res
);
182 if ((status
.error_type
== ENUM_ADS_ERROR_LDAP
) &&
183 (status
.err
.rc
== LDAP_ALREADY_EXISTS
)) {
184 status
= ADS_SUCCESS
;
190 /****************************************************************
191 ****************************************************************/
193 static ADS_STATUS
libnet_unjoin_remove_machine_acct(TALLOC_CTX
*mem_ctx
,
194 struct libnet_UnjoinCtx
*r
)
199 status
= libnet_unjoin_connect_ads(mem_ctx
, r
);
200 if (!ADS_ERR_OK(status
)) {
205 status
= ads_leave_realm(r
->in
.ads
, r
->in
.machine_name
);
206 if (!ADS_ERR_OK(status
)) {
207 libnet_unjoin_set_error_string(mem_ctx
, r
,
208 "failed to leave realm: %s",
216 /****************************************************************
217 ****************************************************************/
219 static ADS_STATUS
libnet_join_find_machine_acct(TALLOC_CTX
*mem_ctx
,
220 struct libnet_JoinCtx
*r
)
223 LDAPMessage
*res
= NULL
;
226 if (!r
->in
.machine_name
) {
227 return ADS_ERROR(LDAP_NO_MEMORY
);
230 status
= ads_find_machine_acct(r
->in
.ads
,
233 if (!ADS_ERR_OK(status
)) {
237 if (ads_count_replies(r
->in
.ads
, res
) != 1) {
238 status
= ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
242 dn
= ads_get_dn(r
->in
.ads
, res
);
244 status
= ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
248 TALLOC_FREE(r
->out
.dn
);
249 r
->out
.dn
= talloc_strdup(mem_ctx
, dn
);
251 status
= ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
256 ads_msgfree(r
->in
.ads
, res
);
257 ads_memfree(r
->in
.ads
, dn
);
262 /****************************************************************
263 ****************************************************************/
265 static ADS_STATUS
libnet_join_set_machine_spn(TALLOC_CTX
*mem_ctx
,
266 struct libnet_JoinCtx
*r
)
271 const char *spn_array
[3] = {NULL
, NULL
, NULL
};
275 status
= libnet_join_connect_ads(mem_ctx
, r
);
276 if (!ADS_ERR_OK(status
)) {
281 status
= libnet_join_find_machine_acct(mem_ctx
, r
);
282 if (!ADS_ERR_OK(status
)) {
286 spn
= talloc_asprintf(mem_ctx
, "HOST/%s", r
->in
.machine_name
);
288 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
293 if (name_to_fqdn(my_fqdn
, r
->in
.machine_name
) &&
294 !strequal(my_fqdn
, r
->in
.machine_name
)) {
297 spn
= talloc_asprintf(mem_ctx
, "HOST/%s", my_fqdn
);
299 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
304 mods
= ads_init_mods(mem_ctx
);
306 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
309 status
= ads_mod_str(mem_ctx
, &mods
, "dNSHostName", my_fqdn
);
310 if (!ADS_ERR_OK(status
)) {
311 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
314 status
= ads_mod_strlist(mem_ctx
, &mods
, "servicePrincipalName",
316 if (!ADS_ERR_OK(status
)) {
317 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
320 return ads_gen_mod(r
->in
.ads
, r
->out
.dn
, mods
);
323 /****************************************************************
324 ****************************************************************/
326 static ADS_STATUS
libnet_join_set_machine_upn(TALLOC_CTX
*mem_ctx
,
327 struct libnet_JoinCtx
*r
)
332 if (!r
->in
.create_upn
) {
337 status
= libnet_join_connect_ads(mem_ctx
, r
);
338 if (!ADS_ERR_OK(status
)) {
343 status
= libnet_join_find_machine_acct(mem_ctx
, r
);
344 if (!ADS_ERR_OK(status
)) {
349 r
->in
.upn
= talloc_asprintf(mem_ctx
,
352 r
->out
.dns_domain_name
);
354 return ADS_ERROR(LDAP_NO_MEMORY
);
358 mods
= ads_init_mods(mem_ctx
);
360 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
363 status
= ads_mod_str(mem_ctx
, &mods
, "userPrincipalName", r
->in
.upn
);
364 if (!ADS_ERR_OK(status
)) {
365 return ADS_ERROR_LDAP(LDAP_NO_MEMORY
);
368 return ads_gen_mod(r
->in
.ads
, r
->out
.dn
, mods
);
372 /****************************************************************
373 ****************************************************************/
375 static ADS_STATUS
libnet_join_set_os_attributes(TALLOC_CTX
*mem_ctx
,
376 struct libnet_JoinCtx
*r
)
382 if (!r
->in
.os_name
|| !r
->in
.os_version
) {
387 status
= libnet_join_connect_ads(mem_ctx
, r
);
388 if (!ADS_ERR_OK(status
)) {
393 status
= libnet_join_find_machine_acct(mem_ctx
, r
);
394 if (!ADS_ERR_OK(status
)) {
398 mods
= ads_init_mods(mem_ctx
);
400 return ADS_ERROR(LDAP_NO_MEMORY
);
403 os_sp
= talloc_asprintf(mem_ctx
, "Samba %s", SAMBA_VERSION_STRING
);
405 return ADS_ERROR(LDAP_NO_MEMORY
);
408 status
= ads_mod_str(mem_ctx
, &mods
, "operatingSystem",
410 if (!ADS_ERR_OK(status
)) {
414 status
= ads_mod_str(mem_ctx
, &mods
, "operatingSystemVersion",
416 if (!ADS_ERR_OK(status
)) {
420 status
= ads_mod_str(mem_ctx
, &mods
, "operatingSystemServicePack",
422 if (!ADS_ERR_OK(status
)) {
426 return ads_gen_mod(r
->in
.ads
, r
->out
.dn
, mods
);
429 /****************************************************************
430 ****************************************************************/
432 static bool libnet_join_create_keytab(TALLOC_CTX
*mem_ctx
,
433 struct libnet_JoinCtx
*r
)
435 if (!lp_use_kerberos_keytab()) {
439 if (!ads_keytab_create_default(r
->in
.ads
)) {
446 /****************************************************************
447 ****************************************************************/
449 static bool libnet_join_derive_salting_principal(TALLOC_CTX
*mem_ctx
,
450 struct libnet_JoinCtx
*r
)
452 uint32_t domain_func
;
454 const char *salt
= NULL
;
455 char *std_salt
= NULL
;
457 status
= ads_domain_func_level(r
->in
.ads
, &domain_func
);
458 if (!ADS_ERR_OK(status
)) {
459 libnet_join_set_error_string(mem_ctx
, r
,
460 "Failed to determine domain functional level!");
464 std_salt
= kerberos_standard_des_salt();
466 libnet_join_set_error_string(mem_ctx
, r
,
467 "failed to obtain standard DES salt");
471 salt
= talloc_strdup(mem_ctx
, std_salt
);
478 if (domain_func
== DS_DOMAIN_FUNCTION_2000
) {
481 upn
= ads_get_upn(r
->in
.ads
, mem_ctx
,
484 salt
= talloc_strdup(mem_ctx
, upn
);
491 return kerberos_secrets_store_des_salt(salt
);
494 /****************************************************************
495 ****************************************************************/
497 static ADS_STATUS
libnet_join_post_processing_ads(TALLOC_CTX
*mem_ctx
,
498 struct libnet_JoinCtx
*r
)
502 status
= libnet_join_set_machine_spn(mem_ctx
, r
);
503 if (!ADS_ERR_OK(status
)) {
504 libnet_join_set_error_string(mem_ctx
, r
,
505 "failed to set machine spn: %s",
510 status
= libnet_join_set_os_attributes(mem_ctx
, r
);
511 if (!ADS_ERR_OK(status
)) {
512 libnet_join_set_error_string(mem_ctx
, r
,
513 "failed to set machine os attributes: %s",
518 status
= libnet_join_set_machine_upn(mem_ctx
, r
);
519 if (!ADS_ERR_OK(status
)) {
520 libnet_join_set_error_string(mem_ctx
, r
,
521 "failed to set machine upn: %s",
526 if (!libnet_join_derive_salting_principal(mem_ctx
, r
)) {
527 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
530 if (!libnet_join_create_keytab(mem_ctx
, r
)) {
531 libnet_join_set_error_string(mem_ctx
, r
,
532 "failed to create kerberos keytab");
533 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
538 #endif /* WITH_ADS */
540 /****************************************************************
541 ****************************************************************/
543 static bool libnet_join_joindomain_store_secrets(TALLOC_CTX
*mem_ctx
,
544 struct libnet_JoinCtx
*r
)
546 if (!secrets_store_domain_sid(r
->out
.netbios_domain_name
,
552 if (!secrets_store_machine_password(r
->in
.machine_password
,
553 r
->out
.netbios_domain_name
,
562 /****************************************************************
563 ****************************************************************/
565 static NTSTATUS
libnet_join_joindomain_rpc(TALLOC_CTX
*mem_ctx
,
566 struct libnet_JoinCtx
*r
)
568 struct cli_state
*cli
= NULL
;
569 struct rpc_pipe_client
*pipe_hnd
= NULL
;
570 POLICY_HND sam_pol
, domain_pol
, user_pol
, lsa_pol
;
571 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
573 const char *const_acct_name
;
575 uint32 num_rids
, *name_types
, *user_rids
;
576 uint32 flags
= 0x3e8;
577 uint32 acb_info
= ACB_WSTRUST
;
578 uint32 fields_present
;
580 SAM_USERINFO_CTR ctr
;
581 SAM_USER_INFO_25 p25
;
582 const int infolevel
= 25;
583 struct MD5Context md5ctx
;
585 DATA_BLOB digested_session_key
;
586 uchar md4_trust_password
[16];
588 if (!r
->in
.machine_password
) {
589 r
->in
.machine_password
= talloc_strdup(mem_ctx
, generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH
));
590 NT_STATUS_HAVE_NO_MEMORY(r
->in
.machine_password
);
593 status
= cli_full_connection(&cli
, NULL
,
599 r
->in
.admin_password
,
603 if (!NT_STATUS_IS_OK(status
)) {
607 pipe_hnd
= cli_rpc_pipe_open_noauth(cli
, PI_LSARPC
, &status
);
612 status
= rpccli_lsa_open_policy(pipe_hnd
, mem_ctx
, True
,
613 SEC_RIGHTS_MAXIMUM_ALLOWED
, &lsa_pol
);
614 if (!NT_STATUS_IS_OK(status
)) {
618 status
= rpccli_lsa_query_info_policy2(pipe_hnd
, mem_ctx
, &lsa_pol
,
620 &r
->out
.netbios_domain_name
,
621 &r
->out
.dns_domain_name
,
626 if (NT_STATUS_IS_OK(status
)) {
627 r
->out
.domain_is_ad
= true;
630 if (!NT_STATUS_IS_OK(status
)) {
631 status
= rpccli_lsa_query_info_policy(pipe_hnd
, mem_ctx
, &lsa_pol
,
633 &r
->out
.netbios_domain_name
,
635 if (!NT_STATUS_IS_OK(status
)) {
640 rpccli_lsa_Close(pipe_hnd
, mem_ctx
, &lsa_pol
);
641 cli_rpc_pipe_close(pipe_hnd
);
643 pipe_hnd
= cli_rpc_pipe_open_noauth(cli
, PI_SAMR
, &status
);
648 status
= rpccli_samr_connect(pipe_hnd
, mem_ctx
,
649 SEC_RIGHTS_MAXIMUM_ALLOWED
, &sam_pol
);
650 if (!NT_STATUS_IS_OK(status
)) {
654 status
= rpccli_samr_open_domain(pipe_hnd
, mem_ctx
, &sam_pol
,
655 SEC_RIGHTS_MAXIMUM_ALLOWED
,
658 if (!NT_STATUS_IS_OK(status
)) {
662 acct_name
= talloc_asprintf(mem_ctx
, "%s$", r
->in
.machine_name
);
663 strlower_m(acct_name
);
664 const_acct_name
= acct_name
;
666 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
) {
667 status
= rpccli_samr_create_dom_user(pipe_hnd
, mem_ctx
,
669 acct_name
, ACB_WSTRUST
,
670 0xe005000b, &user_pol
,
672 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
673 if (!(r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
)) {
678 if (NT_STATUS_IS_OK(status
)) {
679 rpccli_samr_close(pipe_hnd
, mem_ctx
, &user_pol
);
683 status
= rpccli_samr_lookup_names(pipe_hnd
, mem_ctx
,
684 &domain_pol
, flags
, 1,
686 &num_rids
, &user_rids
, &name_types
);
687 if (!NT_STATUS_IS_OK(status
)) {
691 if (name_types
[0] != SID_NAME_USER
) {
692 status
= NT_STATUS_INVALID_WORKSTATION
;
696 user_rid
= user_rids
[0];
698 status
= rpccli_samr_open_user(pipe_hnd
, mem_ctx
, &domain_pol
,
699 SEC_RIGHTS_MAXIMUM_ALLOWED
, user_rid
,
701 if (!NT_STATUS_IS_OK(status
)) {
705 E_md4hash(r
->in
.machine_password
, md4_trust_password
);
706 encode_pw_buffer(pwbuf
, r
->in
.machine_password
, STR_UNICODE
);
708 generate_random_buffer((uint8
*)md5buffer
, sizeof(md5buffer
));
709 digested_session_key
= data_blob_talloc(mem_ctx
, 0, 16);
712 MD5Update(&md5ctx
, md5buffer
, sizeof(md5buffer
));
713 MD5Update(&md5ctx
, cli
->user_session_key
.data
,
714 cli
->user_session_key
.length
);
715 MD5Final(digested_session_key
.data
, &md5ctx
);
717 SamOEMhashBlob(pwbuf
, sizeof(pwbuf
), &digested_session_key
);
718 memcpy(&pwbuf
[516], md5buffer
, sizeof(md5buffer
));
720 acb_info
|= ACB_PWNOEXP
;
721 if (r
->out
.domain_is_ad
) {
722 #if !defined(ENCTYPE_ARCFOUR_HMAC)
723 acb_info
|= ACB_USE_DES_KEY_ONLY
;
731 fields_present
= ACCT_NT_PWD_SET
| ACCT_LM_PWD_SET
| ACCT_FLAGS
;
732 init_sam_user_info25P(&p25
, fields_present
, acb_info
, (char *)pwbuf
);
734 ctr
.switch_value
= infolevel
;
735 ctr
.info
.id25
= &p25
;
737 status
= rpccli_samr_set_userinfo2(pipe_hnd
, mem_ctx
, &user_pol
,
738 infolevel
, &cli
->user_session_key
,
740 if (!NT_STATUS_IS_OK(status
)) {
744 rpccli_samr_close(pipe_hnd
, mem_ctx
, &user_pol
);
745 cli_rpc_pipe_close(pipe_hnd
);
747 status
= NT_STATUS_OK
;
756 /****************************************************************
757 ****************************************************************/
759 static bool libnet_join_unjoindomain_remove_secrets(TALLOC_CTX
*mem_ctx
,
760 struct libnet_UnjoinCtx
*r
)
762 if (!secrets_delete_machine_password_ex(lp_workgroup())) {
766 if (!secrets_delete_domain_sid(lp_workgroup())) {
773 /****************************************************************
774 ****************************************************************/
776 static NTSTATUS
libnet_join_unjoindomain_rpc(TALLOC_CTX
*mem_ctx
,
777 struct libnet_UnjoinCtx
*r
)
779 struct cli_state
*cli
= NULL
;
780 struct rpc_pipe_client
*pipe_hnd
= NULL
;
781 POLICY_HND sam_pol
, domain_pol
, user_pol
;
782 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
784 uint32 flags
= 0x3e8;
785 const char *const_acct_name
;
787 uint32 num_rids
, *name_types
, *user_rids
;
788 SAM_USERINFO_CTR ctr
, *qctr
= NULL
;
789 SAM_USER_INFO_16 p16
;
791 status
= cli_full_connection(&cli
, NULL
,
797 r
->in
.admin_password
,
800 if (!NT_STATUS_IS_OK(status
)) {
804 pipe_hnd
= cli_rpc_pipe_open_noauth(cli
, PI_SAMR
, &status
);
809 status
= rpccli_samr_connect(pipe_hnd
, mem_ctx
,
810 SEC_RIGHTS_MAXIMUM_ALLOWED
, &sam_pol
);
811 if (!NT_STATUS_IS_OK(status
)) {
815 status
= rpccli_samr_open_domain(pipe_hnd
, mem_ctx
, &sam_pol
,
816 SEC_RIGHTS_MAXIMUM_ALLOWED
,
819 if (!NT_STATUS_IS_OK(status
)) {
823 acct_name
= talloc_asprintf(mem_ctx
, "%s$", r
->in
.machine_name
);
824 strlower_m(acct_name
);
825 const_acct_name
= acct_name
;
827 status
= rpccli_samr_lookup_names(pipe_hnd
, mem_ctx
,
828 &domain_pol
, flags
, 1,
830 &num_rids
, &user_rids
, &name_types
);
831 if (!NT_STATUS_IS_OK(status
)) {
835 if (name_types
[0] != SID_NAME_USER
) {
836 status
= NT_STATUS_INVALID_WORKSTATION
;
840 user_rid
= user_rids
[0];
842 status
= rpccli_samr_open_user(pipe_hnd
, mem_ctx
, &domain_pol
,
843 SEC_RIGHTS_MAXIMUM_ALLOWED
,
844 user_rid
, &user_pol
);
845 if (!NT_STATUS_IS_OK(status
)) {
849 status
= rpccli_samr_query_userinfo(pipe_hnd
, mem_ctx
,
850 &user_pol
, 16, &qctr
);
851 if (!NT_STATUS_IS_OK(status
)) {
852 rpccli_samr_close(pipe_hnd
, mem_ctx
, &user_pol
);
857 ctr
.switch_value
= 16;
858 ctr
.info
.id16
= &p16
;
860 p16
.acb_info
= qctr
->info
.id16
->acb_info
| ACB_DISABLED
;
862 status
= rpccli_samr_set_userinfo2(pipe_hnd
, mem_ctx
, &user_pol
, 16,
863 &cli
->user_session_key
, &ctr
);
865 rpccli_samr_close(pipe_hnd
, mem_ctx
, &user_pol
);
869 rpccli_samr_close(pipe_hnd
, mem_ctx
, &domain_pol
);
870 rpccli_samr_close(pipe_hnd
, mem_ctx
, &sam_pol
);
871 cli_rpc_pipe_close(pipe_hnd
);
881 /****************************************************************
882 ****************************************************************/
884 static WERROR
do_join_modify_vals_config(struct libnet_JoinCtx
*r
)
888 if (!(r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
)) {
890 werr
= libnet_conf_set_global_parameter("security", "user");
891 W_ERROR_NOT_OK_RETURN(werr
);
893 werr
= libnet_conf_set_global_parameter("workgroup",
898 werr
= libnet_conf_set_global_parameter("security", "domain");
899 W_ERROR_NOT_OK_RETURN(werr
);
901 werr
= libnet_conf_set_global_parameter("workgroup",
902 r
->out
.netbios_domain_name
);
903 W_ERROR_NOT_OK_RETURN(werr
);
905 if (r
->out
.domain_is_ad
) {
906 werr
= libnet_conf_set_global_parameter("security", "ads");
907 W_ERROR_NOT_OK_RETURN(werr
);
909 werr
= libnet_conf_set_global_parameter("realm",
910 r
->out
.dns_domain_name
);
911 W_ERROR_NOT_OK_RETURN(werr
);
917 /****************************************************************
918 ****************************************************************/
920 static WERROR
do_unjoin_modify_vals_config(struct libnet_UnjoinCtx
*r
)
922 WERROR werr
= WERR_OK
;
924 if (r
->in
.unjoin_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
926 werr
= libnet_conf_set_global_parameter("security", "user");
927 W_ERROR_NOT_OK_RETURN(werr
);
930 libnet_conf_delete_parameter(GLOBAL_NAME
, "realm");
935 /****************************************************************
936 ****************************************************************/
938 static WERROR
do_JoinConfig(struct libnet_JoinCtx
*r
)
942 if (!W_ERROR_IS_OK(r
->out
.result
)) {
943 return r
->out
.result
;
946 if (!r
->in
.modify_config
) {
950 werr
= do_join_modify_vals_config(r
);
951 if (!W_ERROR_IS_OK(werr
)) {
955 r
->out
.modified_config
= true;
956 r
->out
.result
= werr
;
961 /****************************************************************
962 ****************************************************************/
964 static WERROR
do_UnjoinConfig(struct libnet_UnjoinCtx
*r
)
968 if (!W_ERROR_IS_OK(r
->out
.result
)) {
969 return r
->out
.result
;
972 if (!r
->in
.modify_config
) {
976 werr
= do_unjoin_modify_vals_config(r
);
977 if (!W_ERROR_IS_OK(werr
)) {
981 r
->out
.modified_config
= true;
982 r
->out
.result
= werr
;
987 /****************************************************************
988 ****************************************************************/
990 static int libnet_destroy_JoinCtx(struct libnet_JoinCtx
*r
)
993 ads_destroy(&r
->in
.ads
);
999 /****************************************************************
1000 ****************************************************************/
1002 static int libnet_destroy_UnjoinCtx(struct libnet_UnjoinCtx
*r
)
1005 ads_destroy(&r
->in
.ads
);
1011 /****************************************************************
1012 ****************************************************************/
1014 WERROR
libnet_init_JoinCtx(TALLOC_CTX
*mem_ctx
,
1015 struct libnet_JoinCtx
**r
)
1017 struct libnet_JoinCtx
*ctx
;
1019 ctx
= talloc_zero(mem_ctx
, struct libnet_JoinCtx
);
1024 talloc_set_destructor(ctx
, libnet_destroy_JoinCtx
);
1026 ctx
->in
.machine_name
= talloc_strdup(mem_ctx
, global_myname());
1027 W_ERROR_HAVE_NO_MEMORY(ctx
->in
.machine_name
);
1034 /****************************************************************
1035 ****************************************************************/
1037 WERROR
libnet_init_UnjoinCtx(TALLOC_CTX
*mem_ctx
,
1038 struct libnet_UnjoinCtx
**r
)
1040 struct libnet_UnjoinCtx
*ctx
;
1042 ctx
= talloc_zero(mem_ctx
, struct libnet_UnjoinCtx
);
1047 talloc_set_destructor(ctx
, libnet_destroy_UnjoinCtx
);
1049 ctx
->in
.machine_name
= talloc_strdup(mem_ctx
, global_myname());
1050 W_ERROR_HAVE_NO_MEMORY(ctx
->in
.machine_name
);
1057 /****************************************************************
1058 ****************************************************************/
1060 static WERROR
libnet_DomainJoin(TALLOC_CTX
*mem_ctx
,
1061 struct libnet_JoinCtx
*r
)
1065 ADS_STATUS ads_status
;
1067 if (r
->in
.account_ou
) {
1068 ads_status
= libnet_join_connect_ads(mem_ctx
, r
);
1069 if (!ADS_ERR_OK(ads_status
)) {
1070 return WERR_GENERAL_FAILURE
;
1072 ads_status
= libnet_join_precreate_machine_acct(mem_ctx
, r
);
1073 if (!ADS_ERR_OK(ads_status
)) {
1074 libnet_join_set_error_string(mem_ctx
, r
,
1075 "failed to precreate account in ou %s: %s",
1077 ads_errstr(ads_status
));
1078 return WERR_GENERAL_FAILURE
;
1081 r
->in
.join_flags
&= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
;
1083 #endif /* WITH_ADS */
1084 status
= libnet_join_joindomain_rpc(mem_ctx
, r
);
1085 if (!NT_STATUS_IS_OK(status
)) {
1086 if (NT_STATUS_EQUAL(status
, NT_STATUS_USER_EXISTS
)) {
1087 return WERR_SETUP_ALREADY_JOINED
;
1089 return ntstatus_to_werror(status
);
1092 if (!libnet_join_joindomain_store_secrets(mem_ctx
, r
)) {
1093 return WERR_SETUP_NOT_JOINED
;
1097 if (r
->out
.domain_is_ad
) {
1098 ads_status
= libnet_join_post_processing_ads(mem_ctx
, r
);
1099 if (!ADS_ERR_OK(ads_status
)) {
1100 return WERR_GENERAL_FAILURE
;
1103 #endif /* WITH_ADS */
1108 /****************************************************************
1109 ****************************************************************/
1111 WERROR
libnet_Join(TALLOC_CTX
*mem_ctx
,
1112 struct libnet_JoinCtx
*r
)
1116 if (!r
->in
.domain_name
) {
1117 return WERR_INVALID_PARAM
;
1120 if (r
->in
.modify_config
&& !lp_include_registry_globals()) {
1121 return WERR_NOT_SUPPORTED
;
1125 return WERR_SETUP_DOMAIN_CONTROLLER
;
1128 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
1129 werr
= libnet_DomainJoin(mem_ctx
, r
);
1130 if (!W_ERROR_IS_OK(werr
)) {
1135 werr
= do_JoinConfig(r
);
1136 if (!W_ERROR_IS_OK(werr
)) {
1143 /****************************************************************
1144 ****************************************************************/
1146 static WERROR
libnet_DomainUnjoin(TALLOC_CTX
*mem_ctx
,
1147 struct libnet_UnjoinCtx
*r
)
1151 status
= libnet_join_unjoindomain_rpc(mem_ctx
, r
);
1152 if (!NT_STATUS_IS_OK(status
)) {
1153 libnet_unjoin_set_error_string(mem_ctx
, r
,
1154 "failed to unjoin domain: %s",
1156 if (NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_USER
)) {
1157 return WERR_SETUP_NOT_JOINED
;
1159 return ntstatus_to_werror(status
);
1163 if (r
->in
.unjoin_flags
& WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
) {
1164 ADS_STATUS ads_status
;
1165 libnet_unjoin_connect_ads(mem_ctx
, r
);
1166 ads_status
= libnet_unjoin_remove_machine_acct(mem_ctx
, r
);
1167 if (!ADS_ERR_OK(ads_status
)) {
1168 libnet_unjoin_set_error_string(mem_ctx
, r
,
1169 "failed to remove machine account from AD: %s",
1170 ads_errstr(ads_status
));
1173 #endif /* WITH_ADS */
1175 libnet_join_unjoindomain_remove_secrets(mem_ctx
, r
);
1180 /****************************************************************
1181 ****************************************************************/
1183 WERROR
libnet_Unjoin(TALLOC_CTX
*mem_ctx
,
1184 struct libnet_UnjoinCtx
*r
)
1188 if (r
->in
.modify_config
&& !lp_include_registry_globals()) {
1189 return WERR_NOT_SUPPORTED
;
1192 if (r
->in
.unjoin_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
1193 werr
= libnet_DomainUnjoin(mem_ctx
, r
);
1194 if (!W_ERROR_IS_OK(werr
)) {
1200 werr
= do_UnjoinConfig(r
);
1201 if (!W_ERROR_IS_OK(werr
)) {