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"
37 /****************************************************************
38 ****************************************************************/
40 WERROR
NetJoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
41 struct NetJoinDomain
*r
)
43 struct libnet_JoinCtx
*j
= NULL
;
44 struct libnetapi_private_ctx
*priv
;
47 priv
= talloc_get_type_abort(mem_ctx
->private_data
,
48 struct libnetapi_private_ctx
);
51 return WERR_INVALID_PARAMETER
;
54 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
55 W_ERROR_NOT_OK_RETURN(werr
);
57 j
->in
.domain_name
= talloc_strdup(mem_ctx
, r
->in
.domain
);
58 W_ERROR_HAVE_NO_MEMORY(j
->in
.domain_name
);
60 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
62 struct netr_DsRGetDCNameInfo
*info
= NULL
;
63 const char *dc
= NULL
;
64 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
65 DS_WRITABLE_REQUIRED
|
67 status
= dsgetdcname(mem_ctx
, priv
->msg_ctx
, r
->in
.domain
,
68 NULL
, NULL
, flags
, &info
);
69 if (!NT_STATUS_IS_OK(status
)) {
70 libnetapi_set_error_string(mem_ctx
,
71 "%s", get_friendly_nt_error_msg(status
));
72 return ntstatus_to_werror(status
);
75 dc
= strip_hostname(info
->dc_unc
);
76 j
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
77 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
80 if (r
->in
.account_ou
) {
81 j
->in
.account_ou
= talloc_strdup(mem_ctx
, r
->in
.account_ou
);
82 W_ERROR_HAVE_NO_MEMORY(j
->in
.account_ou
);
86 j
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
87 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_account
);
91 j
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
92 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_password
);
95 j
->in
.join_flags
= r
->in
.join_flags
;
96 j
->in
.modify_config
= true;
99 werr
= libnet_Join(mem_ctx
, j
);
100 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
101 libnetapi_set_error_string(mem_ctx
, "%s", j
->out
.error_string
);
108 /****************************************************************
109 ****************************************************************/
111 WERROR
NetJoinDomain_r(struct libnetapi_ctx
*ctx
,
112 struct NetJoinDomain
*r
)
114 struct rpc_pipe_client
*pipe_cli
= NULL
;
115 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
118 unsigned int old_timeout
= 0;
119 struct dcerpc_binding_handle
*b
;
120 DATA_BLOB session_key
;
123 return WERR_NERR_SETUPDOMAINCONTROLLER
;
126 werr
= libnetapi_open_pipe(ctx
, r
->in
.server
,
129 if (!W_ERROR_IS_OK(werr
)) {
133 b
= pipe_cli
->binding_handle
;
135 if (r
->in
.password
) {
137 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &session_key
);
138 if (!NT_STATUS_IS_OK(status
)) {
139 werr
= ntstatus_to_werror(status
);
143 werr
= encode_wkssvc_join_password_buffer(ctx
,
146 &encrypted_password
);
147 if (!W_ERROR_IS_OK(werr
)) {
152 old_timeout
= rpccli_set_timeout(pipe_cli
, 600000);
154 status
= dcerpc_wkssvc_NetrJoinDomain2(b
, talloc_tos(),
162 if (!NT_STATUS_IS_OK(status
)) {
163 werr
= ntstatus_to_werror(status
);
168 if (pipe_cli
&& old_timeout
) {
169 rpccli_set_timeout(pipe_cli
, old_timeout
);
174 /****************************************************************
175 ****************************************************************/
177 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
178 struct NetUnjoinDomain
*r
)
180 struct libnet_UnjoinCtx
*u
= NULL
;
181 struct dom_sid domain_sid
;
182 const char *domain
= NULL
;
184 struct libnetapi_private_ctx
*priv
;
185 const char *realm
= lp_realm();
187 priv
= talloc_get_type_abort(mem_ctx
->private_data
,
188 struct libnetapi_private_ctx
);
190 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
191 return WERR_NERR_SETUPNOTJOINED
;
194 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
195 W_ERROR_NOT_OK_RETURN(werr
);
197 if (realm
[0] != '\0') {
200 domain
= lp_workgroup();
203 if (r
->in
.server_name
) {
204 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
205 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
208 struct netr_DsRGetDCNameInfo
*info
= NULL
;
209 const char *dc
= NULL
;
210 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
211 DS_WRITABLE_REQUIRED
|
213 status
= dsgetdcname(mem_ctx
, priv
->msg_ctx
, domain
,
214 NULL
, NULL
, flags
, &info
);
215 if (!NT_STATUS_IS_OK(status
)) {
216 libnetapi_set_error_string(mem_ctx
,
217 "failed to find DC for domain %s: %s",
219 get_friendly_nt_error_msg(status
));
220 return ntstatus_to_werror(status
);
223 dc
= strip_hostname(info
->dc_unc
);
224 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
225 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
227 u
->in
.domain_name
= domain
;
231 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
232 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
235 if (r
->in
.password
) {
236 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
237 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
240 u
->in
.domain_name
= domain
;
241 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
242 u
->in
.delete_machine_account
= false;
243 u
->in
.modify_config
= true;
246 u
->in
.domain_sid
= &domain_sid
;
248 werr
= libnet_Unjoin(mem_ctx
, u
);
249 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
250 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
257 /****************************************************************
258 ****************************************************************/
260 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
261 struct NetUnjoinDomain
*r
)
263 struct rpc_pipe_client
*pipe_cli
= NULL
;
264 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
267 unsigned int old_timeout
= 0;
268 struct dcerpc_binding_handle
*b
;
269 DATA_BLOB session_key
;
271 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
274 if (!W_ERROR_IS_OK(werr
)) {
278 b
= pipe_cli
->binding_handle
;
280 if (r
->in
.password
) {
282 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &session_key
);
283 if (!NT_STATUS_IS_OK(status
)) {
284 werr
= ntstatus_to_werror(status
);
288 werr
= encode_wkssvc_join_password_buffer(ctx
,
291 &encrypted_password
);
292 if (!W_ERROR_IS_OK(werr
)) {
297 old_timeout
= rpccli_set_timeout(pipe_cli
, 60000);
299 status
= dcerpc_wkssvc_NetrUnjoinDomain2(b
, talloc_tos(),
305 if (!NT_STATUS_IS_OK(status
)) {
306 werr
= ntstatus_to_werror(status
);
311 if (pipe_cli
&& old_timeout
) {
312 rpccli_set_timeout(pipe_cli
, old_timeout
);
318 /****************************************************************
319 ****************************************************************/
321 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
322 struct NetGetJoinInformation
*r
)
324 struct rpc_pipe_client
*pipe_cli
= NULL
;
327 const char *buffer
= NULL
;
328 struct dcerpc_binding_handle
*b
;
330 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
333 if (!W_ERROR_IS_OK(werr
)) {
337 b
= pipe_cli
->binding_handle
;
339 status
= dcerpc_wkssvc_NetrGetJoinInformation(b
, talloc_tos(),
342 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
344 if (!NT_STATUS_IS_OK(status
)) {
345 werr
= ntstatus_to_werror(status
);
349 if (!W_ERROR_IS_OK(werr
)) {
353 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
354 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
360 /****************************************************************
361 ****************************************************************/
363 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
364 struct NetGetJoinInformation
*r
)
366 const char *realm
= lp_realm();
368 if ((lp_security() == SEC_ADS
) && realm
[0] != '\0') {
369 *r
->out
.name_buffer
= talloc_strdup(ctx
, realm
);
371 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
373 if (!*r
->out
.name_buffer
) {
374 return WERR_NOT_ENOUGH_MEMORY
;
377 switch (lp_server_role()) {
378 case ROLE_DOMAIN_MEMBER
:
379 case ROLE_DOMAIN_PDC
:
380 case ROLE_DOMAIN_BDC
:
382 *r
->out
.name_type
= NetSetupDomainName
;
384 case ROLE_STANDALONE
:
386 *r
->out
.name_type
= NetSetupWorkgroupName
;
393 /****************************************************************
394 ****************************************************************/
396 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
397 struct NetGetJoinableOUs
*r
)
400 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
403 ADS_STATUS ads_status
;
404 ADS_STRUCT
*ads
= NULL
;
405 struct netr_DsRGetDCNameInfo
*info
= NULL
;
406 const char *dc
= NULL
;
407 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
409 struct libnetapi_private_ctx
*priv
;
413 priv
= talloc_get_type_abort(ctx
->private_data
,
414 struct libnetapi_private_ctx
);
416 status
= dsgetdcname(tmp_ctx
, priv
->msg_ctx
, r
->in
.domain
,
417 NULL
, NULL
, flags
, &info
);
418 if (!NT_STATUS_IS_OK(status
)) {
419 libnetapi_set_error_string(ctx
, "%s",
420 get_friendly_nt_error_msg(status
));
421 ret
= ntstatus_to_werror(status
);
425 dc
= strip_hostname(info
->dc_unc
);
427 ads
= ads_init(tmp_ctx
,
433 ret
= WERR_GEN_FAILURE
;
437 ADS_TALLOC_CONST_FREE(ads
->auth
.user_name
);
439 ads
->auth
.user_name
= talloc_strdup(ads
, r
->in
.account
);
440 if (ads
->auth
.user_name
== NULL
) {
441 ret
= WERR_NOT_ENOUGH_MEMORY
;
445 const char *username
= NULL
;
447 libnetapi_get_username(ctx
, &username
);
448 if (username
!= NULL
) {
449 ads
->auth
.user_name
= talloc_strdup(ads
, username
);
450 if (ads
->auth
.user_name
== NULL
) {
451 ret
= WERR_NOT_ENOUGH_MEMORY
;
457 ADS_TALLOC_CONST_FREE(ads
->auth
.password
);
458 if (r
->in
.password
) {
459 ads
->auth
.password
= talloc_strdup(ads
, r
->in
.password
);
460 if (ads
->auth
.password
== NULL
) {
461 ret
= WERR_NOT_ENOUGH_MEMORY
;
465 const char *password
= NULL
;
467 libnetapi_get_password(ctx
, &password
);
468 if (password
!= NULL
) {
469 ads
->auth
.password
= talloc_strdup(ads
, password
);
470 if (ads
->auth
.password
== NULL
) {
471 ret
= WERR_NOT_ENOUGH_MEMORY
;
477 ads_status
= ads_connect_user_creds(ads
);
478 if (!ADS_ERR_OK(ads_status
)) {
479 ret
= WERR_NERR_DEFAULTJOINREQUIRED
;
483 ads_status
= ads_get_joinable_ous(ads
, ctx
, &p
, &s
);
484 if (!ADS_ERR_OK(ads_status
)) {
485 ret
= WERR_NERR_DEFAULTJOINREQUIRED
;
488 *r
->out
.ous
= discard_const_p(const char *, p
);
489 *r
->out
.ou_count
= s
;
493 TALLOC_FREE(tmp_ctx
);
497 return WERR_NOT_SUPPORTED
;
501 /****************************************************************
502 ****************************************************************/
504 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
505 struct NetGetJoinableOUs
*r
)
507 struct rpc_pipe_client
*pipe_cli
= NULL
;
508 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
511 struct dcerpc_binding_handle
*b
;
512 DATA_BLOB session_key
;
514 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
517 if (!W_ERROR_IS_OK(werr
)) {
521 b
= pipe_cli
->binding_handle
;
523 if (r
->in
.password
) {
525 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &session_key
);
526 if (!NT_STATUS_IS_OK(status
)) {
527 werr
= ntstatus_to_werror(status
);
531 werr
= encode_wkssvc_join_password_buffer(ctx
,
534 &encrypted_password
);
535 if (!W_ERROR_IS_OK(werr
)) {
540 status
= dcerpc_wkssvc_NetrGetJoinableOus2(b
, talloc_tos(),
548 if (!NT_STATUS_IS_OK(status
)) {
549 werr
= ntstatus_to_werror(status
);
557 /****************************************************************
558 ****************************************************************/
560 WERROR
NetRenameMachineInDomain_r(struct libnetapi_ctx
*ctx
,
561 struct NetRenameMachineInDomain
*r
)
563 struct rpc_pipe_client
*pipe_cli
= NULL
;
564 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
567 struct dcerpc_binding_handle
*b
;
568 DATA_BLOB session_key
;
570 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
573 if (!W_ERROR_IS_OK(werr
)) {
577 b
= pipe_cli
->binding_handle
;
579 if (r
->in
.password
) {
581 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &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
;
640 int use_kerberos
= 0;
641 const char *username
= NULL
;
643 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
644 if (!W_ERROR_IS_OK(werr
)) {
648 j
->in
.domain_name
= talloc_strdup(j
, r
->in
.domain
);
649 if (j
->in
.domain_name
== NULL
) {
651 return WERR_NOT_ENOUGH_MEMORY
;
654 talloc_free(discard_const_p(char *, j
->in
.machine_name
));
655 j
->in
.machine_name
= talloc_strdup(j
, r
->in
.machine_name
);
656 if (j
->in
.machine_name
== NULL
) {
658 return WERR_NOT_ENOUGH_MEMORY
;
662 j
->in
.dc_name
= talloc_strdup(j
, r
->in
.dcname
);
663 if (j
->in
.dc_name
== NULL
) {
665 return WERR_NOT_ENOUGH_MEMORY
;
669 if (r
->in
.machine_account_ou
) {
670 j
->in
.account_ou
= talloc_strdup(j
, r
->in
.machine_account_ou
);
671 if (j
->in
.account_ou
== NULL
) {
673 return WERR_NOT_ENOUGH_MEMORY
;
677 libnetapi_get_username(ctx
, &username
);
678 if (username
== NULL
) {
680 return WERR_NERR_BADUSERNAME
;
683 j
->in
.admin_account
= talloc_strdup(j
, username
);
684 if (j
->in
.admin_account
== NULL
) {
686 return WERR_NOT_ENOUGH_MEMORY
;
689 libnetapi_get_use_kerberos(ctx
, &use_kerberos
);
691 const char *password
= NULL
;
693 libnetapi_get_password(ctx
, &password
);
694 if (password
== NULL
) {
696 return WERR_NERR_BADPASSWORD
;
698 j
->in
.admin_password
= talloc_strdup(j
, password
);
699 if (j
->in
.admin_password
== NULL
) {
701 return WERR_NOT_ENOUGH_MEMORY
;
705 j
->in
.use_kerberos
= use_kerberos
;
707 j
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
708 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
;
710 if (r
->in
.options
& NETSETUP_PROVISION_REUSE_ACCOUNT
) {
711 j
->in
.join_flags
|= WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
;
714 if (r
->in
.options
& NETSETUP_PROVISION_USE_DEFAULT_PASSWORD
) {
715 j
->in
.join_flags
|= WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED
;
716 j
->in
.machine_password
= talloc_strdup(j
, r
->in
.machine_name
);
717 if (j
->in
.machine_password
== NULL
) {
719 return WERR_NOT_ENOUGH_MEMORY
;
723 j
->in
.provision_computer_account_only
= true;
725 werr
= libnet_Join(mem_ctx
, j
);
726 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
727 libnetapi_set_error_string(ctx
, "%s", j
->out
.error_string
);
732 werr
= libnet_odj_compose_ODJ_PROVISION_DATA(mem_ctx
, j
, p
);
733 if (!W_ERROR_IS_OK(werr
)) {
743 WERROR
NetProvisionComputerAccount_l(struct libnetapi_ctx
*ctx
,
744 struct NetProvisionComputerAccount
*r
)
747 enum ndr_err_code ndr_err
;
748 const char *b64_bin_data_str
;
750 struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data
;
751 struct ODJ_PROVISION_DATA
*p
;
752 TALLOC_CTX
*mem_ctx
= talloc_new(ctx
);
754 if (r
->in
.provision_bin_data
== NULL
&&
755 r
->in
.provision_text_data
== NULL
) {
756 return WERR_INVALID_PARAMETER
;
758 if (r
->in
.provision_bin_data
!= NULL
&&
759 r
->in
.provision_text_data
!= NULL
) {
760 return WERR_INVALID_PARAMETER
;
762 if (r
->in
.provision_bin_data
== NULL
&&
763 r
->in
.provision_bin_data_size
!= NULL
) {
764 return WERR_INVALID_PARAMETER
;
766 if (r
->in
.provision_bin_data
!= NULL
&&
767 r
->in
.provision_bin_data_size
== NULL
) {
768 return WERR_INVALID_PARAMETER
;
771 if (r
->in
.domain
== NULL
) {
772 return WERR_INVALID_PARAMETER
;
775 if (r
->in
.machine_name
== NULL
) {
776 return WERR_INVALID_PARAMETER
;
779 werr
= NetProvisionComputerAccount_backend(ctx
, r
, mem_ctx
, &p
);
780 if (!W_ERROR_IS_OK(werr
)) {
781 talloc_free(mem_ctx
);
785 ZERO_STRUCT(odj_provision_data
);
787 odj_provision_data
.s
.p
= p
;
789 ndr_err
= ndr_push_struct_blob(&blob
, ctx
, &odj_provision_data
,
790 (ndr_push_flags_fn_t
)ndr_push_ODJ_PROVISION_DATA_serialized_ptr
);
791 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
792 talloc_free(mem_ctx
);
793 return W_ERROR(NERR_BadOfflineJoinInfo
);
796 talloc_free(mem_ctx
);
798 if (r
->out
.provision_text_data
!= NULL
) {
799 b64_bin_data_str
= base64_encode_data_blob(ctx
, blob
);
800 if (b64_bin_data_str
== NULL
) {
801 return WERR_NOT_ENOUGH_MEMORY
;
803 *r
->out
.provision_text_data
= b64_bin_data_str
;
806 if (r
->out
.provision_bin_data
!= NULL
&&
807 r
->out
.provision_bin_data_size
!= NULL
) {
808 *r
->out
.provision_bin_data
= blob
.data
;
809 *r
->out
.provision_bin_data_size
= blob
.length
;
815 /****************************************************************
816 ****************************************************************/
818 WERROR
NetRequestOfflineDomainJoin_r(struct libnetapi_ctx
*ctx
,
819 struct NetRequestOfflineDomainJoin
*r
)
821 return WERR_NOT_SUPPORTED
;
824 /****************************************************************
825 ****************************************************************/
827 static WERROR
NetRequestOfflineDomainJoin_backend(struct libnetapi_ctx
*ctx
,
828 const struct ODJ_WIN7BLOB
*win7blob
,
829 const struct ODJ_PROVISION_DATA
*odj_provision_data
)
831 struct libnet_JoinCtx
*j
= NULL
;
834 werr
= libnet_init_JoinCtx(ctx
, &j
);
835 if (!W_ERROR_IS_OK(werr
)) {
839 j
->in
.domain_name
= talloc_strdup(j
, win7blob
->lpDomain
);
840 if (j
->in
.domain_name
== NULL
) {
842 return WERR_NOT_ENOUGH_MEMORY
;
845 talloc_free(discard_const_p(char *, j
->in
.machine_name
));
846 j
->in
.machine_name
= talloc_strdup(j
, win7blob
->lpMachineName
);
847 if (j
->in
.machine_name
== NULL
) {
849 return WERR_NOT_ENOUGH_MEMORY
;
852 j
->in
.machine_password
= talloc_strdup(j
, win7blob
->lpMachinePassword
);
853 if (j
->in
.machine_password
== NULL
) {
855 return WERR_NOT_ENOUGH_MEMORY
;
858 j
->in
.request_offline_join
= true;
859 j
->in
.odj_provision_data
= discard_const(odj_provision_data
);
861 j
->in
.join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
862 WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED
;
864 werr
= libnet_Join(j
, j
);
865 if (!W_ERROR_IS_OK(werr
)) {
866 if (j
->out
.error_string
!= NULL
) {
867 libnetapi_set_error_string(ctx
, "%s", j
->out
.error_string
);
878 WERROR
NetRequestOfflineDomainJoin_l(struct libnetapi_ctx
*ctx
,
879 struct NetRequestOfflineDomainJoin
*r
)
881 DATA_BLOB blob
, blob_base64
;
882 enum ndr_err_code ndr_err
;
883 struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data
;
885 struct ODJ_WIN7BLOB win7blob
= { 0 };
888 if (r
->in
.provision_bin_data
== NULL
||
889 r
->in
.provision_bin_data_size
== 0) {
890 return W_ERROR(NERR_NoOfflineJoinInfo
);
893 if (r
->in
.provision_bin_data_size
< 2) {
894 return W_ERROR(NERR_BadOfflineJoinInfo
);
897 if (r
->in
.provision_bin_data
[0] == 0xff &&
898 r
->in
.provision_bin_data
[1] == 0xfe) {
899 ok
= convert_string_talloc(ctx
, CH_UTF16LE
, CH_UNIX
,
900 r
->in
.provision_bin_data
+2,
901 r
->in
.provision_bin_data_size
-2,
903 &blob_base64
.length
);
905 return W_ERROR(NERR_BadOfflineJoinInfo
);
908 blob_base64
= data_blob(r
->in
.provision_bin_data
,
909 r
->in
.provision_bin_data_size
);
912 blob
= base64_decode_data_blob_talloc(ctx
, (const char *)blob_base64
.data
);
914 ndr_err
= ndr_pull_struct_blob(&blob
, ctx
, &odj_provision_data
,
915 (ndr_pull_flags_fn_t
)ndr_pull_ODJ_PROVISION_DATA_serialized_ptr
);
916 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
917 return W_ERROR(NERR_BadOfflineJoinInfo
);
920 if (DEBUGLEVEL
>= 10) {
921 NDR_PRINT_DEBUG(ODJ_PROVISION_DATA_serialized_ptr
, &odj_provision_data
);
924 if (odj_provision_data
.s
.p
->ulVersion
!= 1) {
925 return W_ERROR(NERR_ProvisioningBlobUnsupported
);
928 werr
= libnet_odj_find_win7blob(odj_provision_data
.s
.p
, &win7blob
);
929 if (!W_ERROR_IS_OK(werr
)) {
933 if (!(r
->in
.options
& NETSETUP_PROVISION_ONLINE_CALLER
)) {
934 return WERR_NERR_SETUPNOTJOINED
;
937 werr
= NetRequestOfflineDomainJoin_backend(ctx
,
939 odj_provision_data
.s
.p
);
940 if (!W_ERROR_IS_OK(werr
)) {
944 return W_ERROR(NERR_JoinPerformedMustRestart
);