Line data Source code
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 : #include "libsmb/dsgetdcname.h"
33 : #include "../librpc/gen_ndr/ndr_ODJ.h"
34 : #include "lib/util/base64.h"
35 : #include "libnet/libnet_join_offline.h"
36 :
37 : /****************************************************************
38 : ****************************************************************/
39 :
40 0 : WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
41 : struct NetJoinDomain *r)
42 : {
43 0 : struct libnet_JoinCtx *j = NULL;
44 : struct libnetapi_private_ctx *priv;
45 : WERROR werr;
46 :
47 0 : priv = talloc_get_type_abort(mem_ctx->private_data,
48 : struct libnetapi_private_ctx);
49 :
50 0 : if (!r->in.domain) {
51 0 : return WERR_INVALID_PARAMETER;
52 : }
53 :
54 0 : werr = libnet_init_JoinCtx(mem_ctx, &j);
55 0 : W_ERROR_NOT_OK_RETURN(werr);
56 :
57 0 : j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
58 0 : W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
59 :
60 0 : if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
61 : NTSTATUS status;
62 0 : struct netr_DsRGetDCNameInfo *info = NULL;
63 0 : const char *dc = NULL;
64 0 : uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
65 : DS_WRITABLE_REQUIRED |
66 : DS_RETURN_DNS_NAME;
67 0 : status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
68 : NULL, NULL, flags, &info);
69 0 : if (!NT_STATUS_IS_OK(status)) {
70 0 : libnetapi_set_error_string(mem_ctx,
71 : "%s", get_friendly_nt_error_msg(status));
72 0 : return ntstatus_to_werror(status);
73 : }
74 :
75 0 : dc = strip_hostname(info->dc_unc);
76 0 : j->in.dc_name = talloc_strdup(mem_ctx, dc);
77 0 : W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
78 : }
79 :
80 0 : if (r->in.account_ou) {
81 0 : j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
82 0 : W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
83 : }
84 :
85 0 : if (r->in.account) {
86 0 : j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
87 0 : W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
88 : }
89 :
90 0 : if (r->in.password) {
91 0 : j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
92 0 : W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
93 : }
94 :
95 0 : j->in.join_flags = r->in.join_flags;
96 0 : j->in.modify_config = true;
97 0 : j->in.debug = true;
98 :
99 0 : werr = libnet_Join(mem_ctx, j);
100 0 : if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
101 0 : libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
102 : }
103 0 : TALLOC_FREE(j);
104 :
105 0 : return werr;
106 : }
107 :
108 : /****************************************************************
109 : ****************************************************************/
110 :
111 0 : WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
112 : struct NetJoinDomain *r)
113 : {
114 0 : struct rpc_pipe_client *pipe_cli = NULL;
115 0 : struct wkssvc_PasswordBuffer *encrypted_password = NULL;
116 : NTSTATUS status;
117 : WERROR werr;
118 0 : unsigned int old_timeout = 0;
119 : struct dcerpc_binding_handle *b;
120 : DATA_BLOB session_key;
121 :
122 0 : if (IS_DC) {
123 0 : return WERR_NERR_SETUPDOMAINCONTROLLER;
124 : }
125 :
126 0 : werr = libnetapi_open_pipe(ctx, r->in.server,
127 : &ndr_table_wkssvc,
128 : &pipe_cli);
129 0 : if (!W_ERROR_IS_OK(werr)) {
130 0 : goto done;
131 : }
132 :
133 0 : b = pipe_cli->binding_handle;
134 :
135 0 : if (r->in.password) {
136 :
137 0 : status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
138 0 : if (!NT_STATUS_IS_OK(status)) {
139 0 : werr = ntstatus_to_werror(status);
140 0 : goto done;
141 : }
142 :
143 0 : werr = encode_wkssvc_join_password_buffer(ctx,
144 : r->in.password,
145 : &session_key,
146 : &encrypted_password);
147 0 : if (!W_ERROR_IS_OK(werr)) {
148 0 : goto done;
149 : }
150 : }
151 :
152 0 : old_timeout = rpccli_set_timeout(pipe_cli, 600000);
153 :
154 0 : status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(),
155 : r->in.server,
156 : r->in.domain,
157 : r->in.account_ou,
158 : r->in.account,
159 : encrypted_password,
160 : r->in.join_flags,
161 : &werr);
162 0 : if (!NT_STATUS_IS_OK(status)) {
163 0 : werr = ntstatus_to_werror(status);
164 0 : goto done;
165 : }
166 :
167 0 : done:
168 0 : if (pipe_cli && old_timeout) {
169 0 : rpccli_set_timeout(pipe_cli, old_timeout);
170 : }
171 :
172 0 : return werr;
173 : }
174 : /****************************************************************
175 : ****************************************************************/
176 :
177 0 : WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
178 : struct NetUnjoinDomain *r)
179 : {
180 0 : struct libnet_UnjoinCtx *u = NULL;
181 : struct dom_sid domain_sid;
182 0 : const char *domain = NULL;
183 : WERROR werr;
184 : struct libnetapi_private_ctx *priv;
185 0 : const char *realm = lp_realm();
186 :
187 0 : priv = talloc_get_type_abort(mem_ctx->private_data,
188 : struct libnetapi_private_ctx);
189 :
190 0 : if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
191 0 : return WERR_NERR_SETUPNOTJOINED;
192 : }
193 :
194 0 : werr = libnet_init_UnjoinCtx(mem_ctx, &u);
195 0 : W_ERROR_NOT_OK_RETURN(werr);
196 :
197 0 : if (realm[0] != '\0') {
198 0 : domain = realm;
199 : } else {
200 0 : domain = lp_workgroup();
201 : }
202 :
203 0 : if (r->in.server_name) {
204 0 : u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
205 0 : W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
206 : } else {
207 : NTSTATUS status;
208 0 : struct netr_DsRGetDCNameInfo *info = NULL;
209 0 : const char *dc = NULL;
210 0 : uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
211 : DS_WRITABLE_REQUIRED |
212 : DS_RETURN_DNS_NAME;
213 0 : status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
214 : NULL, NULL, flags, &info);
215 0 : if (!NT_STATUS_IS_OK(status)) {
216 0 : libnetapi_set_error_string(mem_ctx,
217 : "failed to find DC for domain %s: %s",
218 : domain,
219 : get_friendly_nt_error_msg(status));
220 0 : return ntstatus_to_werror(status);
221 : }
222 :
223 0 : dc = strip_hostname(info->dc_unc);
224 0 : u->in.dc_name = talloc_strdup(mem_ctx, dc);
225 0 : W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
226 :
227 0 : u->in.domain_name = domain;
228 : }
229 :
230 0 : if (r->in.account) {
231 0 : u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
232 0 : W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
233 : }
234 :
235 0 : if (r->in.password) {
236 0 : u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
237 0 : W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
238 : }
239 :
240 0 : u->in.domain_name = domain;
241 0 : u->in.unjoin_flags = r->in.unjoin_flags;
242 0 : u->in.delete_machine_account = false;
243 0 : u->in.modify_config = true;
244 0 : u->in.debug = true;
245 :
246 0 : u->in.domain_sid = &domain_sid;
247 :
248 0 : werr = libnet_Unjoin(mem_ctx, u);
249 0 : if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
250 0 : libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
251 : }
252 0 : TALLOC_FREE(u);
253 :
254 0 : return werr;
255 : }
256 :
257 : /****************************************************************
258 : ****************************************************************/
259 :
260 0 : WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
261 : struct NetUnjoinDomain *r)
262 : {
263 0 : struct rpc_pipe_client *pipe_cli = NULL;
264 0 : struct wkssvc_PasswordBuffer *encrypted_password = NULL;
265 : NTSTATUS status;
266 : WERROR werr;
267 0 : unsigned int old_timeout = 0;
268 : struct dcerpc_binding_handle *b;
269 : DATA_BLOB session_key;
270 :
271 0 : werr = libnetapi_open_pipe(ctx, r->in.server_name,
272 : &ndr_table_wkssvc,
273 : &pipe_cli);
274 0 : if (!W_ERROR_IS_OK(werr)) {
275 0 : goto done;
276 : }
277 :
278 0 : b = pipe_cli->binding_handle;
279 :
280 0 : if (r->in.password) {
281 :
282 0 : status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
283 0 : if (!NT_STATUS_IS_OK(status)) {
284 0 : werr = ntstatus_to_werror(status);
285 0 : goto done;
286 : }
287 :
288 0 : werr = encode_wkssvc_join_password_buffer(ctx,
289 : r->in.password,
290 : &session_key,
291 : &encrypted_password);
292 0 : if (!W_ERROR_IS_OK(werr)) {
293 0 : goto done;
294 : }
295 : }
296 :
297 0 : old_timeout = rpccli_set_timeout(pipe_cli, 60000);
298 :
299 0 : status = dcerpc_wkssvc_NetrUnjoinDomain2(b, talloc_tos(),
300 : r->in.server_name,
301 : r->in.account,
302 : encrypted_password,
303 : r->in.unjoin_flags,
304 : &werr);
305 0 : if (!NT_STATUS_IS_OK(status)) {
306 0 : werr = ntstatus_to_werror(status);
307 0 : goto done;
308 : }
309 :
310 0 : done:
311 0 : if (pipe_cli && old_timeout) {
312 0 : rpccli_set_timeout(pipe_cli, old_timeout);
313 : }
314 :
315 0 : return werr;
316 : }
317 :
318 : /****************************************************************
319 : ****************************************************************/
320 :
321 0 : WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
322 : struct NetGetJoinInformation *r)
323 : {
324 0 : struct rpc_pipe_client *pipe_cli = NULL;
325 : NTSTATUS status;
326 : WERROR werr;
327 0 : const char *buffer = NULL;
328 : struct dcerpc_binding_handle *b;
329 :
330 0 : werr = libnetapi_open_pipe(ctx, r->in.server_name,
331 : &ndr_table_wkssvc,
332 : &pipe_cli);
333 0 : if (!W_ERROR_IS_OK(werr)) {
334 0 : goto done;
335 : }
336 :
337 0 : b = pipe_cli->binding_handle;
338 :
339 0 : status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(),
340 : r->in.server_name,
341 : &buffer,
342 0 : (enum wkssvc_NetJoinStatus *)r->out.name_type,
343 : &werr);
344 0 : if (!NT_STATUS_IS_OK(status)) {
345 0 : werr = ntstatus_to_werror(status);
346 0 : goto done;
347 : }
348 :
349 0 : if (!W_ERROR_IS_OK(werr)) {
350 0 : goto done;
351 : }
352 :
353 0 : *r->out.name_buffer = talloc_strdup(ctx, buffer);
354 0 : W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
355 :
356 0 : done:
357 0 : return werr;
358 : }
359 :
360 : /****************************************************************
361 : ****************************************************************/
362 :
363 0 : WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
364 : struct NetGetJoinInformation *r)
365 : {
366 0 : const char *realm = lp_realm();
367 :
368 0 : if ((lp_security() == SEC_ADS) && realm[0] != '\0') {
369 0 : *r->out.name_buffer = talloc_strdup(ctx, realm);
370 : } else {
371 0 : *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
372 : }
373 0 : if (!*r->out.name_buffer) {
374 0 : return WERR_NOT_ENOUGH_MEMORY;
375 : }
376 :
377 0 : switch (lp_server_role()) {
378 0 : case ROLE_DOMAIN_MEMBER:
379 : case ROLE_DOMAIN_PDC:
380 : case ROLE_DOMAIN_BDC:
381 : case ROLE_IPA_DC:
382 0 : *r->out.name_type = NetSetupDomainName;
383 0 : break;
384 0 : case ROLE_STANDALONE:
385 : default:
386 0 : *r->out.name_type = NetSetupWorkgroupName;
387 0 : break;
388 : }
389 :
390 0 : return WERR_OK;
391 : }
392 :
393 : /****************************************************************
394 : ****************************************************************/
395 :
396 0 : WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
397 : struct NetGetJoinableOUs *r)
398 : {
399 : #ifdef HAVE_ADS
400 0 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
401 : WERROR ret;
402 : NTSTATUS status;
403 : ADS_STATUS ads_status;
404 0 : ADS_STRUCT *ads = NULL;
405 0 : struct netr_DsRGetDCNameInfo *info = NULL;
406 0 : const char *dc = NULL;
407 0 : uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
408 : DS_RETURN_DNS_NAME;
409 : struct libnetapi_private_ctx *priv;
410 : char **p;
411 : size_t s;
412 :
413 0 : priv = talloc_get_type_abort(ctx->private_data,
414 : struct libnetapi_private_ctx);
415 :
416 0 : status = dsgetdcname(tmp_ctx, priv->msg_ctx, r->in.domain,
417 : NULL, NULL, flags, &info);
418 0 : if (!NT_STATUS_IS_OK(status)) {
419 0 : libnetapi_set_error_string(ctx, "%s",
420 : get_friendly_nt_error_msg(status));
421 0 : ret = ntstatus_to_werror(status);
422 0 : goto out;
423 : }
424 :
425 0 : dc = strip_hostname(info->dc_unc);
426 :
427 0 : ads = ads_init(tmp_ctx,
428 0 : info->domain_name,
429 0 : info->domain_name,
430 : dc,
431 : ADS_SASL_PLAIN);
432 0 : if (!ads) {
433 0 : ret = WERR_GEN_FAILURE;
434 0 : goto out;
435 : }
436 :
437 0 : TALLOC_FREE(ads->auth.user_name);
438 0 : if (r->in.account) {
439 0 : ads->auth.user_name = talloc_strdup(ads, r->in.account);
440 0 : if (ads->auth.user_name == NULL) {
441 0 : ret = WERR_NOT_ENOUGH_MEMORY;
442 0 : goto out;
443 : }
444 : } else {
445 0 : const char *username = NULL;
446 :
447 0 : libnetapi_get_username(ctx, &username);
448 0 : if (username != NULL) {
449 0 : ads->auth.user_name = talloc_strdup(ads, username);
450 0 : if (ads->auth.user_name == NULL) {
451 0 : ret = WERR_NOT_ENOUGH_MEMORY;
452 0 : goto out;
453 : }
454 : }
455 : }
456 :
457 0 : TALLOC_FREE(ads->auth.password);
458 0 : if (r->in.password) {
459 0 : ads->auth.password = talloc_strdup(ads, r->in.password);
460 0 : if (ads->auth.password == NULL) {
461 0 : ret = WERR_NOT_ENOUGH_MEMORY;
462 0 : goto out;
463 : }
464 : } else {
465 0 : const char *password = NULL;
466 :
467 0 : libnetapi_get_password(ctx, &password);
468 0 : if (password != NULL) {
469 0 : ads->auth.password = talloc_strdup(ads, password);
470 0 : if (ads->auth.password == NULL) {
471 0 : ret = WERR_NOT_ENOUGH_MEMORY;
472 0 : goto out;
473 : }
474 : }
475 : }
476 :
477 0 : ads_status = ads_connect_user_creds(ads);
478 0 : if (!ADS_ERR_OK(ads_status)) {
479 0 : ret = WERR_NERR_DEFAULTJOINREQUIRED;
480 0 : goto out;
481 : }
482 :
483 0 : ads_status = ads_get_joinable_ous(ads, ctx, &p, &s);
484 0 : if (!ADS_ERR_OK(ads_status)) {
485 0 : ret = WERR_NERR_DEFAULTJOINREQUIRED;
486 0 : goto out;
487 : }
488 0 : *r->out.ous = discard_const_p(const char *, p);
489 0 : *r->out.ou_count = s;
490 :
491 0 : ret = WERR_OK;
492 0 : out:
493 0 : TALLOC_FREE(tmp_ctx);
494 :
495 0 : return ret;
496 : #else
497 : return WERR_NOT_SUPPORTED;
498 : #endif
499 : }
500 :
501 : /****************************************************************
502 : ****************************************************************/
503 :
504 0 : WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
505 : struct NetGetJoinableOUs *r)
506 : {
507 0 : struct rpc_pipe_client *pipe_cli = NULL;
508 0 : struct wkssvc_PasswordBuffer *encrypted_password = NULL;
509 : NTSTATUS status;
510 : WERROR werr;
511 : struct dcerpc_binding_handle *b;
512 : DATA_BLOB session_key;
513 :
514 0 : werr = libnetapi_open_pipe(ctx, r->in.server_name,
515 : &ndr_table_wkssvc,
516 : &pipe_cli);
517 0 : if (!W_ERROR_IS_OK(werr)) {
518 0 : goto done;
519 : }
520 :
521 0 : b = pipe_cli->binding_handle;
522 :
523 0 : if (r->in.password) {
524 :
525 0 : status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
526 0 : if (!NT_STATUS_IS_OK(status)) {
527 0 : werr = ntstatus_to_werror(status);
528 0 : goto done;
529 : }
530 :
531 0 : werr = encode_wkssvc_join_password_buffer(ctx,
532 : r->in.password,
533 : &session_key,
534 : &encrypted_password);
535 0 : if (!W_ERROR_IS_OK(werr)) {
536 0 : goto done;
537 : }
538 : }
539 :
540 0 : status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(),
541 : r->in.server_name,
542 : r->in.domain,
543 : r->in.account,
544 : encrypted_password,
545 : r->out.ou_count,
546 : r->out.ous,
547 : &werr);
548 0 : if (!NT_STATUS_IS_OK(status)) {
549 0 : werr = ntstatus_to_werror(status);
550 0 : goto done;
551 : }
552 :
553 0 : done:
554 0 : return werr;
555 : }
556 :
557 : /****************************************************************
558 : ****************************************************************/
559 :
560 0 : WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
561 : struct NetRenameMachineInDomain *r)
562 : {
563 0 : struct rpc_pipe_client *pipe_cli = NULL;
564 0 : struct wkssvc_PasswordBuffer *encrypted_password = NULL;
565 : NTSTATUS status;
566 : WERROR werr;
567 : struct dcerpc_binding_handle *b;
568 : DATA_BLOB session_key;
569 :
570 0 : werr = libnetapi_open_pipe(ctx, r->in.server_name,
571 : &ndr_table_wkssvc,
572 : &pipe_cli);
573 0 : if (!W_ERROR_IS_OK(werr)) {
574 0 : goto done;
575 : }
576 :
577 0 : b = pipe_cli->binding_handle;
578 :
579 0 : if (r->in.password) {
580 :
581 0 : status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
582 0 : if (!NT_STATUS_IS_OK(status)) {
583 0 : werr = ntstatus_to_werror(status);
584 0 : goto done;
585 : }
586 :
587 0 : werr = encode_wkssvc_join_password_buffer(ctx,
588 : r->in.password,
589 : &session_key,
590 : &encrypted_password);
591 0 : if (!W_ERROR_IS_OK(werr)) {
592 0 : goto done;
593 : }
594 : }
595 :
596 0 : status = dcerpc_wkssvc_NetrRenameMachineInDomain2(b, talloc_tos(),
597 : r->in.server_name,
598 : r->in.new_machine_name,
599 : r->in.account,
600 : encrypted_password,
601 : r->in.rename_options,
602 : &werr);
603 0 : if (!NT_STATUS_IS_OK(status)) {
604 0 : werr = ntstatus_to_werror(status);
605 0 : goto done;
606 : }
607 :
608 0 : done:
609 0 : return werr;
610 : }
611 :
612 : /****************************************************************
613 : ****************************************************************/
614 :
615 0 : WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
616 : struct NetRenameMachineInDomain *r)
617 : {
618 0 : LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
619 : }
620 :
621 : /****************************************************************
622 : ****************************************************************/
623 :
624 0 : WERROR NetProvisionComputerAccount_r(struct libnetapi_ctx *ctx,
625 : struct NetProvisionComputerAccount *r)
626 : {
627 0 : return NetProvisionComputerAccount_l(ctx, r);
628 : }
629 :
630 : /****************************************************************
631 : ****************************************************************/
632 :
633 0 : static WERROR NetProvisionComputerAccount_backend(struct libnetapi_ctx *ctx,
634 : struct NetProvisionComputerAccount *r,
635 : TALLOC_CTX *mem_ctx,
636 : struct ODJ_PROVISION_DATA **p)
637 : {
638 : WERROR werr;
639 0 : struct libnet_JoinCtx *j = NULL;
640 0 : int use_kerberos = 0;
641 0 : const char *username = NULL;
642 :
643 0 : werr = libnet_init_JoinCtx(mem_ctx, &j);
644 0 : if (!W_ERROR_IS_OK(werr)) {
645 0 : return werr;
646 : }
647 :
648 0 : j->in.domain_name = talloc_strdup(j, r->in.domain);
649 0 : if (j->in.domain_name == NULL) {
650 0 : talloc_free(j);
651 0 : return WERR_NOT_ENOUGH_MEMORY;
652 : }
653 :
654 0 : talloc_free(discard_const_p(char *, j->in.machine_name));
655 0 : j->in.machine_name = talloc_strdup(j, r->in.machine_name);
656 0 : if (j->in.machine_name == NULL) {
657 0 : talloc_free(j);
658 0 : return WERR_NOT_ENOUGH_MEMORY;
659 : }
660 :
661 0 : if (r->in.dcname) {
662 0 : j->in.dc_name = talloc_strdup(j, r->in.dcname);
663 0 : if (j->in.dc_name == NULL) {
664 0 : talloc_free(j);
665 0 : return WERR_NOT_ENOUGH_MEMORY;
666 : }
667 : }
668 :
669 0 : if (r->in.machine_account_ou) {
670 0 : j->in.account_ou = talloc_strdup(j, r->in.machine_account_ou);
671 0 : if (j->in.account_ou == NULL) {
672 0 : talloc_free(j);
673 0 : return WERR_NOT_ENOUGH_MEMORY;
674 : }
675 : }
676 :
677 0 : libnetapi_get_username(ctx, &username);
678 0 : if (username == NULL) {
679 0 : talloc_free(j);
680 0 : return WERR_NERR_BADUSERNAME;
681 : }
682 :
683 0 : j->in.admin_account = talloc_strdup(j, username);
684 0 : if (j->in.admin_account == NULL) {
685 0 : talloc_free(j);
686 0 : return WERR_NOT_ENOUGH_MEMORY;
687 : }
688 :
689 0 : libnetapi_get_use_kerberos(ctx, &use_kerberos);
690 0 : if (!use_kerberos) {
691 0 : const char *password = NULL;
692 :
693 0 : libnetapi_get_password(ctx, &password);
694 0 : if (password == NULL) {
695 0 : talloc_free(j);
696 0 : return WERR_NERR_BADPASSWORD;
697 : }
698 0 : j->in.admin_password = talloc_strdup(j, password);
699 0 : if (j->in.admin_password == NULL) {
700 0 : talloc_free(j);
701 0 : return WERR_NOT_ENOUGH_MEMORY;
702 : }
703 : }
704 :
705 0 : j->in.use_kerberos = use_kerberos;
706 0 : j->in.debug = true;
707 0 : j->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
708 : WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
709 :
710 0 : if (r->in.options & NETSETUP_PROVISION_REUSE_ACCOUNT) {
711 0 : j->in.join_flags |= WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
712 : }
713 :
714 0 : if (r->in.options & NETSETUP_PROVISION_USE_DEFAULT_PASSWORD) {
715 0 : j->in.join_flags |= WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
716 0 : j->in.machine_password = talloc_strdup(j, r->in.machine_name);
717 0 : if (j->in.machine_password == NULL) {
718 0 : talloc_free(j);
719 0 : return WERR_NOT_ENOUGH_MEMORY;
720 : }
721 : }
722 :
723 0 : j->in.provision_computer_account_only = true;
724 :
725 0 : werr = libnet_Join(mem_ctx, j);
726 0 : if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
727 0 : libnetapi_set_error_string(ctx, "%s", j->out.error_string);
728 0 : talloc_free(j);
729 0 : return werr;
730 : }
731 :
732 0 : werr = libnet_odj_compose_ODJ_PROVISION_DATA(mem_ctx, j, p);
733 0 : if (!W_ERROR_IS_OK(werr)) {
734 0 : talloc_free(j);
735 0 : return werr;
736 : }
737 :
738 0 : TALLOC_FREE(j);
739 :
740 0 : return WERR_OK;
741 : }
742 :
743 0 : WERROR NetProvisionComputerAccount_l(struct libnetapi_ctx *ctx,
744 : struct NetProvisionComputerAccount *r)
745 : {
746 : WERROR werr;
747 : enum ndr_err_code ndr_err;
748 : const char *b64_bin_data_str;
749 : DATA_BLOB blob;
750 : struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data;
751 : struct ODJ_PROVISION_DATA *p;
752 0 : TALLOC_CTX *mem_ctx = talloc_new(ctx);
753 :
754 0 : if (r->in.provision_bin_data == NULL &&
755 0 : r->in.provision_text_data == NULL) {
756 0 : return WERR_INVALID_PARAMETER;
757 : }
758 0 : if (r->in.provision_bin_data != NULL &&
759 0 : r->in.provision_text_data != NULL) {
760 0 : return WERR_INVALID_PARAMETER;
761 : }
762 0 : if (r->in.provision_bin_data == NULL &&
763 0 : r->in.provision_bin_data_size != NULL) {
764 0 : return WERR_INVALID_PARAMETER;
765 : }
766 0 : if (r->in.provision_bin_data != NULL &&
767 0 : r->in.provision_bin_data_size == NULL) {
768 0 : return WERR_INVALID_PARAMETER;
769 : }
770 :
771 0 : if (r->in.domain == NULL) {
772 0 : return WERR_INVALID_PARAMETER;
773 : }
774 :
775 0 : if (r->in.machine_name == NULL) {
776 0 : return WERR_INVALID_PARAMETER;
777 : }
778 :
779 0 : werr = NetProvisionComputerAccount_backend(ctx, r, mem_ctx, &p);
780 0 : if (!W_ERROR_IS_OK(werr)) {
781 0 : talloc_free(mem_ctx);
782 0 : return werr;
783 : }
784 :
785 0 : ZERO_STRUCT(odj_provision_data);
786 :
787 0 : odj_provision_data.s.p = p;
788 :
789 0 : ndr_err = ndr_push_struct_blob(&blob, ctx, &odj_provision_data,
790 : (ndr_push_flags_fn_t)ndr_push_ODJ_PROVISION_DATA_serialized_ptr);
791 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
792 0 : talloc_free(mem_ctx);
793 0 : return W_ERROR(NERR_BadOfflineJoinInfo);
794 : }
795 :
796 0 : talloc_free(mem_ctx);
797 :
798 0 : if (r->out.provision_text_data != NULL) {
799 0 : b64_bin_data_str = base64_encode_data_blob(ctx, blob);
800 0 : if (b64_bin_data_str == NULL) {
801 0 : return WERR_NOT_ENOUGH_MEMORY;
802 : }
803 0 : *r->out.provision_text_data = b64_bin_data_str;
804 : }
805 :
806 0 : if (r->out.provision_bin_data != NULL &&
807 0 : r->out.provision_bin_data_size != NULL) {
808 0 : *r->out.provision_bin_data = blob.data;
809 0 : *r->out.provision_bin_data_size = blob.length;
810 : }
811 :
812 0 : return werr;
813 : }
814 :
815 : /****************************************************************
816 : ****************************************************************/
817 :
818 0 : WERROR NetRequestOfflineDomainJoin_r(struct libnetapi_ctx *ctx,
819 : struct NetRequestOfflineDomainJoin *r)
820 : {
821 0 : return WERR_NOT_SUPPORTED;
822 : }
823 :
824 : /****************************************************************
825 : ****************************************************************/
826 :
827 0 : static WERROR NetRequestOfflineDomainJoin_backend(struct libnetapi_ctx *ctx,
828 : const struct ODJ_WIN7BLOB *win7blob,
829 : const struct ODJ_PROVISION_DATA *odj_provision_data)
830 : {
831 0 : struct libnet_JoinCtx *j = NULL;
832 : WERROR werr;
833 :
834 0 : werr = libnet_init_JoinCtx(ctx, &j);
835 0 : if (!W_ERROR_IS_OK(werr)) {
836 0 : return werr;
837 : }
838 :
839 0 : j->in.domain_name = talloc_strdup(j, win7blob->lpDomain);
840 0 : if (j->in.domain_name == NULL) {
841 0 : talloc_free(j);
842 0 : return WERR_NOT_ENOUGH_MEMORY;
843 : }
844 :
845 0 : talloc_free(discard_const_p(char *, j->in.machine_name));
846 0 : j->in.machine_name = talloc_strdup(j, win7blob->lpMachineName);
847 0 : if (j->in.machine_name == NULL) {
848 0 : talloc_free(j);
849 0 : return WERR_NOT_ENOUGH_MEMORY;
850 : }
851 :
852 0 : j->in.machine_password = talloc_strdup(j, win7blob->lpMachinePassword);
853 0 : if (j->in.machine_password == NULL) {
854 0 : talloc_free(j);
855 0 : return WERR_NOT_ENOUGH_MEMORY;
856 : }
857 :
858 0 : j->in.request_offline_join = true;
859 0 : j->in.odj_provision_data = discard_const(odj_provision_data);
860 0 : j->in.debug = true;
861 0 : j->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
862 : WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
863 :
864 0 : werr = libnet_Join(j, j);
865 0 : if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
866 0 : libnetapi_set_error_string(ctx, "%s", j->out.error_string);
867 0 : talloc_free(j);
868 0 : return werr;
869 : }
870 :
871 0 : TALLOC_FREE(j);
872 :
873 0 : return WERR_OK;
874 : }
875 :
876 0 : WERROR NetRequestOfflineDomainJoin_l(struct libnetapi_ctx *ctx,
877 : struct NetRequestOfflineDomainJoin *r)
878 : {
879 : DATA_BLOB blob, blob_base64;
880 : enum ndr_err_code ndr_err;
881 : struct ODJ_PROVISION_DATA_serialized_ptr odj_provision_data;
882 : bool ok;
883 0 : struct ODJ_WIN7BLOB win7blob = { 0 };
884 : WERROR werr;
885 :
886 0 : if (r->in.provision_bin_data == NULL ||
887 0 : r->in.provision_bin_data_size == 0) {
888 0 : return W_ERROR(NERR_NoOfflineJoinInfo);
889 : }
890 :
891 0 : if (r->in.provision_bin_data_size < 2) {
892 0 : return W_ERROR(NERR_BadOfflineJoinInfo);
893 : }
894 :
895 0 : if (r->in.provision_bin_data[0] == 0xff &&
896 0 : r->in.provision_bin_data[1] == 0xfe) {
897 0 : ok = convert_string_talloc(ctx, CH_UTF16LE, CH_UNIX,
898 0 : r->in.provision_bin_data+2,
899 0 : r->in.provision_bin_data_size-2,
900 : &blob_base64.data,
901 : &blob_base64.length);
902 0 : if (!ok) {
903 0 : return W_ERROR(NERR_BadOfflineJoinInfo);
904 : }
905 : } else {
906 0 : blob_base64 = data_blob(r->in.provision_bin_data,
907 : r->in.provision_bin_data_size);
908 : }
909 :
910 0 : blob = base64_decode_data_blob_talloc(ctx, (const char *)blob_base64.data);
911 :
912 0 : ndr_err = ndr_pull_struct_blob(&blob, ctx, &odj_provision_data,
913 : (ndr_pull_flags_fn_t)ndr_pull_ODJ_PROVISION_DATA_serialized_ptr);
914 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
915 0 : return W_ERROR(NERR_BadOfflineJoinInfo);
916 : }
917 :
918 0 : if (DEBUGLEVEL >= 10) {
919 0 : NDR_PRINT_DEBUG(ODJ_PROVISION_DATA_serialized_ptr, &odj_provision_data);
920 : }
921 :
922 0 : if (odj_provision_data.s.p->ulVersion != 1) {
923 0 : return W_ERROR(NERR_ProvisioningBlobUnsupported);
924 : }
925 :
926 0 : werr = libnet_odj_find_win7blob(odj_provision_data.s.p, &win7blob);
927 0 : if (!W_ERROR_IS_OK(werr)) {
928 0 : return werr;
929 : }
930 :
931 0 : if (!(r->in.options & NETSETUP_PROVISION_ONLINE_CALLER)) {
932 0 : return WERR_NERR_SETUPNOTJOINED;
933 : }
934 :
935 0 : werr = NetRequestOfflineDomainJoin_backend(ctx,
936 : &win7blob,
937 0 : odj_provision_data.s.p);
938 0 : if (!W_ERROR_IS_OK(werr)) {
939 0 : return werr;
940 : }
941 :
942 0 : return W_ERROR(NERR_JoinPerformedMustRestart);
943 : }
|