Fix bug #9147 - winbind can't fetch user or group info from AD via LDAP
[Samba.git] / source3 / lib / netapi / joindomain.c
blob8adca11b1730ccbac72fb76fd0fb915ef017dc3c
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"
28 #include "../librpc/gen_ndr/cli_wkssvc.h"
30 /****************************************************************
31 ****************************************************************/
33 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
34 struct NetJoinDomain *r)
36 struct libnet_JoinCtx *j = NULL;
37 WERROR werr;
39 if (!r->in.domain) {
40 return WERR_INVALID_PARAM;
43 werr = libnet_init_JoinCtx(mem_ctx, &j);
44 W_ERROR_NOT_OK_RETURN(werr);
46 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
47 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
49 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
50 NTSTATUS status;
51 struct netr_DsRGetDCNameInfo *info = NULL;
52 const char *dc = NULL;
53 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
54 DS_WRITABLE_REQUIRED |
55 DS_RETURN_DNS_NAME;
56 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
57 NULL, NULL, flags, &info);
58 if (!NT_STATUS_IS_OK(status)) {
59 libnetapi_set_error_string(mem_ctx,
60 "%s", get_friendly_nt_error_msg(status));
61 return ntstatus_to_werror(status);
64 dc = strip_hostname(info->dc_unc);
65 j->in.dc_name = talloc_strdup(mem_ctx, dc);
66 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
69 if (r->in.account_ou) {
70 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
71 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
74 if (r->in.account) {
75 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
76 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
79 if (r->in.password) {
80 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
81 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
84 j->in.join_flags = r->in.join_flags;
85 j->in.modify_config = true;
86 j->in.debug = true;
88 werr = libnet_Join(mem_ctx, j);
89 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
90 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
92 TALLOC_FREE(j);
94 return werr;
97 /****************************************************************
98 ****************************************************************/
100 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
101 struct NetJoinDomain *r)
103 struct rpc_pipe_client *pipe_cli = NULL;
104 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
105 NTSTATUS status;
106 WERROR werr;
107 unsigned int old_timeout = 0;
109 werr = libnetapi_open_pipe(ctx, r->in.server,
110 &ndr_table_wkssvc.syntax_id,
111 &pipe_cli);
112 if (!W_ERROR_IS_OK(werr)) {
113 goto done;
116 if (r->in.password) {
117 encode_wkssvc_join_password_buffer(ctx,
118 r->in.password,
119 &pipe_cli->auth->user_session_key,
120 &encrypted_password);
123 old_timeout = rpccli_set_timeout(pipe_cli, 600000);
125 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, talloc_tos(),
126 r->in.server,
127 r->in.domain,
128 r->in.account_ou,
129 r->in.account,
130 encrypted_password,
131 r->in.join_flags,
132 &werr);
133 if (!NT_STATUS_IS_OK(status)) {
134 werr = ntstatus_to_werror(status);
135 goto done;
138 done:
139 if (pipe_cli && old_timeout) {
140 rpccli_set_timeout(pipe_cli, old_timeout);
143 return werr;
145 /****************************************************************
146 ****************************************************************/
148 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
149 struct NetUnjoinDomain *r)
151 struct libnet_UnjoinCtx *u = NULL;
152 struct dom_sid domain_sid;
153 const char *domain = NULL;
154 WERROR werr;
156 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
157 return WERR_SETUP_NOT_JOINED;
160 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
161 W_ERROR_NOT_OK_RETURN(werr);
163 if (lp_realm()) {
164 domain = lp_realm();
165 } else {
166 domain = lp_workgroup();
169 if (r->in.server_name) {
170 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
171 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
172 } else {
173 NTSTATUS status;
174 struct netr_DsRGetDCNameInfo *info = NULL;
175 const char *dc = NULL;
176 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
177 DS_WRITABLE_REQUIRED |
178 DS_RETURN_DNS_NAME;
179 status = dsgetdcname(mem_ctx, NULL, domain,
180 NULL, NULL, flags, &info);
181 if (!NT_STATUS_IS_OK(status)) {
182 libnetapi_set_error_string(mem_ctx,
183 "failed to find DC for domain %s: %s",
184 domain,
185 get_friendly_nt_error_msg(status));
186 return ntstatus_to_werror(status);
189 dc = strip_hostname(info->dc_unc);
190 u->in.dc_name = talloc_strdup(mem_ctx, dc);
191 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
193 u->in.domain_name = domain;
196 if (r->in.account) {
197 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
198 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
201 if (r->in.password) {
202 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
203 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
206 u->in.domain_name = domain;
207 u->in.unjoin_flags = r->in.unjoin_flags;
208 u->in.delete_machine_account = false;
209 u->in.modify_config = true;
210 u->in.debug = true;
212 u->in.domain_sid = &domain_sid;
214 werr = libnet_Unjoin(mem_ctx, u);
215 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
216 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
218 TALLOC_FREE(u);
220 return werr;
223 /****************************************************************
224 ****************************************************************/
226 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
227 struct NetUnjoinDomain *r)
229 struct rpc_pipe_client *pipe_cli = NULL;
230 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
231 NTSTATUS status;
232 WERROR werr;
233 unsigned int old_timeout = 0;
235 werr = libnetapi_open_pipe(ctx, r->in.server_name,
236 &ndr_table_wkssvc.syntax_id,
237 &pipe_cli);
238 if (!W_ERROR_IS_OK(werr)) {
239 goto done;
242 if (r->in.password) {
243 encode_wkssvc_join_password_buffer(ctx,
244 r->in.password,
245 &pipe_cli->auth->user_session_key,
246 &encrypted_password);
249 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
251 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, talloc_tos(),
252 r->in.server_name,
253 r->in.account,
254 encrypted_password,
255 r->in.unjoin_flags,
256 &werr);
257 if (!NT_STATUS_IS_OK(status)) {
258 werr = ntstatus_to_werror(status);
259 goto done;
262 done:
263 if (pipe_cli && old_timeout) {
264 rpccli_set_timeout(pipe_cli, old_timeout);
267 return werr;
270 /****************************************************************
271 ****************************************************************/
273 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
274 struct NetGetJoinInformation *r)
276 struct rpc_pipe_client *pipe_cli = NULL;
277 NTSTATUS status;
278 WERROR werr;
279 const char *buffer = NULL;
281 werr = libnetapi_open_pipe(ctx, r->in.server_name,
282 &ndr_table_wkssvc.syntax_id,
283 &pipe_cli);
284 if (!W_ERROR_IS_OK(werr)) {
285 goto done;
288 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, talloc_tos(),
289 r->in.server_name,
290 &buffer,
291 (enum wkssvc_NetJoinStatus *)r->out.name_type,
292 &werr);
293 if (!NT_STATUS_IS_OK(status)) {
294 werr = ntstatus_to_werror(status);
295 goto done;
298 *r->out.name_buffer = talloc_strdup(ctx, buffer);
299 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
301 done:
302 return werr;
305 /****************************************************************
306 ****************************************************************/
308 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
309 struct NetGetJoinInformation *r)
311 if ((lp_security() == SEC_ADS) && lp_realm()) {
312 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
313 } else {
314 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
316 if (!*r->out.name_buffer) {
317 return WERR_NOMEM;
320 switch (lp_server_role()) {
321 case ROLE_DOMAIN_MEMBER:
322 case ROLE_DOMAIN_PDC:
323 case ROLE_DOMAIN_BDC:
324 *r->out.name_type = NetSetupDomainName;
325 break;
326 case ROLE_STANDALONE:
327 default:
328 *r->out.name_type = NetSetupWorkgroupName;
329 break;
332 return WERR_OK;
335 /****************************************************************
336 ****************************************************************/
338 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
339 struct NetGetJoinableOUs *r)
341 #ifdef WITH_ADS
342 NTSTATUS status;
343 ADS_STATUS ads_status;
344 ADS_STRUCT *ads = NULL;
345 struct netr_DsRGetDCNameInfo *info = NULL;
346 const char *dc = NULL;
347 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
348 DS_RETURN_DNS_NAME;
350 status = dsgetdcname(ctx, NULL, r->in.domain,
351 NULL, NULL, flags, &info);
352 if (!NT_STATUS_IS_OK(status)) {
353 libnetapi_set_error_string(ctx, "%s",
354 get_friendly_nt_error_msg(status));
355 return ntstatus_to_werror(status);
358 dc = strip_hostname(info->dc_unc);
360 ads = ads_init(info->domain_name, info->domain_name, dc);
361 if (!ads) {
362 return WERR_GENERAL_FAILURE;
365 SAFE_FREE(ads->auth.user_name);
366 if (r->in.account) {
367 ads->auth.user_name = SMB_STRDUP(r->in.account);
368 } else if (ctx->username) {
369 ads->auth.user_name = SMB_STRDUP(ctx->username);
372 SAFE_FREE(ads->auth.password);
373 if (r->in.password) {
374 ads->auth.password = SMB_STRDUP(r->in.password);
375 } else if (ctx->password) {
376 ads->auth.password = SMB_STRDUP(ctx->password);
379 ads_status = ads_connect_user_creds(ads);
380 if (!ADS_ERR_OK(ads_status)) {
381 ads_destroy(&ads);
382 return WERR_DEFAULT_JOIN_REQUIRED;
385 ads_status = ads_get_joinable_ous(ads, ctx,
386 (char ***)r->out.ous,
387 (size_t *)r->out.ou_count);
388 if (!ADS_ERR_OK(ads_status)) {
389 ads_destroy(&ads);
390 return WERR_DEFAULT_JOIN_REQUIRED;
393 ads_destroy(&ads);
394 return WERR_OK;
395 #else
396 return WERR_NOT_SUPPORTED;
397 #endif
400 /****************************************************************
401 ****************************************************************/
403 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
404 struct NetGetJoinableOUs *r)
406 struct rpc_pipe_client *pipe_cli = NULL;
407 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
408 NTSTATUS status;
409 WERROR werr;
411 werr = libnetapi_open_pipe(ctx, r->in.server_name,
412 &ndr_table_wkssvc.syntax_id,
413 &pipe_cli);
414 if (!W_ERROR_IS_OK(werr)) {
415 goto done;
418 if (r->in.password) {
419 encode_wkssvc_join_password_buffer(ctx,
420 r->in.password,
421 &pipe_cli->auth->user_session_key,
422 &encrypted_password);
425 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, talloc_tos(),
426 r->in.server_name,
427 r->in.domain,
428 r->in.account,
429 encrypted_password,
430 r->out.ou_count,
431 r->out.ous,
432 &werr);
433 if (!NT_STATUS_IS_OK(status)) {
434 werr = ntstatus_to_werror(status);
435 goto done;
438 done:
439 return werr;
442 /****************************************************************
443 ****************************************************************/
445 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
446 struct NetRenameMachineInDomain *r)
448 struct rpc_pipe_client *pipe_cli = NULL;
449 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
450 NTSTATUS status;
451 WERROR werr;
453 werr = libnetapi_open_pipe(ctx, r->in.server_name,
454 &ndr_table_wkssvc.syntax_id,
455 &pipe_cli);
456 if (!W_ERROR_IS_OK(werr)) {
457 goto done;
460 if (r->in.password) {
461 encode_wkssvc_join_password_buffer(ctx,
462 r->in.password,
463 &pipe_cli->auth->user_session_key,
464 &encrypted_password);
467 status = rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli, talloc_tos(),
468 r->in.server_name,
469 r->in.new_machine_name,
470 r->in.account,
471 encrypted_password,
472 r->in.rename_options,
473 &werr);
474 if (!NT_STATUS_IS_OK(status)) {
475 werr = ntstatus_to_werror(status);
476 goto done;
479 done:
480 return werr;
483 /****************************************************************
484 ****************************************************************/
486 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
487 struct NetRenameMachineInDomain *r)
489 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);