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_pipe(ctx
, r
->in
.server
,
109 &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 &cli
->user_session_key
,
120 &encrypted_password
);
123 old_timeout
= cli_set_timeout(cli
, 600000);
125 status
= rpccli_wkssvc_NetrJoinDomain2(pipe_cli
, ctx
,
133 if (!NT_STATUS_IS_OK(status
)) {
134 werr
= ntstatus_to_werror(status
);
141 cli_set_timeout(cli
, old_timeout
);
147 /****************************************************************
148 ****************************************************************/
150 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
151 struct NetUnjoinDomain
*r
)
153 struct libnet_UnjoinCtx
*u
= NULL
;
154 struct dom_sid domain_sid
;
155 const char *domain
= NULL
;
158 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
159 return WERR_SETUP_NOT_JOINED
;
162 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
163 W_ERROR_NOT_OK_RETURN(werr
);
168 domain
= lp_workgroup();
171 if (r
->in
.server_name
) {
172 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
173 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
176 struct netr_DsRGetDCNameInfo
*info
= NULL
;
177 const char *dc
= NULL
;
178 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
179 DS_WRITABLE_REQUIRED
|
181 status
= dsgetdcname(mem_ctx
, NULL
, domain
,
182 NULL
, NULL
, flags
, &info
);
183 if (!NT_STATUS_IS_OK(status
)) {
184 libnetapi_set_error_string(mem_ctx
,
185 "failed to find DC for domain %s: %s",
187 get_friendly_nt_error_msg(status
));
188 return ntstatus_to_werror(status
);
191 dc
= strip_hostname(info
->dc_unc
);
192 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
193 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
195 u
->in
.domain_name
= domain
;
199 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
200 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
203 if (r
->in
.password
) {
204 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
205 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
208 u
->in
.domain_name
= domain
;
209 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
210 u
->in
.modify_config
= true;
213 u
->in
.domain_sid
= &domain_sid
;
215 werr
= libnet_Unjoin(mem_ctx
, u
);
216 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
217 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
224 /****************************************************************
225 ****************************************************************/
227 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
228 struct NetUnjoinDomain
*r
)
230 struct cli_state
*cli
= NULL
;
231 struct rpc_pipe_client
*pipe_cli
= NULL
;
232 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
235 unsigned int old_timeout
= 0;
237 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
238 &ndr_table_wkssvc
.syntax_id
,
241 if (!W_ERROR_IS_OK(werr
)) {
245 if (r
->in
.password
) {
246 encode_wkssvc_join_password_buffer(ctx
,
248 &cli
->user_session_key
,
249 &encrypted_password
);
252 old_timeout
= cli_set_timeout(cli
, 60000);
254 status
= rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli
, ctx
,
260 if (!NT_STATUS_IS_OK(status
)) {
261 werr
= ntstatus_to_werror(status
);
268 cli_set_timeout(cli
, old_timeout
);
275 /****************************************************************
276 ****************************************************************/
278 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
279 struct NetGetJoinInformation
*r
)
281 struct cli_state
*cli
= NULL
;
282 struct rpc_pipe_client
*pipe_cli
= NULL
;
285 const char *buffer
= NULL
;
287 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
288 &ndr_table_wkssvc
.syntax_id
,
291 if (!W_ERROR_IS_OK(werr
)) {
295 status
= rpccli_wkssvc_NetrGetJoinInformation(pipe_cli
, ctx
,
298 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
300 if (!NT_STATUS_IS_OK(status
)) {
301 werr
= ntstatus_to_werror(status
);
305 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
306 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
312 /****************************************************************
313 ****************************************************************/
315 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
316 struct NetGetJoinInformation
*r
)
318 if ((lp_security() == SEC_ADS
) && lp_realm()) {
319 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
321 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
323 if (!*r
->out
.name_buffer
) {
327 switch (lp_server_role()) {
328 case ROLE_DOMAIN_MEMBER
:
329 case ROLE_DOMAIN_PDC
:
330 case ROLE_DOMAIN_BDC
:
331 *r
->out
.name_type
= NetSetupDomainName
;
333 case ROLE_STANDALONE
:
335 *r
->out
.name_type
= NetSetupWorkgroupName
;
342 /****************************************************************
343 ****************************************************************/
345 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
346 struct NetGetJoinableOUs
*r
)
350 ADS_STATUS ads_status
;
351 ADS_STRUCT
*ads
= NULL
;
352 struct netr_DsRGetDCNameInfo
*info
= NULL
;
353 const char *dc
= NULL
;
354 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
357 status
= dsgetdcname(ctx
, NULL
, r
->in
.domain
,
358 NULL
, NULL
, flags
, &info
);
359 if (!NT_STATUS_IS_OK(status
)) {
360 libnetapi_set_error_string(ctx
, "%s",
361 get_friendly_nt_error_msg(status
));
362 return ntstatus_to_werror(status
);
365 dc
= strip_hostname(info
->dc_unc
);
367 ads
= ads_init(info
->domain_name
, info
->domain_name
, dc
);
369 return WERR_GENERAL_FAILURE
;
372 SAFE_FREE(ads
->auth
.user_name
);
374 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
375 } else if (ctx
->username
) {
376 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
379 SAFE_FREE(ads
->auth
.password
);
380 if (r
->in
.password
) {
381 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
382 } else if (ctx
->password
) {
383 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
386 ads_status
= ads_connect_user_creds(ads
);
387 if (!ADS_ERR_OK(ads_status
)) {
389 return WERR_DEFAULT_JOIN_REQUIRED
;
392 ads_status
= ads_get_joinable_ous(ads
, ctx
,
393 (char ***)r
->out
.ous
,
394 (size_t *)r
->out
.ou_count
);
395 if (!ADS_ERR_OK(ads_status
)) {
397 return WERR_DEFAULT_JOIN_REQUIRED
;
403 return WERR_NOT_SUPPORTED
;
407 /****************************************************************
408 ****************************************************************/
410 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
411 struct NetGetJoinableOUs
*r
)
413 struct cli_state
*cli
= NULL
;
414 struct rpc_pipe_client
*pipe_cli
= NULL
;
415 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
419 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
420 &ndr_table_wkssvc
.syntax_id
,
423 if (!W_ERROR_IS_OK(werr
)) {
427 if (r
->in
.password
) {
428 encode_wkssvc_join_password_buffer(ctx
,
430 &cli
->user_session_key
,
431 &encrypted_password
);
434 status
= rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli
, ctx
,
442 if (!NT_STATUS_IS_OK(status
)) {
443 werr
= ntstatus_to_werror(status
);