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"
28 #include "../librpc/gen_ndr/cli_wkssvc.h"
30 /****************************************************************
31 ****************************************************************/
33 WERROR
NetJoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
34 struct NetJoinDomain
*r
)
36 struct libnet_JoinCtx
*j
= NULL
;
40 return WERR_INVALID_PARAM
;
43 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
44 W_ERROR_NOT_OK_RETURN(werr
);
46 j
->in
.domain_name
= talloc_strdup(mem_ctx
, r
->in
.domain
);
47 W_ERROR_HAVE_NO_MEMORY(j
->in
.domain_name
);
49 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
51 struct netr_DsRGetDCNameInfo
*info
= NULL
;
52 const char *dc
= NULL
;
53 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
54 DS_WRITABLE_REQUIRED
|
56 status
= dsgetdcname(mem_ctx
, NULL
, r
->in
.domain
,
57 NULL
, NULL
, flags
, &info
);
58 if (!NT_STATUS_IS_OK(status
)) {
59 libnetapi_set_error_string(mem_ctx
,
60 "%s", get_friendly_nt_error_msg(status
));
61 return ntstatus_to_werror(status
);
64 dc
= strip_hostname(info
->dc_unc
);
65 j
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
66 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
69 if (r
->in
.account_ou
) {
70 j
->in
.account_ou
= talloc_strdup(mem_ctx
, r
->in
.account_ou
);
71 W_ERROR_HAVE_NO_MEMORY(j
->in
.account_ou
);
75 j
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
76 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_account
);
80 j
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
81 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_password
);
84 j
->in
.join_flags
= r
->in
.join_flags
;
85 j
->in
.modify_config
= true;
88 werr
= libnet_Join(mem_ctx
, j
);
89 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
90 libnetapi_set_error_string(mem_ctx
, "%s", j
->out
.error_string
);
97 /****************************************************************
98 ****************************************************************/
100 WERROR
NetJoinDomain_r(struct libnetapi_ctx
*ctx
,
101 struct NetJoinDomain
*r
)
103 struct rpc_pipe_client
*pipe_cli
= NULL
;
104 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
107 unsigned int old_timeout
= 0;
109 werr
= libnetapi_open_pipe(ctx
, r
->in
.server
,
110 &ndr_table_wkssvc
.syntax_id
,
112 if (!W_ERROR_IS_OK(werr
)) {
116 if (r
->in
.password
) {
117 encode_wkssvc_join_password_buffer(ctx
,
119 &pipe_cli
->auth
->user_session_key
,
120 &encrypted_password
);
123 old_timeout
= rpccli_set_timeout(pipe_cli
, 600000);
125 status
= rpccli_wkssvc_NetrJoinDomain2(pipe_cli
, talloc_tos(),
133 if (!NT_STATUS_IS_OK(status
)) {
134 werr
= ntstatus_to_werror(status
);
139 if (pipe_cli
&& old_timeout
) {
140 rpccli_set_timeout(pipe_cli
, old_timeout
);
145 /****************************************************************
146 ****************************************************************/
148 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
149 struct NetUnjoinDomain
*r
)
151 struct libnet_UnjoinCtx
*u
= NULL
;
152 struct dom_sid domain_sid
;
153 const char *domain
= NULL
;
156 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
157 return WERR_SETUP_NOT_JOINED
;
160 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
161 W_ERROR_NOT_OK_RETURN(werr
);
166 domain
= lp_workgroup();
169 if (r
->in
.server_name
) {
170 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
171 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
174 struct netr_DsRGetDCNameInfo
*info
= NULL
;
175 const char *dc
= NULL
;
176 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
177 DS_WRITABLE_REQUIRED
|
179 status
= dsgetdcname(mem_ctx
, NULL
, domain
,
180 NULL
, NULL
, flags
, &info
);
181 if (!NT_STATUS_IS_OK(status
)) {
182 libnetapi_set_error_string(mem_ctx
,
183 "failed to find DC for domain %s: %s",
185 get_friendly_nt_error_msg(status
));
186 return ntstatus_to_werror(status
);
189 dc
= strip_hostname(info
->dc_unc
);
190 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
191 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
193 u
->in
.domain_name
= domain
;
197 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
198 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
201 if (r
->in
.password
) {
202 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
203 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
206 u
->in
.domain_name
= domain
;
207 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
208 u
->in
.delete_machine_account
= false;
209 u
->in
.modify_config
= true;
212 u
->in
.domain_sid
= &domain_sid
;
214 werr
= libnet_Unjoin(mem_ctx
, u
);
215 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
216 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
223 /****************************************************************
224 ****************************************************************/
226 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
227 struct NetUnjoinDomain
*r
)
229 struct rpc_pipe_client
*pipe_cli
= NULL
;
230 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
233 unsigned int old_timeout
= 0;
235 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
236 &ndr_table_wkssvc
.syntax_id
,
238 if (!W_ERROR_IS_OK(werr
)) {
242 if (r
->in
.password
) {
243 encode_wkssvc_join_password_buffer(ctx
,
245 &pipe_cli
->auth
->user_session_key
,
246 &encrypted_password
);
249 old_timeout
= rpccli_set_timeout(pipe_cli
, 60000);
251 status
= rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli
, talloc_tos(),
257 if (!NT_STATUS_IS_OK(status
)) {
258 werr
= ntstatus_to_werror(status
);
263 if (pipe_cli
&& old_timeout
) {
264 rpccli_set_timeout(pipe_cli
, old_timeout
);
270 /****************************************************************
271 ****************************************************************/
273 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
274 struct NetGetJoinInformation
*r
)
276 struct rpc_pipe_client
*pipe_cli
= NULL
;
279 const char *buffer
= NULL
;
281 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
282 &ndr_table_wkssvc
.syntax_id
,
284 if (!W_ERROR_IS_OK(werr
)) {
288 status
= rpccli_wkssvc_NetrGetJoinInformation(pipe_cli
, talloc_tos(),
291 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
293 if (!NT_STATUS_IS_OK(status
)) {
294 werr
= ntstatus_to_werror(status
);
298 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
299 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
305 /****************************************************************
306 ****************************************************************/
308 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
309 struct NetGetJoinInformation
*r
)
311 if ((lp_security() == SEC_ADS
) && lp_realm()) {
312 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
314 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
316 if (!*r
->out
.name_buffer
) {
320 switch (lp_server_role()) {
321 case ROLE_DOMAIN_MEMBER
:
322 case ROLE_DOMAIN_PDC
:
323 case ROLE_DOMAIN_BDC
:
324 *r
->out
.name_type
= NetSetupDomainName
;
326 case ROLE_STANDALONE
:
328 *r
->out
.name_type
= NetSetupWorkgroupName
;
335 /****************************************************************
336 ****************************************************************/
338 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
339 struct NetGetJoinableOUs
*r
)
343 ADS_STATUS ads_status
;
344 ADS_STRUCT
*ads
= NULL
;
345 struct netr_DsRGetDCNameInfo
*info
= NULL
;
346 const char *dc
= NULL
;
347 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
350 status
= dsgetdcname(ctx
, NULL
, r
->in
.domain
,
351 NULL
, NULL
, flags
, &info
);
352 if (!NT_STATUS_IS_OK(status
)) {
353 libnetapi_set_error_string(ctx
, "%s",
354 get_friendly_nt_error_msg(status
));
355 return ntstatus_to_werror(status
);
358 dc
= strip_hostname(info
->dc_unc
);
360 ads
= ads_init(info
->domain_name
, info
->domain_name
, dc
);
362 return WERR_GENERAL_FAILURE
;
365 SAFE_FREE(ads
->auth
.user_name
);
367 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
368 } else if (ctx
->username
) {
369 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
372 SAFE_FREE(ads
->auth
.password
);
373 if (r
->in
.password
) {
374 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
375 } else if (ctx
->password
) {
376 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
379 ads_status
= ads_connect_user_creds(ads
);
380 if (!ADS_ERR_OK(ads_status
)) {
382 return WERR_DEFAULT_JOIN_REQUIRED
;
385 ads_status
= ads_get_joinable_ous(ads
, ctx
,
386 (char ***)r
->out
.ous
,
387 (size_t *)r
->out
.ou_count
);
388 if (!ADS_ERR_OK(ads_status
)) {
390 return WERR_DEFAULT_JOIN_REQUIRED
;
396 return WERR_NOT_SUPPORTED
;
400 /****************************************************************
401 ****************************************************************/
403 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
404 struct NetGetJoinableOUs
*r
)
406 struct rpc_pipe_client
*pipe_cli
= NULL
;
407 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
411 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
412 &ndr_table_wkssvc
.syntax_id
,
414 if (!W_ERROR_IS_OK(werr
)) {
418 if (r
->in
.password
) {
419 encode_wkssvc_join_password_buffer(ctx
,
421 &pipe_cli
->auth
->user_session_key
,
422 &encrypted_password
);
425 status
= rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli
, talloc_tos(),
433 if (!NT_STATUS_IS_OK(status
)) {
434 werr
= ntstatus_to_werror(status
);
442 /****************************************************************
443 ****************************************************************/
445 WERROR
NetRenameMachineInDomain_r(struct libnetapi_ctx
*ctx
,
446 struct NetRenameMachineInDomain
*r
)
448 struct rpc_pipe_client
*pipe_cli
= NULL
;
449 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
453 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
454 &ndr_table_wkssvc
.syntax_id
,
456 if (!W_ERROR_IS_OK(werr
)) {
460 if (r
->in
.password
) {
461 encode_wkssvc_join_password_buffer(ctx
,
463 &pipe_cli
->auth
->user_session_key
,
464 &encrypted_password
);
467 status
= rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli
, talloc_tos(),
469 r
->in
.new_machine_name
,
472 r
->in
.rename_options
,
474 if (!NT_STATUS_IS_OK(status
)) {
475 werr
= ntstatus_to_werror(status
);
483 /****************************************************************
484 ****************************************************************/
486 WERROR
NetRenameMachineInDomain_l(struct libnetapi_ctx
*ctx
,
487 struct NetRenameMachineInDomain
*r
)
489 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetRenameMachineInDomain
);