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 /****************************************************************
26 ****************************************************************/
28 static WERROR NetJoinDomainLocal(struct libnetapi_ctx *mem_ctx,
29 const char *server_name,
30 const char *domain_name,
31 const char *account_ou,
36 struct libnet_JoinCtx *r = NULL;
40 return WERR_INVALID_PARAM;
43 werr = libnet_init_JoinCtx(mem_ctx, &r);
44 W_ERROR_NOT_OK_RETURN(werr);
46 r->in.domain_name = talloc_strdup(mem_ctx, domain_name);
47 W_ERROR_HAVE_NO_MEMORY(r->in.domain_name);
49 if (join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
51 struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
52 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
53 DS_WRITABLE_REQUIRED |
55 status = dsgetdcname(mem_ctx, domain_name,
56 NULL, NULL, flags, &info);
57 if (!NT_STATUS_IS_OK(status)) {
58 libnetapi_set_error_string(mem_ctx,
59 "%s", get_friendly_nt_error_msg(status));
60 return ntstatus_to_werror(status);
62 r->in.dc_name = talloc_strdup(mem_ctx,
63 info->domain_controller_name);
64 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
68 r->in.account_ou = talloc_strdup(mem_ctx, account_ou);
69 W_ERROR_HAVE_NO_MEMORY(r->in.account_ou);
73 r->in.admin_account = talloc_strdup(mem_ctx, Account);
74 W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
78 r->in.admin_password = talloc_strdup(mem_ctx, password);
79 W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
82 r->in.join_flags = join_flags;
83 r->in.modify_config = true;
85 werr = libnet_Join(mem_ctx, r);
86 if (!W_ERROR_IS_OK(werr) && r->out.error_string) {
87 libnetapi_set_error_string(mem_ctx, "%s", r->out.error_string);
94 /****************************************************************
95 ****************************************************************/
97 static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx,
98 const char *server_name,
99 const char *domain_name,
100 const char *account_ou,
102 const char *password,
105 struct cli_state *cli = NULL;
106 struct rpc_pipe_client *pipe_cli = NULL;
107 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
110 unsigned int old_timeout = 0;
112 status = cli_full_connection(&cli, NULL, server_name,
120 if (!NT_STATUS_IS_OK(status)) {
121 werr = ntstatus_to_werror(status);
125 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
128 werr = ntstatus_to_werror(status);
133 encode_wkssvc_join_password_buffer(ctx,
135 &cli->user_session_key,
136 &encrypted_password);
139 old_timeout = cli_set_timeout(cli, 60000);
141 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
142 server_name, domain_name,
146 if (!NT_STATUS_IS_OK(status)) {
147 werr = ntstatus_to_werror(status);
153 cli_set_timeout(cli, old_timeout);
160 /****************************************************************
161 ****************************************************************/
163 static WERROR libnetapi_NetJoinDomain(struct libnetapi_ctx *ctx,
164 const char *server_name,
165 const char *domain_name,
166 const char *account_ou,
168 const char *password,
172 return WERR_INVALID_PARAM;
175 if (!server_name || is_myname_or_ipaddr(server_name)) {
177 return NetJoinDomainLocal(ctx,
186 return NetJoinDomainRemote(ctx,
195 /****************************************************************
197 ****************************************************************/
199 NET_API_STATUS NetJoinDomain(const char *server_name,
200 const char *domain_name,
201 const char *account_ou,
203 const char *password,
206 struct libnetapi_ctx *ctx = NULL;
207 NET_API_STATUS status;
210 status = libnetapi_getctx(&ctx);
215 werr = libnetapi_NetJoinDomain(ctx,
222 if (!W_ERROR_IS_OK(werr)) {
223 return W_ERROR_V(werr);
226 return NET_API_STATUS_SUCCESS;
229 /****************************************************************
230 ****************************************************************/
232 static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
233 const char *server_name,
235 const char *password,
236 uint32_t unjoin_flags)
238 struct libnet_UnjoinCtx *r = NULL;
239 struct dom_sid domain_sid;
242 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
243 return WERR_SETUP_NOT_JOINED;
246 werr = libnet_init_UnjoinCtx(mem_ctx, &r);
247 W_ERROR_NOT_OK_RETURN(werr);
250 r->in.dc_name = talloc_strdup(mem_ctx, server_name);
251 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
254 const char *domain = NULL;
255 struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
256 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
257 DS_WRITABLE_REQUIRED |
262 domain = lp_workgroup();
264 status = dsgetdcname(mem_ctx, domain,
265 NULL, NULL, flags, &info);
266 if (!NT_STATUS_IS_OK(status)) {
267 libnetapi_set_error_string(mem_ctx,
268 "%s", get_friendly_nt_error_msg(status));
269 return ntstatus_to_werror(status);
271 r->in.dc_name = talloc_strdup(mem_ctx,
272 info->domain_controller_name);
273 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
277 r->in.admin_account = talloc_strdup(mem_ctx, account);
278 W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
282 r->in.admin_password = talloc_strdup(mem_ctx, password);
283 W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
286 r->in.unjoin_flags = unjoin_flags;
287 r->in.modify_config = true;
290 r->in.domain_sid = &domain_sid;
292 werr = libnet_Unjoin(mem_ctx, r);
293 if (!W_ERROR_IS_OK(werr) && r->out.error_string) {
294 libnetapi_set_error_string(mem_ctx, "%s", r->out.error_string);
301 /****************************************************************
302 ****************************************************************/
304 static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx,
305 const char *server_name,
307 const char *password,
308 uint32_t unjoin_flags)
310 struct cli_state *cli = NULL;
311 struct rpc_pipe_client *pipe_cli = NULL;
312 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
315 unsigned int old_timeout = 0;
317 status = cli_full_connection(&cli, NULL, server_name,
325 if (!NT_STATUS_IS_OK(status)) {
326 werr = ntstatus_to_werror(status);
330 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
333 werr = ntstatus_to_werror(status);
338 encode_wkssvc_join_password_buffer(ctx,
340 &cli->user_session_key,
341 &encrypted_password);
344 old_timeout = cli_set_timeout(cli, 60000);
346 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
352 if (!NT_STATUS_IS_OK(status)) {
353 werr = ntstatus_to_werror(status);
359 cli_set_timeout(cli, old_timeout);
366 /****************************************************************
367 ****************************************************************/
369 static WERROR libnetapi_NetUnjoinDomain(struct libnetapi_ctx *ctx,
370 const char *server_name,
372 const char *password,
373 uint32_t unjoin_flags)
375 if (!server_name || is_myname_or_ipaddr(server_name)) {
377 return NetUnjoinDomainLocal(ctx,
384 return NetUnjoinDomainRemote(ctx,
391 /****************************************************************
393 ****************************************************************/
395 NET_API_STATUS NetUnjoinDomain(const char *server_name,
397 const char *password,
398 uint32_t unjoin_flags)
400 struct libnetapi_ctx *ctx = NULL;
401 NET_API_STATUS status;
404 status = libnetapi_getctx(&ctx);
409 werr = libnetapi_NetUnjoinDomain(ctx,
414 if (!W_ERROR_IS_OK(werr)) {
415 return W_ERROR_V(werr);
418 return NET_API_STATUS_SUCCESS;
421 /****************************************************************
422 ****************************************************************/
424 static WERROR NetGetJoinInformationRemote(struct libnetapi_ctx *ctx,
425 const char *server_name,
426 const char **name_buffer,
429 struct cli_state *cli = NULL;
430 struct rpc_pipe_client *pipe_cli = NULL;
434 status = cli_full_connection(&cli, NULL, server_name,
442 if (!NT_STATUS_IS_OK(status)) {
443 werr = ntstatus_to_werror(status);
447 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
450 werr = ntstatus_to_werror(status);
454 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
457 (enum wkssvc_NetJoinStatus *)name_type,
459 if (!NT_STATUS_IS_OK(status)) {
460 werr = ntstatus_to_werror(status);
472 /****************************************************************
473 ****************************************************************/
475 static WERROR NetGetJoinInformationLocal(struct libnetapi_ctx *ctx,
476 const char *server_name,
477 const char **name_buffer,
480 if ((lp_security() == SEC_ADS) && lp_realm()) {
481 *name_buffer = talloc_strdup(ctx, lp_realm());
483 *name_buffer = talloc_strdup(ctx, lp_workgroup());
489 switch (lp_server_role()) {
490 case ROLE_DOMAIN_MEMBER:
491 case ROLE_DOMAIN_PDC:
492 case ROLE_DOMAIN_BDC:
493 *name_type = NetSetupDomainName;
495 case ROLE_STANDALONE:
497 *name_type = NetSetupWorkgroupName;
504 static WERROR libnetapi_NetGetJoinInformation(struct libnetapi_ctx *ctx,
505 const char *server_name,
506 const char **name_buffer,
509 if (!server_name || is_myname_or_ipaddr(server_name)) {
510 return NetGetJoinInformationLocal(ctx,
516 return NetGetJoinInformationRemote(ctx,
522 /****************************************************************
523 NetGetJoinInformation
524 ****************************************************************/
526 NET_API_STATUS NetGetJoinInformation(const char *server_name,
527 const char **name_buffer,
530 struct libnetapi_ctx *ctx = NULL;
531 NET_API_STATUS status;
534 status = libnetapi_getctx(&ctx);
539 werr = libnetapi_NetGetJoinInformation(ctx,
543 if (!W_ERROR_IS_OK(werr)) {
544 return W_ERROR_V(werr);
547 return NET_API_STATUS_SUCCESS;
550 /****************************************************************
551 ****************************************************************/
553 static WERROR NetGetJoinableOUsLocal(struct libnetapi_ctx *ctx,
554 const char *server_name,
557 const char *password,
563 ADS_STATUS ads_status;
564 ADS_STRUCT *ads = NULL;
565 struct DS_DOMAIN_CONTROLLER_INFO *info = NULL;
566 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
569 status = dsgetdcname(ctx, domain,
570 NULL, NULL, flags, &info);
571 if (!NT_STATUS_IS_OK(status)) {
572 libnetapi_set_error_string(ctx, "%s",
573 get_friendly_nt_error_msg(status));
574 return ntstatus_to_werror(status);
577 ads = ads_init(domain, domain, info->domain_controller_name);
579 return WERR_GENERAL_FAILURE;
582 SAFE_FREE(ads->auth.user_name);
584 ads->auth.user_name = SMB_STRDUP(account);
585 } else if (ctx->username) {
586 ads->auth.user_name = SMB_STRDUP(ctx->username);
589 SAFE_FREE(ads->auth.password);
591 ads->auth.password = SMB_STRDUP(password);
592 } else if (ctx->password) {
593 ads->auth.password = SMB_STRDUP(ctx->password);
596 ads_status = ads_connect(ads);
597 if (!ADS_ERR_OK(ads_status)) {
599 return WERR_DEFAULT_JOIN_REQUIRED;
602 ads_status = ads_get_joinable_ous(ads, ctx,
605 if (!ADS_ERR_OK(ads_status)) {
607 return WERR_DEFAULT_JOIN_REQUIRED;
613 return WERR_NOT_SUPPORTED;
617 /****************************************************************
618 ****************************************************************/
620 static WERROR NetGetJoinableOUsRemote(struct libnetapi_ctx *ctx,
621 const char *server_name,
624 const char *password,
628 struct cli_state *cli = NULL;
629 struct rpc_pipe_client *pipe_cli = NULL;
630 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
634 status = cli_full_connection(&cli, NULL, server_name,
642 if (!NT_STATUS_IS_OK(status)) {
643 werr = ntstatus_to_werror(status);
647 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
650 werr = ntstatus_to_werror(status);
655 encode_wkssvc_join_password_buffer(ctx,
657 &cli->user_session_key,
658 &encrypted_password);
661 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
669 if (!NT_STATUS_IS_OK(status)) {
670 werr = ntstatus_to_werror(status);
682 /****************************************************************
683 ****************************************************************/
685 static WERROR libnetapi_NetGetJoinableOUs(struct libnetapi_ctx *ctx,
686 const char *server_name,
689 const char *password,
693 if (!server_name || is_myname_or_ipaddr(server_name)) {
694 return NetGetJoinableOUsLocal(ctx,
703 return NetGetJoinableOUsRemote(ctx,
712 /****************************************************************
714 ****************************************************************/
716 NET_API_STATUS NetGetJoinableOUs(const char *server_name,
719 const char *password,
723 struct libnetapi_ctx *ctx = NULL;
724 NET_API_STATUS status;
727 status = libnetapi_getctx(&ctx);
732 werr = libnetapi_NetGetJoinableOUs(ctx,
739 if (!W_ERROR_IS_OK(werr)) {
740 return W_ERROR_V(werr);
743 return NET_API_STATUS_SUCCESS;