source: vendor/current/source3/lib/netapi/joindomain.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 14.1 KB
Line 
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#include "ads.h"
22#include "librpc/gen_ndr/libnetapi.h"
23#include "libcli/auth/libcli_auth.h"
24#include "lib/netapi/netapi.h"
25#include "lib/netapi/netapi_private.h"
26#include "lib/netapi/libnetapi.h"
27#include "librpc/gen_ndr/libnet_join.h"
28#include "libnet/libnet_join.h"
29#include "../librpc/gen_ndr/ndr_wkssvc_c.h"
30#include "rpc_client/cli_pipe.h"
31#include "secrets.h"
32
33/****************************************************************
34****************************************************************/
35
36WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
37 struct NetJoinDomain *r)
38{
39 struct libnet_JoinCtx *j = NULL;
40 struct libnetapi_private_ctx *priv;
41 WERROR werr;
42
43 priv = talloc_get_type_abort(mem_ctx->private_data,
44 struct libnetapi_private_ctx);
45
46 if (!r->in.domain) {
47 return WERR_INVALID_PARAM;
48 }
49
50 werr = libnet_init_JoinCtx(mem_ctx, &j);
51 W_ERROR_NOT_OK_RETURN(werr);
52
53 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
54 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
55
56 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
57 NTSTATUS status;
58 struct netr_DsRGetDCNameInfo *info = NULL;
59 const char *dc = NULL;
60 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
61 DS_WRITABLE_REQUIRED |
62 DS_RETURN_DNS_NAME;
63 status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
64 NULL, NULL, flags, &info);
65 if (!NT_STATUS_IS_OK(status)) {
66 libnetapi_set_error_string(mem_ctx,
67 "%s", get_friendly_nt_error_msg(status));
68 return ntstatus_to_werror(status);
69 }
70
71 dc = strip_hostname(info->dc_unc);
72 j->in.dc_name = talloc_strdup(mem_ctx, dc);
73 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
74 }
75
76 if (r->in.account_ou) {
77 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
78 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
79 }
80
81 if (r->in.account) {
82 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
83 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
84 }
85
86 if (r->in.password) {
87 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
88 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
89 }
90
91 j->in.join_flags = r->in.join_flags;
92 j->in.modify_config = true;
93 j->in.debug = true;
94
95 werr = libnet_Join(mem_ctx, j);
96 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
97 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
98 }
99 TALLOC_FREE(j);
100
101 return werr;
102}
103
104/****************************************************************
105****************************************************************/
106
107WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
108 struct NetJoinDomain *r)
109{
110 struct rpc_pipe_client *pipe_cli = NULL;
111 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
112 NTSTATUS status;
113 WERROR werr;
114 unsigned int old_timeout = 0;
115 struct dcerpc_binding_handle *b;
116 DATA_BLOB session_key;
117
118 if (IS_DC) {
119 return WERR_SETUP_DOMAIN_CONTROLLER;
120 }
121
122 werr = libnetapi_open_pipe(ctx, r->in.server,
123 &ndr_table_wkssvc,
124 &pipe_cli);
125 if (!W_ERROR_IS_OK(werr)) {
126 goto done;
127 }
128
129 b = pipe_cli->binding_handle;
130
131 if (r->in.password) {
132
133 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
134 if (!NT_STATUS_IS_OK(status)) {
135 werr = ntstatus_to_werror(status);
136 goto done;
137 }
138
139 encode_wkssvc_join_password_buffer(ctx,
140 r->in.password,
141 &session_key,
142 &encrypted_password);
143 }
144
145 old_timeout = rpccli_set_timeout(pipe_cli, 600000);
146
147 status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(),
148 r->in.server,
149 r->in.domain,
150 r->in.account_ou,
151 r->in.account,
152 encrypted_password,
153 r->in.join_flags,
154 &werr);
155 if (!NT_STATUS_IS_OK(status)) {
156 werr = ntstatus_to_werror(status);
157 goto done;
158 }
159
160 done:
161 if (pipe_cli && old_timeout) {
162 rpccli_set_timeout(pipe_cli, old_timeout);
163 }
164
165 return werr;
166}
167/****************************************************************
168****************************************************************/
169
170WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
171 struct NetUnjoinDomain *r)
172{
173 struct libnet_UnjoinCtx *u = NULL;
174 struct dom_sid domain_sid;
175 const char *domain = NULL;
176 WERROR werr;
177 struct libnetapi_private_ctx *priv;
178
179 priv = talloc_get_type_abort(mem_ctx->private_data,
180 struct libnetapi_private_ctx);
181
182 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
183 return WERR_SETUP_NOT_JOINED;
184 }
185
186 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
187 W_ERROR_NOT_OK_RETURN(werr);
188
189 if (lp_realm()) {
190 domain = lp_realm();
191 } else {
192 domain = lp_workgroup();
193 }
194
195 if (r->in.server_name) {
196 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
197 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
198 } else {
199 NTSTATUS status;
200 struct netr_DsRGetDCNameInfo *info = NULL;
201 const char *dc = NULL;
202 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
203 DS_WRITABLE_REQUIRED |
204 DS_RETURN_DNS_NAME;
205 status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
206 NULL, NULL, flags, &info);
207 if (!NT_STATUS_IS_OK(status)) {
208 libnetapi_set_error_string(mem_ctx,
209 "failed to find DC for domain %s: %s",
210 domain,
211 get_friendly_nt_error_msg(status));
212 return ntstatus_to_werror(status);
213 }
214
215 dc = strip_hostname(info->dc_unc);
216 u->in.dc_name = talloc_strdup(mem_ctx, dc);
217 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
218
219 u->in.domain_name = domain;
220 }
221
222 if (r->in.account) {
223 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
224 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
225 }
226
227 if (r->in.password) {
228 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
229 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
230 }
231
232 u->in.domain_name = domain;
233 u->in.unjoin_flags = r->in.unjoin_flags;
234 u->in.delete_machine_account = false;
235 u->in.modify_config = true;
236 u->in.debug = true;
237
238 u->in.domain_sid = &domain_sid;
239
240 werr = libnet_Unjoin(mem_ctx, u);
241 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
242 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
243 }
244 TALLOC_FREE(u);
245
246 return werr;
247}
248
249/****************************************************************
250****************************************************************/
251
252WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
253 struct NetUnjoinDomain *r)
254{
255 struct rpc_pipe_client *pipe_cli = NULL;
256 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
257 NTSTATUS status;
258 WERROR werr;
259 unsigned int old_timeout = 0;
260 struct dcerpc_binding_handle *b;
261 DATA_BLOB session_key;
262
263 werr = libnetapi_open_pipe(ctx, r->in.server_name,
264 &ndr_table_wkssvc,
265 &pipe_cli);
266 if (!W_ERROR_IS_OK(werr)) {
267 goto done;
268 }
269
270 b = pipe_cli->binding_handle;
271
272 if (r->in.password) {
273
274 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
275 if (!NT_STATUS_IS_OK(status)) {
276 werr = ntstatus_to_werror(status);
277 goto done;
278 }
279
280 encode_wkssvc_join_password_buffer(ctx,
281 r->in.password,
282 &session_key,
283 &encrypted_password);
284 }
285
286 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
287
288 status = dcerpc_wkssvc_NetrUnjoinDomain2(b, talloc_tos(),
289 r->in.server_name,
290 r->in.account,
291 encrypted_password,
292 r->in.unjoin_flags,
293 &werr);
294 if (!NT_STATUS_IS_OK(status)) {
295 werr = ntstatus_to_werror(status);
296 goto done;
297 }
298
299 done:
300 if (pipe_cli && old_timeout) {
301 rpccli_set_timeout(pipe_cli, old_timeout);
302 }
303
304 return werr;
305}
306
307/****************************************************************
308****************************************************************/
309
310WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
311 struct NetGetJoinInformation *r)
312{
313 struct rpc_pipe_client *pipe_cli = NULL;
314 NTSTATUS status;
315 WERROR werr;
316 const char *buffer = NULL;
317 struct dcerpc_binding_handle *b;
318
319 werr = libnetapi_open_pipe(ctx, r->in.server_name,
320 &ndr_table_wkssvc,
321 &pipe_cli);
322 if (!W_ERROR_IS_OK(werr)) {
323 goto done;
324 }
325
326 b = pipe_cli->binding_handle;
327
328 status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(),
329 r->in.server_name,
330 &buffer,
331 (enum wkssvc_NetJoinStatus *)r->out.name_type,
332 &werr);
333 if (!NT_STATUS_IS_OK(status)) {
334 werr = ntstatus_to_werror(status);
335 goto done;
336 }
337
338 if (!W_ERROR_IS_OK(werr)) {
339 goto done;
340 }
341
342 *r->out.name_buffer = talloc_strdup(ctx, buffer);
343 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
344
345 done:
346 return werr;
347}
348
349/****************************************************************
350****************************************************************/
351
352WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
353 struct NetGetJoinInformation *r)
354{
355 if ((lp_security() == SEC_ADS) && lp_realm()) {
356 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
357 } else {
358 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
359 }
360 if (!*r->out.name_buffer) {
361 return WERR_NOMEM;
362 }
363
364 switch (lp_server_role()) {
365 case ROLE_DOMAIN_MEMBER:
366 case ROLE_DOMAIN_PDC:
367 case ROLE_DOMAIN_BDC:
368 *r->out.name_type = NetSetupDomainName;
369 break;
370 case ROLE_STANDALONE:
371 default:
372 *r->out.name_type = NetSetupWorkgroupName;
373 break;
374 }
375
376 return WERR_OK;
377}
378
379/****************************************************************
380****************************************************************/
381
382WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
383 struct NetGetJoinableOUs *r)
384{
385#ifdef HAVE_ADS
386 NTSTATUS status;
387 ADS_STATUS ads_status;
388 ADS_STRUCT *ads = NULL;
389 struct netr_DsRGetDCNameInfo *info = NULL;
390 const char *dc = NULL;
391 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
392 DS_RETURN_DNS_NAME;
393 struct libnetapi_private_ctx *priv;
394 char **p;
395 size_t s;
396
397 priv = talloc_get_type_abort(ctx->private_data,
398 struct libnetapi_private_ctx);
399
400 status = dsgetdcname(ctx, priv->msg_ctx, r->in.domain,
401 NULL, NULL, flags, &info);
402 if (!NT_STATUS_IS_OK(status)) {
403 libnetapi_set_error_string(ctx, "%s",
404 get_friendly_nt_error_msg(status));
405 return ntstatus_to_werror(status);
406 }
407
408 dc = strip_hostname(info->dc_unc);
409
410 ads = ads_init(info->domain_name, info->domain_name, dc);
411 if (!ads) {
412 return WERR_GENERAL_FAILURE;
413 }
414
415 SAFE_FREE(ads->auth.user_name);
416 if (r->in.account) {
417 ads->auth.user_name = SMB_STRDUP(r->in.account);
418 } else if (ctx->username) {
419 ads->auth.user_name = SMB_STRDUP(ctx->username);
420 }
421
422 SAFE_FREE(ads->auth.password);
423 if (r->in.password) {
424 ads->auth.password = SMB_STRDUP(r->in.password);
425 } else if (ctx->password) {
426 ads->auth.password = SMB_STRDUP(ctx->password);
427 }
428
429 ads_status = ads_connect_user_creds(ads);
430 if (!ADS_ERR_OK(ads_status)) {
431 ads_destroy(&ads);
432 return WERR_DEFAULT_JOIN_REQUIRED;
433 }
434
435 ads_status = ads_get_joinable_ous(ads, ctx, &p, &s);
436 if (!ADS_ERR_OK(ads_status)) {
437 ads_destroy(&ads);
438 return WERR_DEFAULT_JOIN_REQUIRED;
439 }
440 *r->out.ous = discard_const_p(const char *, p);
441 *r->out.ou_count = s;
442
443 ads_destroy(&ads);
444 return WERR_OK;
445#else
446 return WERR_NOT_SUPPORTED;
447#endif
448}
449
450/****************************************************************
451****************************************************************/
452
453WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
454 struct NetGetJoinableOUs *r)
455{
456 struct rpc_pipe_client *pipe_cli = NULL;
457 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
458 NTSTATUS status;
459 WERROR werr;
460 struct dcerpc_binding_handle *b;
461 DATA_BLOB session_key;
462
463 werr = libnetapi_open_pipe(ctx, r->in.server_name,
464 &ndr_table_wkssvc,
465 &pipe_cli);
466 if (!W_ERROR_IS_OK(werr)) {
467 goto done;
468 }
469
470 b = pipe_cli->binding_handle;
471
472 if (r->in.password) {
473
474 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
475 if (!NT_STATUS_IS_OK(status)) {
476 werr = ntstatus_to_werror(status);
477 goto done;
478 }
479
480 encode_wkssvc_join_password_buffer(ctx,
481 r->in.password,
482 &session_key,
483 &encrypted_password);
484 }
485
486 status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(),
487 r->in.server_name,
488 r->in.domain,
489 r->in.account,
490 encrypted_password,
491 r->out.ou_count,
492 r->out.ous,
493 &werr);
494 if (!NT_STATUS_IS_OK(status)) {
495 werr = ntstatus_to_werror(status);
496 goto done;
497 }
498
499 done:
500 return werr;
501}
502
503/****************************************************************
504****************************************************************/
505
506WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
507 struct NetRenameMachineInDomain *r)
508{
509 struct rpc_pipe_client *pipe_cli = NULL;
510 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
511 NTSTATUS status;
512 WERROR werr;
513 struct dcerpc_binding_handle *b;
514 DATA_BLOB session_key;
515
516 werr = libnetapi_open_pipe(ctx, r->in.server_name,
517 &ndr_table_wkssvc,
518 &pipe_cli);
519 if (!W_ERROR_IS_OK(werr)) {
520 goto done;
521 }
522
523 b = pipe_cli->binding_handle;
524
525 if (r->in.password) {
526
527 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
528 if (!NT_STATUS_IS_OK(status)) {
529 werr = ntstatus_to_werror(status);
530 goto done;
531 }
532
533 encode_wkssvc_join_password_buffer(ctx,
534 r->in.password,
535 &session_key,
536 &encrypted_password);
537 }
538
539 status = dcerpc_wkssvc_NetrRenameMachineInDomain2(b, talloc_tos(),
540 r->in.server_name,
541 r->in.new_machine_name,
542 r->in.account,
543 encrypted_password,
544 r->in.rename_options,
545 &werr);
546 if (!NT_STATUS_IS_OK(status)) {
547 werr = ntstatus_to_werror(status);
548 goto done;
549 }
550
551 done:
552 return werr;
553}
554
555/****************************************************************
556****************************************************************/
557
558WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
559 struct NetRenameMachineInDomain *r)
560{
561 LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
562}
Note: See TracBrowser for help on using the repository browser.