Don't require "Modify property" perms to unjoin bug #6481)
[Samba/ekacnet.git] / source3 / lib / netapi / joindomain.c
blob9970a0655a383b8fc29dbb6b40cc2eaf6b67b7f1
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi Join Support
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/>.
20 #include "includes.h"
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"
29 /****************************************************************
30 ****************************************************************/
32 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
33 struct NetJoinDomain *r)
35 struct libnet_JoinCtx *j = NULL;
36 WERROR werr;
38 if (!r->in.domain) {
39 return WERR_INVALID_PARAM;
42 werr = libnet_init_JoinCtx(mem_ctx, &j);
43 W_ERROR_NOT_OK_RETURN(werr);
45 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
46 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
48 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
49 NTSTATUS status;
50 struct netr_DsRGetDCNameInfo *info = NULL;
51 const char *dc = NULL;
52 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
53 DS_WRITABLE_REQUIRED |
54 DS_RETURN_DNS_NAME;
55 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
56 NULL, NULL, flags, &info);
57 if (!NT_STATUS_IS_OK(status)) {
58 libnetapi_set_error_string(mem_ctx,
59 "%s", get_friendly_nt_error_msg(status));
60 return ntstatus_to_werror(status);
63 dc = strip_hostname(info->dc_unc);
64 j->in.dc_name = talloc_strdup(mem_ctx, dc);
65 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
68 if (r->in.account_ou) {
69 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
70 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
73 if (r->in.account) {
74 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
75 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
78 if (r->in.password) {
79 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
80 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
83 j->in.join_flags = r->in.join_flags;
84 j->in.modify_config = true;
85 j->in.debug = true;
87 werr = libnet_Join(mem_ctx, j);
88 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
89 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
91 TALLOC_FREE(j);
93 return werr;
96 /****************************************************************
97 ****************************************************************/
99 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
100 struct NetJoinDomain *r)
102 struct rpc_pipe_client *pipe_cli = NULL;
103 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
104 NTSTATUS status;
105 WERROR werr;
106 unsigned int old_timeout = 0;
108 werr = libnetapi_open_pipe(ctx, r->in.server,
109 &ndr_table_wkssvc.syntax_id,
110 &pipe_cli);
111 if (!W_ERROR_IS_OK(werr)) {
112 goto done;
115 if (r->in.password) {
116 encode_wkssvc_join_password_buffer(ctx,
117 r->in.password,
118 &pipe_cli->auth->user_session_key,
119 &encrypted_password);
122 old_timeout = rpccli_set_timeout(pipe_cli, 600000);
124 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
125 r->in.server,
126 r->in.domain,
127 r->in.account_ou,
128 r->in.account,
129 encrypted_password,
130 r->in.join_flags,
131 &werr);
132 if (!NT_STATUS_IS_OK(status)) {
133 werr = ntstatus_to_werror(status);
134 goto done;
137 done:
138 if (pipe_cli && old_timeout) {
139 rpccli_set_timeout(pipe_cli, old_timeout);
142 return werr;
144 /****************************************************************
145 ****************************************************************/
147 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
148 struct NetUnjoinDomain *r)
150 struct libnet_UnjoinCtx *u = NULL;
151 struct dom_sid domain_sid;
152 const char *domain = NULL;
153 WERROR werr;
155 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
156 return WERR_SETUP_NOT_JOINED;
159 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
160 W_ERROR_NOT_OK_RETURN(werr);
162 if (lp_realm()) {
163 domain = lp_realm();
164 } else {
165 domain = lp_workgroup();
168 if (r->in.server_name) {
169 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
170 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
171 } else {
172 NTSTATUS status;
173 struct netr_DsRGetDCNameInfo *info = NULL;
174 const char *dc = NULL;
175 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
176 DS_WRITABLE_REQUIRED |
177 DS_RETURN_DNS_NAME;
178 status = dsgetdcname(mem_ctx, NULL, domain,
179 NULL, NULL, flags, &info);
180 if (!NT_STATUS_IS_OK(status)) {
181 libnetapi_set_error_string(mem_ctx,
182 "failed to find DC for domain %s: %s",
183 domain,
184 get_friendly_nt_error_msg(status));
185 return ntstatus_to_werror(status);
188 dc = strip_hostname(info->dc_unc);
189 u->in.dc_name = talloc_strdup(mem_ctx, dc);
190 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
192 u->in.domain_name = domain;
195 if (r->in.account) {
196 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
197 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
200 if (r->in.password) {
201 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
202 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
205 u->in.domain_name = domain;
206 u->in.unjoin_flags = r->in.unjoin_flags;
207 u->in.delete_machine_account = false;
208 u->in.modify_config = true;
209 u->in.debug = true;
211 u->in.domain_sid = &domain_sid;
213 werr = libnet_Unjoin(mem_ctx, u);
214 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
215 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
217 TALLOC_FREE(u);
219 return werr;
222 /****************************************************************
223 ****************************************************************/
225 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
226 struct NetUnjoinDomain *r)
228 struct rpc_pipe_client *pipe_cli = NULL;
229 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
230 NTSTATUS status;
231 WERROR werr;
232 unsigned int old_timeout = 0;
234 werr = libnetapi_open_pipe(ctx, r->in.server_name,
235 &ndr_table_wkssvc.syntax_id,
236 &pipe_cli);
237 if (!W_ERROR_IS_OK(werr)) {
238 goto done;
241 if (r->in.password) {
242 encode_wkssvc_join_password_buffer(ctx,
243 r->in.password,
244 &pipe_cli->auth->user_session_key,
245 &encrypted_password);
248 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
250 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
251 r->in.server_name,
252 r->in.account,
253 encrypted_password,
254 r->in.unjoin_flags,
255 &werr);
256 if (!NT_STATUS_IS_OK(status)) {
257 werr = ntstatus_to_werror(status);
258 goto done;
261 done:
262 if (pipe_cli && old_timeout) {
263 rpccli_set_timeout(pipe_cli, old_timeout);
266 return werr;
269 /****************************************************************
270 ****************************************************************/
272 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
273 struct NetGetJoinInformation *r)
275 struct rpc_pipe_client *pipe_cli = NULL;
276 NTSTATUS status;
277 WERROR werr;
278 const char *buffer = NULL;
280 werr = libnetapi_open_pipe(ctx, r->in.server_name,
281 &ndr_table_wkssvc.syntax_id,
282 &pipe_cli);
283 if (!W_ERROR_IS_OK(werr)) {
284 goto done;
287 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
288 r->in.server_name,
289 &buffer,
290 (enum wkssvc_NetJoinStatus *)r->out.name_type,
291 &werr);
292 if (!NT_STATUS_IS_OK(status)) {
293 werr = ntstatus_to_werror(status);
294 goto done;
297 *r->out.name_buffer = talloc_strdup(ctx, buffer);
298 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
300 done:
301 return werr;
304 /****************************************************************
305 ****************************************************************/
307 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
308 struct NetGetJoinInformation *r)
310 if ((lp_security() == SEC_ADS) && lp_realm()) {
311 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
312 } else {
313 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
315 if (!*r->out.name_buffer) {
316 return WERR_NOMEM;
319 switch (lp_server_role()) {
320 case ROLE_DOMAIN_MEMBER:
321 case ROLE_DOMAIN_PDC:
322 case ROLE_DOMAIN_BDC:
323 *r->out.name_type = NetSetupDomainName;
324 break;
325 case ROLE_STANDALONE:
326 default:
327 *r->out.name_type = NetSetupWorkgroupName;
328 break;
331 return WERR_OK;
334 /****************************************************************
335 ****************************************************************/
337 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
338 struct NetGetJoinableOUs *r)
340 #ifdef WITH_ADS
341 NTSTATUS status;
342 ADS_STATUS ads_status;
343 ADS_STRUCT *ads = NULL;
344 struct netr_DsRGetDCNameInfo *info = NULL;
345 const char *dc = NULL;
346 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
347 DS_RETURN_DNS_NAME;
349 status = dsgetdcname(ctx, NULL, r->in.domain,
350 NULL, NULL, flags, &info);
351 if (!NT_STATUS_IS_OK(status)) {
352 libnetapi_set_error_string(ctx, "%s",
353 get_friendly_nt_error_msg(status));
354 return ntstatus_to_werror(status);
357 dc = strip_hostname(info->dc_unc);
359 ads = ads_init(info->domain_name, info->domain_name, dc);
360 if (!ads) {
361 return WERR_GENERAL_FAILURE;
364 SAFE_FREE(ads->auth.user_name);
365 if (r->in.account) {
366 ads->auth.user_name = SMB_STRDUP(r->in.account);
367 } else if (ctx->username) {
368 ads->auth.user_name = SMB_STRDUP(ctx->username);
371 SAFE_FREE(ads->auth.password);
372 if (r->in.password) {
373 ads->auth.password = SMB_STRDUP(r->in.password);
374 } else if (ctx->password) {
375 ads->auth.password = SMB_STRDUP(ctx->password);
378 ads_status = ads_connect_user_creds(ads);
379 if (!ADS_ERR_OK(ads_status)) {
380 ads_destroy(&ads);
381 return WERR_DEFAULT_JOIN_REQUIRED;
384 ads_status = ads_get_joinable_ous(ads, ctx,
385 (char ***)r->out.ous,
386 (size_t *)r->out.ou_count);
387 if (!ADS_ERR_OK(ads_status)) {
388 ads_destroy(&ads);
389 return WERR_DEFAULT_JOIN_REQUIRED;
392 ads_destroy(&ads);
393 return WERR_OK;
394 #else
395 return WERR_NOT_SUPPORTED;
396 #endif
399 /****************************************************************
400 ****************************************************************/
402 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
403 struct NetGetJoinableOUs *r)
405 struct rpc_pipe_client *pipe_cli = NULL;
406 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
407 NTSTATUS status;
408 WERROR werr;
410 werr = libnetapi_open_pipe(ctx, r->in.server_name,
411 &ndr_table_wkssvc.syntax_id,
412 &pipe_cli);
413 if (!W_ERROR_IS_OK(werr)) {
414 goto done;
417 if (r->in.password) {
418 encode_wkssvc_join_password_buffer(ctx,
419 r->in.password,
420 &pipe_cli->auth->user_session_key,
421 &encrypted_password);
424 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
425 r->in.server_name,
426 r->in.domain,
427 r->in.account,
428 encrypted_password,
429 r->out.ou_count,
430 r->out.ous,
431 &werr);
432 if (!NT_STATUS_IS_OK(status)) {
433 werr = ntstatus_to_werror(status);
434 goto done;
437 done:
438 return werr;
441 /****************************************************************
442 ****************************************************************/
444 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
445 struct NetRenameMachineInDomain *r)
447 struct rpc_pipe_client *pipe_cli = NULL;
448 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
449 NTSTATUS status;
450 WERROR werr;
452 werr = libnetapi_open_pipe(ctx, r->in.server_name,
453 &ndr_table_wkssvc.syntax_id,
454 &pipe_cli);
455 if (!W_ERROR_IS_OK(werr)) {
456 goto done;
459 if (r->in.password) {
460 encode_wkssvc_join_password_buffer(ctx,
461 r->in.password,
462 &pipe_cli->auth->user_session_key,
463 &encrypted_password);
466 status = rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli, ctx,
467 r->in.server_name,
468 r->in.new_machine_name,
469 r->in.account,
470 encrypted_password,
471 r->in.rename_options,
472 &werr);
473 if (!NT_STATUS_IS_OK(status)) {
474 werr = ntstatus_to_werror(status);
475 goto done;
478 done:
479 return werr;
482 /****************************************************************
483 ****************************************************************/
485 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
486 struct NetRenameMachineInDomain *r)
488 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);