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"
28 /****************************************************************
29 ****************************************************************/
31 WERROR
NetJoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
32 struct NetJoinDomain
*r
)
34 struct libnet_JoinCtx
*j
= NULL
;
38 return WERR_INVALID_PARAM
;
41 werr
= libnet_init_JoinCtx(mem_ctx
, &j
);
42 W_ERROR_NOT_OK_RETURN(werr
);
44 j
->in
.domain_name
= talloc_strdup(mem_ctx
, r
->in
.domain
);
45 W_ERROR_HAVE_NO_MEMORY(j
->in
.domain_name
);
47 if (r
->in
.join_flags
& WKSSVC_JOIN_FLAGS_JOIN_TYPE
) {
49 struct netr_DsRGetDCNameInfo
*info
= NULL
;
50 const char *dc
= NULL
;
51 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
52 DS_WRITABLE_REQUIRED
|
54 status
= dsgetdcname(mem_ctx
, NULL
, r
->in
.domain
,
55 NULL
, NULL
, flags
, &info
);
56 if (!NT_STATUS_IS_OK(status
)) {
57 libnetapi_set_error_string(mem_ctx
,
58 "%s", get_friendly_nt_error_msg(status
));
59 return ntstatus_to_werror(status
);
62 dc
= strip_hostname(info
->dc_unc
);
63 j
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
64 W_ERROR_HAVE_NO_MEMORY(j
->in
.dc_name
);
67 if (r
->in
.account_ou
) {
68 j
->in
.account_ou
= talloc_strdup(mem_ctx
, r
->in
.account_ou
);
69 W_ERROR_HAVE_NO_MEMORY(j
->in
.account_ou
);
73 j
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
74 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_account
);
78 j
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
79 W_ERROR_HAVE_NO_MEMORY(j
->in
.admin_password
);
82 j
->in
.join_flags
= r
->in
.join_flags
;
83 j
->in
.modify_config
= true;
86 werr
= libnet_Join(mem_ctx
, j
);
87 if (!W_ERROR_IS_OK(werr
) && j
->out
.error_string
) {
88 libnetapi_set_error_string(mem_ctx
, "%s", j
->out
.error_string
);
95 /****************************************************************
96 ****************************************************************/
98 WERROR
NetJoinDomain_r(struct libnetapi_ctx
*ctx
,
99 struct NetJoinDomain
*r
)
101 struct cli_state
*cli
= NULL
;
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_ipc_connection(ctx
, r
->in
.server
, &cli
);
109 if (!W_ERROR_IS_OK(werr
)) {
113 werr
= libnetapi_open_pipe(ctx
, cli
, PI_WKSSVC
, &pipe_cli
);
114 if (!W_ERROR_IS_OK(werr
)) {
118 if (r
->in
.password
) {
119 encode_wkssvc_join_password_buffer(ctx
,
121 &cli
->user_session_key
,
122 &encrypted_password
);
125 old_timeout
= cli_set_timeout(cli
, 600000);
127 status
= rpccli_wkssvc_NetrJoinDomain2(pipe_cli
, ctx
,
135 if (!NT_STATUS_IS_OK(status
)) {
136 werr
= ntstatus_to_werror(status
);
143 cli_set_timeout(cli
, old_timeout
);
149 /****************************************************************
150 ****************************************************************/
152 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
153 struct NetUnjoinDomain
*r
)
155 struct libnet_UnjoinCtx
*u
= NULL
;
156 struct dom_sid domain_sid
;
157 const char *domain
= NULL
;
160 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
161 return WERR_SETUP_NOT_JOINED
;
164 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
165 W_ERROR_NOT_OK_RETURN(werr
);
170 domain
= lp_workgroup();
173 if (r
->in
.server_name
) {
174 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
175 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
178 struct netr_DsRGetDCNameInfo
*info
= NULL
;
179 const char *dc
= NULL
;
180 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
181 DS_WRITABLE_REQUIRED
|
183 status
= dsgetdcname(mem_ctx
, NULL
, domain
,
184 NULL
, NULL
, flags
, &info
);
185 if (!NT_STATUS_IS_OK(status
)) {
186 libnetapi_set_error_string(mem_ctx
,
187 "failed to find DC for domain %s: %s",
189 get_friendly_nt_error_msg(status
));
190 return ntstatus_to_werror(status
);
193 dc
= strip_hostname(info
->dc_unc
);
194 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
195 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
197 u
->in
.domain_name
= domain
;
201 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
202 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
205 if (r
->in
.password
) {
206 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
207 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
210 u
->in
.domain_name
= domain
;
211 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
212 u
->in
.modify_config
= true;
215 u
->in
.domain_sid
= &domain_sid
;
217 werr
= libnet_Unjoin(mem_ctx
, u
);
218 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
219 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
226 /****************************************************************
227 ****************************************************************/
229 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
230 struct NetUnjoinDomain
*r
)
232 struct cli_state
*cli
= NULL
;
233 struct rpc_pipe_client
*pipe_cli
= NULL
;
234 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
237 unsigned int old_timeout
= 0;
239 werr
= libnetapi_open_ipc_connection(ctx
, r
->in
.server_name
, &cli
);
240 if (!W_ERROR_IS_OK(werr
)) {
244 werr
= libnetapi_open_pipe(ctx
, cli
, PI_WKSSVC
, &pipe_cli
);
245 if (!W_ERROR_IS_OK(werr
)) {
249 if (r
->in
.password
) {
250 encode_wkssvc_join_password_buffer(ctx
,
252 &cli
->user_session_key
,
253 &encrypted_password
);
256 old_timeout
= cli_set_timeout(cli
, 60000);
258 status
= rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli
, ctx
,
264 if (!NT_STATUS_IS_OK(status
)) {
265 werr
= ntstatus_to_werror(status
);
272 cli_set_timeout(cli
, old_timeout
);
279 /****************************************************************
280 ****************************************************************/
282 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
283 struct NetGetJoinInformation
*r
)
285 struct cli_state
*cli
= NULL
;
286 struct rpc_pipe_client
*pipe_cli
= NULL
;
289 const char *buffer
= NULL
;
291 werr
= libnetapi_open_ipc_connection(ctx
, r
->in
.server_name
, &cli
);
292 if (!W_ERROR_IS_OK(werr
)) {
296 werr
= libnetapi_open_pipe(ctx
, cli
, PI_WKSSVC
, &pipe_cli
);
297 if (!W_ERROR_IS_OK(werr
)) {
301 status
= rpccli_wkssvc_NetrGetJoinInformation(pipe_cli
, ctx
,
304 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
306 if (!NT_STATUS_IS_OK(status
)) {
307 werr
= ntstatus_to_werror(status
);
311 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
312 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
318 /****************************************************************
319 ****************************************************************/
321 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
322 struct NetGetJoinInformation
*r
)
324 if ((lp_security() == SEC_ADS
) && lp_realm()) {
325 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
327 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
329 if (!*r
->out
.name_buffer
) {
333 switch (lp_server_role()) {
334 case ROLE_DOMAIN_MEMBER
:
335 case ROLE_DOMAIN_PDC
:
336 case ROLE_DOMAIN_BDC
:
337 *r
->out
.name_type
= NetSetupDomainName
;
339 case ROLE_STANDALONE
:
341 *r
->out
.name_type
= NetSetupWorkgroupName
;
348 /****************************************************************
349 ****************************************************************/
351 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
352 struct NetGetJoinableOUs
*r
)
356 ADS_STATUS ads_status
;
357 ADS_STRUCT
*ads
= NULL
;
358 struct netr_DsRGetDCNameInfo
*info
= NULL
;
359 const char *dc
= NULL
;
360 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
363 status
= dsgetdcname(ctx
, NULL
, r
->in
.domain
,
364 NULL
, NULL
, flags
, &info
);
365 if (!NT_STATUS_IS_OK(status
)) {
366 libnetapi_set_error_string(ctx
, "%s",
367 get_friendly_nt_error_msg(status
));
368 return ntstatus_to_werror(status
);
371 dc
= strip_hostname(info
->dc_unc
);
373 ads
= ads_init(r
->in
.domain
, r
->in
.domain
, dc
);
375 return WERR_GENERAL_FAILURE
;
378 SAFE_FREE(ads
->auth
.user_name
);
380 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
381 } else if (ctx
->username
) {
382 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
385 SAFE_FREE(ads
->auth
.password
);
386 if (r
->in
.password
) {
387 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
388 } else if (ctx
->password
) {
389 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
392 ads_status
= ads_connect(ads
);
393 if (!ADS_ERR_OK(ads_status
)) {
395 return WERR_DEFAULT_JOIN_REQUIRED
;
398 ads_status
= ads_get_joinable_ous(ads
, ctx
,
399 (char ***)r
->out
.ous
,
400 (size_t *)r
->out
.ou_count
);
401 if (!ADS_ERR_OK(ads_status
)) {
403 return WERR_DEFAULT_JOIN_REQUIRED
;
409 return WERR_NOT_SUPPORTED
;
413 /****************************************************************
414 ****************************************************************/
416 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
417 struct NetGetJoinableOUs
*r
)
419 struct cli_state
*cli
= NULL
;
420 struct rpc_pipe_client
*pipe_cli
= NULL
;
421 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
425 werr
= libnetapi_open_ipc_connection(ctx
, r
->in
.server_name
, &cli
);
426 if (!W_ERROR_IS_OK(werr
)) {
430 werr
= libnetapi_open_pipe(ctx
, cli
, PI_WKSSVC
, &pipe_cli
);
431 if (!W_ERROR_IS_OK(werr
)) {
435 if (r
->in
.password
) {
436 encode_wkssvc_join_password_buffer(ctx
,
438 &cli
->user_session_key
,
439 &encrypted_password
);
442 status
= rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli
, ctx
,
450 if (!NT_STATUS_IS_OK(status
)) {
451 werr
= ntstatus_to_werror(status
);