/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- NetJoinDomain_l
- NetJoinDomain_r
- NetUnjoinDomain_l
- NetUnjoinDomain_r
- NetGetJoinInformation_r
- NetGetJoinInformation_l
- NetGetJoinableOUs_l
- NetGetJoinableOUs_r
- NetRenameMachineInDomain_r
- NetRenameMachineInDomain_l
1 /*
2 * Unix SMB/CIFS implementation.
3 * NetApi Join Support
4 * Copyright (C) Guenther Deschner 2007-2008
5 *
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.
10 *
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.
15 *
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/>.
18 */
19
20 #include "includes.h"
21
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"
27
28 /****************************************************************
29 ****************************************************************/
30
31 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
32 struct NetJoinDomain *r)
33 {
34 struct libnet_JoinCtx *j = NULL;
35 WERROR werr;
36
37 if (!r->in.domain) {
38 return WERR_INVALID_PARAM;
39 }
40
41 werr = libnet_init_JoinCtx(mem_ctx, &j);
42 W_ERROR_NOT_OK_RETURN(werr);
43
44 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
45 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
46
47 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
48 NTSTATUS status;
49 struct netr_DsRGetDCNameInfo *info = NULL;
50 const char *dc = NULL;
51 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
52 DS_WRITABLE_REQUIRED |
53 DS_RETURN_DNS_NAME;
54 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
55 NULL, NULL, flags, &info);
56 if (!NT_STATUS_IS_OK(status)) {
57 libnetapi_set_error_string(mem_ctx,
58 "%s", get_friendly_nt_error_msg(status));
59 return ntstatus_to_werror(status);
60 }
61
62 dc = strip_hostname(info->dc_unc);
63 j->in.dc_name = talloc_strdup(mem_ctx, dc);
64 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
65 }
66
67 if (r->in.account_ou) {
68 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
69 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
70 }
71
72 if (r->in.account) {
73 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
74 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
75 }
76
77 if (r->in.password) {
78 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
79 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
80 }
81
82 j->in.join_flags = r->in.join_flags;
83 j->in.modify_config = true;
84 j->in.debug = true;
85
86 werr = libnet_Join(mem_ctx, j);
87 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
88 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
89 }
90 TALLOC_FREE(j);
91
92 return werr;
93 }
94
95 /****************************************************************
96 ****************************************************************/
97
98 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
99 struct NetJoinDomain *r)
100 {
101 struct rpc_pipe_client *pipe_cli = NULL;
102 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
103 NTSTATUS status;
104 WERROR werr;
105 unsigned int old_timeout = 0;
106
107 werr = libnetapi_open_pipe(ctx, r->in.server,
108 &ndr_table_wkssvc.syntax_id,
109 &pipe_cli);
110 if (!W_ERROR_IS_OK(werr)) {
111 goto done;
112 }
113
114 if (r->in.password) {
115 encode_wkssvc_join_password_buffer(ctx,
116 r->in.password,
117 &pipe_cli->auth->user_session_key,
118 &encrypted_password);
119 }
120
121 old_timeout = rpccli_set_timeout(pipe_cli, 600000);
122
123 status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
124 r->in.server,
125 r->in.domain,
126 r->in.account_ou,
127 r->in.account,
128 encrypted_password,
129 r->in.join_flags,
130 &werr);
131 if (!NT_STATUS_IS_OK(status)) {
132 werr = ntstatus_to_werror(status);
133 goto done;
134 }
135
136 done:
137 if (pipe_cli && old_timeout) {
138 rpccli_set_timeout(pipe_cli, old_timeout);
139 }
140
141 return werr;
142 }
143 /****************************************************************
144 ****************************************************************/
145
146 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
/* [<][>][^][v][top][bottom][index][help] */
147 struct NetUnjoinDomain *r)
148 {
149 struct libnet_UnjoinCtx *u = NULL;
150 struct dom_sid domain_sid;
151 const char *domain = NULL;
152 WERROR werr;
153
154 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
155 return WERR_SETUP_NOT_JOINED;
156 }
157
158 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
159 W_ERROR_NOT_OK_RETURN(werr);
160
161 if (lp_realm()) {
162 domain = lp_realm();
163 } else {
164 domain = lp_workgroup();
165 }
166
167 if (r->in.server_name) {
168 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
169 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
170 } else {
171 NTSTATUS status;
172 struct netr_DsRGetDCNameInfo *info = NULL;
173 const char *dc = NULL;
174 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
175 DS_WRITABLE_REQUIRED |
176 DS_RETURN_DNS_NAME;
177 status = dsgetdcname(mem_ctx, NULL, domain,
178 NULL, NULL, flags, &info);
179 if (!NT_STATUS_IS_OK(status)) {
180 libnetapi_set_error_string(mem_ctx,
181 "failed to find DC for domain %s: %s",
182 domain,
183 get_friendly_nt_error_msg(status));
184 return ntstatus_to_werror(status);
185 }
186
187 dc = strip_hostname(info->dc_unc);
188 u->in.dc_name = talloc_strdup(mem_ctx, dc);
189 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
190
191 u->in.domain_name = domain;
192 }
193
194 if (r->in.account) {
195 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
196 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
197 }
198
199 if (r->in.password) {
200 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
201 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
202 }
203
204 u->in.domain_name = domain;
205 u->in.unjoin_flags = r->in.unjoin_flags;
206 u->in.delete_machine_account = false;
207 u->in.modify_config = true;
208 u->in.debug = true;
209
210 u->in.domain_sid = &domain_sid;
211
212 werr = libnet_Unjoin(mem_ctx, u);
213 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
214 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
215 }
216 TALLOC_FREE(u);
217
218 return werr;
219 }
220
221 /****************************************************************
222 ****************************************************************/
223
224 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
225 struct NetUnjoinDomain *r)
226 {
227 struct rpc_pipe_client *pipe_cli = NULL;
228 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
229 NTSTATUS status;
230 WERROR werr;
231 unsigned int old_timeout = 0;
232
233 werr = libnetapi_open_pipe(ctx, r->in.server_name,
234 &ndr_table_wkssvc.syntax_id,
235 &pipe_cli);
236 if (!W_ERROR_IS_OK(werr)) {
237 goto done;
238 }
239
240 if (r->in.password) {
241 encode_wkssvc_join_password_buffer(ctx,
242 r->in.password,
243 &pipe_cli->auth->user_session_key,
244 &encrypted_password);
245 }
246
247 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
248
249 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
250 r->in.server_name,
251 r->in.account,
252 encrypted_password,
253 r->in.unjoin_flags,
254 &werr);
255 if (!NT_STATUS_IS_OK(status)) {
256 werr = ntstatus_to_werror(status);
257 goto done;
258 }
259
260 done:
261 if (pipe_cli && old_timeout) {
262 rpccli_set_timeout(pipe_cli, old_timeout);
263 }
264
265 return werr;
266 }
267
268 /****************************************************************
269 ****************************************************************/
270
271 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
272 struct NetGetJoinInformation *r)
273 {
274 struct rpc_pipe_client *pipe_cli = NULL;
275 NTSTATUS status;
276 WERROR werr;
277 const char *buffer = NULL;
278
279 werr = libnetapi_open_pipe(ctx, r->in.server_name,
280 &ndr_table_wkssvc.syntax_id,
281 &pipe_cli);
282 if (!W_ERROR_IS_OK(werr)) {
283 goto done;
284 }
285
286 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
287 r->in.server_name,
288 &buffer,
289 (enum wkssvc_NetJoinStatus *)r->out.name_type,
290 &werr);
291 if (!NT_STATUS_IS_OK(status)) {
292 werr = ntstatus_to_werror(status);
293 goto done;
294 }
295
296 *r->out.name_buffer = talloc_strdup(ctx, buffer);
297 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
298
299 done:
300 return werr;
301 }
302
303 /****************************************************************
304 ****************************************************************/
305
306 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
307 struct NetGetJoinInformation *r)
308 {
309 if ((lp_security() == SEC_ADS) && lp_realm()) {
310 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
311 } else {
312 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
313 }
314 if (!*r->out.name_buffer) {
315 return WERR_NOMEM;
316 }
317
318 switch (lp_server_role()) {
319 case ROLE_DOMAIN_MEMBER:
320 case ROLE_DOMAIN_PDC:
321 case ROLE_DOMAIN_BDC:
322 *r->out.name_type = NetSetupDomainName;
323 break;
324 case ROLE_STANDALONE:
325 default:
326 *r->out.name_type = NetSetupWorkgroupName;
327 break;
328 }
329
330 return WERR_OK;
331 }
332
333 /****************************************************************
334 ****************************************************************/
335
336 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
337 struct NetGetJoinableOUs *r)
338 {
339 #ifdef WITH_ADS
340 NTSTATUS status;
341 ADS_STATUS ads_status;
342 ADS_STRUCT *ads = NULL;
343 struct netr_DsRGetDCNameInfo *info = NULL;
344 const char *dc = NULL;
345 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
346 DS_RETURN_DNS_NAME;
347
348 status = dsgetdcname(ctx, NULL, r->in.domain,
349 NULL, NULL, flags, &info);
350 if (!NT_STATUS_IS_OK(status)) {
351 libnetapi_set_error_string(ctx, "%s",
352 get_friendly_nt_error_msg(status));
353 return ntstatus_to_werror(status);
354 }
355
356 dc = strip_hostname(info->dc_unc);
357
358 ads = ads_init(info->domain_name, info->domain_name, dc);
359 if (!ads) {
360 return WERR_GENERAL_FAILURE;
361 }
362
363 SAFE_FREE(ads->auth.user_name);
364 if (r->in.account) {
365 ads->auth.user_name = SMB_STRDUP(r->in.account);
366 } else if (ctx->username) {
367 ads->auth.user_name = SMB_STRDUP(ctx->username);
368 }
369
370 SAFE_FREE(ads->auth.password);
371 if (r->in.password) {
372 ads->auth.password = SMB_STRDUP(r->in.password);
373 } else if (ctx->password) {
374 ads->auth.password = SMB_STRDUP(ctx->password);
375 }
376
377 ads_status = ads_connect_user_creds(ads);
378 if (!ADS_ERR_OK(ads_status)) {
379 ads_destroy(&ads);
380 return WERR_DEFAULT_JOIN_REQUIRED;
381 }
382
383 ads_status = ads_get_joinable_ous(ads, ctx,
384 (char ***)r->out.ous,
385 (size_t *)r->out.ou_count);
386 if (!ADS_ERR_OK(ads_status)) {
387 ads_destroy(&ads);
388 return WERR_DEFAULT_JOIN_REQUIRED;
389 }
390
391 ads_destroy(&ads);
392 return WERR_OK;
393 #else
394 return WERR_NOT_SUPPORTED;
395 #endif
396 }
397
398 /****************************************************************
399 ****************************************************************/
400
401 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
402 struct NetGetJoinableOUs *r)
403 {
404 struct rpc_pipe_client *pipe_cli = NULL;
405 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
406 NTSTATUS status;
407 WERROR werr;
408
409 werr = libnetapi_open_pipe(ctx, r->in.server_name,
410 &ndr_table_wkssvc.syntax_id,
411 &pipe_cli);
412 if (!W_ERROR_IS_OK(werr)) {
413 goto done;
414 }
415
416 if (r->in.password) {
417 encode_wkssvc_join_password_buffer(ctx,
418 r->in.password,
419 &pipe_cli->auth->user_session_key,
420 &encrypted_password);
421 }
422
423 status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
424 r->in.server_name,
425 r->in.domain,
426 r->in.account,
427 encrypted_password,
428 r->out.ou_count,
429 r->out.ous,
430 &werr);
431 if (!NT_STATUS_IS_OK(status)) {
432 werr = ntstatus_to_werror(status);
433 goto done;
434 }
435
436 done:
437 return werr;
438 }
439
440 /****************************************************************
441 ****************************************************************/
442
443 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
444 struct NetRenameMachineInDomain *r)
445 {
446 struct rpc_pipe_client *pipe_cli = NULL;
447 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
448 NTSTATUS status;
449 WERROR werr;
450
451 werr = libnetapi_open_pipe(ctx, r->in.server_name,
452 &ndr_table_wkssvc.syntax_id,
453 &pipe_cli);
454 if (!W_ERROR_IS_OK(werr)) {
455 goto done;
456 }
457
458 if (r->in.password) {
459 encode_wkssvc_join_password_buffer(ctx,
460 r->in.password,
461 &pipe_cli->auth->user_session_key,
462 &encrypted_password);
463 }
464
465 status = rpccli_wkssvc_NetrRenameMachineInDomain2(pipe_cli, ctx,
466 r->in.server_name,
467 r->in.new_machine_name,
468 r->in.account,
469 encrypted_password,
470 r->in.rename_options,
471 &werr);
472 if (!NT_STATUS_IS_OK(status)) {
473 werr = ntstatus_to_werror(status);
474 goto done;
475 }
476
477 done:
478 return werr;
479 }
480
481 /****************************************************************
482 ****************************************************************/
483
484 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
/* [<][>][^][v][top][bottom][index][help] */
485 struct NetRenameMachineInDomain *r)
486 {
487 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
488 }