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 "libnet/libnet.h"
28 /****************************************************************
29 ****************************************************************/
31 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
32 struct NetJoinDomain *r)
34 struct libnet_JoinCtx *j = NULL;
38 return WERR_INVALID_PARAM;
41 werr = libnet_init_JoinCtx(mem_ctx, &j);
42 W_ERROR_NOT_OK_RETURN(werr);
44 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
45 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
47 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
49 struct netr_DsRGetDCNameInfo *info = NULL;
50 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
51 DS_WRITABLE_REQUIRED |
53 status = dsgetdcname(mem_ctx, r->in.domain,
54 NULL, NULL, flags, &info);
55 if (!NT_STATUS_IS_OK(status)) {
56 libnetapi_set_error_string(mem_ctx,
57 "%s", get_friendly_nt_error_msg(status));
58 return ntstatus_to_werror(status);
60 j->in.dc_name = talloc_strdup(mem_ctx,
62 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
65 if (r->in.account_ou) {
66 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
67 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
71 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
72 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
76 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
77 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
80 j->in.join_flags = r->in.join_flags;
81 j->in.modify_config = true;
84 werr = libnet_Join(mem_ctx, j);
85 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
86 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
93 /****************************************************************
94 ****************************************************************/
96 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
97 struct NetJoinDomain *r)
99 struct cli_state *cli = NULL;
100 struct rpc_pipe_client *pipe_cli = NULL;
101 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
104 unsigned int old_timeout = 0;
106 werr = libnetapi_open_ipc_connection(ctx, r->in.server, &cli);
107 if (!W_ERROR_IS_OK(werr)) {
111 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
112 if (!W_ERROR_IS_OK(werr)) {
116 if (r->in.password) {
117 encode_wkssvc_join_password_buffer(ctx,
119 &cli->user_session_key,
120 &encrypted_password);
123 old_timeout = cli_set_timeout(cli, 600000);
125 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
133 if (!NT_STATUS_IS_OK(status)) {
134 werr = ntstatus_to_werror(status);
141 cli_set_timeout(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 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
178 DS_WRITABLE_REQUIRED |
180 status = dsgetdcname(mem_ctx, domain,
181 NULL, NULL, flags, &info);
182 if (!NT_STATUS_IS_OK(status)) {
183 libnetapi_set_error_string(mem_ctx,
184 "failed to find DC for domain %s: %s",
186 get_friendly_nt_error_msg(status));
187 return ntstatus_to_werror(status);
189 u->in.dc_name = talloc_strdup(mem_ctx,
191 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
193 u->in.domain_name = domain;
197 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
198 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
201 if (r->in.password) {
202 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
203 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
206 u->in.domain_name = domain;
207 u->in.unjoin_flags = r->in.unjoin_flags;
208 u->in.modify_config = true;
211 u->in.domain_sid = &domain_sid;
213 werr = libnet_Unjoin(mem_ctx, u);
214 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
215 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
222 /****************************************************************
223 ****************************************************************/
225 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
226 struct NetUnjoinDomain *r)
228 struct cli_state *cli = NULL;
229 struct rpc_pipe_client *pipe_cli = NULL;
230 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
233 unsigned int old_timeout = 0;
235 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
236 if (!W_ERROR_IS_OK(werr)) {
240 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
241 if (!W_ERROR_IS_OK(werr)) {
245 if (r->in.password) {
246 encode_wkssvc_join_password_buffer(ctx,
248 &cli->user_session_key,
249 &encrypted_password);
252 old_timeout = cli_set_timeout(cli, 60000);
254 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
260 if (!NT_STATUS_IS_OK(status)) {
261 werr = ntstatus_to_werror(status);
268 cli_set_timeout(cli, old_timeout);
275 /****************************************************************
276 ****************************************************************/
278 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
279 struct NetGetJoinInformation *r)
281 struct cli_state *cli = NULL;
282 struct rpc_pipe_client *pipe_cli = NULL;
285 const char *buffer = NULL;
287 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
288 if (!W_ERROR_IS_OK(werr)) {
292 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
293 if (!W_ERROR_IS_OK(werr)) {
297 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
300 (enum wkssvc_NetJoinStatus *)r->out.name_type,
302 if (!NT_STATUS_IS_OK(status)) {
303 werr = ntstatus_to_werror(status);
307 *r->out.name_buffer = talloc_strdup(ctx, buffer);
308 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
314 /****************************************************************
315 ****************************************************************/
317 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
318 struct NetGetJoinInformation *r)
320 if ((lp_security() == SEC_ADS) && lp_realm()) {
321 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
323 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
325 if (!*r->out.name_buffer) {
329 switch (lp_server_role()) {
330 case ROLE_DOMAIN_MEMBER:
331 case ROLE_DOMAIN_PDC:
332 case ROLE_DOMAIN_BDC:
333 *r->out.name_type = NetSetupDomainName;
335 case ROLE_STANDALONE:
337 *r->out.name_type = NetSetupWorkgroupName;
344 /****************************************************************
345 ****************************************************************/
347 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
348 struct NetGetJoinableOUs *r)
352 ADS_STATUS ads_status;
353 ADS_STRUCT *ads = NULL;
354 struct netr_DsRGetDCNameInfo *info = NULL;
355 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
358 status = dsgetdcname(ctx, r->in.domain,
359 NULL, NULL, flags, &info);
360 if (!NT_STATUS_IS_OK(status)) {
361 libnetapi_set_error_string(ctx, "%s",
362 get_friendly_nt_error_msg(status));
363 return ntstatus_to_werror(status);
366 ads = ads_init(r->in.domain, r->in.domain, info->dc_unc);
368 return WERR_GENERAL_FAILURE;
371 SAFE_FREE(ads->auth.user_name);
373 ads->auth.user_name = SMB_STRDUP(r->in.account);
374 } else if (ctx->username) {
375 ads->auth.user_name = SMB_STRDUP(ctx->username);
378 SAFE_FREE(ads->auth.password);
379 if (r->in.password) {
380 ads->auth.password = SMB_STRDUP(r->in.password);
381 } else if (ctx->password) {
382 ads->auth.password = SMB_STRDUP(ctx->password);
385 ads_status = ads_connect(ads);
386 if (!ADS_ERR_OK(ads_status)) {
388 return WERR_DEFAULT_JOIN_REQUIRED;
391 ads_status = ads_get_joinable_ous(ads, ctx,
392 (char ***)r->out.ous,
393 (size_t *)r->out.ou_count);
394 if (!ADS_ERR_OK(ads_status)) {
396 return WERR_DEFAULT_JOIN_REQUIRED;
402 return WERR_NOT_SUPPORTED;
406 /****************************************************************
407 ****************************************************************/
409 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
410 struct NetGetJoinableOUs *r)
412 struct cli_state *cli = NULL;
413 struct rpc_pipe_client *pipe_cli = NULL;
414 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
418 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
419 if (!W_ERROR_IS_OK(werr)) {
423 werr = libnetapi_open_pipe(ctx, cli, PI_WKSSVC, &pipe_cli);
424 if (!W_ERROR_IS_OK(werr)) {
428 if (r->in.password) {
429 encode_wkssvc_join_password_buffer(ctx,
431 &cli->user_session_key,
432 &encrypted_password);
435 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
443 if (!NT_STATUS_IS_OK(status)) {
444 werr = ntstatus_to_werror(status);