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 netr_DsRGetDCNameInfo *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,
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;
86 werr = libnet_Join(mem_ctx, r);
87 if (!W_ERROR_IS_OK(werr) && r->out.error_string) {
88 libnetapi_set_error_string(mem_ctx, "%s", r->out.error_string);
95 /****************************************************************
96 ****************************************************************/
98 static WERROR NetJoinDomainRemote(struct libnetapi_ctx *ctx,
99 const char *server_name,
100 const char *domain_name,
101 const char *account_ou,
103 const char *password,
106 struct cli_state *cli = NULL;
107 struct rpc_pipe_client *pipe_cli = NULL;
108 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
111 unsigned int old_timeout = 0;
113 status = cli_full_connection(&cli, NULL, server_name,
121 if (!NT_STATUS_IS_OK(status)) {
122 werr = ntstatus_to_werror(status);
126 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
129 werr = ntstatus_to_werror(status);
134 encode_wkssvc_join_password_buffer(ctx,
136 &cli->user_session_key,
137 &encrypted_password);
140 old_timeout = cli_set_timeout(cli, 60000);
142 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
143 server_name, domain_name,
147 if (!NT_STATUS_IS_OK(status)) {
148 werr = ntstatus_to_werror(status);
154 cli_set_timeout(cli, old_timeout);
161 /****************************************************************
162 ****************************************************************/
164 static WERROR libnetapi_NetJoinDomain(struct libnetapi_ctx *ctx,
165 const char *server_name,
166 const char *domain_name,
167 const char *account_ou,
169 const char *password,
173 return WERR_INVALID_PARAM;
176 if (!server_name || is_myname_or_ipaddr(server_name)) {
178 return NetJoinDomainLocal(ctx,
187 return NetJoinDomainRemote(ctx,
196 /****************************************************************
198 ****************************************************************/
200 NET_API_STATUS NetJoinDomain(const char *server_name,
201 const char *domain_name,
202 const char *account_ou,
204 const char *password,
207 struct libnetapi_ctx *ctx = NULL;
208 NET_API_STATUS status;
211 status = libnetapi_getctx(&ctx);
216 werr = libnetapi_NetJoinDomain(ctx,
223 if (!W_ERROR_IS_OK(werr)) {
224 return W_ERROR_V(werr);
227 return NET_API_STATUS_SUCCESS;
230 /****************************************************************
231 ****************************************************************/
233 static WERROR NetUnjoinDomainLocal(struct libnetapi_ctx *mem_ctx,
234 const char *server_name,
236 const char *password,
237 uint32_t unjoin_flags)
239 struct libnet_UnjoinCtx *r = NULL;
240 struct dom_sid domain_sid;
243 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
244 return WERR_SETUP_NOT_JOINED;
247 werr = libnet_init_UnjoinCtx(mem_ctx, &r);
248 W_ERROR_NOT_OK_RETURN(werr);
251 r->in.dc_name = talloc_strdup(mem_ctx, server_name);
252 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
255 const char *domain = NULL;
256 struct netr_DsRGetDCNameInfo *info = NULL;
257 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
258 DS_WRITABLE_REQUIRED |
263 domain = lp_workgroup();
265 status = dsgetdcname(mem_ctx, domain,
266 NULL, NULL, flags, &info);
267 if (!NT_STATUS_IS_OK(status)) {
268 libnetapi_set_error_string(mem_ctx,
269 "%s", get_friendly_nt_error_msg(status));
270 return ntstatus_to_werror(status);
272 r->in.dc_name = talloc_strdup(mem_ctx,
274 W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
278 r->in.admin_account = talloc_strdup(mem_ctx, account);
279 W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
283 r->in.admin_password = talloc_strdup(mem_ctx, password);
284 W_ERROR_HAVE_NO_MEMORY(r->in.admin_password);
287 r->in.unjoin_flags = unjoin_flags;
288 r->in.modify_config = true;
291 r->in.domain_sid = &domain_sid;
293 werr = libnet_Unjoin(mem_ctx, r);
294 if (!W_ERROR_IS_OK(werr) && r->out.error_string) {
295 libnetapi_set_error_string(mem_ctx, "%s", r->out.error_string);
302 /****************************************************************
303 ****************************************************************/
305 static WERROR NetUnjoinDomainRemote(struct libnetapi_ctx *ctx,
306 const char *server_name,
308 const char *password,
309 uint32_t unjoin_flags)
311 struct cli_state *cli = NULL;
312 struct rpc_pipe_client *pipe_cli = NULL;
313 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
316 unsigned int old_timeout = 0;
318 status = cli_full_connection(&cli, NULL, server_name,
326 if (!NT_STATUS_IS_OK(status)) {
327 werr = ntstatus_to_werror(status);
331 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
334 werr = ntstatus_to_werror(status);
339 encode_wkssvc_join_password_buffer(ctx,
341 &cli->user_session_key,
342 &encrypted_password);
345 old_timeout = cli_set_timeout(cli, 60000);
347 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
353 if (!NT_STATUS_IS_OK(status)) {
354 werr = ntstatus_to_werror(status);
360 cli_set_timeout(cli, old_timeout);
367 /****************************************************************
368 ****************************************************************/
370 static WERROR libnetapi_NetUnjoinDomain(struct libnetapi_ctx *ctx,
371 const char *server_name,
373 const char *password,
374 uint32_t unjoin_flags)
376 if (!server_name || is_myname_or_ipaddr(server_name)) {
378 return NetUnjoinDomainLocal(ctx,
385 return NetUnjoinDomainRemote(ctx,
392 /****************************************************************
394 ****************************************************************/
396 NET_API_STATUS NetUnjoinDomain(const char *server_name,
398 const char *password,
399 uint32_t unjoin_flags)
401 struct libnetapi_ctx *ctx = NULL;
402 NET_API_STATUS status;
405 status = libnetapi_getctx(&ctx);
410 werr = libnetapi_NetUnjoinDomain(ctx,
415 if (!W_ERROR_IS_OK(werr)) {
416 return W_ERROR_V(werr);
419 return NET_API_STATUS_SUCCESS;
422 /****************************************************************
423 ****************************************************************/
425 static WERROR NetGetJoinInformationRemote(struct libnetapi_ctx *ctx,
426 const char *server_name,
427 const char **name_buffer,
430 struct cli_state *cli = NULL;
431 struct rpc_pipe_client *pipe_cli = NULL;
435 status = cli_full_connection(&cli, NULL, server_name,
443 if (!NT_STATUS_IS_OK(status)) {
444 werr = ntstatus_to_werror(status);
448 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
451 werr = ntstatus_to_werror(status);
455 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
458 (enum wkssvc_NetJoinStatus *)name_type,
460 if (!NT_STATUS_IS_OK(status)) {
461 werr = ntstatus_to_werror(status);
473 /****************************************************************
474 ****************************************************************/
476 static WERROR NetGetJoinInformationLocal(struct libnetapi_ctx *ctx,
477 const char *server_name,
478 const char **name_buffer,
481 if ((lp_security() == SEC_ADS) && lp_realm()) {
482 *name_buffer = talloc_strdup(ctx, lp_realm());
484 *name_buffer = talloc_strdup(ctx, lp_workgroup());
490 switch (lp_server_role()) {
491 case ROLE_DOMAIN_MEMBER:
492 case ROLE_DOMAIN_PDC:
493 case ROLE_DOMAIN_BDC:
494 *name_type = NetSetupDomainName;
496 case ROLE_STANDALONE:
498 *name_type = NetSetupWorkgroupName;
505 static WERROR libnetapi_NetGetJoinInformation(struct libnetapi_ctx *ctx,
506 const char *server_name,
507 const char **name_buffer,
510 if (!server_name || is_myname_or_ipaddr(server_name)) {
511 return NetGetJoinInformationLocal(ctx,
517 return NetGetJoinInformationRemote(ctx,
523 /****************************************************************
524 NetGetJoinInformation
525 ****************************************************************/
527 NET_API_STATUS NetGetJoinInformation(const char *server_name,
528 const char **name_buffer,
531 struct libnetapi_ctx *ctx = NULL;
532 NET_API_STATUS status;
535 status = libnetapi_getctx(&ctx);
540 werr = libnetapi_NetGetJoinInformation(ctx,
544 if (!W_ERROR_IS_OK(werr)) {
545 return W_ERROR_V(werr);
548 return NET_API_STATUS_SUCCESS;
551 /****************************************************************
552 ****************************************************************/
554 static WERROR NetGetJoinableOUsLocal(struct libnetapi_ctx *ctx,
555 const char *server_name,
558 const char *password,
564 ADS_STATUS ads_status;
565 ADS_STRUCT *ads = NULL;
566 struct netr_DsRGetDCNameInfo *info = NULL;
567 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
570 status = dsgetdcname(ctx, domain,
571 NULL, NULL, flags, &info);
572 if (!NT_STATUS_IS_OK(status)) {
573 libnetapi_set_error_string(ctx, "%s",
574 get_friendly_nt_error_msg(status));
575 return ntstatus_to_werror(status);
578 ads = ads_init(domain, domain, info->dc_unc);
580 return WERR_GENERAL_FAILURE;
583 SAFE_FREE(ads->auth.user_name);
585 ads->auth.user_name = SMB_STRDUP(account);
586 } else if (ctx->username) {
587 ads->auth.user_name = SMB_STRDUP(ctx->username);
590 SAFE_FREE(ads->auth.password);
592 ads->auth.password = SMB_STRDUP(password);
593 } else if (ctx->password) {
594 ads->auth.password = SMB_STRDUP(ctx->password);
597 ads_status = ads_connect(ads);
598 if (!ADS_ERR_OK(ads_status)) {
600 return WERR_DEFAULT_JOIN_REQUIRED;
603 ads_status = ads_get_joinable_ous(ads, ctx,
606 if (!ADS_ERR_OK(ads_status)) {
608 return WERR_DEFAULT_JOIN_REQUIRED;
614 return WERR_NOT_SUPPORTED;
618 /****************************************************************
619 ****************************************************************/
621 static WERROR NetGetJoinableOUsRemote(struct libnetapi_ctx *ctx,
622 const char *server_name,
625 const char *password,
629 struct cli_state *cli = NULL;
630 struct rpc_pipe_client *pipe_cli = NULL;
631 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
635 status = cli_full_connection(&cli, NULL, server_name,
643 if (!NT_STATUS_IS_OK(status)) {
644 werr = ntstatus_to_werror(status);
648 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
651 werr = ntstatus_to_werror(status);
656 encode_wkssvc_join_password_buffer(ctx,
658 &cli->user_session_key,
659 &encrypted_password);
662 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
670 if (!NT_STATUS_IS_OK(status)) {
671 werr = ntstatus_to_werror(status);
683 /****************************************************************
684 ****************************************************************/
686 static WERROR libnetapi_NetGetJoinableOUs(struct libnetapi_ctx *ctx,
687 const char *server_name,
690 const char *password,
694 if (!server_name || is_myname_or_ipaddr(server_name)) {
695 return NetGetJoinableOUsLocal(ctx,
704 return NetGetJoinableOUsRemote(ctx,
713 /****************************************************************
715 ****************************************************************/
717 NET_API_STATUS NetGetJoinableOUs(const char *server_name,
720 const char *password,
724 struct libnetapi_ctx *ctx = NULL;
725 NET_API_STATUS status;
728 status = libnetapi_getctx(&ctx);
733 werr = libnetapi_NetGetJoinableOUs(ctx,
740 if (!W_ERROR_IS_OK(werr)) {
741 return W_ERROR_V(werr);
744 return NET_API_STATUS_SUCCESS;