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
;
117 werr
= libnetapi_open_pipe(ctx
, r
->in
.server
,
118 &ndr_table_wkssvc
.syntax_id
,
120 if (!W_ERROR_IS_OK(werr
)) {
124 b
= pipe_cli
->binding_handle
;
126 if (r
->in
.password
) {
127 encode_wkssvc_join_password_buffer(ctx
,
129 &pipe_cli
->auth
->user_session_key
,
130 &encrypted_password
);
133 old_timeout
= rpccli_set_timeout(pipe_cli
, 600000);
135 status
= dcerpc_wkssvc_NetrJoinDomain2(b
, talloc_tos(),
143 if (!NT_STATUS_IS_OK(status
)) {
144 werr
= ntstatus_to_werror(status
);
149 if (pipe_cli
&& old_timeout
) {
150 rpccli_set_timeout(pipe_cli
, old_timeout
);
155 /****************************************************************
156 ****************************************************************/
158 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
159 struct NetUnjoinDomain
*r
)
161 struct libnet_UnjoinCtx
*u
= NULL
;
162 struct dom_sid domain_sid
;
163 const char *domain
= NULL
;
165 struct libnetapi_private_ctx
*priv
;
167 priv
= talloc_get_type_abort(mem_ctx
->private_data
,
168 struct libnetapi_private_ctx
);
170 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
171 return WERR_SETUP_NOT_JOINED
;
174 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
175 W_ERROR_NOT_OK_RETURN(werr
);
180 domain
= lp_workgroup();
183 if (r
->in
.server_name
) {
184 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
185 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
188 struct netr_DsRGetDCNameInfo
*info
= NULL
;
189 const char *dc
= NULL
;
190 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
191 DS_WRITABLE_REQUIRED
|
193 status
= dsgetdcname(mem_ctx
, priv
->msg_ctx
, domain
,
194 NULL
, NULL
, flags
, &info
);
195 if (!NT_STATUS_IS_OK(status
)) {
196 libnetapi_set_error_string(mem_ctx
,
197 "failed to find DC for domain %s: %s",
199 get_friendly_nt_error_msg(status
));
200 return ntstatus_to_werror(status
);
203 dc
= strip_hostname(info
->dc_unc
);
204 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
205 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
207 u
->in
.domain_name
= domain
;
211 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
212 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
215 if (r
->in
.password
) {
216 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
217 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
220 u
->in
.domain_name
= domain
;
221 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
222 u
->in
.delete_machine_account
= false;
223 u
->in
.modify_config
= true;
226 u
->in
.domain_sid
= &domain_sid
;
228 werr
= libnet_Unjoin(mem_ctx
, u
);
229 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
230 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
237 /****************************************************************
238 ****************************************************************/
240 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
241 struct NetUnjoinDomain
*r
)
243 struct rpc_pipe_client
*pipe_cli
= NULL
;
244 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
247 unsigned int old_timeout
= 0;
248 struct dcerpc_binding_handle
*b
;
250 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
251 &ndr_table_wkssvc
.syntax_id
,
253 if (!W_ERROR_IS_OK(werr
)) {
257 b
= pipe_cli
->binding_handle
;
259 if (r
->in
.password
) {
260 encode_wkssvc_join_password_buffer(ctx
,
262 &pipe_cli
->auth
->user_session_key
,
263 &encrypted_password
);
266 old_timeout
= rpccli_set_timeout(pipe_cli
, 60000);
268 status
= dcerpc_wkssvc_NetrUnjoinDomain2(b
, talloc_tos(),
274 if (!NT_STATUS_IS_OK(status
)) {
275 werr
= ntstatus_to_werror(status
);
280 if (pipe_cli
&& old_timeout
) {
281 rpccli_set_timeout(pipe_cli
, old_timeout
);
287 /****************************************************************
288 ****************************************************************/
290 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
291 struct NetGetJoinInformation
*r
)
293 struct rpc_pipe_client
*pipe_cli
= NULL
;
296 const char *buffer
= NULL
;
297 struct dcerpc_binding_handle
*b
;
299 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
300 &ndr_table_wkssvc
.syntax_id
,
302 if (!W_ERROR_IS_OK(werr
)) {
306 b
= pipe_cli
->binding_handle
;
308 status
= dcerpc_wkssvc_NetrGetJoinInformation(b
, talloc_tos(),
311 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
313 if (!NT_STATUS_IS_OK(status
)) {
314 werr
= ntstatus_to_werror(status
);
318 if (!W_ERROR_IS_OK(werr
)) {
322 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
323 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
329 /****************************************************************
330 ****************************************************************/
332 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
333 struct NetGetJoinInformation
*r
)
335 if ((lp_security() == SEC_ADS
) && lp_realm()) {
336 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
338 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
340 if (!*r
->out
.name_buffer
) {
344 switch (lp_server_role()) {
345 case ROLE_DOMAIN_MEMBER
:
346 case ROLE_DOMAIN_PDC
:
347 case ROLE_DOMAIN_BDC
:
348 *r
->out
.name_type
= NetSetupDomainName
;
350 case ROLE_STANDALONE
:
352 *r
->out
.name_type
= NetSetupWorkgroupName
;
359 /****************************************************************
360 ****************************************************************/
362 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
363 struct NetGetJoinableOUs
*r
)
367 ADS_STATUS ads_status
;
368 ADS_STRUCT
*ads
= NULL
;
369 struct netr_DsRGetDCNameInfo
*info
= NULL
;
370 const char *dc
= NULL
;
371 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
373 struct libnetapi_private_ctx
*priv
;
375 priv
= talloc_get_type_abort(ctx
->private_data
,
376 struct libnetapi_private_ctx
);
378 status
= dsgetdcname(ctx
, priv
->msg_ctx
, r
->in
.domain
,
379 NULL
, NULL
, flags
, &info
);
380 if (!NT_STATUS_IS_OK(status
)) {
381 libnetapi_set_error_string(ctx
, "%s",
382 get_friendly_nt_error_msg(status
));
383 return ntstatus_to_werror(status
);
386 dc
= strip_hostname(info
->dc_unc
);
388 ads
= ads_init(info
->domain_name
, info
->domain_name
, dc
);
390 return WERR_GENERAL_FAILURE
;
393 SAFE_FREE(ads
->auth
.user_name
);
395 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
396 } else if (ctx
->username
) {
397 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
400 SAFE_FREE(ads
->auth
.password
);
401 if (r
->in
.password
) {
402 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
403 } else if (ctx
->password
) {
404 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
407 ads_status
= ads_connect_user_creds(ads
);
408 if (!ADS_ERR_OK(ads_status
)) {
410 return WERR_DEFAULT_JOIN_REQUIRED
;
413 ads_status
= ads_get_joinable_ous(ads
, ctx
,
414 (char ***)r
->out
.ous
,
415 (size_t *)r
->out
.ou_count
);
416 if (!ADS_ERR_OK(ads_status
)) {
418 return WERR_DEFAULT_JOIN_REQUIRED
;
424 return WERR_NOT_SUPPORTED
;
428 /****************************************************************
429 ****************************************************************/
431 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
432 struct NetGetJoinableOUs
*r
)
434 struct rpc_pipe_client
*pipe_cli
= NULL
;
435 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
438 struct dcerpc_binding_handle
*b
;
440 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
441 &ndr_table_wkssvc
.syntax_id
,
443 if (!W_ERROR_IS_OK(werr
)) {
447 b
= pipe_cli
->binding_handle
;
449 if (r
->in
.password
) {
450 encode_wkssvc_join_password_buffer(ctx
,
452 &pipe_cli
->auth
->user_session_key
,
453 &encrypted_password
);
456 status
= dcerpc_wkssvc_NetrGetJoinableOus2(b
, talloc_tos(),
464 if (!NT_STATUS_IS_OK(status
)) {
465 werr
= ntstatus_to_werror(status
);
473 /****************************************************************
474 ****************************************************************/
476 WERROR
NetRenameMachineInDomain_r(struct libnetapi_ctx
*ctx
,
477 struct NetRenameMachineInDomain
*r
)
479 struct rpc_pipe_client
*pipe_cli
= NULL
;
480 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
483 struct dcerpc_binding_handle
*b
;
485 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
486 &ndr_table_wkssvc
.syntax_id
,
488 if (!W_ERROR_IS_OK(werr
)) {
492 b
= pipe_cli
->binding_handle
;
494 if (r
->in
.password
) {
495 encode_wkssvc_join_password_buffer(ctx
,
497 &pipe_cli
->auth
->user_session_key
,
498 &encrypted_password
);
501 status
= dcerpc_wkssvc_NetrRenameMachineInDomain2(b
, talloc_tos(),
503 r
->in
.new_machine_name
,
506 r
->in
.rename_options
,
508 if (!NT_STATUS_IS_OK(status
)) {
509 werr
= ntstatus_to_werror(status
);
517 /****************************************************************
518 ****************************************************************/
520 WERROR
NetRenameMachineInDomain_l(struct libnetapi_ctx
*ctx
,
521 struct NetRenameMachineInDomain
*r
)
523 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetRenameMachineInDomain
);