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/libnetapi.h"
25 #include "libnet/libnet.h"
27 /****************************************************************
28 ****************************************************************/
30 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
31 struct NetJoinDomain *r)
33 struct libnet_JoinCtx *j = NULL;
37 return WERR_INVALID_PARAM;
40 werr = libnet_init_JoinCtx(mem_ctx, &j);
41 W_ERROR_NOT_OK_RETURN(werr);
43 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
44 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
46 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
48 struct netr_DsRGetDCNameInfo *info = NULL;
49 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
50 DS_WRITABLE_REQUIRED |
52 status = dsgetdcname(mem_ctx, r->in.domain,
53 NULL, NULL, flags, &info);
54 if (!NT_STATUS_IS_OK(status)) {
55 libnetapi_set_error_string(mem_ctx,
56 "%s", get_friendly_nt_error_msg(status));
57 return ntstatus_to_werror(status);
59 j->in.dc_name = talloc_strdup(mem_ctx,
61 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
64 if (r->in.account_ou) {
65 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
66 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
70 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
71 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
75 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
76 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
79 j->in.join_flags = r->in.join_flags;
80 j->in.modify_config = true;
83 werr = libnet_Join(mem_ctx, j);
84 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
85 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
92 /****************************************************************
93 ****************************************************************/
95 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
96 struct NetJoinDomain *r)
98 struct cli_state *cli = NULL;
99 struct rpc_pipe_client *pipe_cli = NULL;
100 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
103 unsigned int old_timeout = 0;
105 status = cli_full_connection(&cli, NULL, r->in.server,
113 if (!NT_STATUS_IS_OK(status)) {
114 werr = ntstatus_to_werror(status);
118 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
121 werr = ntstatus_to_werror(status);
125 if (r->in.password) {
126 encode_wkssvc_join_password_buffer(ctx,
128 &cli->user_session_key,
129 &encrypted_password);
132 old_timeout = cli_set_timeout(cli, 600000);
134 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
142 if (!NT_STATUS_IS_OK(status)) {
143 werr = ntstatus_to_werror(status);
150 cli_set_timeout(cli, old_timeout);
157 /****************************************************************
158 ****************************************************************/
160 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
161 struct NetUnjoinDomain *r)
163 struct libnet_UnjoinCtx *u = NULL;
164 struct dom_sid domain_sid;
165 const char *domain = NULL;
168 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
169 return WERR_SETUP_NOT_JOINED;
172 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
173 W_ERROR_NOT_OK_RETURN(werr);
178 domain = lp_workgroup();
181 if (r->in.server_name) {
182 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
183 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
186 struct netr_DsRGetDCNameInfo *info = NULL;
187 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
188 DS_WRITABLE_REQUIRED |
190 status = dsgetdcname(mem_ctx, domain,
191 NULL, NULL, flags, &info);
192 if (!NT_STATUS_IS_OK(status)) {
193 libnetapi_set_error_string(mem_ctx,
194 "failed to find DC for domain %s: %s",
196 get_friendly_nt_error_msg(status));
197 return ntstatus_to_werror(status);
199 u->in.dc_name = talloc_strdup(mem_ctx,
201 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
203 u->in.domain_name = domain;
207 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
208 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
211 if (r->in.password) {
212 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
213 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
216 u->in.domain_name = domain;
217 u->in.unjoin_flags = r->in.unjoin_flags;
218 u->in.modify_config = true;
221 u->in.domain_sid = &domain_sid;
223 werr = libnet_Unjoin(mem_ctx, u);
224 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
225 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
232 /****************************************************************
233 ****************************************************************/
235 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
236 struct NetUnjoinDomain *r)
238 struct cli_state *cli = NULL;
239 struct rpc_pipe_client *pipe_cli = NULL;
240 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
243 unsigned int old_timeout = 0;
245 status = cli_full_connection(&cli, NULL, r->in.server_name,
253 if (!NT_STATUS_IS_OK(status)) {
254 werr = ntstatus_to_werror(status);
258 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
261 werr = ntstatus_to_werror(status);
265 if (r->in.password) {
266 encode_wkssvc_join_password_buffer(ctx,
268 &cli->user_session_key,
269 &encrypted_password);
272 old_timeout = cli_set_timeout(cli, 60000);
274 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
280 if (!NT_STATUS_IS_OK(status)) {
281 werr = ntstatus_to_werror(status);
287 cli_set_timeout(cli, old_timeout);
294 /****************************************************************
295 ****************************************************************/
297 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
298 struct NetGetJoinInformation *r)
300 struct cli_state *cli = NULL;
301 struct rpc_pipe_client *pipe_cli = NULL;
305 status = cli_full_connection(&cli, NULL, r->in.server_name,
313 if (!NT_STATUS_IS_OK(status)) {
314 werr = ntstatus_to_werror(status);
318 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
321 werr = ntstatus_to_werror(status);
325 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
328 (enum wkssvc_NetJoinStatus *)r->out.name_type,
330 if (!NT_STATUS_IS_OK(status)) {
331 werr = ntstatus_to_werror(status);
343 /****************************************************************
344 ****************************************************************/
346 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
347 struct NetGetJoinInformation *r)
349 if ((lp_security() == SEC_ADS) && lp_realm()) {
350 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
352 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
354 if (!*r->out.name_buffer) {
358 switch (lp_server_role()) {
359 case ROLE_DOMAIN_MEMBER:
360 case ROLE_DOMAIN_PDC:
361 case ROLE_DOMAIN_BDC:
362 *r->out.name_type = NetSetupDomainName;
364 case ROLE_STANDALONE:
366 *r->out.name_type = NetSetupWorkgroupName;
373 /****************************************************************
374 ****************************************************************/
376 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
377 struct NetGetJoinableOUs *r)
381 ADS_STATUS ads_status;
382 ADS_STRUCT *ads = NULL;
383 struct netr_DsRGetDCNameInfo *info = NULL;
384 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
387 status = dsgetdcname(ctx, r->in.domain,
388 NULL, NULL, flags, &info);
389 if (!NT_STATUS_IS_OK(status)) {
390 libnetapi_set_error_string(ctx, "%s",
391 get_friendly_nt_error_msg(status));
392 return ntstatus_to_werror(status);
395 ads = ads_init(r->in.domain, r->in.domain, info->dc_unc);
397 return WERR_GENERAL_FAILURE;
400 SAFE_FREE(ads->auth.user_name);
402 ads->auth.user_name = SMB_STRDUP(r->in.account);
403 } else if (ctx->username) {
404 ads->auth.user_name = SMB_STRDUP(ctx->username);
407 SAFE_FREE(ads->auth.password);
408 if (r->in.password) {
409 ads->auth.password = SMB_STRDUP(r->in.password);
410 } else if (ctx->password) {
411 ads->auth.password = SMB_STRDUP(ctx->password);
414 ads_status = ads_connect(ads);
415 if (!ADS_ERR_OK(ads_status)) {
417 return WERR_DEFAULT_JOIN_REQUIRED;
420 ads_status = ads_get_joinable_ous(ads, ctx,
421 (char ***)r->out.ous,
422 (size_t *)r->out.ou_count);
423 if (!ADS_ERR_OK(ads_status)) {
425 return WERR_DEFAULT_JOIN_REQUIRED;
431 return WERR_NOT_SUPPORTED;
435 /****************************************************************
436 ****************************************************************/
438 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
439 struct NetGetJoinableOUs *r)
441 struct cli_state *cli = NULL;
442 struct rpc_pipe_client *pipe_cli = NULL;
443 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
447 status = cli_full_connection(&cli, NULL, r->in.server_name,
455 if (!NT_STATUS_IS_OK(status)) {
456 werr = ntstatus_to_werror(status);
460 pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
463 werr = ntstatus_to_werror(status);
467 if (r->in.password) {
468 encode_wkssvc_join_password_buffer(ctx,
470 &cli->user_session_key,
471 &encrypted_password);
474 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
482 if (!NT_STATUS_IS_OK(status)) {
483 werr = ntstatus_to_werror(status);