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 "lib/netapi/netapi.h"
23 #include "libnet/libnet.h"
25 static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx,
26 const char *server_name,
27 const char *domain_name,
28 const char *account_ou,
33 struct libnet_JoinCtx *r = NULL;
37 return WERR_INVALID_PARAM;
40 werr = libnet_init_JoinCtx(mem_ctx, &r);
41 W_ERROR_NOT_OK_RETURN(werr);
43 r->in.domain_name = talloc_strdup(mem_ctx, domain_name);
44 W_ERROR_HAVE_NO_MEMORY(r->in.domain_name);
46 if (join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
48 struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
49 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
50 DS_WRITABLE_REQUIRED |
52 status = DsGetDcName(mem_ctx, NULL, domain_name,
53 NULL, NULL, flags, &info);
54 if (!NT_STATUS_IS_OK(status)) {
55 return ntstatus_to_werror(status);
57 r->in.dc_name = talloc_strdup(mem_ctx,
58 info->domain_controller_name);
59 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
63 r->in.account_ou = talloc_strdup(mem_ctx, account_ou);
64 W_ERROR_HAVE_NO_MEMORY(r->in.account_ou);
68 r->in.admin_account = talloc_strdup(mem_ctx, Account);
69 W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
73 r->in.admin_password = talloc_strdup(mem_ctx, password);
74 W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
77 r->in.join_flags = join_flags;
78 r->in.modify_config = true;
80 werr = libnet_Join(mem_ctx, r);
81 if (!W_ERROR_IS_OK(werr) && r->out.error_string) {
82 libnetapi_set_error_string(mem_ctx, r->out.error_string);
89 static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx,
90 const char *server_name,
91 const char *domain_name,
92 const char *account_ou,
97 struct cli_state *cli = NULL;
98 struct rpc_pipe_client *pipe_cli = NULL;
99 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
102 unsigned int old_timeout = 0;
104 status = cli_full_connection(&cli, NULL, server_name,
112 if (!NT_STATUS_IS_OK(status)) {
113 werr = ntstatus_to_werror(status);
117 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
120 werr = ntstatus_to_werror(status);
125 encode_wkssvc_join_password_buffer(ctx,
127 &cli->user_session_key,
128 &encrypted_password);
131 old_timeout = cli_set_timeout(cli, 60000);
133 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
134 server_name, domain_name,
138 if (!NT_STATUS_IS_OK(status)) {
139 werr = ntstatus_to_werror(status);
145 cli_set_timeout(cli, old_timeout);
152 static WERROR libnetapi_NetJoinDomain(struct libnetapi_ctx *ctx,
153 const char *server_name,
154 const char *domain_name,
155 const char *account_ou,
157 const char *password,
161 return WERR_INVALID_PARAM;
164 if (!server_name || is_myname_or_ipaddr(server_name)) {
166 return NetJoinDomainLocal(ctx,
175 return NetJoinDomainRemote(ctx,
184 NET_API_STATUS NetJoinDomain(const char *server_name,
185 const char *domain_name,
186 const char *account_ou,
188 const char *password,
191 struct libnetapi_ctx *ctx = NULL;
192 NET_API_STATUS status;
195 status = libnetapi_getctx(&ctx);
200 werr = libnetapi_NetJoinDomain(ctx,
207 if (!W_ERROR_IS_OK(werr)) {
208 return W_ERROR_V(werr);
214 static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
215 const char *server_name,
217 const char *password,
218 uint32_t unjoin_flags)
220 struct libnet_UnjoinCtx *r = NULL;
221 struct dom_sid domain_sid;
224 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
225 return WERR_SETUP_NOT_JOINED;
228 werr = libnet_init_UnjoinCtx(mem_ctx, &r);
229 W_ERROR_NOT_OK_RETURN(werr);
232 r->in.dc_name = talloc_strdup(mem_ctx, server_name);
233 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
237 const char *domain = NULL;
238 struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
239 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
240 DS_WRITABLE_REQUIRED |
245 domain = lp_workgroup();
247 status = DsGetDcName(mem_ctx, NULL, domain,
248 NULL, NULL, flags, &info);
249 if (!NT_STATUS_IS_OK(status)) {
250 return ntstatus_to_werror(status);
252 r->in.dc_name = talloc_strdup(mem_ctx,
253 info->domain_controller_name);
254 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
258 r->in.admin_account = talloc_strdup(mem_ctx, account);
259 W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
263 r->in.admin_password = talloc_strdup(mem_ctx, password);
264 W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
267 r->in.unjoin_flags = unjoin_flags;
268 r->in.modify_config = true;
270 r->in.domain_sid = &domain_sid;
272 return libnet_Unjoin(mem_ctx, r);
276 static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx,
277 const char *server_name,
279 const char *password,
280 uint32_t unjoin_flags)
282 struct cli_state *cli = NULL;
283 struct rpc_pipe_client *pipe_cli = NULL;
284 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
287 unsigned int old_timeout = 0;
289 status = cli_full_connection(&cli, NULL, server_name,
297 if (!NT_STATUS_IS_OK(status)) {
298 werr = ntstatus_to_werror(status);
302 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
305 werr = ntstatus_to_werror(status);
310 encode_wkssvc_join_password_buffer(ctx,
312 &cli->user_session_key,
313 &encrypted_password);
316 old_timeout = cli_set_timeout(cli, 60000);
318 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
324 if (!NT_STATUS_IS_OK(status)) {
325 werr = ntstatus_to_werror(status);
331 cli_set_timeout(cli, old_timeout);
338 static WERROR libnetapi_NetUnjoinDomain(struct libnetapi_ctx *ctx,
339 const char *server_name,
341 const char *password,
342 uint32_t unjoin_flags)
344 if (!server_name || is_myname_or_ipaddr(server_name)) {
346 return NetUnjoinDomainLocal(ctx,
353 return NetUnjoinDomainRemote(ctx,
360 NET_API_STATUS NetUnjoinDomain(const char *server_name,
362 const char *password,
363 uint32_t unjoin_flags)
365 struct libnetapi_ctx *ctx = NULL;
366 NET_API_STATUS status;
369 status = libnetapi_getctx(&ctx);
374 werr = libnetapi_NetUnjoinDomain(ctx,
379 if (!W_ERROR_IS_OK(werr)) {
380 return W_ERROR_V(werr);
386 static WERROR NetGetJoinInformationRemote(struct libnetapi_ctx *ctx,
387 const char *server_name,
388 const char **name_buffer,
391 struct cli_state *cli = NULL;
392 struct rpc_pipe_client *pipe_cli = NULL;
396 status = cli_full_connection(&cli, NULL, server_name,
404 if (!NT_STATUS_IS_OK(status)) {
405 werr = ntstatus_to_werror(status);
409 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
412 werr = ntstatus_to_werror(status);
416 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
419 (enum wkssvc_NetJoinStatus *)name_type,
421 if (!NT_STATUS_IS_OK(status)) {
422 werr = ntstatus_to_werror(status);
434 static WERROR NetGetJoinInformationLocal(struct libnetapi_ctx *ctx,
435 const char *server_name,
436 const char **name_buffer,
439 if ((lp_security() == SEC_ADS) && lp_realm()) {
440 *name_buffer = talloc_strdup(ctx, lp_realm());
442 *name_buffer = talloc_strdup(ctx, lp_workgroup());
448 switch (lp_server_role()) {
449 case ROLE_DOMAIN_MEMBER:
450 case ROLE_DOMAIN_PDC:
451 case ROLE_DOMAIN_BDC:
452 *name_type = NetSetupDomainName;
454 case ROLE_STANDALONE:
456 *name_type = NetSetupWorkgroupName;
463 static WERROR libnetapi_NetGetJoinInformation(struct libnetapi_ctx *ctx,
464 const char *server_name,
465 const char **name_buffer,
468 if (!server_name || is_myname_or_ipaddr(server_name)) {
469 return NetGetJoinInformationLocal(ctx,
475 return NetGetJoinInformationRemote(ctx,
481 NET_API_STATUS NetGetJoinInformation(const char *server_name,
482 const char **name_buffer,
485 struct libnetapi_ctx *ctx = NULL;
486 NET_API_STATUS status;
489 status = libnetapi_getctx(&ctx);
494 werr = libnetapi_NetGetJoinInformation(ctx,
498 if (!W_ERROR_IS_OK(werr)) {
499 return W_ERROR_V(werr);