2 * Unix SMB/CIFS implementation.
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/>.
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;
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) {
49 struct netr_DsRGetDCNameInfo *info = NULL;
50 const char *dc = NULL;
51 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
52 DS_WRITABLE_REQUIRED |
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);
73 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
74 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
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;
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);
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;
106 unsigned int old_timeout = 0;
108 werr = libnetapi_open_ipc_connection(ctx, r->in.server, &cli);
109 if (!W_ERROR_IS_OK(werr)) {
113 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
114 if (!W_ERROR_IS_OK(werr)) {
118 if (r->in.password) {
119 encode_wkssvc_join_password_buffer(ctx,
121 &cli->user_session_key,
122 &encrypted_password);
125 old_timeout = cli_set_timeout(cli, 600000);
127 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
135 if (!NT_STATUS_IS_OK(status)) {
136 werr = ntstatus_to_werror(status);
143 cli_set_timeout(cli, old_timeout);
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;
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);
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);
178 struct netr_DsRGetDCNameInfo *info = NULL;
179 const char *dc = NULL;
180 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
181 DS_WRITABLE_REQUIRED |
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",
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;
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;
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);
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;
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)) {
244 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
245 if (!W_ERROR_IS_OK(werr)) {
249 if (r->in.password) {
250 encode_wkssvc_join_password_buffer(ctx,
252 &cli->user_session_key,
253 &encrypted_password);
256 old_timeout = cli_set_timeout(cli, 60000);
258 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
264 if (!NT_STATUS_IS_OK(status)) {
265 werr = ntstatus_to_werror(status);
272 cli_set_timeout(cli, old_timeout);
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;
289 const char *buffer = NULL;
291 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
292 if (!W_ERROR_IS_OK(werr)) {
296 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
297 if (!W_ERROR_IS_OK(werr)) {
301 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
304 (enum wkssvc_NetJoinStatus *)r->out.name_type,
306 if (!NT_STATUS_IS_OK(status)) {
307 werr = ntstatus_to_werror(status);
311 *r->out.name_buffer = talloc_strdup(ctx, buffer);
312 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
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());
327 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
329 if (!*r->out.name_buffer) {
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;
339 case ROLE_STANDALONE:
341 *r->out.name_type = NetSetupWorkgroupName;
348 /****************************************************************
349 ****************************************************************/
351 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
352 struct NetGetJoinableOUs *r)
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 |
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);
375 return WERR_GENERAL_FAILURE;
378 SAFE_FREE(ads->auth.user_name);
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)) {
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)) {
403 return WERR_DEFAULT_JOIN_REQUIRED;
409 return WERR_NOT_SUPPORTED;
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;
425 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
426 if (!W_ERROR_IS_OK(werr)) {
430 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
431 if (!W_ERROR_IS_OK(werr)) {
435 if (r->in.password) {
436 encode_wkssvc_join_password_buffer(ctx,
438 &cli->user_session_key,
439 &encrypted_password);
442 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
450 if (!NT_STATUS_IS_OK(status)) {
451 werr = ntstatus_to_werror(status);