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 "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
26 #include "libnet/libnet.h"
27 #include "libcli/auth/libcli_auth.h"
29 /****************************************************************
30 ****************************************************************/
32 WERROR
NetJoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
33 struct NetJoinDomain
*r
)
35 struct libnet_JoinCtx
*j
= NULL
;
39 return WERR_INVALID_PARAM
;
42 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
43 W_ERROR_NOT_OK_RETURN(werr
);
45 j
->in
.domain_name
= talloc_strdup(mem_ctx
, r
->in
.domain
);
46 W_ERROR_HAVE_NO_MEMORY(j
->in
.domain_name
);
48 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
50 struct netr_DsRGetDCNameInfo
*info
= NULL
;
51 const char *dc
= NULL
;
52 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
53 DS_WRITABLE_REQUIRED
|
55 status
= dsgetdcname(mem_ctx
, NULL
, r
->in
.domain
,
56 NULL
, NULL
, flags
, &info
);
57 if (!NT_STATUS_IS_OK(status
)) {
58 libnetapi_set_error_string(mem_ctx
,
59 "%s", get_friendly_nt_error_msg(status
));
60 return ntstatus_to_werror(status
);
63 dc
= strip_hostname(info
->dc_unc
);
64 j
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
65 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
68 if (r
->in
.account_ou
) {
69 j
->in
.account_ou
= talloc_strdup(mem_ctx
, r
->in
.account_ou
);
70 W_ERROR_HAVE_NO_MEMORY(j
->in
.account_ou
);
74 j
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
75 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_account
);
79 j
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
80 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_password
);
83 j
->in
.join_flags
= r
->in
.join_flags
;
84 j
->in
.modify_config
= true;
87 werr
= libnet_Join(mem_ctx
, j
);
88 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
89 libnetapi_set_error_string(mem_ctx
, "%s", j
->out
.error_string
);
96 /****************************************************************
97 ****************************************************************/
99 WERROR
NetJoinDomain_r(struct libnetapi_ctx
*ctx
,
100 struct NetJoinDomain
*r
)
102 struct rpc_pipe_client
*pipe_cli
= NULL
;
103 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
106 unsigned int old_timeout
= 0;
108 werr
= libnetapi_open_pipe(ctx
, r
->in
.server
,
109 &ndr_table_wkssvc
.syntax_id
,
111 if (!W_ERROR_IS_OK(werr
)) {
115 if (r
->in
.password
) {
116 encode_wkssvc_join_password_buffer(ctx
,
118 &pipe_cli
->auth
->user_session_key
,
119 &encrypted_password
);
122 old_timeout
= rpccli_set_timeout(pipe_cli
, 600000);
124 status
= rpccli_wkssvc_NetrJoinDomain2(pipe_cli
, ctx
,
132 if (!NT_STATUS_IS_OK(status
)) {
133 werr
= ntstatus_to_werror(status
);
138 if (pipe_cli
&& old_timeout
) {
139 rpccli_set_timeout(pipe_cli
, old_timeout
);
144 /****************************************************************
145 ****************************************************************/
147 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
148 struct NetUnjoinDomain
*r
)
150 struct libnet_UnjoinCtx
*u
= NULL
;
151 struct dom_sid domain_sid
;
152 const char *domain
= NULL
;
155 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
156 return WERR_SETUP_NOT_JOINED
;
159 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
160 W_ERROR_NOT_OK_RETURN(werr
);
165 domain
= lp_workgroup();
168 if (r
->in
.server_name
) {
169 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
170 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
173 struct netr_DsRGetDCNameInfo
*info
= NULL
;
174 const char *dc
= NULL
;
175 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
176 DS_WRITABLE_REQUIRED
|
178 status
= dsgetdcname(mem_ctx
, NULL
, domain
,
179 NULL
, NULL
, flags
, &info
);
180 if (!NT_STATUS_IS_OK(status
)) {
181 libnetapi_set_error_string(mem_ctx
,
182 "failed to find DC for domain %s: %s",
184 get_friendly_nt_error_msg(status
));
185 return ntstatus_to_werror(status
);
188 dc
= strip_hostname(info
->dc_unc
);
189 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
190 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
192 u
->in
.domain_name
= domain
;
196 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
197 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
200 if (r
->in
.password
) {
201 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
202 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
205 u
->in
.domain_name
= domain
;
206 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
207 u
->in
.delete_machine_account
= false;
208 u
->in
.modify_config
= true;
211 u
->in
.domain_sid
= &domain_sid
;
213 werr
= libnet_Unjoin(mem_ctx
, u
);
214 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
215 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
222 /****************************************************************
223 ****************************************************************/
225 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
226 struct NetUnjoinDomain
*r
)
228 struct rpc_pipe_client
*pipe_cli
= NULL
;
229 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
232 unsigned int old_timeout
= 0;
234 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
235 &ndr_table_wkssvc
.syntax_id
,
237 if (!W_ERROR_IS_OK(werr
)) {
241 if (r
->in
.password
) {
242 encode_wkssvc_join_password_buffer(ctx
,
244 &pipe_cli
->auth
->user_session_key
,
245 &encrypted_password
);
248 old_timeout
= rpccli_set_timeout(pipe_cli
, 60000);
250 status
= rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli
, ctx
,
256 if (!NT_STATUS_IS_OK(status
)) {
257 werr
= ntstatus_to_werror(status
);
262 if (pipe_cli
&& old_timeout
) {
263 rpccli_set_timeout(pipe_cli
, old_timeout
);
269 /****************************************************************
270 ****************************************************************/
272 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
273 struct NetGetJoinInformation
*r
)
275 struct rpc_pipe_client
*pipe_cli
= NULL
;
278 const char *buffer
= NULL
;
280 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
281 &ndr_table_wkssvc
.syntax_id
,
283 if (!W_ERROR_IS_OK(werr
)) {
287 status
= rpccli_wkssvc_NetrGetJoinInformation(pipe_cli
, ctx
,
290 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
292 if (!NT_STATUS_IS_OK(status
)) {
293 werr
= ntstatus_to_werror(status
);
297 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
298 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
304 /****************************************************************
305 ****************************************************************/
307 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
308 struct NetGetJoinInformation
*r
)
310 if ((lp_security() == SEC_ADS
) && lp_realm()) {
311 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
313 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
315 if (!*r
->out
.name_buffer
) {
319 switch (lp_server_role()) {
320 case ROLE_DOMAIN_MEMBER
:
321 case ROLE_DOMAIN_PDC
:
322 case ROLE_DOMAIN_BDC
:
323 *r
->out
.name_type
= NetSetupDomainName
;
325 case ROLE_STANDALONE
:
327 *r
->out
.name_type
= NetSetupWorkgroupName
;
334 /****************************************************************
335 ****************************************************************/
337 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
338 struct NetGetJoinableOUs
*r
)
342 ADS_STATUS ads_status
;
343 ADS_STRUCT
*ads
= NULL
;
344 struct netr_DsRGetDCNameInfo
*info
= NULL
;
345 const char *dc
= NULL
;
346 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
349 status
= dsgetdcname(ctx
, NULL
, r
->in
.domain
,
350 NULL
, NULL
, flags
, &info
);
351 if (!NT_STATUS_IS_OK(status
)) {
352 libnetapi_set_error_string(ctx
, "%s",
353 get_friendly_nt_error_msg(status
));
354 return ntstatus_to_werror(status
);
357 dc
= strip_hostname(info
->dc_unc
);
359 ads
= ads_init(info
->domain_name
, info
->domain_name
, dc
);
361 return WERR_GENERAL_FAILURE
;
364 SAFE_FREE(ads
->auth
.user_name
);
366 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
367 } else if (ctx
->username
) {
368 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
371 SAFE_FREE(ads
->auth
.password
);
372 if (r
->in
.password
) {
373 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
374 } else if (ctx
->password
) {
375 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
378 ads_status
= ads_connect_user_creds(ads
);
379 if (!ADS_ERR_OK(ads_status
)) {
381 return WERR_DEFAULT_JOIN_REQUIRED
;
384 ads_status
= ads_get_joinable_ous(ads
, ctx
,
385 (char ***)r
->out
.ous
,
386 (size_t *)r
->out
.ou_count
);
387 if (!ADS_ERR_OK(ads_status
)) {
389 return WERR_DEFAULT_JOIN_REQUIRED
;
395 return WERR_NOT_SUPPORTED
;
399 /****************************************************************
400 ****************************************************************/
402 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
403 struct NetGetJoinableOUs
*r
)
405 struct rpc_pipe_client
*pipe_cli
= NULL
;
406 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
410 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
411 &ndr_table_wkssvc
.syntax_id
,
413 if (!W_ERROR_IS_OK(werr
)) {
417 if (r
->in
.password
) {
418 encode_wkssvc_join_password_buffer(ctx
,
420 &pipe_cli
->auth
->user_session_key
,
421 &encrypted_password
);
424 status
= rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli
, ctx
,
432 if (!NT_STATUS_IS_OK(status
)) {
433 werr
= ntstatus_to_werror(status
);
441 /****************************************************************
442 ****************************************************************/
444 WERROR
NetRenameMachineInDomain_r(struct libnetapi_ctx
*ctx
,
445 struct NetRenameMachineInDomain
*r
)
447 struct rpc_pipe_client
*pipe_cli
= NULL
;
448 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
452 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
453 &ndr_table_wkssvc
.syntax_id
,
455 if (!W_ERROR_IS_OK(werr
)) {
459 if (r
->in
.password
) {
460 encode_wkssvc_join_password_buffer(ctx
,
462 &pipe_cli
->auth
->user_session_key
,
463 &encrypted_password
);
466 status
= rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli
, ctx
,
468 r
->in
.new_machine_name
,
471 r
->in
.rename_options
,
473 if (!NT_STATUS_IS_OK(status
)) {
474 werr
= ntstatus_to_werror(status
);
482 /****************************************************************
483 ****************************************************************/
485 WERROR
NetRenameMachineInDomain_l(struct libnetapi_ctx
*ctx
,
486 struct NetRenameMachineInDomain
*r
)
488 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetRenameMachineInDomain
);