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"
33 /****************************************************************
34 ****************************************************************/
36 WERROR
NetJoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
37 struct NetJoinDomain
*r
)
39 struct libnet_JoinCtx
*j
= NULL
;
40 struct libnetapi_private_ctx
*priv
;
43 priv
= talloc_get_type_abort(mem_ctx
->private_data
,
44 struct libnetapi_private_ctx
);
47 return WERR_INVALID_PARAM
;
50 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
51 W_ERROR_NOT_OK_RETURN(werr
);
53 j
->in
.domain_name
= talloc_strdup(mem_ctx
, r
->in
.domain
);
54 W_ERROR_HAVE_NO_MEMORY(j
->in
.domain_name
);
56 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
58 struct netr_DsRGetDCNameInfo
*info
= NULL
;
59 const char *dc
= NULL
;
60 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
61 DS_WRITABLE_REQUIRED
|
63 status
= dsgetdcname(mem_ctx
, priv
->msg_ctx
, r
->in
.domain
,
64 NULL
, NULL
, flags
, &info
);
65 if (!NT_STATUS_IS_OK(status
)) {
66 libnetapi_set_error_string(mem_ctx
,
67 "%s", get_friendly_nt_error_msg(status
));
68 return ntstatus_to_werror(status
);
71 dc
= strip_hostname(info
->dc_unc
);
72 j
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
73 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
76 if (r
->in
.account_ou
) {
77 j
->in
.account_ou
= talloc_strdup(mem_ctx
, r
->in
.account_ou
);
78 W_ERROR_HAVE_NO_MEMORY(j
->in
.account_ou
);
82 j
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
83 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_account
);
87 j
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
88 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_password
);
91 j
->in
.join_flags
= r
->in
.join_flags
;
92 j
->in
.modify_config
= true;
95 werr
= libnet_Join(mem_ctx
, j
);
96 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
97 libnetapi_set_error_string(mem_ctx
, "%s", j
->out
.error_string
);
104 /****************************************************************
105 ****************************************************************/
107 WERROR
NetJoinDomain_r(struct libnetapi_ctx
*ctx
,
108 struct NetJoinDomain
*r
)
110 struct rpc_pipe_client
*pipe_cli
= NULL
;
111 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
114 unsigned int old_timeout
= 0;
115 struct dcerpc_binding_handle
*b
;
116 DATA_BLOB session_key
;
118 werr
= libnetapi_open_pipe(ctx
, r
->in
.server
,
119 &ndr_table_wkssvc
.syntax_id
,
121 if (!W_ERROR_IS_OK(werr
)) {
125 b
= pipe_cli
->binding_handle
;
127 if (r
->in
.password
) {
129 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &session_key
);
130 if (!NT_STATUS_IS_OK(status
)) {
131 werr
= ntstatus_to_werror(status
);
135 encode_wkssvc_join_password_buffer(ctx
,
138 &encrypted_password
);
141 old_timeout
= rpccli_set_timeout(pipe_cli
, 600000);
143 status
= dcerpc_wkssvc_NetrJoinDomain2(b
, talloc_tos(),
151 if (!NT_STATUS_IS_OK(status
)) {
152 werr
= ntstatus_to_werror(status
);
157 if (pipe_cli
&& old_timeout
) {
158 rpccli_set_timeout(pipe_cli
, old_timeout
);
163 /****************************************************************
164 ****************************************************************/
166 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
167 struct NetUnjoinDomain
*r
)
169 struct libnet_UnjoinCtx
*u
= NULL
;
170 struct dom_sid domain_sid
;
171 const char *domain
= NULL
;
173 struct libnetapi_private_ctx
*priv
;
175 priv
= talloc_get_type_abort(mem_ctx
->private_data
,
176 struct libnetapi_private_ctx
);
178 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
179 return WERR_SETUP_NOT_JOINED
;
182 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
183 W_ERROR_NOT_OK_RETURN(werr
);
188 domain
= lp_workgroup();
191 if (r
->in
.server_name
) {
192 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
193 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
196 struct netr_DsRGetDCNameInfo
*info
= NULL
;
197 const char *dc
= NULL
;
198 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
199 DS_WRITABLE_REQUIRED
|
201 status
= dsgetdcname(mem_ctx
, priv
->msg_ctx
, domain
,
202 NULL
, NULL
, flags
, &info
);
203 if (!NT_STATUS_IS_OK(status
)) {
204 libnetapi_set_error_string(mem_ctx
,
205 "failed to find DC for domain %s: %s",
207 get_friendly_nt_error_msg(status
));
208 return ntstatus_to_werror(status
);
211 dc
= strip_hostname(info
->dc_unc
);
212 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
213 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
215 u
->in
.domain_name
= domain
;
219 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
220 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
223 if (r
->in
.password
) {
224 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
225 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
228 u
->in
.domain_name
= domain
;
229 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
230 u
->in
.delete_machine_account
= false;
231 u
->in
.modify_config
= true;
234 u
->in
.domain_sid
= &domain_sid
;
236 werr
= libnet_Unjoin(mem_ctx
, u
);
237 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
238 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
245 /****************************************************************
246 ****************************************************************/
248 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
249 struct NetUnjoinDomain
*r
)
251 struct rpc_pipe_client
*pipe_cli
= NULL
;
252 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
255 unsigned int old_timeout
= 0;
256 struct dcerpc_binding_handle
*b
;
257 DATA_BLOB session_key
;
259 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
260 &ndr_table_wkssvc
.syntax_id
,
262 if (!W_ERROR_IS_OK(werr
)) {
266 b
= pipe_cli
->binding_handle
;
268 if (r
->in
.password
) {
270 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &session_key
);
271 if (!NT_STATUS_IS_OK(status
)) {
272 werr
= ntstatus_to_werror(status
);
276 encode_wkssvc_join_password_buffer(ctx
,
279 &encrypted_password
);
282 old_timeout
= rpccli_set_timeout(pipe_cli
, 60000);
284 status
= dcerpc_wkssvc_NetrUnjoinDomain2(b
, talloc_tos(),
290 if (!NT_STATUS_IS_OK(status
)) {
291 werr
= ntstatus_to_werror(status
);
296 if (pipe_cli
&& old_timeout
) {
297 rpccli_set_timeout(pipe_cli
, old_timeout
);
303 /****************************************************************
304 ****************************************************************/
306 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
307 struct NetGetJoinInformation
*r
)
309 struct rpc_pipe_client
*pipe_cli
= NULL
;
312 const char *buffer
= NULL
;
313 struct dcerpc_binding_handle
*b
;
315 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
316 &ndr_table_wkssvc
.syntax_id
,
318 if (!W_ERROR_IS_OK(werr
)) {
322 b
= pipe_cli
->binding_handle
;
324 status
= dcerpc_wkssvc_NetrGetJoinInformation(b
, talloc_tos(),
327 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
329 if (!NT_STATUS_IS_OK(status
)) {
330 werr
= ntstatus_to_werror(status
);
334 if (!W_ERROR_IS_OK(werr
)) {
338 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
339 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
345 /****************************************************************
346 ****************************************************************/
348 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
349 struct NetGetJoinInformation
*r
)
351 if ((lp_security() == SEC_ADS
) && lp_realm()) {
352 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
354 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
356 if (!*r
->out
.name_buffer
) {
360 switch (lp_server_role()) {
361 case ROLE_DOMAIN_MEMBER
:
362 case ROLE_DOMAIN_PDC
:
363 case ROLE_DOMAIN_BDC
:
364 *r
->out
.name_type
= NetSetupDomainName
;
366 case ROLE_STANDALONE
:
368 *r
->out
.name_type
= NetSetupWorkgroupName
;
375 /****************************************************************
376 ****************************************************************/
378 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
379 struct NetGetJoinableOUs
*r
)
383 ADS_STATUS ads_status
;
384 ADS_STRUCT
*ads
= NULL
;
385 struct netr_DsRGetDCNameInfo
*info
= NULL
;
386 const char *dc
= NULL
;
387 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
389 struct libnetapi_private_ctx
*priv
;
391 priv
= talloc_get_type_abort(ctx
->private_data
,
392 struct libnetapi_private_ctx
);
394 status
= dsgetdcname(ctx
, priv
->msg_ctx
, r
->in
.domain
,
395 NULL
, NULL
, flags
, &info
);
396 if (!NT_STATUS_IS_OK(status
)) {
397 libnetapi_set_error_string(ctx
, "%s",
398 get_friendly_nt_error_msg(status
));
399 return ntstatus_to_werror(status
);
402 dc
= strip_hostname(info
->dc_unc
);
404 ads
= ads_init(info
->domain_name
, info
->domain_name
, dc
);
406 return WERR_GENERAL_FAILURE
;
409 SAFE_FREE(ads
->auth
.user_name
);
411 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
412 } else if (ctx
->username
) {
413 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
416 SAFE_FREE(ads
->auth
.password
);
417 if (r
->in
.password
) {
418 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
419 } else if (ctx
->password
) {
420 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
423 ads_status
= ads_connect_user_creds(ads
);
424 if (!ADS_ERR_OK(ads_status
)) {
426 return WERR_DEFAULT_JOIN_REQUIRED
;
429 ads_status
= ads_get_joinable_ous(ads
, ctx
,
430 (char ***)r
->out
.ous
,
431 (size_t *)r
->out
.ou_count
);
432 if (!ADS_ERR_OK(ads_status
)) {
434 return WERR_DEFAULT_JOIN_REQUIRED
;
440 return WERR_NOT_SUPPORTED
;
444 /****************************************************************
445 ****************************************************************/
447 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
448 struct NetGetJoinableOUs
*r
)
450 struct rpc_pipe_client
*pipe_cli
= NULL
;
451 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
454 struct dcerpc_binding_handle
*b
;
455 DATA_BLOB session_key
;
457 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
458 &ndr_table_wkssvc
.syntax_id
,
460 if (!W_ERROR_IS_OK(werr
)) {
464 b
= pipe_cli
->binding_handle
;
466 if (r
->in
.password
) {
468 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &session_key
);
469 if (!NT_STATUS_IS_OK(status
)) {
470 werr
= ntstatus_to_werror(status
);
474 encode_wkssvc_join_password_buffer(ctx
,
477 &encrypted_password
);
480 status
= dcerpc_wkssvc_NetrGetJoinableOus2(b
, talloc_tos(),
488 if (!NT_STATUS_IS_OK(status
)) {
489 werr
= ntstatus_to_werror(status
);
497 /****************************************************************
498 ****************************************************************/
500 WERROR
NetRenameMachineInDomain_r(struct libnetapi_ctx
*ctx
,
501 struct NetRenameMachineInDomain
*r
)
503 struct rpc_pipe_client
*pipe_cli
= NULL
;
504 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
507 struct dcerpc_binding_handle
*b
;
508 DATA_BLOB session_key
;
510 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
511 &ndr_table_wkssvc
.syntax_id
,
513 if (!W_ERROR_IS_OK(werr
)) {
517 b
= pipe_cli
->binding_handle
;
519 if (r
->in
.password
) {
521 status
= cli_get_session_key(talloc_tos(), pipe_cli
, &session_key
);
522 if (!NT_STATUS_IS_OK(status
)) {
523 werr
= ntstatus_to_werror(status
);
527 encode_wkssvc_join_password_buffer(ctx
,
530 &encrypted_password
);
533 status
= dcerpc_wkssvc_NetrRenameMachineInDomain2(b
, talloc_tos(),
535 r
->in
.new_machine_name
,
538 r
->in
.rename_options
,
540 if (!NT_STATUS_IS_OK(status
)) {
541 werr
= ntstatus_to_werror(status
);
549 /****************************************************************
550 ****************************************************************/
552 WERROR
NetRenameMachineInDomain_l(struct libnetapi_ctx
*ctx
,
553 struct NetRenameMachineInDomain
*r
)
555 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetRenameMachineInDomain
);