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 rpc_pipe_client
*pipe_cli
= NULL
;
102 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
105 unsigned int old_timeout
= 0;
107 werr
= libnetapi_open_pipe(ctx
, r
->in
.server
,
108 &ndr_table_wkssvc
.syntax_id
,
110 if (!W_ERROR_IS_OK(werr
)) {
114 if (r
->in
.password
) {
115 encode_wkssvc_join_password_buffer(ctx
,
117 &pipe_cli
->auth
->user_session_key
,
118 &encrypted_password
);
121 old_timeout
= rpccli_set_timeout(pipe_cli
, 600000);
123 status
= rpccli_wkssvc_NetrJoinDomain2(pipe_cli
, ctx
,
131 if (!NT_STATUS_IS_OK(status
)) {
132 werr
= ntstatus_to_werror(status
);
137 if (pipe_cli
&& old_timeout
) {
138 rpccli_set_timeout(pipe_cli
, old_timeout
);
143 /****************************************************************
144 ****************************************************************/
146 WERROR
NetUnjoinDomain_l(struct libnetapi_ctx
*mem_ctx
,
147 struct NetUnjoinDomain
*r
)
149 struct libnet_UnjoinCtx
*u
= NULL
;
150 struct dom_sid domain_sid
;
151 const char *domain
= NULL
;
154 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid
)) {
155 return WERR_SETUP_NOT_JOINED
;
158 werr
= libnet_init_UnjoinCtx(mem_ctx
, &u
);
159 W_ERROR_NOT_OK_RETURN(werr
);
164 domain
= lp_workgroup();
167 if (r
->in
.server_name
) {
168 u
->in
.dc_name
= talloc_strdup(mem_ctx
, r
->in
.server_name
);
169 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
172 struct netr_DsRGetDCNameInfo
*info
= NULL
;
173 const char *dc
= NULL
;
174 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
175 DS_WRITABLE_REQUIRED
|
177 status
= dsgetdcname(mem_ctx
, NULL
, domain
,
178 NULL
, NULL
, flags
, &info
);
179 if (!NT_STATUS_IS_OK(status
)) {
180 libnetapi_set_error_string(mem_ctx
,
181 "failed to find DC for domain %s: %s",
183 get_friendly_nt_error_msg(status
));
184 return ntstatus_to_werror(status
);
187 dc
= strip_hostname(info
->dc_unc
);
188 u
->in
.dc_name
= talloc_strdup(mem_ctx
, dc
);
189 W_ERROR_HAVE_NO_MEMORY(u
->in
.dc_name
);
191 u
->in
.domain_name
= domain
;
195 u
->in
.admin_account
= talloc_strdup(mem_ctx
, r
->in
.account
);
196 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_account
);
199 if (r
->in
.password
) {
200 u
->in
.admin_password
= talloc_strdup(mem_ctx
, r
->in
.password
);
201 W_ERROR_HAVE_NO_MEMORY(u
->in
.admin_password
);
204 u
->in
.domain_name
= domain
;
205 u
->in
.unjoin_flags
= r
->in
.unjoin_flags
;
206 u
->in
.modify_config
= true;
209 u
->in
.domain_sid
= &domain_sid
;
211 werr
= libnet_Unjoin(mem_ctx
, u
);
212 if (!W_ERROR_IS_OK(werr
) && u
->out
.error_string
) {
213 libnetapi_set_error_string(mem_ctx
, "%s", u
->out
.error_string
);
220 /****************************************************************
221 ****************************************************************/
223 WERROR
NetUnjoinDomain_r(struct libnetapi_ctx
*ctx
,
224 struct NetUnjoinDomain
*r
)
226 struct rpc_pipe_client
*pipe_cli
= NULL
;
227 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
230 unsigned int old_timeout
= 0;
232 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
233 &ndr_table_wkssvc
.syntax_id
,
235 if (!W_ERROR_IS_OK(werr
)) {
239 if (r
->in
.password
) {
240 encode_wkssvc_join_password_buffer(ctx
,
242 &pipe_cli
->auth
->user_session_key
,
243 &encrypted_password
);
246 old_timeout
= rpccli_set_timeout(pipe_cli
, 60000);
248 status
= rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli
, ctx
,
254 if (!NT_STATUS_IS_OK(status
)) {
255 werr
= ntstatus_to_werror(status
);
260 if (pipe_cli
&& old_timeout
) {
261 rpccli_set_timeout(pipe_cli
, old_timeout
);
267 /****************************************************************
268 ****************************************************************/
270 WERROR
NetGetJoinInformation_r(struct libnetapi_ctx
*ctx
,
271 struct NetGetJoinInformation
*r
)
273 struct rpc_pipe_client
*pipe_cli
= NULL
;
276 const char *buffer
= NULL
;
278 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
279 &ndr_table_wkssvc
.syntax_id
,
281 if (!W_ERROR_IS_OK(werr
)) {
285 status
= rpccli_wkssvc_NetrGetJoinInformation(pipe_cli
, ctx
,
288 (enum wkssvc_NetJoinStatus
*)r
->out
.name_type
,
290 if (!NT_STATUS_IS_OK(status
)) {
291 werr
= ntstatus_to_werror(status
);
295 *r
->out
.name_buffer
= talloc_strdup(ctx
, buffer
);
296 W_ERROR_HAVE_NO_MEMORY(*r
->out
.name_buffer
);
302 /****************************************************************
303 ****************************************************************/
305 WERROR
NetGetJoinInformation_l(struct libnetapi_ctx
*ctx
,
306 struct NetGetJoinInformation
*r
)
308 if ((lp_security() == SEC_ADS
) && lp_realm()) {
309 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_realm());
311 *r
->out
.name_buffer
= talloc_strdup(ctx
, lp_workgroup());
313 if (!*r
->out
.name_buffer
) {
317 switch (lp_server_role()) {
318 case ROLE_DOMAIN_MEMBER
:
319 case ROLE_DOMAIN_PDC
:
320 case ROLE_DOMAIN_BDC
:
321 *r
->out
.name_type
= NetSetupDomainName
;
323 case ROLE_STANDALONE
:
325 *r
->out
.name_type
= NetSetupWorkgroupName
;
332 /****************************************************************
333 ****************************************************************/
335 WERROR
NetGetJoinableOUs_l(struct libnetapi_ctx
*ctx
,
336 struct NetGetJoinableOUs
*r
)
340 ADS_STATUS ads_status
;
341 ADS_STRUCT
*ads
= NULL
;
342 struct netr_DsRGetDCNameInfo
*info
= NULL
;
343 const char *dc
= NULL
;
344 uint32_t flags
= DS_DIRECTORY_SERVICE_REQUIRED
|
347 status
= dsgetdcname(ctx
, NULL
, r
->in
.domain
,
348 NULL
, NULL
, flags
, &info
);
349 if (!NT_STATUS_IS_OK(status
)) {
350 libnetapi_set_error_string(ctx
, "%s",
351 get_friendly_nt_error_msg(status
));
352 return ntstatus_to_werror(status
);
355 dc
= strip_hostname(info
->dc_unc
);
357 ads
= ads_init(info
->domain_name
, info
->domain_name
, dc
);
359 return WERR_GENERAL_FAILURE
;
362 SAFE_FREE(ads
->auth
.user_name
);
364 ads
->auth
.user_name
= SMB_STRDUP(r
->in
.account
);
365 } else if (ctx
->username
) {
366 ads
->auth
.user_name
= SMB_STRDUP(ctx
->username
);
369 SAFE_FREE(ads
->auth
.password
);
370 if (r
->in
.password
) {
371 ads
->auth
.password
= SMB_STRDUP(r
->in
.password
);
372 } else if (ctx
->password
) {
373 ads
->auth
.password
= SMB_STRDUP(ctx
->password
);
376 ads_status
= ads_connect_user_creds(ads
);
377 if (!ADS_ERR_OK(ads_status
)) {
379 return WERR_DEFAULT_JOIN_REQUIRED
;
382 ads_status
= ads_get_joinable_ous(ads
, ctx
,
383 (char ***)r
->out
.ous
,
384 (size_t *)r
->out
.ou_count
);
385 if (!ADS_ERR_OK(ads_status
)) {
387 return WERR_DEFAULT_JOIN_REQUIRED
;
393 return WERR_NOT_SUPPORTED
;
397 /****************************************************************
398 ****************************************************************/
400 WERROR
NetGetJoinableOUs_r(struct libnetapi_ctx
*ctx
,
401 struct NetGetJoinableOUs
*r
)
403 struct rpc_pipe_client
*pipe_cli
= NULL
;
404 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
408 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
409 &ndr_table_wkssvc
.syntax_id
,
411 if (!W_ERROR_IS_OK(werr
)) {
415 if (r
->in
.password
) {
416 encode_wkssvc_join_password_buffer(ctx
,
418 &pipe_cli
->auth
->user_session_key
,
419 &encrypted_password
);
422 status
= rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli
, ctx
,
430 if (!NT_STATUS_IS_OK(status
)) {
431 werr
= ntstatus_to_werror(status
);
439 /****************************************************************
440 ****************************************************************/
442 WERROR
NetRenameMachineInDomain_r(struct libnetapi_ctx
*ctx
,
443 struct NetRenameMachineInDomain
*r
)
445 struct rpc_pipe_client
*pipe_cli
= NULL
;
446 struct wkssvc_PasswordBuffer
*encrypted_password
= NULL
;
450 werr
= libnetapi_open_pipe(ctx
, r
->in
.server_name
,
451 &ndr_table_wkssvc
.syntax_id
,
453 if (!W_ERROR_IS_OK(werr
)) {
457 if (r
->in
.password
) {
458 encode_wkssvc_join_password_buffer(ctx
,
460 &pipe_cli
->auth
->user_session_key
,
461 &encrypted_password
);
464 status
= rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli
, ctx
,
466 r
->in
.new_machine_name
,
469 r
->in
.rename_options
,
471 if (!NT_STATUS_IS_OK(status
)) {
472 werr
= ntstatus_to_werror(status
);
480 /****************************************************************
481 ****************************************************************/
483 WERROR
NetRenameMachineInDomain_l(struct libnetapi_ctx
*ctx
,
484 struct NetRenameMachineInDomain
*r
)
486 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx
, r
, NetRenameMachineInDomain
);