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 "librpc/gen_ndr/libnet_join.h"
27 #include "libnet/libnet_join.h"
28 #include "libcli/auth/libcli_auth.h"
29 #include "../librpc/gen_ndr/cli_wkssvc.h"
31 /****************************************************************
32 ****************************************************************/
34 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
35 struct NetJoinDomain *r)
37 struct libnet_JoinCtx *j = NULL;
41 return WERR_INVALID_PARAM;
44 werr = libnet_init_JoinCtx(mem_ctx, &j);
45 W_ERROR_NOT_OK_RETURN(werr);
47 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
48 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
50 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
52 struct netr_DsRGetDCNameInfo *info = NULL;
53 const char *dc = NULL;
54 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
55 DS_WRITABLE_REQUIRED |
57 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
58 NULL, NULL, flags, &info);
59 if (!NT_STATUS_IS_OK(status)) {
60 libnetapi_set_error_string(mem_ctx,
61 "%s", get_friendly_nt_error_msg(status));
62 return ntstatus_to_werror(status);
65 dc = strip_hostname(info->dc_unc);
66 j->in.dc_name = talloc_strdup(mem_ctx, dc);
67 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
70 if (r->in.account_ou) {
71 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
72 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
76 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
77 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
81 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
82 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
85 j->in.join_flags = r->in.join_flags;
86 j->in.modify_config = true;
89 werr = libnet_Join(mem_ctx, j);
90 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
91 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
98 /****************************************************************
99 ****************************************************************/
101 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
102 struct NetJoinDomain *r)
104 struct rpc_pipe_client *pipe_cli = NULL;
105 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
108 unsigned int old_timeout = 0;
110 werr = libnetapi_open_pipe(ctx, r->in.server,
111 &ndr_table_wkssvc.syntax_id,
113 if (!W_ERROR_IS_OK(werr)) {
117 if (r->in.password) {
118 encode_wkssvc_join_password_buffer(ctx,
120 &pipe_cli->auth->user_session_key,
121 &encrypted_password);
124 old_timeout = rpccli_set_timeout(pipe_cli, 600000);
126 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
134 if (!NT_STATUS_IS_OK(status)) {
135 werr = ntstatus_to_werror(status);
140 if (pipe_cli && old_timeout) {
141 rpccli_set_timeout(pipe_cli, old_timeout);
146 /****************************************************************
147 ****************************************************************/
149 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
150 struct NetUnjoinDomain *r)
152 struct libnet_UnjoinCtx *u = NULL;
153 struct dom_sid domain_sid;
154 const char *domain = NULL;
157 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
158 return WERR_SETUP_NOT_JOINED;
161 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
162 W_ERROR_NOT_OK_RETURN(werr);
167 domain = lp_workgroup();
170 if (r->in.server_name) {
171 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
172 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
175 struct netr_DsRGetDCNameInfo *info = NULL;
176 const char *dc = NULL;
177 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
178 DS_WRITABLE_REQUIRED |
180 status = dsgetdcname(mem_ctx, NULL, domain,
181 NULL, NULL, flags, &info);
182 if (!NT_STATUS_IS_OK(status)) {
183 libnetapi_set_error_string(mem_ctx,
184 "failed to find DC for domain %s: %s",
186 get_friendly_nt_error_msg(status));
187 return ntstatus_to_werror(status);
190 dc = strip_hostname(info->dc_unc);
191 u->in.dc_name = talloc_strdup(mem_ctx, dc);
192 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
194 u->in.domain_name = domain;
198 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
199 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
202 if (r->in.password) {
203 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
204 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
207 u->in.domain_name = domain;
208 u->in.unjoin_flags = r->in.unjoin_flags;
209 u->in.delete_machine_account = false;
210 u->in.modify_config = 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);
224 /****************************************************************
225 ****************************************************************/
227 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
228 struct NetUnjoinDomain *r)
230 struct rpc_pipe_client *pipe_cli = NULL;
231 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
234 unsigned int old_timeout = 0;
236 werr = libnetapi_open_pipe(ctx, r->in.server_name,
237 &ndr_table_wkssvc.syntax_id,
239 if (!W_ERROR_IS_OK(werr)) {
243 if (r->in.password) {
244 encode_wkssvc_join_password_buffer(ctx,
246 &pipe_cli->auth->user_session_key,
247 &encrypted_password);
250 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
252 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
258 if (!NT_STATUS_IS_OK(status)) {
259 werr = ntstatus_to_werror(status);
264 if (pipe_cli && old_timeout) {
265 rpccli_set_timeout(pipe_cli, old_timeout);
271 /****************************************************************
272 ****************************************************************/
274 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
275 struct NetGetJoinInformation *r)
277 struct rpc_pipe_client *pipe_cli = NULL;
280 const char *buffer = NULL;
282 werr = libnetapi_open_pipe(ctx, r->in.server_name,
283 &ndr_table_wkssvc.syntax_id,
285 if (!W_ERROR_IS_OK(werr)) {
289 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
292 (enum wkssvc_NetJoinStatus *)r->out.name_type,
294 if (!NT_STATUS_IS_OK(status)) {
295 werr = ntstatus_to_werror(status);
299 *r->out.name_buffer = talloc_strdup(ctx, buffer);
300 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
306 /****************************************************************
307 ****************************************************************/
309 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
310 struct NetGetJoinInformation *r)
312 if ((lp_security() == SEC_ADS) && lp_realm()) {
313 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
315 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
317 if (!*r->out.name_buffer) {
321 switch (lp_server_role()) {
322 case ROLE_DOMAIN_MEMBER:
323 case ROLE_DOMAIN_PDC:
324 case ROLE_DOMAIN_BDC:
325 *r->out.name_type = NetSetupDomainName;
327 case ROLE_STANDALONE:
329 *r->out.name_type = NetSetupWorkgroupName;
336 /****************************************************************
337 ****************************************************************/
339 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
340 struct NetGetJoinableOUs *r)
344 ADS_STATUS ads_status;
345 ADS_STRUCT *ads = NULL;
346 struct netr_DsRGetDCNameInfo *info = NULL;
347 const char *dc = NULL;
348 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
351 status = dsgetdcname(ctx, NULL, r->in.domain,
352 NULL, NULL, flags, &info);
353 if (!NT_STATUS_IS_OK(status)) {
354 libnetapi_set_error_string(ctx, "%s",
355 get_friendly_nt_error_msg(status));
356 return ntstatus_to_werror(status);
359 dc = strip_hostname(info->dc_unc);
361 ads = ads_init(info->domain_name, info->domain_name, dc);
363 return WERR_GENERAL_FAILURE;
366 SAFE_FREE(ads->auth.user_name);
368 ads->auth.user_name = SMB_STRDUP(r->in.account);
369 } else if (ctx->username) {
370 ads->auth.user_name = SMB_STRDUP(ctx->username);
373 SAFE_FREE(ads->auth.password);
374 if (r->in.password) {
375 ads->auth.password = SMB_STRDUP(r->in.password);
376 } else if (ctx->password) {
377 ads->auth.password = SMB_STRDUP(ctx->password);
380 ads_status = ads_connect_user_creds(ads);
381 if (!ADS_ERR_OK(ads_status)) {
383 return WERR_DEFAULT_JOIN_REQUIRED;
386 ads_status = ads_get_joinable_ous(ads, ctx,
387 (char ***)r->out.ous,
388 (size_t *)r->out.ou_count);
389 if (!ADS_ERR_OK(ads_status)) {
391 return WERR_DEFAULT_JOIN_REQUIRED;
397 return WERR_NOT_SUPPORTED;
401 /****************************************************************
402 ****************************************************************/
404 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
405 struct NetGetJoinableOUs *r)
407 struct rpc_pipe_client *pipe_cli = NULL;
408 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
412 werr = libnetapi_open_pipe(ctx, r->in.server_name,
413 &ndr_table_wkssvc.syntax_id,
415 if (!W_ERROR_IS_OK(werr)) {
419 if (r->in.password) {
420 encode_wkssvc_join_password_buffer(ctx,
422 &pipe_cli->auth->user_session_key,
423 &encrypted_password);
426 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
434 if (!NT_STATUS_IS_OK(status)) {
435 werr = ntstatus_to_werror(status);
443 /****************************************************************
444 ****************************************************************/
446 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
447 struct NetRenameMachineInDomain *r)
449 struct rpc_pipe_client *pipe_cli = NULL;
450 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
454 werr = libnetapi_open_pipe(ctx, r->in.server_name,
455 &ndr_table_wkssvc.syntax_id,
457 if (!W_ERROR_IS_OK(werr)) {
461 if (r->in.password) {
462 encode_wkssvc_join_password_buffer(ctx,
464 &pipe_cli->auth->user_session_key,
465 &encrypted_password);
468 status = rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli, ctx,
470 r->in.new_machine_name,
473 r->in.rename_options,
475 if (!NT_STATUS_IS_OK(status)) {
476 werr = ntstatus_to_werror(status);
484 /****************************************************************
485 ****************************************************************/
487 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
488 struct NetRenameMachineInDomain *r)
490 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);