2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Guenther Deschner 2007-2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "libcli/auth/libcli_auth.h"
24 #include "lib/netapi/netapi.h"
25 #include "lib/netapi/netapi_private.h"
26 #include "lib/netapi/libnetapi.h"
27 #include "librpc/gen_ndr/libnet_join.h"
28 #include "libnet/libnet_join.h"
29 #include "../librpc/gen_ndr/ndr_wkssvc_c.h"
30 #include "rpc_client/cli_pipe.h"
32 #include "libsmb/dsgetdcname.h"
33 #include "../librpc/gen_ndr/ndr_ODJ.h"
34 #include "lib/util/base64.h"
35 #include "libnet/libnet_join_offline.h"
36 #include "libcli/security/dom_sid.h"
38 /****************************************************************
39 ****************************************************************/
41 WERROR
NetJoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
42 struct NetJoinDomain
*r
)
44 struct libnet_JoinCtx
*j
= NULL
;
45 struct libnetapi_private_ctx
*priv
;
48 priv
= talloc_get_type_abort(mem_ctx
->private_data
,
49 struct libnetapi_private_ctx
);
52 return WERR_INVALID_PARAMETER
;
55 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
56 W_ERROR_NOT_OK_RETURN(werr
);
58 j
->in
.domain_name
= talloc_strdup(mem_ctx
, r
->in
.domain
);
59 W_ERROR_HAVE_NO_MEMORY(j
->in
.domain_name
);
61 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
63 struct netr_DsRGetDCNameInfo
*info
= NULL
;
64 const char *dc
= NULL
;
65 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
66 DS_WRITABLE_REQUIRED
|
68 status
= dsgetdcname(mem_ctx
, priv
->msg_ctx
, r
->in
.domain
,
69 NULL
, NULL
, flags
, &info
);
70 if (!NT_STATUS_IS_OK(status
)) {
71 libnetapi_set_error_string(mem_ctx
,
72 "%s", get_friendly_nt_error_msg(status
));
73 return ntstatus_to_werror(status
);
76 dc
= strip_hostname(info
->dc_unc
);
77 j
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
78 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
81 if (r
->in
.account_ou
) {
82 j
->in
.account_ou
= talloc_strdup(mem_ctx
, r
->in
.account_ou
);
83 W_ERROR_HAVE_NO_MEMORY(j
->in
.account_ou
);
86 if (r
->in
.account
!= NULL
) {
89 status
= ads_simple_creds(j
,
93 &j
->in
.admin_credentials
);
94 if (!NT_STATUS_IS_OK(status
)) {
96 return WERR_NERR_BADUSERNAME
;
99 libnetapi_get_creds(mem_ctx
, &j
->in
.admin_credentials
);
100 if (j
->in
.admin_credentials
== NULL
) {
102 return WERR_NERR_BADUSERNAME
;
106 j
->in
.join_flags
= r
->in
.join_flags
;
107 j
->in
.modify_config
= true;
110 werr
= libnet_Join(mem_ctx
, j
);
111 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
112 libnetapi_set_error_string(mem_ctx
, "%s", j
->out
.error_string
);
119 /****************************************************************
120 ****************************************************************/
122 WERROR
NetJoinDomain_r(struct libnetapi_ctx
*ctx
,
123 struct NetJoinDomain
*r
)
125 struct rpc_pipe_client
*pipe_cli
= NULL
;
126 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
129 unsigned int old_timeout
= 0;
130 struct dcerpc_binding_handle
*b
;
131 DATA_BLOB session_key
;
134 return WERR_NERR_SETUPDOMAINCONTROLLER
;
137 werr
= libnetapi_open_pipe(ctx
, r
->in
.server
,
140 if (!W_ERROR_IS_OK(werr
)) {
144 b
= pipe_cli
->binding_handle
;
146 if (r
->in
.password
) {
148 status
= dcerpc_binding_handle_transport_session_key(
149 b
, talloc_tos(), &session_key
);
150 if (!NT_STATUS_IS_OK(status
)) {
151 werr
= ntstatus_to_werror(status
);
155 werr
= encode_wkssvc_join_password_buffer(ctx
,
158 &encrypted_password
);
159 if (!W_ERROR_IS_OK(werr
)) {
164 old_timeout
= rpccli_set_timeout(pipe_cli
, 600000);
166 status
= dcerpc_wkssvc_NetrJoinDomain2(b
, talloc_tos(),
174 if (!NT_STATUS_IS_OK(status
)) {
175 werr
= ntstatus_to_werror(status
);
180 if (pipe_cli
&& old_timeout
) {
181 rpccli_set_timeout(pipe_cli
, old_timeout
);
186 /****************************************************************
187 ****************************************************************/
189 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
190 struct NetUnjoinDomain
*r
)
192 struct libnet_UnjoinCtx
*u
= NULL
;
193 struct dom_sid domain_sid
;
194 const char *domain
= NULL
;
196 struct libnetapi_private_ctx
*priv
;
197 const char *realm
= lp_realm();
199 priv
= talloc_get_type_abort(mem_ctx
->private_data
,
200 struct libnetapi_private_ctx
);
202 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
203 return WERR_NERR_SETUPNOTJOINED
;
206 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
207 W_ERROR_NOT_OK_RETURN(werr
);
209 if (realm
[0] != '\0') {
212 domain
= lp_workgroup();
215 if (r
->in
.server_name
) {
216 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
217 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
220 struct netr_DsRGetDCNameInfo
*info
= NULL
;
221 const char *dc
= NULL
;
222 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
223 DS_WRITABLE_REQUIRED
|
225 status
= dsgetdcname(mem_ctx
, priv
->msg_ctx
, domain
,
226 NULL
, NULL
, flags
, &info
);
227 if (!NT_STATUS_IS_OK(status
)) {
228 libnetapi_set_error_string(mem_ctx
,
229 "failed to find DC for domain %s: %s",
231 get_friendly_nt_error_msg(status
));
232 return ntstatus_to_werror(status
);
235 dc
= strip_hostname(info
->dc_unc
);
236 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
237 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
239 u
->in
.domain_name
= domain
;
242 if (r
->in
.account
!= NULL
) {
245 status
= ads_simple_creds(u
,
249 &u
->in
.admin_credentials
);
250 if (!NT_STATUS_IS_OK(status
)) {
252 return WERR_NERR_BADUSERNAME
;
255 libnetapi_get_creds(mem_ctx
, &u
->in
.admin_credentials
);
256 if (u
->in
.admin_credentials
== NULL
) {
258 return WERR_NERR_BADUSERNAME
;
262 u
->in
.domain_name
= domain
;
263 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
264 u
->in
.delete_machine_account
= false;
265 u
->in
.modify_config
= true;
268 u
->in
.domain_sid
= &domain_sid
;
270 werr
= libnet_Unjoin(mem_ctx
, u
);
271 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
272 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
279 /****************************************************************
280 ****************************************************************/
282 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
283 struct NetUnjoinDomain
*r
)
285 struct rpc_pipe_client
*pipe_cli
= NULL
;
286 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
289 unsigned int old_timeout
= 0;
290 struct dcerpc_binding_handle
*b
;
291 DATA_BLOB session_key
;
293 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
296 if (!W_ERROR_IS_OK(werr
)) {
300 b
= pipe_cli
->binding_handle
;
302 if (r
->in
.password
) {
304 status
= dcerpc_binding_handle_transport_session_key(
305 b
, talloc_tos(), &session_key
);
306 if (!NT_STATUS_IS_OK(status
)) {
307 werr
= ntstatus_to_werror(status
);
311 werr
= encode_wkssvc_join_password_buffer(ctx
,
314 &encrypted_password
);
315 if (!W_ERROR_IS_OK(werr
)) {
320 old_timeout
= rpccli_set_timeout(pipe_cli
, 60000);
322 status
= dcerpc_wkssvc_NetrUnjoinDomain2(b
, talloc_tos(),
328 if (!NT_STATUS_IS_OK(status
)) {
329 werr
= ntstatus_to_werror(status
);
334 if (pipe_cli
&& old_timeout
) {
335 rpccli_set_timeout(pipe_cli
, old_timeout
);
341 /****************************************************************
342 ****************************************************************/
344 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
345 struct NetGetJoinInformation
*r
)
347 struct rpc_pipe_client
*pipe_cli
= NULL
;
350 const char *buffer
= NULL
;
351 struct dcerpc_binding_handle
*b
;
353 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
356 if (!W_ERROR_IS_OK(werr
)) {
360 b
= pipe_cli
->binding_handle
;
362 status
= dcerpc_wkssvc_NetrGetJoinInformation(b
, talloc_tos(),
365 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
367 if (!NT_STATUS_IS_OK(status
)) {
368 werr
= ntstatus_to_werror(status
);
372 if (!W_ERROR_IS_OK(werr
)) {
376 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
377 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
383 /****************************************************************
384 ****************************************************************/
386 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
387 struct NetGetJoinInformation
*r
)
389 const char *realm
= lp_realm();
391 if ((lp_security() == SEC_ADS
) && realm
[0] != '\0') {
392 *r
->out
.name_buffer
= talloc_strdup(ctx
, realm
);
394 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
396 if (!*r
->out
.name_buffer
) {
397 return WERR_NOT_ENOUGH_MEMORY
;
400 switch (lp_server_role()) {
401 case ROLE_DOMAIN_MEMBER
:
402 case ROLE_DOMAIN_PDC
:
403 case ROLE_DOMAIN_BDC
:
405 *r
->out
.name_type
= NetSetupDomainName
;
407 case ROLE_STANDALONE
:
409 *r
->out
.name_type
= NetSetupWorkgroupName
;
416 /****************************************************************
417 ****************************************************************/
419 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
420 struct NetGetJoinableOUs
*r
)
423 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
426 ADS_STATUS ads_status
;
427 ADS_STRUCT
*ads
= NULL
;
428 struct cli_credentials
*creds
= NULL
;
429 struct netr_DsRGetDCNameInfo
*info
= NULL
;
430 const char *dc
= NULL
;
431 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
433 struct libnetapi_private_ctx
*priv
;
437 priv
= talloc_get_type_abort(ctx
->private_data
,
438 struct libnetapi_private_ctx
);
440 status
= dsgetdcname(tmp_ctx
, priv
->msg_ctx
, r
->in
.domain
,
441 NULL
, NULL
, flags
, &info
);
442 if (!NT_STATUS_IS_OK(status
)) {
443 libnetapi_set_error_string(ctx
, "%s",
444 get_friendly_nt_error_msg(status
));
445 ret
= ntstatus_to_werror(status
);
449 dc
= strip_hostname(info
->dc_unc
);
451 ads
= ads_init(tmp_ctx
,
457 ret
= WERR_GEN_FAILURE
;
461 if (r
->in
.account
!= NULL
) {
462 status
= ads_simple_creds(ads
,
467 if (!NT_STATUS_IS_OK(status
)) {
468 ret
= WERR_NERR_DEFAULTJOINREQUIRED
;
472 libnetapi_get_creds(ctx
, &creds
);
475 ads_status
= ads_connect_creds(ads
, creds
);
476 if (!ADS_ERR_OK(ads_status
)) {
477 ret
= WERR_NERR_DEFAULTJOINREQUIRED
;
481 ads_status
= ads_get_joinable_ous(ads
, ctx
, &p
, &s
);
482 if (!ADS_ERR_OK(ads_status
)) {
483 ret
= WERR_NERR_DEFAULTJOINREQUIRED
;
486 *r
->out
.ous
= discard_const_p(const char *, p
);
487 *r
->out
.ou_count
= s
;
491 TALLOC_FREE(tmp_ctx
);
495 return WERR_NOT_SUPPORTED
;
499 /****************************************************************
500 ****************************************************************/
502 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
503 struct NetGetJoinableOUs
*r
)
505 struct rpc_pipe_client
*pipe_cli
= NULL
;
506 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
509 struct dcerpc_binding_handle
*b
;
510 DATA_BLOB session_key
;
512 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
515 if (!W_ERROR_IS_OK(werr
)) {
519 b
= pipe_cli
->binding_handle
;
521 if (r
->in
.password
) {
523 status
= dcerpc_binding_handle_transport_session_key(
524 b
, talloc_tos(), &session_key
);
525 if (!NT_STATUS_IS_OK(status
)) {
526 werr
= ntstatus_to_werror(status
);
530 werr
= encode_wkssvc_join_password_buffer(ctx
,
533 &encrypted_password
);
534 if (!W_ERROR_IS_OK(werr
)) {
539 status
= dcerpc_wkssvc_NetrGetJoinableOus2(b
, talloc_tos(),
547 if (!NT_STATUS_IS_OK(status
)) {
548 werr
= ntstatus_to_werror(status
);
556 /****************************************************************
557 ****************************************************************/
559 WERROR
NetRenameMachineInDomain_r(struct libnetapi_ctx
*ctx
,
560 struct NetRenameMachineInDomain
*r
)
562 struct rpc_pipe_client
*pipe_cli
= NULL
;
563 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
566 struct dcerpc_binding_handle
*b
;
567 DATA_BLOB session_key
;
569 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
572 if (!W_ERROR_IS_OK(werr
)) {
576 b
= pipe_cli
->binding_handle
;
578 if (r
->in
.password
) {
580 status
= dcerpc_binding_handle_transport_session_key(
581 b
, talloc_tos(), &session_key
);
582 if (!NT_STATUS_IS_OK(status
)) {
583 werr
= ntstatus_to_werror(status
);
587 werr
= encode_wkssvc_join_password_buffer(ctx
,
590 &encrypted_password
);
591 if (!W_ERROR_IS_OK(werr
)) {
596 status
= dcerpc_wkssvc_NetrRenameMachineInDomain2(b
, talloc_tos(),
598 r
->in
.new_machine_name
,
601 r
->in
.rename_options
,
603 if (!NT_STATUS_IS_OK(status
)) {
604 werr
= ntstatus_to_werror(status
);
612 /****************************************************************
613 ****************************************************************/
615 WERROR
NetRenameMachineInDomain_l(struct libnetapi_ctx
*ctx
,
616 struct NetRenameMachineInDomain
*r
)
618 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetRenameMachineInDomain
);
621 /****************************************************************
622 ****************************************************************/
624 WERROR
NetProvisionComputerAccount_r(struct libnetapi_ctx
*ctx
,
625 struct NetProvisionComputerAccount
*r
)
627 return NetProvisionComputerAccount_l(ctx
, r
);
630 /****************************************************************
631 ****************************************************************/
633 static WERROR
NetProvisionComputerAccount_backend(struct libnetapi_ctx
*ctx
,
634 struct NetProvisionComputerAccount
*r
,
636 struct ODJ_PROVISION_DATA
**p
)
639 struct libnet_JoinCtx
*j
= NULL
;
641 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
642 if (!W_ERROR_IS_OK(werr
)) {
646 j
->in
.domain_name
= talloc_strdup(j
, r
->in
.domain
);
647 if (j
->in
.domain_name
== NULL
) {
649 return WERR_NOT_ENOUGH_MEMORY
;
652 talloc_free(discard_const_p(char *, j
->in
.machine_name
));
653 j
->in
.machine_name
= talloc_strdup(j
, r
->in
.machine_name
);
654 if (j
->in
.machine_name
== NULL
) {
656 return WERR_NOT_ENOUGH_MEMORY
;
660 j
->in
.dc_name
= talloc_strdup(j
, r
->in
.dcname
);
661 if (j
->in
.dc_name
== NULL
) {
663 return WERR_NOT_ENOUGH_MEMORY
;
667 if (r
->in
.machine_account_ou
) {
668 j
->in
.account_ou
= talloc_strdup(j
, r
->in
.machine_account_ou
);
669 if (j
->in
.account_ou
== NULL
) {
671 return WERR_NOT_ENOUGH_MEMORY
;
675 libnetapi_get_creds(ctx
, &j
->in
.admin_credentials
);
676 if (j
->in
.admin_credentials
== NULL
) {
678 return WERR_NERR_BADUSERNAME
;
682 j
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
683 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
;
685 if (r
->in
.options
& NETSETUP_PROVISION_REUSE_ACCOUNT
) {
686 j
->in
.join_flags
|= WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
;
689 if (r
->in
.options
& NETSETUP_PROVISION_USE_DEFAULT_PASSWORD
) {
690 j
->in
.join_flags
|= WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED
;
691 j
->in
.machine_password
= talloc_strdup(j
, r
->in
.machine_name
);
692 if (j
->in
.machine_password
== NULL
) {
694 return WERR_NOT_ENOUGH_MEMORY
;
698 j
->in
.provision_computer_account_only
= true;
700 werr
= libnet_Join(mem_ctx
, j
);
701 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
702 libnetapi_set_error_string(ctx
, "%s", j
->out
.error_string
);
707 werr
= libnet_odj_compose_ODJ_PROVISION_DATA(mem_ctx
, j
, p
);
708 if (!W_ERROR_IS_OK(werr
)) {
718 WERROR
NetProvisionComputerAccount_l(struct libnetapi_ctx
*ctx
,
719 struct NetProvisionComputerAccount
*r
)
722 enum ndr_err_code ndr_err
;
723 const char *b64_bin_data_str
;
725 struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data
;
726 struct ODJ_PROVISION_DATA
*p
;
727 TALLOC_CTX
*mem_ctx
= talloc_new(ctx
);
729 if (r
->in
.provision_bin_data
== NULL
&&
730 r
->in
.provision_text_data
== NULL
) {
731 return WERR_INVALID_PARAMETER
;
733 if (r
->in
.provision_bin_data
!= NULL
&&
734 r
->in
.provision_text_data
!= NULL
) {
735 return WERR_INVALID_PARAMETER
;
737 if (r
->in
.provision_bin_data
== NULL
&&
738 r
->in
.provision_bin_data_size
!= NULL
) {
739 return WERR_INVALID_PARAMETER
;
741 if (r
->in
.provision_bin_data
!= NULL
&&
742 r
->in
.provision_bin_data_size
== NULL
) {
743 return WERR_INVALID_PARAMETER
;
746 if (r
->in
.domain
== NULL
) {
747 return WERR_INVALID_PARAMETER
;
750 if (r
->in
.machine_name
== NULL
) {
751 return WERR_INVALID_PARAMETER
;
754 werr
= NetProvisionComputerAccount_backend(ctx
, r
, mem_ctx
, &p
);
755 if (!W_ERROR_IS_OK(werr
)) {
756 talloc_free(mem_ctx
);
760 ZERO_STRUCT(odj_provision_data
);
762 odj_provision_data
.s
.p
= p
;
764 ndr_err
= ndr_push_struct_blob(&blob
, ctx
, &odj_provision_data
,
765 (ndr_push_flags_fn_t
)ndr_push_ODJ_PROVISION_DATA_serialized_ptr
);
766 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
767 talloc_free(mem_ctx
);
768 return W_ERROR(NERR_BadOfflineJoinInfo
);
771 talloc_free(mem_ctx
);
773 if (r
->out
.provision_text_data
!= NULL
) {
774 b64_bin_data_str
= base64_encode_data_blob(ctx
, blob
);
775 if (b64_bin_data_str
== NULL
) {
776 return WERR_NOT_ENOUGH_MEMORY
;
778 *r
->out
.provision_text_data
= b64_bin_data_str
;
781 if (r
->out
.provision_bin_data
!= NULL
&&
782 r
->out
.provision_bin_data_size
!= NULL
) {
783 *r
->out
.provision_bin_data
= blob
.data
;
784 *r
->out
.provision_bin_data_size
= blob
.length
;
790 /****************************************************************
791 ****************************************************************/
793 WERROR
NetRequestOfflineDomainJoin_r(struct libnetapi_ctx
*ctx
,
794 struct NetRequestOfflineDomainJoin
*r
)
796 return WERR_NOT_SUPPORTED
;
799 /****************************************************************
800 ****************************************************************/
802 static WERROR
NetRequestOfflineDomainJoin_backend(struct libnetapi_ctx
*ctx
,
803 const struct ODJ_WIN7BLOB
*win7blob
,
804 const struct ODJ_PROVISION_DATA
*odj_provision_data
)
806 struct libnet_JoinCtx
*j
= NULL
;
809 werr
= libnet_init_JoinCtx(ctx
, &j
);
810 if (!W_ERROR_IS_OK(werr
)) {
814 j
->in
.domain_name
= talloc_strdup(j
, win7blob
->lpDomain
);
815 if (j
->in
.domain_name
== NULL
) {
817 return WERR_NOT_ENOUGH_MEMORY
;
820 talloc_free(discard_const_p(char *, j
->in
.machine_name
));
821 j
->in
.machine_name
= talloc_strdup(j
, win7blob
->lpMachineName
);
822 if (j
->in
.machine_name
== NULL
) {
824 return WERR_NOT_ENOUGH_MEMORY
;
827 j
->in
.machine_password
= talloc_strdup(j
, win7blob
->lpMachinePassword
);
828 if (j
->in
.machine_password
== NULL
) {
830 return WERR_NOT_ENOUGH_MEMORY
;
833 j
->in
.request_offline_join
= true;
834 j
->in
.odj_provision_data
= discard_const(odj_provision_data
);
836 j
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
837 WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED
;
839 werr
= libnet_Join(j
, j
);
840 if (!W_ERROR_IS_OK(werr
)) {
841 if (j
->out
.error_string
!= NULL
) {
842 libnetapi_set_error_string(ctx
, "%s", j
->out
.error_string
);
853 WERROR
NetRequestOfflineDomainJoin_l(struct libnetapi_ctx
*ctx
,
854 struct NetRequestOfflineDomainJoin
*r
)
856 DATA_BLOB blob
, blob_base64
;
857 enum ndr_err_code ndr_err
;
858 struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data
;
860 struct ODJ_WIN7BLOB win7blob
= { 0 };
863 if (r
->in
.provision_bin_data
== NULL
||
864 r
->in
.provision_bin_data_size
== 0) {
865 return W_ERROR(NERR_NoOfflineJoinInfo
);
868 if (r
->in
.provision_bin_data_size
< 2) {
869 return W_ERROR(NERR_BadOfflineJoinInfo
);
873 * Windows produces and consumes UTF16/UCS2 encoded blobs. Check for the
874 * unicode BOM mark and convert back to UNIX charset if necessary.
876 if (r
->in
.provision_bin_data
[0] == 0xff &&
877 r
->in
.provision_bin_data
[1] == 0xfe) {
878 ok
= convert_string_talloc(ctx
, CH_UTF16LE
, CH_UNIX
,
879 r
->in
.provision_bin_data
+2,
880 r
->in
.provision_bin_data_size
-2,
882 &blob_base64
.length
);
884 return W_ERROR(NERR_BadOfflineJoinInfo
);
887 blob_base64
= data_blob(r
->in
.provision_bin_data
,
888 r
->in
.provision_bin_data_size
);
891 blob
= base64_decode_data_blob_talloc(ctx
, (const char *)blob_base64
.data
);
893 ndr_err
= ndr_pull_struct_blob(&blob
, ctx
, &odj_provision_data
,
894 (ndr_pull_flags_fn_t
)ndr_pull_ODJ_PROVISION_DATA_serialized_ptr
);
895 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
896 return W_ERROR(NERR_BadOfflineJoinInfo
);
899 if (DEBUGLEVEL
>= 10) {
900 NDR_PRINT_DEBUG(ODJ_PROVISION_DATA_serialized_ptr
, &odj_provision_data
);
903 if (odj_provision_data
.s
.p
->ulVersion
!= 1) {
904 return W_ERROR(NERR_ProvisioningBlobUnsupported
);
907 werr
= libnet_odj_find_win7blob(odj_provision_data
.s
.p
, &win7blob
);
908 if (!W_ERROR_IS_OK(werr
)) {
912 if (!(r
->in
.options
& NETSETUP_PROVISION_ONLINE_CALLER
)) {
913 return WERR_NERR_SETUPNOTJOINED
;
916 werr
= NetRequestOfflineDomainJoin_backend(ctx
,
918 odj_provision_data
.s
.p
);
919 if (!W_ERROR_IS_OK(werr
)) {
923 return W_ERROR(NERR_JoinPerformedMustRestart
);
926 /****************************************************************
927 ****************************************************************/
929 WERROR
NetComposeOfflineDomainJoin_r(struct libnetapi_ctx
*ctx
,
930 struct NetComposeOfflineDomainJoin
*r
)
932 return WERR_NOT_SUPPORTED
;
935 /****************************************************************
936 ****************************************************************/
938 static WERROR
NetComposeOfflineDomainJoin_backend(struct libnetapi_ctx
*ctx
,
939 struct NetComposeOfflineDomainJoin
*r
,
941 struct ODJ_PROVISION_DATA
**p
)
943 struct libnet_JoinCtx
*j
= NULL
;
946 werr
= libnet_init_JoinCtx(ctx
, &j
);
947 if (!W_ERROR_IS_OK(werr
)) {
951 j
->in
.domain_name
= talloc_strdup(j
, r
->in
.dns_domain_name
);
952 if (j
->in
.domain_name
== NULL
) {
953 return WERR_NOT_ENOUGH_MEMORY
;
956 j
->in
.dc_name
= talloc_strdup(j
, r
->in
.dc_name
);
957 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
959 j
->in
.machine_password
= talloc_strdup(j
, r
->in
.machine_account_password
);
960 W_ERROR_HAVE_NO_MEMORY(j
->in
.machine_password
);
962 j
->out
.account_name
= talloc_strdup(j
, r
->in
.machine_account_name
);
963 W_ERROR_HAVE_NO_MEMORY(j
->out
.account_name
);
965 j
->out
.dns_domain_name
= talloc_strdup(j
, r
->in
.dns_domain_name
);
966 W_ERROR_HAVE_NO_MEMORY(j
->out
.dns_domain_name
);
968 j
->out
.netbios_domain_name
= talloc_strdup(j
, r
->in
.netbios_domain_name
);
969 W_ERROR_HAVE_NO_MEMORY(j
->out
.netbios_domain_name
);
971 j
->out
.domain_sid
= dom_sid_dup(j
, (struct dom_sid
*)r
->in
.domain_sid
);
972 W_ERROR_HAVE_NO_MEMORY(j
->out
.domain_sid
);
974 j
->out
.domain_guid
= *r
->in
.domain_guid
;
976 j
->out
.forest_name
= talloc_strdup(j
, r
->in
.forest_name
);
977 W_ERROR_HAVE_NO_MEMORY(j
->out
.forest_name
);
979 j
->out
.domain_is_ad
= r
->in
.domain_is_ad
;
981 j
->out
.dcinfo
= talloc_zero(j
, struct netr_DsRGetDCNameInfo
);
982 W_ERROR_HAVE_NO_MEMORY(j
->out
.dcinfo
);
984 j
->out
.dcinfo
->dc_unc
= talloc_asprintf(j
->out
.dcinfo
, "\\\\%s", r
->in
.dc_name
);
985 W_ERROR_HAVE_NO_MEMORY(j
->out
.dcinfo
->dc_unc
);
987 j
->out
.dcinfo
->dc_address
= talloc_asprintf(j
->out
.dcinfo
, "\\\\%s", r
->in
.dc_address
);
988 W_ERROR_HAVE_NO_MEMORY(j
->out
.dcinfo
->dc_address
);
990 j
->out
.dcinfo
->dc_address_type
= DS_ADDRESS_TYPE_INET
;
992 j
->out
.dcinfo
->domain_guid
= *r
->in
.domain_guid
;
994 j
->out
.dcinfo
->domain_name
= talloc_strdup(j
->out
.dcinfo
, r
->in
.dns_domain_name
);
995 W_ERROR_HAVE_NO_MEMORY(j
->out
.dcinfo
->domain_name
);
997 j
->out
.dcinfo
->forest_name
= talloc_strdup(j
->out
.dcinfo
, r
->in
.forest_name
);
998 W_ERROR_HAVE_NO_MEMORY(j
->out
.dcinfo
->forest_name
);
1000 werr
= libnet_odj_compose_ODJ_PROVISION_DATA(mem_ctx
, j
, p
);
1001 if (!W_ERROR_IS_OK(werr
)) {
1008 WERROR
NetComposeOfflineDomainJoin_l(struct libnetapi_ctx
*ctx
,
1009 struct NetComposeOfflineDomainJoin
*r
)
1012 enum ndr_err_code ndr_err
;
1013 const char *b64_bin_data_str
;
1015 struct ODJ_PROVISION_DATA_serialized_ptr odj_compose_data
;
1016 struct ODJ_PROVISION_DATA
*p
;
1017 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
1019 if (r
->in
.compose_bin_data
== NULL
&&
1020 r
->in
.compose_text_data
== NULL
) {
1021 werr
= WERR_INVALID_PARAMETER
;
1024 if (r
->in
.compose_bin_data
!= NULL
&&
1025 r
->in
.compose_text_data
!= NULL
) {
1026 werr
= WERR_INVALID_PARAMETER
;
1029 if (r
->in
.compose_bin_data
== NULL
&&
1030 r
->in
.compose_bin_data_size
!= NULL
) {
1031 werr
= WERR_INVALID_PARAMETER
;
1034 if (r
->in
.compose_bin_data
!= NULL
&&
1035 r
->in
.compose_bin_data_size
== NULL
) {
1036 werr
= WERR_INVALID_PARAMETER
;
1040 if (r
->in
.dns_domain_name
== NULL
) {
1041 werr
= WERR_INVALID_PARAMETER
;
1045 if (r
->in
.netbios_domain_name
== NULL
) {
1046 werr
= WERR_INVALID_PARAMETER
;
1050 if (r
->in
.domain_sid
== NULL
) {
1051 werr
= WERR_INVALID_PARAMETER
;
1055 if (r
->in
.domain_guid
== NULL
) {
1056 werr
= WERR_INVALID_PARAMETER
;
1060 if (r
->in
.forest_name
== NULL
) {
1061 werr
= WERR_INVALID_PARAMETER
;
1065 if (r
->in
.machine_account_name
== NULL
) {
1066 werr
= WERR_INVALID_PARAMETER
;
1070 if (r
->in
.machine_account_password
== NULL
) {
1071 werr
= WERR_INVALID_PARAMETER
;
1075 if (r
->in
.dc_name
== NULL
) {
1076 werr
= WERR_INVALID_PARAMETER
;
1080 if (r
->in
.dc_address
== NULL
) {
1081 werr
= WERR_INVALID_PARAMETER
;
1085 werr
= NetComposeOfflineDomainJoin_backend(ctx
, r
, tmp_ctx
, &p
);
1086 if (!W_ERROR_IS_OK(werr
)) {
1090 ZERO_STRUCT(odj_compose_data
);
1092 odj_compose_data
.s
.p
= p
;
1094 ndr_err
= ndr_push_struct_blob(&blob
, ctx
, &odj_compose_data
,
1095 (ndr_push_flags_fn_t
)ndr_push_ODJ_PROVISION_DATA_serialized_ptr
);
1096 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1097 werr
= W_ERROR(NERR_BadOfflineJoinInfo
);
1101 if (r
->out
.compose_text_data
!= NULL
) {
1102 b64_bin_data_str
= base64_encode_data_blob(ctx
, blob
);
1103 if (b64_bin_data_str
== NULL
) {
1104 werr
= WERR_NOT_ENOUGH_MEMORY
;
1106 *r
->out
.compose_text_data
= b64_bin_data_str
;
1109 if (r
->out
.compose_bin_data
!= NULL
&&
1110 r
->out
.compose_bin_data_size
!= NULL
) {
1111 *r
->out
.compose_bin_data
= blob
.data
;
1112 *r
->out
.compose_bin_data_size
= blob
.length
;
1117 talloc_free(tmp_ctx
);