s3-build: use HAVE_ADS define in some more places.
[Samba.git] / source3 / lib / netapi / joindomain.c
blob6bae363b1439cbb6a3f020ddf2f94781c652e7e4
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"
21 #include "ads.h"
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "libcli/auth/libcli_auth.h"
24 #include "lib/netapi/netapi.h"
25 #include "lib/netapi/netapi_private.h"
26 #include "lib/netapi/libnetapi.h"
27 #include "librpc/gen_ndr/libnet_join.h"
28 #include "libnet/libnet_join.h"
29 #include "../librpc/gen_ndr/ndr_wkssvc_c.h"
30 #include "rpc_client/cli_pipe.h"
31 #include "secrets.h"
33 /****************************************************************
34 ****************************************************************/
36 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
37 struct NetJoinDomain *r)
39 struct libnet_JoinCtx *j = NULL;
40 struct libnetapi_private_ctx *priv;
41 WERROR werr;
43 priv = talloc_get_type_abort(mem_ctx->private_data,
44 struct libnetapi_private_ctx);
46 if (!r->in.domain) {
47 return WERR_INVALID_PARAM;
50 werr = libnet_init_JoinCtx(mem_ctx, &j);
51 W_ERROR_NOT_OK_RETURN(werr);
53 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
54 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
56 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
57 NTSTATUS status;
58 struct netr_DsRGetDCNameInfo *info = NULL;
59 const char *dc = NULL;
60 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
61 DS_WRITABLE_REQUIRED |
62 DS_RETURN_DNS_NAME;
63 status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
64 NULL, NULL, flags, &info);
65 if (!NT_STATUS_IS_OK(status)) {
66 libnetapi_set_error_string(mem_ctx,
67 "%s", get_friendly_nt_error_msg(status));
68 return ntstatus_to_werror(status);
71 dc = strip_hostname(info->dc_unc);
72 j->in.dc_name = talloc_strdup(mem_ctx, dc);
73 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
76 if (r->in.account_ou) {
77 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
78 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
81 if (r->in.account) {
82 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
83 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
86 if (r->in.password) {
87 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
88 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
91 j->in.join_flags = r->in.join_flags;
92 j->in.modify_config = true;
93 j->in.debug = true;
95 werr = libnet_Join(mem_ctx, j);
96 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
97 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
99 TALLOC_FREE(j);
101 return werr;
104 /****************************************************************
105 ****************************************************************/
107 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
108 struct NetJoinDomain *r)
110 struct rpc_pipe_client *pipe_cli = NULL;
111 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
112 NTSTATUS status;
113 WERROR werr;
114 unsigned int old_timeout = 0;
115 struct dcerpc_binding_handle *b;
117 werr = libnetapi_open_pipe(ctx, r->in.server,
118 &ndr_table_wkssvc.syntax_id,
119 &pipe_cli);
120 if (!W_ERROR_IS_OK(werr)) {
121 goto done;
124 b = pipe_cli->binding_handle;
126 if (r->in.password) {
127 encode_wkssvc_join_password_buffer(ctx,
128 r->in.password,
129 &pipe_cli->auth->user_session_key,
130 &encrypted_password);
133 old_timeout = rpccli_set_timeout(pipe_cli, 600000);
135 status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(),
136 r->in.server,
137 r->in.domain,
138 r->in.account_ou,
139 r->in.account,
140 encrypted_password,
141 r->in.join_flags,
142 &werr);
143 if (!NT_STATUS_IS_OK(status)) {
144 werr = ntstatus_to_werror(status);
145 goto done;
148 done:
149 if (pipe_cli && old_timeout) {
150 rpccli_set_timeout(pipe_cli, old_timeout);
153 return werr;
155 /****************************************************************
156 ****************************************************************/
158 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
159 struct NetUnjoinDomain *r)
161 struct libnet_UnjoinCtx *u = NULL;
162 struct dom_sid domain_sid;
163 const char *domain = NULL;
164 WERROR werr;
165 struct libnetapi_private_ctx *priv;
167 priv = talloc_get_type_abort(mem_ctx->private_data,
168 struct libnetapi_private_ctx);
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);
177 if (lp_realm()) {
178 domain = lp_realm();
179 } else {
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);
186 } else {
187 NTSTATUS status;
188 struct netr_DsRGetDCNameInfo *info = NULL;
189 const char *dc = NULL;
190 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
191 DS_WRITABLE_REQUIRED |
192 DS_RETURN_DNS_NAME;
193 status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
194 NULL, NULL, flags, &info);
195 if (!NT_STATUS_IS_OK(status)) {
196 libnetapi_set_error_string(mem_ctx,
197 "failed to find DC for domain %s: %s",
198 domain,
199 get_friendly_nt_error_msg(status));
200 return ntstatus_to_werror(status);
203 dc = strip_hostname(info->dc_unc);
204 u->in.dc_name = talloc_strdup(mem_ctx, dc);
205 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
207 u->in.domain_name = domain;
210 if (r->in.account) {
211 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
212 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
215 if (r->in.password) {
216 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
217 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
220 u->in.domain_name = domain;
221 u->in.unjoin_flags = r->in.unjoin_flags;
222 u->in.delete_machine_account = false;
223 u->in.modify_config = true;
224 u->in.debug = true;
226 u->in.domain_sid = &domain_sid;
228 werr = libnet_Unjoin(mem_ctx, u);
229 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
230 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
232 TALLOC_FREE(u);
234 return werr;
237 /****************************************************************
238 ****************************************************************/
240 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
241 struct NetUnjoinDomain *r)
243 struct rpc_pipe_client *pipe_cli = NULL;
244 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
245 NTSTATUS status;
246 WERROR werr;
247 unsigned int old_timeout = 0;
248 struct dcerpc_binding_handle *b;
250 werr = libnetapi_open_pipe(ctx, r->in.server_name,
251 &ndr_table_wkssvc.syntax_id,
252 &pipe_cli);
253 if (!W_ERROR_IS_OK(werr)) {
254 goto done;
257 b = pipe_cli->binding_handle;
259 if (r->in.password) {
260 encode_wkssvc_join_password_buffer(ctx,
261 r->in.password,
262 &pipe_cli->auth->user_session_key,
263 &encrypted_password);
266 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
268 status = dcerpc_wkssvc_NetrUnjoinDomain2(b, talloc_tos(),
269 r->in.server_name,
270 r->in.account,
271 encrypted_password,
272 r->in.unjoin_flags,
273 &werr);
274 if (!NT_STATUS_IS_OK(status)) {
275 werr = ntstatus_to_werror(status);
276 goto done;
279 done:
280 if (pipe_cli && old_timeout) {
281 rpccli_set_timeout(pipe_cli, old_timeout);
284 return werr;
287 /****************************************************************
288 ****************************************************************/
290 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
291 struct NetGetJoinInformation *r)
293 struct rpc_pipe_client *pipe_cli = NULL;
294 NTSTATUS status;
295 WERROR werr;
296 const char *buffer = NULL;
297 struct dcerpc_binding_handle *b;
299 werr = libnetapi_open_pipe(ctx, r->in.server_name,
300 &ndr_table_wkssvc.syntax_id,
301 &pipe_cli);
302 if (!W_ERROR_IS_OK(werr)) {
303 goto done;
306 b = pipe_cli->binding_handle;
308 status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(),
309 r->in.server_name,
310 &buffer,
311 (enum wkssvc_NetJoinStatus *)r->out.name_type,
312 &werr);
313 if (!NT_STATUS_IS_OK(status)) {
314 werr = ntstatus_to_werror(status);
315 goto done;
318 if (!W_ERROR_IS_OK(werr)) {
319 goto done;
322 *r->out.name_buffer = talloc_strdup(ctx, buffer);
323 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
325 done:
326 return werr;
329 /****************************************************************
330 ****************************************************************/
332 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
333 struct NetGetJoinInformation *r)
335 if ((lp_security() == SEC_ADS) && lp_realm()) {
336 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
337 } else {
338 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
340 if (!*r->out.name_buffer) {
341 return WERR_NOMEM;
344 switch (lp_server_role()) {
345 case ROLE_DOMAIN_MEMBER:
346 case ROLE_DOMAIN_PDC:
347 case ROLE_DOMAIN_BDC:
348 *r->out.name_type = NetSetupDomainName;
349 break;
350 case ROLE_STANDALONE:
351 default:
352 *r->out.name_type = NetSetupWorkgroupName;
353 break;
356 return WERR_OK;
359 /****************************************************************
360 ****************************************************************/
362 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
363 struct NetGetJoinableOUs *r)
365 #ifdef HAVE_ADS
366 NTSTATUS status;
367 ADS_STATUS ads_status;
368 ADS_STRUCT *ads = NULL;
369 struct netr_DsRGetDCNameInfo *info = NULL;
370 const char *dc = NULL;
371 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
372 DS_RETURN_DNS_NAME;
373 struct libnetapi_private_ctx *priv;
375 priv = talloc_get_type_abort(ctx->private_data,
376 struct libnetapi_private_ctx);
378 status = dsgetdcname(ctx, priv->msg_ctx, r->in.domain,
379 NULL, NULL, flags, &info);
380 if (!NT_STATUS_IS_OK(status)) {
381 libnetapi_set_error_string(ctx, "%s",
382 get_friendly_nt_error_msg(status));
383 return ntstatus_to_werror(status);
386 dc = strip_hostname(info->dc_unc);
388 ads = ads_init(info->domain_name, info->domain_name, dc);
389 if (!ads) {
390 return WERR_GENERAL_FAILURE;
393 SAFE_FREE(ads->auth.user_name);
394 if (r->in.account) {
395 ads->auth.user_name = SMB_STRDUP(r->in.account);
396 } else if (ctx->username) {
397 ads->auth.user_name = SMB_STRDUP(ctx->username);
400 SAFE_FREE(ads->auth.password);
401 if (r->in.password) {
402 ads->auth.password = SMB_STRDUP(r->in.password);
403 } else if (ctx->password) {
404 ads->auth.password = SMB_STRDUP(ctx->password);
407 ads_status = ads_connect_user_creds(ads);
408 if (!ADS_ERR_OK(ads_status)) {
409 ads_destroy(&ads);
410 return WERR_DEFAULT_JOIN_REQUIRED;
413 ads_status = ads_get_joinable_ous(ads, ctx,
414 (char ***)r->out.ous,
415 (size_t *)r->out.ou_count);
416 if (!ADS_ERR_OK(ads_status)) {
417 ads_destroy(&ads);
418 return WERR_DEFAULT_JOIN_REQUIRED;
421 ads_destroy(&ads);
422 return WERR_OK;
423 #else
424 return WERR_NOT_SUPPORTED;
425 #endif
428 /****************************************************************
429 ****************************************************************/
431 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
432 struct NetGetJoinableOUs *r)
434 struct rpc_pipe_client *pipe_cli = NULL;
435 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
436 NTSTATUS status;
437 WERROR werr;
438 struct dcerpc_binding_handle *b;
440 werr = libnetapi_open_pipe(ctx, r->in.server_name,
441 &ndr_table_wkssvc.syntax_id,
442 &pipe_cli);
443 if (!W_ERROR_IS_OK(werr)) {
444 goto done;
447 b = pipe_cli->binding_handle;
449 if (r->in.password) {
450 encode_wkssvc_join_password_buffer(ctx,
451 r->in.password,
452 &pipe_cli->auth->user_session_key,
453 &encrypted_password);
456 status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(),
457 r->in.server_name,
458 r->in.domain,
459 r->in.account,
460 encrypted_password,
461 r->out.ou_count,
462 r->out.ous,
463 &werr);
464 if (!NT_STATUS_IS_OK(status)) {
465 werr = ntstatus_to_werror(status);
466 goto done;
469 done:
470 return werr;
473 /****************************************************************
474 ****************************************************************/
476 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
477 struct NetRenameMachineInDomain *r)
479 struct rpc_pipe_client *pipe_cli = NULL;
480 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
481 NTSTATUS status;
482 WERROR werr;
483 struct dcerpc_binding_handle *b;
485 werr = libnetapi_open_pipe(ctx, r->in.server_name,
486 &ndr_table_wkssvc.syntax_id,
487 &pipe_cli);
488 if (!W_ERROR_IS_OK(werr)) {
489 goto done;
492 b = pipe_cli->binding_handle;
494 if (r->in.password) {
495 encode_wkssvc_join_password_buffer(ctx,
496 r->in.password,
497 &pipe_cli->auth->user_session_key,
498 &encrypted_password);
501 status = dcerpc_wkssvc_NetrRenameMachineInDomain2(b, talloc_tos(),
502 r->in.server_name,
503 r->in.new_machine_name,
504 r->in.account,
505 encrypted_password,
506 r->in.rename_options,
507 &werr);
508 if (!NT_STATUS_IS_OK(status)) {
509 werr = ntstatus_to_werror(status);
510 goto done;
513 done:
514 return werr;
517 /****************************************************************
518 ****************************************************************/
520 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
521 struct NetRenameMachineInDomain *r)
523 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);