Fix resume handle for _samr_EnumDomainGroups
[Samba.git] / source / lib / netapi / joindomain.c
blob66f7cfb13ff8ee7fbc1cd88051eab1d0fbd318a3
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_ipc_connection(ctx, r->in.server, &cli);
109 if (!W_ERROR_IS_OK(werr)) {
110 goto done;
113 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
114 if (!W_ERROR_IS_OK(werr)) {
115 goto done;
118 if (r->in.password) {
119 encode_wkssvc_join_password_buffer(ctx,
120 r->in.password,
121 &cli->user_session_key,
122 &encrypted_password);
125 old_timeout = cli_set_timeout(cli, 600000);
127 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
128 r->in.server,
129 r->in.domain,
130 r->in.account_ou,
131 r->in.account,
132 encrypted_password,
133 r->in.join_flags,
134 &werr);
135 if (!NT_STATUS_IS_OK(status)) {
136 werr = ntstatus_to_werror(status);
137 goto done;
140 done:
141 if (cli) {
142 if (old_timeout) {
143 cli_set_timeout(cli, old_timeout);
147 return werr;
149 /****************************************************************
150 ****************************************************************/
152 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
153 struct NetUnjoinDomain *r)
155 struct libnet_UnjoinCtx *u = NULL;
156 struct dom_sid domain_sid;
157 const char *domain = NULL;
158 WERROR werr;
160 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
161 return WERR_SETUP_NOT_JOINED;
164 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
165 W_ERROR_NOT_OK_RETURN(werr);
167 if (lp_realm()) {
168 domain = lp_realm();
169 } else {
170 domain = lp_workgroup();
173 if (r->in.server_name) {
174 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
175 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
176 } else {
177 NTSTATUS status;
178 struct netr_DsRGetDCNameInfo *info = NULL;
179 const char *dc = NULL;
180 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
181 DS_WRITABLE_REQUIRED |
182 DS_RETURN_DNS_NAME;
183 status = dsgetdcname(mem_ctx, NULL, domain,
184 NULL, NULL, flags, &info);
185 if (!NT_STATUS_IS_OK(status)) {
186 libnetapi_set_error_string(mem_ctx,
187 "failed to find DC for domain %s: %s",
188 domain,
189 get_friendly_nt_error_msg(status));
190 return ntstatus_to_werror(status);
193 dc = strip_hostname(info->dc_unc);
194 u->in.dc_name = talloc_strdup(mem_ctx, dc);
195 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
197 u->in.domain_name = domain;
200 if (r->in.account) {
201 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
202 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
205 if (r->in.password) {
206 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
207 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
210 u->in.domain_name = domain;
211 u->in.unjoin_flags = r->in.unjoin_flags;
212 u->in.modify_config = true;
213 u->in.debug = true;
215 u->in.domain_sid = &domain_sid;
217 werr = libnet_Unjoin(mem_ctx, u);
218 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
219 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
221 TALLOC_FREE(u);
223 return werr;
226 /****************************************************************
227 ****************************************************************/
229 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
230 struct NetUnjoinDomain *r)
232 struct cli_state *cli = NULL;
233 struct rpc_pipe_client *pipe_cli = NULL;
234 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
235 NTSTATUS status;
236 WERROR werr;
237 unsigned int old_timeout = 0;
239 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
240 if (!W_ERROR_IS_OK(werr)) {
241 goto done;
244 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
245 if (!W_ERROR_IS_OK(werr)) {
246 goto done;
249 if (r->in.password) {
250 encode_wkssvc_join_password_buffer(ctx,
251 r->in.password,
252 &cli->user_session_key,
253 &encrypted_password);
256 old_timeout = cli_set_timeout(cli, 60000);
258 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
259 r->in.server_name,
260 r->in.account,
261 encrypted_password,
262 r->in.unjoin_flags,
263 &werr);
264 if (!NT_STATUS_IS_OK(status)) {
265 werr = ntstatus_to_werror(status);
266 goto done;
269 done:
270 if (cli) {
271 if (old_timeout) {
272 cli_set_timeout(cli, old_timeout);
276 return werr;
279 /****************************************************************
280 ****************************************************************/
282 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
283 struct NetGetJoinInformation *r)
285 struct cli_state *cli = NULL;
286 struct rpc_pipe_client *pipe_cli = NULL;
287 NTSTATUS status;
288 WERROR werr;
289 const char *buffer = NULL;
291 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
292 if (!W_ERROR_IS_OK(werr)) {
293 goto done;
296 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
297 if (!W_ERROR_IS_OK(werr)) {
298 goto done;
301 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
302 r->in.server_name,
303 &buffer,
304 (enum wkssvc_NetJoinStatus *)r->out.name_type,
305 &werr);
306 if (!NT_STATUS_IS_OK(status)) {
307 werr = ntstatus_to_werror(status);
308 goto done;
311 *r->out.name_buffer = talloc_strdup(ctx, buffer);
312 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
314 done:
315 return werr;
318 /****************************************************************
319 ****************************************************************/
321 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
322 struct NetGetJoinInformation *r)
324 if ((lp_security() == SEC_ADS) && lp_realm()) {
325 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
326 } else {
327 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
329 if (!*r->out.name_buffer) {
330 return WERR_NOMEM;
333 switch (lp_server_role()) {
334 case ROLE_DOMAIN_MEMBER:
335 case ROLE_DOMAIN_PDC:
336 case ROLE_DOMAIN_BDC:
337 *r->out.name_type = NetSetupDomainName;
338 break;
339 case ROLE_STANDALONE:
340 default:
341 *r->out.name_type = NetSetupWorkgroupName;
342 break;
345 return WERR_OK;
348 /****************************************************************
349 ****************************************************************/
351 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
352 struct NetGetJoinableOUs *r)
354 #ifdef WITH_ADS
355 NTSTATUS status;
356 ADS_STATUS ads_status;
357 ADS_STRUCT *ads = NULL;
358 struct netr_DsRGetDCNameInfo *info = NULL;
359 const char *dc = NULL;
360 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
361 DS_RETURN_DNS_NAME;
363 status = dsgetdcname(ctx, NULL, r->in.domain,
364 NULL, NULL, flags, &info);
365 if (!NT_STATUS_IS_OK(status)) {
366 libnetapi_set_error_string(ctx, "%s",
367 get_friendly_nt_error_msg(status));
368 return ntstatus_to_werror(status);
371 dc = strip_hostname(info->dc_unc);
373 ads = ads_init(r->in.domain, r->in.domain, dc);
374 if (!ads) {
375 return WERR_GENERAL_FAILURE;
378 SAFE_FREE(ads->auth.user_name);
379 if (r->in.account) {
380 ads->auth.user_name = SMB_STRDUP(r->in.account);
381 } else if (ctx->username) {
382 ads->auth.user_name = SMB_STRDUP(ctx->username);
385 SAFE_FREE(ads->auth.password);
386 if (r->in.password) {
387 ads->auth.password = SMB_STRDUP(r->in.password);
388 } else if (ctx->password) {
389 ads->auth.password = SMB_STRDUP(ctx->password);
392 ads_status = ads_connect(ads);
393 if (!ADS_ERR_OK(ads_status)) {
394 ads_destroy(&ads);
395 return WERR_DEFAULT_JOIN_REQUIRED;
398 ads_status = ads_get_joinable_ous(ads, ctx,
399 (char ***)r->out.ous,
400 (size_t *)r->out.ou_count);
401 if (!ADS_ERR_OK(ads_status)) {
402 ads_destroy(&ads);
403 return WERR_DEFAULT_JOIN_REQUIRED;
406 ads_destroy(&ads);
407 return WERR_OK;
408 #else
409 return WERR_NOT_SUPPORTED;
410 #endif
413 /****************************************************************
414 ****************************************************************/
416 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
417 struct NetGetJoinableOUs *r)
419 struct cli_state *cli = NULL;
420 struct rpc_pipe_client *pipe_cli = NULL;
421 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
422 NTSTATUS status;
423 WERROR werr;
425 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
426 if (!W_ERROR_IS_OK(werr)) {
427 goto done;
430 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
431 if (!W_ERROR_IS_OK(werr)) {
432 goto done;
435 if (r->in.password) {
436 encode_wkssvc_join_password_buffer(ctx,
437 r->in.password,
438 &cli->user_session_key,
439 &encrypted_password);
442 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
443 r->in.server_name,
444 r->in.domain,
445 r->in.account,
446 encrypted_password,
447 r->out.ou_count,
448 r->out.ous,
449 &werr);
450 if (!NT_STATUS_IS_OK(status)) {
451 werr = ntstatus_to_werror(status);
452 goto done;
455 done:
456 if (cli) {
457 cli_shutdown(cli);
460 return werr;