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"
32 /****************************************************************
33 ****************************************************************/
35 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
36 struct NetJoinDomain *r)
38 struct libnet_JoinCtx *j = NULL;
42 return WERR_INVALID_PARAM;
45 werr = libnet_init_JoinCtx(mem_ctx, &j);
46 W_ERROR_NOT_OK_RETURN(werr);
48 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
49 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
51 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
53 struct netr_DsRGetDCNameInfo *info = NULL;
54 const char *dc = NULL;
55 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
56 DS_WRITABLE_REQUIRED |
58 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
59 NULL, NULL, flags, &info);
60 if (!NT_STATUS_IS_OK(status)) {
61 libnetapi_set_error_string(mem_ctx,
62 "%s", get_friendly_nt_error_msg(status));
63 return ntstatus_to_werror(status);
66 dc = strip_hostname(info->dc_unc);
67 j->in.dc_name = talloc_strdup(mem_ctx, dc);
68 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
71 if (r->in.account_ou) {
72 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
73 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
77 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
78 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
82 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
83 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
86 j->in.join_flags = r->in.join_flags;
87 j->in.modify_config = true;
90 werr = libnet_Join(mem_ctx, j);
91 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
92 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
99 /****************************************************************
100 ****************************************************************/
102 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
103 struct NetJoinDomain *r)
105 struct rpc_pipe_client *pipe_cli = NULL;
106 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
109 unsigned int old_timeout = 0;
111 werr = libnetapi_open_pipe(ctx, r->in.server,
112 &ndr_table_wkssvc.syntax_id,
114 if (!W_ERROR_IS_OK(werr)) {
118 if (r->in.password) {
119 encode_wkssvc_join_password_buffer(ctx,
121 &pipe_cli->auth->user_session_key,
122 &encrypted_password);
125 old_timeout = rpccli_set_timeout(pipe_cli, 600000);
127 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
135 if (!NT_STATUS_IS_OK(status)) {
136 werr = ntstatus_to_werror(status);
141 if (pipe_cli && old_timeout) {
142 rpccli_set_timeout(pipe_cli, old_timeout);
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;
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);
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);
176 struct netr_DsRGetDCNameInfo *info = NULL;
177 const char *dc = NULL;
178 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
179 DS_WRITABLE_REQUIRED |
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",
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;
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.delete_machine_account = false;
211 u->in.modify_config = true;
214 u->in.domain_sid = &domain_sid;
216 werr = libnet_Unjoin(mem_ctx, u);
217 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
218 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
225 /****************************************************************
226 ****************************************************************/
228 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
229 struct NetUnjoinDomain *r)
231 struct rpc_pipe_client *pipe_cli = NULL;
232 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
235 unsigned int old_timeout = 0;
237 werr = libnetapi_open_pipe(ctx, r->in.server_name,
238 &ndr_table_wkssvc.syntax_id,
240 if (!W_ERROR_IS_OK(werr)) {
244 if (r->in.password) {
245 encode_wkssvc_join_password_buffer(ctx,
247 &pipe_cli->auth->user_session_key,
248 &encrypted_password);
251 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
253 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
259 if (!NT_STATUS_IS_OK(status)) {
260 werr = ntstatus_to_werror(status);
265 if (pipe_cli && old_timeout) {
266 rpccli_set_timeout(pipe_cli, old_timeout);
272 /****************************************************************
273 ****************************************************************/
275 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
276 struct NetGetJoinInformation *r)
278 struct rpc_pipe_client *pipe_cli = NULL;
281 const char *buffer = NULL;
283 werr = libnetapi_open_pipe(ctx, r->in.server_name,
284 &ndr_table_wkssvc.syntax_id,
286 if (!W_ERROR_IS_OK(werr)) {
290 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
293 (enum wkssvc_NetJoinStatus *)r->out.name_type,
295 if (!NT_STATUS_IS_OK(status)) {
296 werr = ntstatus_to_werror(status);
300 *r->out.name_buffer = talloc_strdup(ctx, buffer);
301 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
307 /****************************************************************
308 ****************************************************************/
310 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
311 struct NetGetJoinInformation *r)
313 if ((lp_security() == SEC_ADS) && lp_realm()) {
314 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
316 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
318 if (!*r->out.name_buffer) {
322 switch (lp_server_role()) {
323 case ROLE_DOMAIN_MEMBER:
324 case ROLE_DOMAIN_PDC:
325 case ROLE_DOMAIN_BDC:
326 *r->out.name_type = NetSetupDomainName;
328 case ROLE_STANDALONE:
330 *r->out.name_type = NetSetupWorkgroupName;
337 /****************************************************************
338 ****************************************************************/
340 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
341 struct NetGetJoinableOUs *r)
345 ADS_STATUS ads_status;
346 ADS_STRUCT *ads = NULL;
347 struct netr_DsRGetDCNameInfo *info = NULL;
348 const char *dc = NULL;
349 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
352 status = dsgetdcname(ctx, NULL, r->in.domain,
353 NULL, NULL, flags, &info);
354 if (!NT_STATUS_IS_OK(status)) {
355 libnetapi_set_error_string(ctx, "%s",
356 get_friendly_nt_error_msg(status));
357 return ntstatus_to_werror(status);
360 dc = strip_hostname(info->dc_unc);
362 ads = ads_init(info->domain_name, info->domain_name, dc);
364 return WERR_GENERAL_FAILURE;
367 SAFE_FREE(ads->auth.user_name);
369 ads->auth.user_name = SMB_STRDUP(r->in.account);
370 } else if (ctx->username) {
371 ads->auth.user_name = SMB_STRDUP(ctx->username);
374 SAFE_FREE(ads->auth.password);
375 if (r->in.password) {
376 ads->auth.password = SMB_STRDUP(r->in.password);
377 } else if (ctx->password) {
378 ads->auth.password = SMB_STRDUP(ctx->password);
381 ads_status = ads_connect_user_creds(ads);
382 if (!ADS_ERR_OK(ads_status)) {
384 return WERR_DEFAULT_JOIN_REQUIRED;
387 ads_status = ads_get_joinable_ous(ads, ctx,
388 (char ***)r->out.ous,
389 (size_t *)r->out.ou_count);
390 if (!ADS_ERR_OK(ads_status)) {
392 return WERR_DEFAULT_JOIN_REQUIRED;
398 return WERR_NOT_SUPPORTED;
402 /****************************************************************
403 ****************************************************************/
405 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
406 struct NetGetJoinableOUs *r)
408 struct rpc_pipe_client *pipe_cli = NULL;
409 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
413 werr = libnetapi_open_pipe(ctx, r->in.server_name,
414 &ndr_table_wkssvc.syntax_id,
416 if (!W_ERROR_IS_OK(werr)) {
420 if (r->in.password) {
421 encode_wkssvc_join_password_buffer(ctx,
423 &pipe_cli->auth->user_session_key,
424 &encrypted_password);
427 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
435 if (!NT_STATUS_IS_OK(status)) {
436 werr = ntstatus_to_werror(status);
444 /****************************************************************
445 ****************************************************************/
447 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
448 struct NetRenameMachineInDomain *r)
450 struct rpc_pipe_client *pipe_cli = NULL;
451 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
455 werr = libnetapi_open_pipe(ctx, r->in.server_name,
456 &ndr_table_wkssvc.syntax_id,
458 if (!W_ERROR_IS_OK(werr)) {
462 if (r->in.password) {
463 encode_wkssvc_join_password_buffer(ctx,
465 &pipe_cli->auth->user_session_key,
466 &encrypted_password);
469 status = rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli, ctx,
471 r->in.new_machine_name,
474 r->in.rename_options,
476 if (!NT_STATUS_IS_OK(status)) {
477 werr = ntstatus_to_werror(status);
485 /****************************************************************
486 ****************************************************************/
488 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
489 struct NetRenameMachineInDomain *r)
491 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);