netapi: fix NetGetJoinableOUs_l.
[Samba.git] / source / lib / netapi / joindomain.c
blob17ea3923fee5f254cc8b076dcb393083937421bb
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"
28 /****************************************************************
29 ****************************************************************/
31 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
32 struct NetJoinDomain *r)
34 struct libnet_JoinCtx *j = NULL;
35 WERROR werr;
37 if (!r->in.domain) {
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) {
48 NTSTATUS status;
49 struct netr_DsRGetDCNameInfo *info = NULL;
50 const char *dc = NULL;
51 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
52 DS_WRITABLE_REQUIRED |
53 DS_RETURN_DNS_NAME;
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);
72 if (r->in.account) {
73 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
74 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
77 if (r->in.password) {
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;
84 j->in.debug = 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);
90 TALLOC_FREE(j);
92 return werr;
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;
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 &cli,
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 &cli->user_session_key,
120 &encrypted_password);
123 old_timeout = cli_set_timeout(cli, 600000);
125 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
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 (cli) {
140 if (old_timeout) {
141 cli_set_timeout(cli, old_timeout);
145 return werr;
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;
156 WERROR werr;
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);
165 if (lp_realm()) {
166 domain = lp_realm();
167 } else {
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);
174 } else {
175 NTSTATUS status;
176 struct netr_DsRGetDCNameInfo *info = NULL;
177 const char *dc = NULL;
178 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
179 DS_WRITABLE_REQUIRED |
180 DS_RETURN_DNS_NAME;
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",
186 domain,
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;
198 if (r->in.account) {
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;
211 u->in.debug = 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);
219 TALLOC_FREE(u);
221 return werr;
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;
233 NTSTATUS status;
234 WERROR werr;
235 unsigned int old_timeout = 0;
237 werr = libnetapi_open_pipe(ctx, r->in.server_name,
238 &ndr_table_wkssvc.syntax_id,
239 &cli,
240 &pipe_cli);
241 if (!W_ERROR_IS_OK(werr)) {
242 goto done;
245 if (r->in.password) {
246 encode_wkssvc_join_password_buffer(ctx,
247 r->in.password,
248 &cli->user_session_key,
249 &encrypted_password);
252 old_timeout = cli_set_timeout(cli, 60000);
254 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
255 r->in.server_name,
256 r->in.account,
257 encrypted_password,
258 r->in.unjoin_flags,
259 &werr);
260 if (!NT_STATUS_IS_OK(status)) {
261 werr = ntstatus_to_werror(status);
262 goto done;
265 done:
266 if (cli) {
267 if (old_timeout) {
268 cli_set_timeout(cli, old_timeout);
272 return werr;
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;
283 NTSTATUS status;
284 WERROR werr;
285 const char *buffer = NULL;
287 werr = libnetapi_open_pipe(ctx, r->in.server_name,
288 &ndr_table_wkssvc.syntax_id,
289 &cli,
290 &pipe_cli);
291 if (!W_ERROR_IS_OK(werr)) {
292 goto done;
295 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
296 r->in.server_name,
297 &buffer,
298 (enum wkssvc_NetJoinStatus *)r->out.name_type,
299 &werr);
300 if (!NT_STATUS_IS_OK(status)) {
301 werr = ntstatus_to_werror(status);
302 goto done;
305 *r->out.name_buffer = talloc_strdup(ctx, buffer);
306 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
308 done:
309 return werr;
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());
320 } else {
321 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
323 if (!*r->out.name_buffer) {
324 return WERR_NOMEM;
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;
332 break;
333 case ROLE_STANDALONE:
334 default:
335 *r->out.name_type = NetSetupWorkgroupName;
336 break;
339 return WERR_OK;
342 /****************************************************************
343 ****************************************************************/
345 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
346 struct NetGetJoinableOUs *r)
348 #ifdef WITH_ADS
349 NTSTATUS status;
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 |
355 DS_RETURN_DNS_NAME;
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);
368 if (!ads) {
369 return WERR_GENERAL_FAILURE;
372 SAFE_FREE(ads->auth.user_name);
373 if (r->in.account) {
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)) {
388 ads_destroy(&ads);
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)) {
396 ads_destroy(&ads);
397 return WERR_DEFAULT_JOIN_REQUIRED;
400 ads_destroy(&ads);
401 return WERR_OK;
402 #else
403 return WERR_NOT_SUPPORTED;
404 #endif
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;
416 NTSTATUS status;
417 WERROR werr;
419 werr = libnetapi_open_pipe(ctx, r->in.server_name,
420 &ndr_table_wkssvc.syntax_id,
421 &cli,
422 &pipe_cli);
423 if (!W_ERROR_IS_OK(werr)) {
424 goto done;
427 if (r->in.password) {
428 encode_wkssvc_join_password_buffer(ctx,
429 r->in.password,
430 &cli->user_session_key,
431 &encrypted_password);
434 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
435 r->in.server_name,
436 r->in.domain,
437 r->in.account,
438 encrypted_password,
439 r->out.ou_count,
440 r->out.ous,
441 &werr);
442 if (!NT_STATUS_IS_OK(status)) {
443 werr = ntstatus_to_werror(status);
444 goto done;
447 done:
448 if (cli) {
449 cli_shutdown(cli);
452 return werr;