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/libnetapi.h"
25 #include "libnet/libnet.h"
27 /****************************************************************
28 ****************************************************************/
30 WERROR
NetJoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
31 struct NetJoinDomain
*r
)
33 struct libnet_JoinCtx
*j
= NULL
;
37 return WERR_INVALID_PARAM
;
40 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
41 W_ERROR_NOT_OK_RETURN(werr
);
43 j
->in
.domain_name
= talloc_strdup(mem_ctx
, r
->in
.domain
);
44 W_ERROR_HAVE_NO_MEMORY(j
->in
.domain_name
);
46 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
48 struct netr_DsRGetDCNameInfo
*info
= NULL
;
49 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
50 DS_WRITABLE_REQUIRED
|
52 status
= dsgetdcname(mem_ctx
, r
->in
.domain
,
53 NULL
, NULL
, flags
, &info
);
54 if (!NT_STATUS_IS_OK(status
)) {
55 libnetapi_set_error_string(mem_ctx
,
56 "%s", get_friendly_nt_error_msg(status
));
57 return ntstatus_to_werror(status
);
59 j
->in
.dc_name
= talloc_strdup(mem_ctx
,
61 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
64 if (r
->in
.account_ou
) {
65 j
->in
.account_ou
= talloc_strdup(mem_ctx
, r
->in
.account_ou
);
66 W_ERROR_HAVE_NO_MEMORY(j
->in
.account_ou
);
70 j
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
71 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_account
);
75 j
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
76 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_password
);
79 j
->in
.join_flags
= r
->in
.join_flags
;
80 j
->in
.modify_config
= true;
83 werr
= libnet_Join(mem_ctx
, j
);
84 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
85 libnetapi_set_error_string(mem_ctx
, "%s", j
->out
.error_string
);
92 /****************************************************************
93 ****************************************************************/
95 WERROR
NetJoinDomain_r(struct libnetapi_ctx
*ctx
,
96 struct NetJoinDomain
*r
)
98 struct cli_state
*cli
= NULL
;
99 struct rpc_pipe_client
*pipe_cli
= NULL
;
100 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
103 unsigned int old_timeout
= 0;
105 status
= cli_full_connection(&cli
, NULL
, r
->in
.server
,
111 CLI_FULL_CONNECTION_USE_KERBEROS
|
112 CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
,
115 if (!NT_STATUS_IS_OK(status
)) {
116 werr
= ntstatus_to_werror(status
);
120 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_WKSSVC
,
123 werr
= ntstatus_to_werror(status
);
127 if (r
->in
.password
) {
128 encode_wkssvc_join_password_buffer(ctx
,
130 &cli
->user_session_key
,
131 &encrypted_password
);
134 old_timeout
= cli_set_timeout(cli
, 600000);
136 status
= rpccli_wkssvc_NetrJoinDomain2(pipe_cli
, ctx
,
144 if (!NT_STATUS_IS_OK(status
)) {
145 werr
= ntstatus_to_werror(status
);
152 cli_set_timeout(cli
, old_timeout
);
159 /****************************************************************
160 ****************************************************************/
162 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
163 struct NetUnjoinDomain
*r
)
165 struct libnet_UnjoinCtx
*u
= NULL
;
166 struct dom_sid domain_sid
;
167 const char *domain
= NULL
;
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 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
190 DS_WRITABLE_REQUIRED
|
192 status
= dsgetdcname(mem_ctx
, domain
,
193 NULL
, NULL
, flags
, &info
);
194 if (!NT_STATUS_IS_OK(status
)) {
195 libnetapi_set_error_string(mem_ctx
,
196 "failed to find DC for domain %s: %s",
198 get_friendly_nt_error_msg(status
));
199 return ntstatus_to_werror(status
);
201 u
->in
.dc_name
= talloc_strdup(mem_ctx
,
203 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
205 u
->in
.domain_name
= domain
;
209 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
210 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
213 if (r
->in
.password
) {
214 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
215 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
218 u
->in
.domain_name
= domain
;
219 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
220 u
->in
.modify_config
= true;
223 u
->in
.domain_sid
= &domain_sid
;
225 werr
= libnet_Unjoin(mem_ctx
, u
);
226 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
227 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
234 /****************************************************************
235 ****************************************************************/
237 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
238 struct NetUnjoinDomain
*r
)
240 struct cli_state
*cli
= NULL
;
241 struct rpc_pipe_client
*pipe_cli
= NULL
;
242 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
245 unsigned int old_timeout
= 0;
247 status
= cli_full_connection(&cli
, NULL
, r
->in
.server_name
,
253 CLI_FULL_CONNECTION_USE_KERBEROS
|
254 CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
,
257 if (!NT_STATUS_IS_OK(status
)) {
258 werr
= ntstatus_to_werror(status
);
262 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_WKSSVC
,
265 werr
= ntstatus_to_werror(status
);
269 if (r
->in
.password
) {
270 encode_wkssvc_join_password_buffer(ctx
,
272 &cli
->user_session_key
,
273 &encrypted_password
);
276 old_timeout
= cli_set_timeout(cli
, 60000);
278 status
= rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli
, ctx
,
284 if (!NT_STATUS_IS_OK(status
)) {
285 werr
= ntstatus_to_werror(status
);
291 cli_set_timeout(cli
, old_timeout
);
298 /****************************************************************
299 ****************************************************************/
301 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
302 struct NetGetJoinInformation
*r
)
304 struct cli_state
*cli
= NULL
;
305 struct rpc_pipe_client
*pipe_cli
= NULL
;
309 status
= cli_full_connection(&cli
, NULL
, r
->in
.server_name
,
315 CLI_FULL_CONNECTION_USE_KERBEROS
|
316 CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
,
319 if (!NT_STATUS_IS_OK(status
)) {
320 werr
= ntstatus_to_werror(status
);
324 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_WKSSVC
,
327 werr
= ntstatus_to_werror(status
);
331 status
= rpccli_wkssvc_NetrGetJoinInformation(pipe_cli
, ctx
,
334 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
336 if (!NT_STATUS_IS_OK(status
)) {
337 werr
= ntstatus_to_werror(status
);
349 /****************************************************************
350 ****************************************************************/
352 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
353 struct NetGetJoinInformation
*r
)
355 if ((lp_security() == SEC_ADS
) && lp_realm()) {
356 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
358 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
360 if (!*r
->out
.name_buffer
) {
364 switch (lp_server_role()) {
365 case ROLE_DOMAIN_MEMBER
:
366 case ROLE_DOMAIN_PDC
:
367 case ROLE_DOMAIN_BDC
:
368 *r
->out
.name_type
= NetSetupDomainName
;
370 case ROLE_STANDALONE
:
372 *r
->out
.name_type
= NetSetupWorkgroupName
;
379 /****************************************************************
380 ****************************************************************/
382 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
383 struct NetGetJoinableOUs
*r
)
387 ADS_STATUS ads_status
;
388 ADS_STRUCT
*ads
= NULL
;
389 struct netr_DsRGetDCNameInfo
*info
= NULL
;
390 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
393 status
= dsgetdcname(ctx
, r
->in
.domain
,
394 NULL
, NULL
, flags
, &info
);
395 if (!NT_STATUS_IS_OK(status
)) {
396 libnetapi_set_error_string(ctx
, "%s",
397 get_friendly_nt_error_msg(status
));
398 return ntstatus_to_werror(status
);
401 ads
= ads_init(r
->in
.domain
, r
->in
.domain
, info
->dc_unc
);
403 return WERR_GENERAL_FAILURE
;
406 SAFE_FREE(ads
->auth
.user_name
);
408 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
409 } else if (ctx
->username
) {
410 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
413 SAFE_FREE(ads
->auth
.password
);
414 if (r
->in
.password
) {
415 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
416 } else if (ctx
->password
) {
417 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
420 ads_status
= ads_connect(ads
);
421 if (!ADS_ERR_OK(ads_status
)) {
423 return WERR_DEFAULT_JOIN_REQUIRED
;
426 ads_status
= ads_get_joinable_ous(ads
, ctx
,
427 (char ***)r
->out
.ous
,
428 (size_t *)r
->out
.ou_count
);
429 if (!ADS_ERR_OK(ads_status
)) {
431 return WERR_DEFAULT_JOIN_REQUIRED
;
437 return WERR_NOT_SUPPORTED
;
441 /****************************************************************
442 ****************************************************************/
444 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
445 struct NetGetJoinableOUs
*r
)
447 struct cli_state
*cli
= NULL
;
448 struct rpc_pipe_client
*pipe_cli
= NULL
;
449 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
453 status
= cli_full_connection(&cli
, NULL
, r
->in
.server_name
,
459 CLI_FULL_CONNECTION_USE_KERBEROS
|
460 CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS
,
463 if (!NT_STATUS_IS_OK(status
)) {
464 werr
= ntstatus_to_werror(status
);
468 pipe_cli
= cli_rpc_pipe_open_noauth(cli
, PI_WKSSVC
,
471 werr
= ntstatus_to_werror(status
);
475 if (r
->in
.password
) {
476 encode_wkssvc_join_password_buffer(ctx
,
478 &cli
->user_session_key
,
479 &encrypted_password
);
482 status
= rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli
, ctx
,
490 if (!NT_STATUS_IS_OK(status
)) {
491 werr
= ntstatus_to_werror(status
);