1 /*
2  *  Unix SMB/CIFS implementation.
3  *  libnet Join Support
4  *  Copyright (C) Gerald (Jerry) Carter 2006
5  *  Copyright (C) Guenther Deschner 2007-2008
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "includes.h"
22 #include "ads.h"
23 #include "libsmb/namequery.h"
24 #include "librpc/gen_ndr/ndr_libnet_join.h"
25 #include "libnet/libnet_join.h"
26 #include "libcli/auth/libcli_auth.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/init_samr.h"
29 #include "../librpc/gen_ndr/ndr_lsa_c.h"
30 #include "rpc_client/cli_lsarpc.h"
31 #include "../librpc/gen_ndr/ndr_netlogon.h"
32 #include "rpc_client/cli_netlogon.h"
33 #include "lib/smbconf/smbconf.h"
34 #include "lib/smbconf/smbconf_reg.h"
35 #include "../libds/common/flags.h"
36 #include "secrets.h"
37 #include "rpc_client/init_lsa.h"
38 #include "rpc_client/cli_pipe.h"
39 #include "../libcli/security/security.h"
40 #include "passdb.h"
41 #include "libsmb/libsmb.h"
42 #include "../libcli/smb/smbXcli_base.h"
43 #include "lib/param/loadparm.h"
44 #include "libcli/auth/netlogon_creds_cli.h"
45 #include "auth/credentials/credentials.h"
46 #include "krb5_env.h"
47 #include "libsmb/dsgetdcname.h"
48 
49 /****************************************************************
50 ****************************************************************/
51 
52 #define LIBNET_JOIN_DUMP_CTX(ctx, r, f) \
53 	do { \
54 		char *str = NULL; \
55 		str = NDR_PRINT_FUNCTION_STRING(ctx, libnet_JoinCtx, f, r); \
56 		DEBUG(1,("libnet_Join:\n%s", str)); \
57 		TALLOC_FREE(str); \
58 	} while (0)
59 
60 #define LIBNET_JOIN_IN_DUMP_CTX(ctx, r) \
61 	LIBNET_JOIN_DUMP_CTX(ctx, r, NDR_IN | NDR_SET_VALUES)
62 #define LIBNET_JOIN_OUT_DUMP_CTX(ctx, r) \
63 	LIBNET_JOIN_DUMP_CTX(ctx, r, NDR_OUT)
64 
65 #define LIBNET_UNJOIN_DUMP_CTX(ctx, r, f) \
66 	do { \
67 		char *str = NULL; \
68 		str = NDR_PRINT_FUNCTION_STRING(ctx, libnet_UnjoinCtx, f, r); \
69 		DEBUG(1,("libnet_Unjoin:\n%s", str)); \
70 		TALLOC_FREE(str); \
71 	} while (0)
72 
73 #define LIBNET_UNJOIN_IN_DUMP_CTX(ctx, r) \
74 	LIBNET_UNJOIN_DUMP_CTX(ctx, r, NDR_IN | NDR_SET_VALUES)
75 #define LIBNET_UNJOIN_OUT_DUMP_CTX(ctx, r) \
76 	LIBNET_UNJOIN_DUMP_CTX(ctx, r, NDR_OUT)
77 
78 /****************************************************************
79 ****************************************************************/
80 
81 static void libnet_join_set_error_string(TALLOC_CTX *mem_ctx,
82 					 struct libnet_JoinCtx *r,
83 					 const char *format, ...)
84 					 PRINTF_ATTRIBUTE(3,4);
85 
libnet_join_set_error_string(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r,const char * format,...)86 static void libnet_join_set_error_string(TALLOC_CTX *mem_ctx,
87 					 struct libnet_JoinCtx *r,
88 					 const char *format, ...)
89 {
90 	va_list args;
91 
92 	if (r->out.error_string) {
93 		return;
94 	}
95 
96 	va_start(args, format);
97 	r->out.error_string = talloc_vasprintf(mem_ctx, format, args);
98 	va_end(args);
99 }
100 
101 /****************************************************************
102 ****************************************************************/
103 
104 static void libnet_unjoin_set_error_string(TALLOC_CTX *mem_ctx,
105 					   struct libnet_UnjoinCtx *r,
106 					   const char *format, ...)
107 					   PRINTF_ATTRIBUTE(3,4);
108 
libnet_unjoin_set_error_string(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r,const char * format,...)109 static void libnet_unjoin_set_error_string(TALLOC_CTX *mem_ctx,
110 					   struct libnet_UnjoinCtx *r,
111 					   const char *format, ...)
112 {
113 	va_list args;
114 
115 	if (r->out.error_string) {
116 		return;
117 	}
118 
119 	va_start(args, format);
120 	r->out.error_string = talloc_vasprintf(mem_ctx, format, args);
121 	va_end(args);
122 }
123 
124 #ifdef HAVE_ADS
125 
126 /****************************************************************
127 ****************************************************************/
128 
libnet_connect_ads(const char * dns_domain_name,const char * netbios_domain_name,const char * dc_name,const char * user_name,const char * password,const char * ccname,ADS_STRUCT ** ads)129 static ADS_STATUS libnet_connect_ads(const char *dns_domain_name,
130 				     const char *netbios_domain_name,
131 				     const char *dc_name,
132 				     const char *user_name,
133 				     const char *password,
134 				     const char *ccname,
135 				     ADS_STRUCT **ads)
136 {
137 	ADS_STATUS status;
138 	ADS_STRUCT *my_ads = NULL;
139 	char *cp;
140 
141 	my_ads = ads_init(dns_domain_name,
142 			  netbios_domain_name,
143 			  dc_name,
144 			  ADS_SASL_SEAL);
145 	if (!my_ads) {
146 		return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
147 	}
148 
149 	my_ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
150 
151 	if (user_name) {
152 		SAFE_FREE(my_ads->auth.user_name);
153 		my_ads->auth.user_name = SMB_STRDUP(user_name);
154 		if ((cp = strchr_m(my_ads->auth.user_name, '@'))!=0) {
155 			*cp++ = '\0';
156 			SAFE_FREE(my_ads->auth.realm);
157 			my_ads->auth.realm = smb_xstrdup(cp);
158 			if (!strupper_m(my_ads->auth.realm)) {
159 				ads_destroy(&my_ads);
160 				return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
161 			}
162 		}
163 	}
164 
165 	if (password) {
166 		SAFE_FREE(my_ads->auth.password);
167 		my_ads->auth.password = SMB_STRDUP(password);
168 	}
169 
170 	if (ccname != NULL) {
171 		SAFE_FREE(my_ads->auth.ccache_name);
172 		my_ads->auth.ccache_name = SMB_STRDUP(ccname);
173 		setenv(KRB5_ENV_CCNAME, my_ads->auth.ccache_name, 1);
174 	}
175 
176 	status = ads_connect_user_creds(my_ads);
177 	if (!ADS_ERR_OK(status)) {
178 		ads_destroy(&my_ads);
179 		return status;
180 	}
181 
182 	*ads = my_ads;
183 	return ADS_SUCCESS;
184 }
185 
186 /****************************************************************
187 ****************************************************************/
188 
libnet_join_connect_ads(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r,bool use_machine_creds)189 static ADS_STATUS libnet_join_connect_ads(TALLOC_CTX *mem_ctx,
190 					  struct libnet_JoinCtx *r,
191 					  bool use_machine_creds)
192 {
193 	ADS_STATUS status;
194 	const char *username;
195 	const char *password;
196 	const char *ccname = NULL;
197 
198 	if (use_machine_creds) {
199 		if (r->in.machine_name == NULL ||
200 		    r->in.machine_password == NULL) {
201 			return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
202 		}
203 		username = talloc_asprintf(mem_ctx, "%s$",
204 					   r->in.machine_name);
205 		if (username == NULL) {
206 			return ADS_ERROR(LDAP_NO_MEMORY);
207 		}
208 		password = r->in.machine_password;
209 		ccname = "MEMORY:libnet_join_machine_creds";
210 	} else {
211 		char *p = NULL;
212 
213 		username = r->in.admin_account;
214 
215 		p = strchr(r->in.admin_account, '@');
216 		if (p == NULL) {
217 			username = talloc_asprintf(mem_ctx, "%s@%s",
218 						   r->in.admin_account,
219 						   r->in.admin_domain);
220 		}
221 		if (username == NULL) {
222 			return ADS_ERROR(LDAP_NO_MEMORY);
223 		}
224 		password = r->in.admin_password;
225 
226 		/*
227 		 * when r->in.use_kerberos is set to allow "net ads join -k" we
228 		 * may not override the provided credential cache - gd
229 		 */
230 
231 		if (!r->in.use_kerberos) {
232 			ccname = "MEMORY:libnet_join_user_creds";
233 		}
234 	}
235 
236 	status = libnet_connect_ads(r->out.dns_domain_name,
237 				    r->out.netbios_domain_name,
238 				    r->in.dc_name,
239 				    username,
240 				    password,
241 				    ccname,
242 				    &r->in.ads);
243 	if (!ADS_ERR_OK(status)) {
244 		libnet_join_set_error_string(mem_ctx, r,
245 			"failed to connect to AD: %s",
246 			ads_errstr(status));
247 		return status;
248 	}
249 
250 	if (!r->out.netbios_domain_name) {
251 		r->out.netbios_domain_name = talloc_strdup(mem_ctx,
252 							   r->in.ads->server.workgroup);
253 		ADS_ERROR_HAVE_NO_MEMORY(r->out.netbios_domain_name);
254 	}
255 
256 	if (!r->out.dns_domain_name) {
257 		r->out.dns_domain_name = talloc_strdup(mem_ctx,
258 						       r->in.ads->config.realm);
259 		ADS_ERROR_HAVE_NO_MEMORY(r->out.dns_domain_name);
260 	}
261 
262 	r->out.domain_is_ad = true;
263 
264 	return ADS_SUCCESS;
265 }
266 
267 /****************************************************************
268 ****************************************************************/
269 
libnet_join_connect_ads_user(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)270 static ADS_STATUS libnet_join_connect_ads_user(TALLOC_CTX *mem_ctx,
271 					       struct libnet_JoinCtx *r)
272 {
273 	return libnet_join_connect_ads(mem_ctx, r, false);
274 }
275 
276 /****************************************************************
277 ****************************************************************/
278 
libnet_join_connect_ads_machine(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)279 static ADS_STATUS libnet_join_connect_ads_machine(TALLOC_CTX *mem_ctx,
280 						  struct libnet_JoinCtx *r)
281 {
282 	return libnet_join_connect_ads(mem_ctx, r, true);
283 }
284 
285 /****************************************************************
286 ****************************************************************/
287 
libnet_unjoin_connect_ads(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)288 static ADS_STATUS libnet_unjoin_connect_ads(TALLOC_CTX *mem_ctx,
289 					    struct libnet_UnjoinCtx *r)
290 {
291 	ADS_STATUS status;
292 
293 	status = libnet_connect_ads(r->in.domain_name,
294 				    r->in.domain_name,
295 				    r->in.dc_name,
296 				    r->in.admin_account,
297 				    r->in.admin_password,
298 				    NULL,
299 				    &r->in.ads);
300 	if (!ADS_ERR_OK(status)) {
301 		libnet_unjoin_set_error_string(mem_ctx, r,
302 			"failed to connect to AD: %s",
303 			ads_errstr(status));
304 	}
305 
306 	return status;
307 }
308 
309 /****************************************************************
310  join a domain using ADS (LDAP mods)
311 ****************************************************************/
312 
libnet_join_precreate_machine_acct(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)313 static ADS_STATUS libnet_join_precreate_machine_acct(TALLOC_CTX *mem_ctx,
314 						     struct libnet_JoinCtx *r)
315 {
316 	ADS_STATUS status;
317 	LDAPMessage *res = NULL;
318 	const char *attrs[] = { "dn", NULL };
319 	bool moved = false;
320 
321 	status = ads_check_ou_dn(mem_ctx, r->in.ads, &r->in.account_ou);
322 	if (!ADS_ERR_OK(status)) {
323 		return status;
324 	}
325 
326 	status = ads_search_dn(r->in.ads, &res, r->in.account_ou, attrs);
327 	if (!ADS_ERR_OK(status)) {
328 		return status;
329 	}
330 
331 	if (ads_count_replies(r->in.ads, res) != 1) {
332 		ads_msgfree(r->in.ads, res);
333 		return ADS_ERROR_LDAP(LDAP_NO_SUCH_OBJECT);
334 	}
335 
336 	ads_msgfree(r->in.ads, res);
337 
338 	/* Attempt to create the machine account and bail if this fails.
339 	   Assume that the admin wants exactly what they requested */
340 
341 	if (r->in.machine_password == NULL) {
342 		r->in.machine_password =
343 			trust_pw_new_value(mem_ctx,
344 					   r->in.secure_channel_type,
345 					   SEC_ADS);
346 		if (r->in.machine_password == NULL) {
347 			return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
348 		}
349 	}
350 
351 	status = ads_create_machine_acct(r->in.ads,
352 					 r->in.machine_name,
353 					 r->in.machine_password,
354 					 r->in.account_ou,
355 					 r->in.desired_encryption_types,
356 					 r->out.dns_domain_name);
357 
358 	if (ADS_ERR_OK(status)) {
359 		DBG_WARNING("Machine account successfully created\n");
360 		return status;
361 	} else  if ((status.error_type == ENUM_ADS_ERROR_LDAP) &&
362 		    (status.err.rc == LDAP_ALREADY_EXISTS)) {
363 		status = ADS_SUCCESS;
364 	}
365 
366 	if (!ADS_ERR_OK(status)) {
367 		DBG_WARNING("Failed to create machine account\n");
368 		return status;
369 	}
370 
371 	status = ads_move_machine_acct(r->in.ads,
372 				       r->in.machine_name,
373 				       r->in.account_ou,
374 				       &moved);
375 	if (!ADS_ERR_OK(status)) {
376 		DEBUG(1,("failure to locate/move pre-existing "
377 			"machine account\n"));
378 		return status;
379 	}
380 
381 	DEBUG(1,("The machine account %s the specified OU.\n",
382 		moved ? "was moved into" : "already exists in"));
383 
384 	return status;
385 }
386 
387 /****************************************************************
388 ****************************************************************/
389 
libnet_unjoin_remove_machine_acct(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)390 static ADS_STATUS libnet_unjoin_remove_machine_acct(TALLOC_CTX *mem_ctx,
391 						    struct libnet_UnjoinCtx *r)
392 {
393 	ADS_STATUS status;
394 
395 	if (!r->in.ads) {
396 		status = libnet_unjoin_connect_ads(mem_ctx, r);
397 		if (!ADS_ERR_OK(status)) {
398 			libnet_unjoin_set_error_string(mem_ctx, r,
399 				"failed to connect to AD: %s",
400 				ads_errstr(status));
401 			return status;
402 		}
403 	}
404 
405 	status = ads_leave_realm(r->in.ads, r->in.machine_name);
406 	if (!ADS_ERR_OK(status)) {
407 		libnet_unjoin_set_error_string(mem_ctx, r,
408 			"failed to leave realm: %s",
409 			ads_errstr(status));
410 		return status;
411 	}
412 
413 	return ADS_SUCCESS;
414 }
415 
416 /****************************************************************
417 ****************************************************************/
418 
libnet_join_find_machine_acct(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)419 static ADS_STATUS libnet_join_find_machine_acct(TALLOC_CTX *mem_ctx,
420 						struct libnet_JoinCtx *r)
421 {
422 	ADS_STATUS status;
423 	LDAPMessage *res = NULL;
424 	char *dn = NULL;
425 
426 	if (!r->in.machine_name) {
427 		return ADS_ERROR(LDAP_NO_MEMORY);
428 	}
429 
430 	status = ads_find_machine_acct(r->in.ads,
431 				       &res,
432 				       r->in.machine_name);
433 	if (!ADS_ERR_OK(status)) {
434 		return status;
435 	}
436 
437 	if (ads_count_replies(r->in.ads, res) != 1) {
438 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
439 		goto done;
440 	}
441 
442 	dn = ads_get_dn(r->in.ads, mem_ctx, res);
443 	if (!dn) {
444 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
445 		goto done;
446 	}
447 
448 	r->out.dn = talloc_strdup(mem_ctx, dn);
449 	if (!r->out.dn) {
450 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
451 		goto done;
452 	}
453 
454 	if (!ads_pull_uint32(r->in.ads, res, "msDS-SupportedEncryptionTypes",
455 			     &r->out.set_encryption_types)) {
456 		r->out.set_encryption_types = 0;
457 	}
458 
459  done:
460 	ads_msgfree(r->in.ads, res);
461 	TALLOC_FREE(dn);
462 
463 	return status;
464 }
465 
libnet_join_get_machine_spns(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r,char *** spn_array,size_t * num_spns)466 static ADS_STATUS libnet_join_get_machine_spns(TALLOC_CTX *mem_ctx,
467 					       struct libnet_JoinCtx *r,
468 					       char ***spn_array,
469 					       size_t *num_spns)
470 {
471 	ADS_STATUS status;
472 
473 	if (r->in.machine_name == NULL) {
474 		return ADS_ERROR_SYSTEM(EINVAL);
475 	}
476 
477 	status = ads_get_service_principal_names(mem_ctx,
478 						 r->in.ads,
479 						 r->in.machine_name,
480 						 spn_array,
481 						 num_spns);
482 
483 	return status;
484 }
485 
add_uniq_spn(TALLOC_CTX * mem_ctx,const char * spn,const char *** array,size_t * num)486 static ADS_STATUS add_uniq_spn(TALLOC_CTX *mem_ctx, const  char *spn,
487 			       const char ***array, size_t *num)
488 {
489 	bool ok = ads_element_in_array(*array, *num, spn);
490 	if (!ok) {
491 		ok = add_string_to_array(mem_ctx, spn, array, num);
492 		if (!ok) {
493 			return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
494 		}
495 	}
496 	return ADS_SUCCESS;
497 }
498 
499 /****************************************************************
500  Set a machines dNSHostName and servicePrincipalName attributes
501 ****************************************************************/
502 
libnet_join_set_machine_spn(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)503 static ADS_STATUS libnet_join_set_machine_spn(TALLOC_CTX *mem_ctx,
504 					      struct libnet_JoinCtx *r)
505 {
506 	TALLOC_CTX *frame = talloc_stackframe();
507 	ADS_STATUS status;
508 	ADS_MODLIST mods;
509 	fstring my_fqdn;
510 	fstring my_alias;
511 	const char **spn_array = NULL;
512 	size_t num_spns = 0;
513 	char *spn = NULL;
514 	const char **netbios_aliases = NULL;
515 	const char **addl_hostnames = NULL;
516 
517 	/* Find our DN */
518 
519 	status = libnet_join_find_machine_acct(mem_ctx, r);
520 	if (!ADS_ERR_OK(status)) {
521 		return status;
522 	}
523 
524 	status = libnet_join_get_machine_spns(frame,
525 					      r,
526 					      discard_const_p(char **, &spn_array),
527 					      &num_spns);
528 	if (!ADS_ERR_OK(status)) {
529 		DEBUG(5, ("Retrieving the servicePrincipalNames failed.\n"));
530 	}
531 
532 	/* Windows only creates HOST/shortname & HOST/fqdn. */
533 
534 	spn = talloc_asprintf(frame, "HOST/%s", r->in.machine_name);
535 	if (spn == NULL) {
536 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
537 		goto done;
538 	}
539 	if (!strupper_m(spn)) {
540 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
541 		goto done;
542 	}
543 
544 	status = add_uniq_spn(frame, spn, &spn_array, &num_spns);
545 	if (!ADS_ERR_OK(status)) {
546 		goto done;
547 	}
548 
549 	if (r->in.dnshostname != NULL) {
550 		fstr_sprintf(my_fqdn, "%s", r->in.dnshostname);
551 	} else {
552 		fstr_sprintf(my_fqdn, "%s.%s", r->in.machine_name,
553 			     lp_dnsdomain());
554 	}
555 
556 	if (!strlower_m(my_fqdn)) {
557 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
558 		goto done;
559 	}
560 
561 	spn = talloc_asprintf(frame, "HOST/%s", my_fqdn);
562 	if (spn == NULL) {
563 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
564 		goto done;
565 	}
566 
567 	status = add_uniq_spn(frame, spn, &spn_array, &num_spns);
568 	if (!ADS_ERR_OK(status)) {
569 		goto done;
570 	}
571 
572 	for (netbios_aliases = lp_netbios_aliases();
573 	     netbios_aliases != NULL && *netbios_aliases != NULL;
574 	     netbios_aliases++) {
575 		/*
576 		 * Add HOST/NETBIOSNAME
577 		 */
578 		spn = talloc_asprintf(frame, "HOST/%s", *netbios_aliases);
579 		if (spn == NULL) {
580 			status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
581 			goto done;
582 		}
583 		if (!strupper_m(spn)) {
584 			status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
585 			goto done;
586 		}
587 
588 		status = add_uniq_spn(frame, spn, &spn_array, &num_spns);
589 		if (!ADS_ERR_OK(status)) {
590 			goto done;
591 		}
592 
593 		/*
594 		 * Add HOST/netbiosname.domainname
595 		 */
596 		fstr_sprintf(my_alias, "%s.%s",
597 			     *netbios_aliases,
598 			     lp_dnsdomain());
599 
600 		spn = talloc_asprintf(frame, "HOST/%s", my_alias);
601 		if (spn == NULL) {
602 			status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
603 			goto done;
604 		}
605 
606 		status = add_uniq_spn(frame, spn, &spn_array, &num_spns);
607 		if (!ADS_ERR_OK(status)) {
608 			goto done;
609 		}
610 	}
611 
612 	for (addl_hostnames = lp_additional_dns_hostnames();
613 	     addl_hostnames != NULL && *addl_hostnames != NULL;
614 	     addl_hostnames++) {
615 
616 		spn = talloc_asprintf(frame, "HOST/%s", *addl_hostnames);
617 		if (spn == NULL) {
618 			status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
619 			goto done;
620 		}
621 
622 		status = add_uniq_spn(frame, spn, &spn_array, &num_spns);
623 		if (!ADS_ERR_OK(status)) {
624 			goto done;
625 		}
626 	}
627 
628 	/* make sure to NULL terminate the array */
629 	spn_array = talloc_realloc(frame, spn_array, const char *, num_spns + 1);
630 	if (spn_array == NULL) {
631 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
632 		goto done;
633 	}
634 	spn_array[num_spns] = NULL;
635 
636 	mods = ads_init_mods(mem_ctx);
637 	if (!mods) {
638 		status = ADS_ERROR_LDAP(LDAP_NO_MEMORY);
639 		goto done;
640 	}
641 
642 	/* fields of primary importance */
643 
644 	status = ads_mod_str(mem_ctx, &mods, "dNSHostName", my_fqdn);
645 	if (!ADS_ERR_OK(status)) {
646 		goto done;
647 	}
648 
649 	status = ads_mod_strlist(mem_ctx, &mods, "servicePrincipalName",
650 				 spn_array);
651 	if (!ADS_ERR_OK(status)) {
652 		goto done;
653 	}
654 
655 	addl_hostnames = lp_additional_dns_hostnames();
656 	if (addl_hostnames != NULL && *addl_hostnames != NULL) {
657 		status = ads_mod_strlist(mem_ctx, &mods,
658 					 "msDS-AdditionalDnsHostName",
659 					 addl_hostnames);
660 		if (!ADS_ERR_OK(status)) {
661 			goto done;
662 		}
663 	}
664 
665 	status = ads_gen_mod(r->in.ads, r->out.dn, mods);
666 
667 done:
668 	TALLOC_FREE(frame);
669 	return status;
670 }
671 
672 /****************************************************************
673 ****************************************************************/
674 
libnet_join_set_machine_upn(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)675 static ADS_STATUS libnet_join_set_machine_upn(TALLOC_CTX *mem_ctx,
676 					      struct libnet_JoinCtx *r)
677 {
678 	ADS_STATUS status;
679 	ADS_MODLIST mods;
680 
681 	if (!r->in.create_upn) {
682 		return ADS_SUCCESS;
683 	}
684 
685 	/* Find our DN */
686 
687 	status = libnet_join_find_machine_acct(mem_ctx, r);
688 	if (!ADS_ERR_OK(status)) {
689 		return status;
690 	}
691 
692 	if (!r->in.upn) {
693 		const char *realm = r->out.dns_domain_name;
694 
695 		/* in case we are about to generate a keytab during the join
696 		 * make sure the default upn we create is usable with kinit -k.
697 		 * gd */
698 
699 		if (USE_KERBEROS_KEYTAB) {
700 			realm = talloc_strdup_upper(mem_ctx,
701 						    r->out.dns_domain_name);
702 		}
703 
704 		if (!realm) {
705 			return ADS_ERROR(LDAP_NO_MEMORY);
706 		}
707 
708 		r->in.upn = talloc_asprintf(mem_ctx,
709 					    "host/%s@%s",
710 					    r->in.machine_name,
711 					    realm);
712 		if (!r->in.upn) {
713 			return ADS_ERROR(LDAP_NO_MEMORY);
714 		}
715 	}
716 
717 	/* now do the mods */
718 
719 	mods = ads_init_mods(mem_ctx);
720 	if (!mods) {
721 		return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
722 	}
723 
724 	/* fields of primary importance */
725 
726 	status = ads_mod_str(mem_ctx, &mods, "userPrincipalName", r->in.upn);
727 	if (!ADS_ERR_OK(status)) {
728 		return ADS_ERROR_LDAP(LDAP_NO_MEMORY);
729 	}
730 
731 	return ads_gen_mod(r->in.ads, r->out.dn, mods);
732 }
733 
734 
735 /****************************************************************
736 ****************************************************************/
737 
libnet_join_set_os_attributes(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)738 static ADS_STATUS libnet_join_set_os_attributes(TALLOC_CTX *mem_ctx,
739 						struct libnet_JoinCtx *r)
740 {
741 	ADS_STATUS status;
742 	ADS_MODLIST mods;
743 	char *os_sp = NULL;
744 
745 	if (!r->in.os_name || !r->in.os_version ) {
746 		return ADS_SUCCESS;
747 	}
748 
749 	/* Find our DN */
750 
751 	status = libnet_join_find_machine_acct(mem_ctx, r);
752 	if (!ADS_ERR_OK(status)) {
753 		return status;
754 	}
755 
756 	/* now do the mods */
757 
758 	mods = ads_init_mods(mem_ctx);
759 	if (!mods) {
760 		return ADS_ERROR(LDAP_NO_MEMORY);
761 	}
762 
763 	if (r->in.os_servicepack) {
764 		/*
765 		 * if blank string then leave os_sp equal to NULL to force
766 		 * attribute delete (LDAP_MOD_DELETE)
767 		 */
768 		if (!strequal(r->in.os_servicepack,"")) {
769 			os_sp = talloc_strdup(mem_ctx, r->in.os_servicepack);
770 		}
771 	} else {
772 		os_sp = talloc_asprintf(mem_ctx, "Samba %s",
773 					samba_version_string());
774 	}
775 	if (!os_sp && !strequal(r->in.os_servicepack,"")) {
776 		return ADS_ERROR(LDAP_NO_MEMORY);
777 	}
778 
779 	/* fields of primary importance */
780 
781 	status = ads_mod_str(mem_ctx, &mods, "operatingSystem",
782 			     r->in.os_name);
783 	if (!ADS_ERR_OK(status)) {
784 		return status;
785 	}
786 
787 	status = ads_mod_str(mem_ctx, &mods, "operatingSystemVersion",
788 			     r->in.os_version);
789 	if (!ADS_ERR_OK(status)) {
790 		return status;
791 	}
792 
793 	status = ads_mod_str(mem_ctx, &mods, "operatingSystemServicePack",
794 			     os_sp);
795 	if (!ADS_ERR_OK(status)) {
796 		return status;
797 	}
798 
799 	return ads_gen_mod(r->in.ads, r->out.dn, mods);
800 }
801 
802 /****************************************************************
803 ****************************************************************/
804 
libnet_join_set_etypes(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)805 static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx,
806 					 struct libnet_JoinCtx *r)
807 {
808 	ADS_STATUS status;
809 	ADS_MODLIST mods;
810 	const char *etype_list_str;
811 
812 	etype_list_str = talloc_asprintf(mem_ctx, "%d",
813 					 r->in.desired_encryption_types);
814 	if (!etype_list_str) {
815 		return ADS_ERROR(LDAP_NO_MEMORY);
816 	}
817 
818 	/* Find our DN */
819 
820 	status = libnet_join_find_machine_acct(mem_ctx, r);
821 	if (!ADS_ERR_OK(status)) {
822 		return status;
823 	}
824 
825 	if (r->in.desired_encryption_types == r->out.set_encryption_types) {
826 		return ADS_SUCCESS;
827 	}
828 
829 	/* now do the mods */
830 
831 	mods = ads_init_mods(mem_ctx);
832 	if (!mods) {
833 		return ADS_ERROR(LDAP_NO_MEMORY);
834 	}
835 
836 	status = ads_mod_str(mem_ctx, &mods, "msDS-SupportedEncryptionTypes",
837 			     etype_list_str);
838 	if (!ADS_ERR_OK(status)) {
839 		return status;
840 	}
841 
842 	status = ads_gen_mod(r->in.ads, r->out.dn, mods);
843 	if (!ADS_ERR_OK(status)) {
844 		return status;
845 	}
846 
847 	r->out.set_encryption_types = r->in.desired_encryption_types;
848 
849 	return ADS_SUCCESS;
850 }
851 
852 /****************************************************************
853 ****************************************************************/
854 
libnet_join_create_keytab(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)855 static bool libnet_join_create_keytab(TALLOC_CTX *mem_ctx,
856 				      struct libnet_JoinCtx *r)
857 {
858 	if (!USE_SYSTEM_KEYTAB) {
859 		return true;
860 	}
861 
862 	if (ads_keytab_create_default(r->in.ads) != 0) {
863 		return false;
864 	}
865 
866 	return true;
867 }
868 
869 /****************************************************************
870 ****************************************************************/
871 
libnet_join_derive_salting_principal(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)872 static bool libnet_join_derive_salting_principal(TALLOC_CTX *mem_ctx,
873 						 struct libnet_JoinCtx *r)
874 {
875 	uint32_t domain_func;
876 	ADS_STATUS status;
877 	const char *salt = NULL;
878 	char *std_salt = NULL;
879 
880 	status = ads_domain_func_level(r->in.ads, &domain_func);
881 	if (!ADS_ERR_OK(status)) {
882 		libnet_join_set_error_string(mem_ctx, r,
883 			"failed to determine domain functional level: %s",
884 			ads_errstr(status));
885 		return false;
886 	}
887 
888 	/* go ahead and setup the default salt */
889 
890 	std_salt = kerberos_standard_des_salt();
891 	if (!std_salt) {
892 		libnet_join_set_error_string(mem_ctx, r,
893 			"failed to obtain standard DES salt");
894 		return false;
895 	}
896 
897 	salt = talloc_strdup(mem_ctx, std_salt);
898 	if (!salt) {
899 		return false;
900 	}
901 
902 	SAFE_FREE(std_salt);
903 
904 	/* if it's a Windows functional domain, we have to look for the UPN */
905 
906 	if (domain_func == DS_DOMAIN_FUNCTION_2000) {
907 		char *upn;
908 
909 		upn = ads_get_upn(r->in.ads, mem_ctx,
910 				  r->in.machine_name);
911 		if (upn) {
912 			salt = talloc_strdup(mem_ctx, upn);
913 			if (!salt) {
914 				return false;
915 			}
916 		}
917 	}
918 
919 	r->out.krb5_salt = salt;
920 	return true;
921 }
922 
923 /****************************************************************
924 ****************************************************************/
925 
libnet_join_post_processing_ads_modify(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)926 static ADS_STATUS libnet_join_post_processing_ads_modify(TALLOC_CTX *mem_ctx,
927 							 struct libnet_JoinCtx *r)
928 {
929 	ADS_STATUS status;
930 	bool need_etype_update = false;
931 
932 	if (!r->in.ads) {
933 		status = libnet_join_connect_ads_user(mem_ctx, r);
934 		if (!ADS_ERR_OK(status)) {
935 			return status;
936 		}
937 	}
938 
939 	status = libnet_join_set_machine_spn(mem_ctx, r);
940 	if (!ADS_ERR_OK(status)) {
941 		libnet_join_set_error_string(mem_ctx, r,
942 			"Failed to set machine spn: %s\n"
943 			"Do you have sufficient permissions to create machine "
944 			"accounts?",
945 			ads_errstr(status));
946 		return status;
947 	}
948 
949 	status = libnet_join_set_os_attributes(mem_ctx, r);
950 	if (!ADS_ERR_OK(status)) {
951 		libnet_join_set_error_string(mem_ctx, r,
952 			"failed to set machine os attributes: %s",
953 			ads_errstr(status));
954 		return status;
955 	}
956 
957 	status = libnet_join_set_machine_upn(mem_ctx, r);
958 	if (!ADS_ERR_OK(status)) {
959 		libnet_join_set_error_string(mem_ctx, r,
960 			"failed to set machine upn: %s",
961 			ads_errstr(status));
962 		return status;
963 	}
964 
965 	status = libnet_join_find_machine_acct(mem_ctx, r);
966 	if (!ADS_ERR_OK(status)) {
967 		return status;
968 	}
969 
970 	if (r->in.desired_encryption_types != r->out.set_encryption_types) {
971 		uint32_t func_level = 0;
972 
973 		status = ads_domain_func_level(r->in.ads, &func_level);
974 		if (!ADS_ERR_OK(status)) {
975 			libnet_join_set_error_string(mem_ctx, r,
976 				"failed to query domain controller functional level: %s",
977 				ads_errstr(status));
978 			return status;
979 		}
980 
981 		if (func_level >= DS_DOMAIN_FUNCTION_2008) {
982 			need_etype_update = true;
983 		}
984 	}
985 
986 	if (need_etype_update) {
987 		/*
988 		 * We need to reconnect as machine account in order
989 		 * to update msDS-SupportedEncryptionTypes reliable
990 		 */
991 
992 		if (r->in.ads->auth.ccache_name != NULL) {
993 			ads_kdestroy(r->in.ads->auth.ccache_name);
994 			r->in.ads->auth.ccache_name = NULL;
995 		}
996 
997 		ads_destroy(&r->in.ads);
998 
999 		status = libnet_join_connect_ads_machine(mem_ctx, r);
1000 		if (!ADS_ERR_OK(status)) {
1001 			libnet_join_set_error_string(mem_ctx, r,
1002 				"Failed to connect as machine account: %s",
1003 				ads_errstr(status));
1004 			return status;
1005 		}
1006 
1007 		status = libnet_join_set_etypes(mem_ctx, r);
1008 		if (!ADS_ERR_OK(status)) {
1009 			libnet_join_set_error_string(mem_ctx, r,
1010 				"failed to set machine kerberos encryption types: %s",
1011 				ads_errstr(status));
1012 			return status;
1013 		}
1014 	}
1015 
1016 	if (!libnet_join_derive_salting_principal(mem_ctx, r)) {
1017 		return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
1018 	}
1019 
1020 	return ADS_SUCCESS;
1021 }
1022 
libnet_join_post_processing_ads_sync(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)1023 static ADS_STATUS libnet_join_post_processing_ads_sync(TALLOC_CTX *mem_ctx,
1024 							struct libnet_JoinCtx *r)
1025 {
1026 	if (!libnet_join_create_keytab(mem_ctx, r)) {
1027 		libnet_join_set_error_string(mem_ctx, r,
1028 			"failed to create kerberos keytab");
1029 		return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
1030 	}
1031 
1032 	return ADS_SUCCESS;
1033 }
1034 #endif /* HAVE_ADS */
1035 
1036 /****************************************************************
1037  Store the machine password and domain SID
1038 ****************************************************************/
1039 
libnet_join_joindomain_store_secrets(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)1040 static bool libnet_join_joindomain_store_secrets(TALLOC_CTX *mem_ctx,
1041 						 struct libnet_JoinCtx *r)
1042 {
1043 	NTSTATUS status;
1044 
1045 	status = secrets_store_JoinCtx(r);
1046 	if (!NT_STATUS_IS_OK(status)) {
1047 		DBG_ERR("secrets_store_JoinCtx() failed %s\n",
1048 			nt_errstr(status));
1049 		return false;
1050 	}
1051 
1052 	return true;
1053 }
1054 
1055 /****************************************************************
1056  Connect dc's IPC$ share
1057 ****************************************************************/
1058 
libnet_join_connect_dc_ipc(const char * dc,const char * user,const char * domain,const char * pass,bool use_kerberos,struct cli_state ** cli)1059 static NTSTATUS libnet_join_connect_dc_ipc(const char *dc,
1060 					   const char *user,
1061 					   const char *domain,
1062 					   const char *pass,
1063 					   bool use_kerberos,
1064 					   struct cli_state **cli)
1065 {
1066 	int flags = 0;
1067 
1068 	if (use_kerberos) {
1069 		flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
1070 	}
1071 
1072 	if (use_kerberos && pass) {
1073 		flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
1074 	}
1075 
1076 	return cli_full_connection(cli, NULL,
1077 				   dc,
1078 				   NULL, 0,
1079 				   "IPC$", "IPC",
1080 				   user,
1081 				   domain,
1082 				   pass,
1083 				   flags,
1084 				   SMB_SIGNING_IPC_DEFAULT);
1085 }
1086 
1087 /****************************************************************
1088  Lookup domain dc's info
1089 ****************************************************************/
1090 
libnet_join_lookup_dc_rpc(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r,struct cli_state ** cli)1091 static NTSTATUS libnet_join_lookup_dc_rpc(TALLOC_CTX *mem_ctx,
1092 					  struct libnet_JoinCtx *r,
1093 					  struct cli_state **cli)
1094 {
1095 	struct rpc_pipe_client *pipe_hnd = NULL;
1096 	struct policy_handle lsa_pol;
1097 	NTSTATUS status, result;
1098 	union lsa_PolicyInformation *info = NULL;
1099 	struct dcerpc_binding_handle *b;
1100 	const char *account = r->in.admin_account;
1101 	const char *domain = r->in.admin_domain;
1102 	const char *password = r->in.admin_password;
1103 	bool use_kerberos = r->in.use_kerberos;
1104 
1105 	if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE) {
1106 		account = "";
1107 		domain = "";
1108 		password = NULL;
1109 		use_kerberos = false;
1110 	}
1111 
1112 	status = libnet_join_connect_dc_ipc(r->in.dc_name,
1113 					    account,
1114 					    domain,
1115 					    password,
1116 					    use_kerberos,
1117 					    cli);
1118 	if (!NT_STATUS_IS_OK(status)) {
1119 		goto done;
1120 	}
1121 
1122 	status = cli_rpc_pipe_open_noauth(*cli, &ndr_table_lsarpc,
1123 					  &pipe_hnd);
1124 	if (!NT_STATUS_IS_OK(status)) {
1125 		DEBUG(0,("Error connecting to LSA pipe. Error was %s\n",
1126 			nt_errstr(status)));
1127 		goto done;
1128 	}
1129 
1130 	b = pipe_hnd->binding_handle;
1131 
1132 	status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
1133 					SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1134 	if (!NT_STATUS_IS_OK(status)) {
1135 		goto done;
1136 	}
1137 
1138 	status = dcerpc_lsa_QueryInfoPolicy2(b, mem_ctx,
1139 					     &lsa_pol,
1140 					     LSA_POLICY_INFO_DNS,
1141 					     &info,
1142 					     &result);
1143 	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result)) {
1144 		r->out.domain_is_ad = true;
1145 		r->out.netbios_domain_name = info->dns.name.string;
1146 		r->out.dns_domain_name = info->dns.dns_domain.string;
1147 		r->out.forest_name = info->dns.dns_forest.string;
1148 		r->out.domain_guid = info->dns.domain_guid;
1149 		r->out.domain_sid = dom_sid_dup(mem_ctx, info->dns.sid);
1150 		NT_STATUS_HAVE_NO_MEMORY(r->out.domain_sid);
1151 	}
1152 
1153 	if (!NT_STATUS_IS_OK(status)) {
1154 		status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
1155 						    &lsa_pol,
1156 						    LSA_POLICY_INFO_ACCOUNT_DOMAIN,
1157 						    &info,
1158 						    &result);
1159 		if (!NT_STATUS_IS_OK(status)) {
1160 			goto done;
1161 		}
1162 		if (!NT_STATUS_IS_OK(result)) {
1163 			status = result;
1164 			goto done;
1165 		}
1166 
1167 		r->out.netbios_domain_name = info->account_domain.name.string;
1168 		r->out.domain_sid = dom_sid_dup(mem_ctx, info->account_domain.sid);
1169 		NT_STATUS_HAVE_NO_MEMORY(r->out.domain_sid);
1170 	}
1171 
1172 	dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
1173 	TALLOC_FREE(pipe_hnd);
1174 
1175  done:
1176 	return status;
1177 }
1178 
1179 /****************************************************************
1180  Do the domain join unsecure
1181 ****************************************************************/
1182 
libnet_join_joindomain_rpc_unsecure(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r,struct cli_state * cli)1183 static NTSTATUS libnet_join_joindomain_rpc_unsecure(TALLOC_CTX *mem_ctx,
1184 						    struct libnet_JoinCtx *r,
1185 						    struct cli_state *cli)
1186 {
1187 	TALLOC_CTX *frame = talloc_stackframe();
1188 	struct rpc_pipe_client *authenticate_pipe = NULL;
1189 	struct rpc_pipe_client *passwordset_pipe = NULL;
1190 	struct cli_credentials *cli_creds;
1191 	struct netlogon_creds_cli_context *netlogon_creds = NULL;
1192 	struct netlogon_creds_CredentialState *creds = NULL;
1193 	uint32_t netlogon_flags = 0;
1194 	size_t len = 0;
1195 	bool ok;
1196 	DATA_BLOB new_trust_blob = data_blob_null;
1197 	NTSTATUS status;
1198 
1199 	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon,
1200 					  &authenticate_pipe);
1201 	if (!NT_STATUS_IS_OK(status)) {
1202 		TALLOC_FREE(frame);
1203 		return status;
1204 	}
1205 
1206 	if (!r->in.machine_password) {
1207 		int security = r->in.ads ? SEC_ADS : SEC_DOMAIN;
1208 
1209 		r->in.machine_password = trust_pw_new_value(mem_ctx,
1210 						r->in.secure_channel_type,
1211 						security);
1212 		if (r->in.machine_password == NULL) {
1213 			TALLOC_FREE(frame);
1214 			return NT_STATUS_NO_MEMORY;
1215 		}
1216 	}
1217 
1218 	cli_creds = cli_credentials_init(talloc_tos());
1219 	if (cli_creds == NULL) {
1220 		TALLOC_FREE(frame);
1221 		return NT_STATUS_NO_MEMORY;
1222 	}
1223 
1224 	cli_credentials_set_username(cli_creds, r->out.account_name,
1225 				     CRED_SPECIFIED);
1226 	cli_credentials_set_domain(cli_creds, r->in.domain_name,
1227 				   CRED_SPECIFIED);
1228 	cli_credentials_set_realm(cli_creds, "", CRED_SPECIFIED);
1229 	cli_credentials_set_secure_channel_type(cli_creds,
1230 						r->in.secure_channel_type);
1231 
1232 	/* according to WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED */
1233 	cli_credentials_set_password(cli_creds, r->in.admin_password,
1234 				     CRED_SPECIFIED);
1235 
1236 	status = rpccli_create_netlogon_creds_ctx(
1237 		cli_creds, authenticate_pipe->desthost, r->in.msg_ctx,
1238 		frame, &netlogon_creds);
1239 	if (!NT_STATUS_IS_OK(status)) {
1240 		TALLOC_FREE(frame);
1241 		return status;
1242 	}
1243 
1244 	status = rpccli_setup_netlogon_creds(
1245 		cli, NCACN_NP, netlogon_creds, true /* force_reauth */,
1246 		cli_creds);
1247 	if (!NT_STATUS_IS_OK(status)) {
1248 		TALLOC_FREE(frame);
1249 		return status;
1250 	}
1251 
1252 	status = netlogon_creds_cli_get(netlogon_creds, frame, &creds);
1253 	if (!NT_STATUS_IS_OK(status)) {
1254 		TALLOC_FREE(frame);
1255 		return status;
1256 	}
1257 
1258 	netlogon_flags = creds->negotiate_flags;
1259 	TALLOC_FREE(creds);
1260 
1261 	if (netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC) {
1262 		status = cli_rpc_pipe_open_schannel_with_creds(cli,
1263 							       &ndr_table_netlogon,
1264 							       NCACN_NP,
1265 							       netlogon_creds,
1266 							       &passwordset_pipe);
1267 		if (!NT_STATUS_IS_OK(status)) {
1268 			TALLOC_FREE(frame);
1269 			return status;
1270 		}
1271 	} else {
1272 		passwordset_pipe = authenticate_pipe;
1273 	}
1274 
1275 	len = strlen(r->in.machine_password);
1276 	ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16,
1277 				   r->in.machine_password, len,
1278 				   (void **)&new_trust_blob.data,
1279 				   &new_trust_blob.length);
1280 	if (!ok) {
1281 		status = NT_STATUS_UNMAPPABLE_CHARACTER;
1282 		if (errno == ENOMEM) {
1283 			status = NT_STATUS_NO_MEMORY;
1284 		}
1285 		TALLOC_FREE(frame);
1286 		return status;
1287 	}
1288 
1289 	status = netlogon_creds_cli_ServerPasswordSet(netlogon_creds,
1290 						      passwordset_pipe->binding_handle,
1291 						      &new_trust_blob,
1292 						      NULL); /* new_version */
1293 	if (!NT_STATUS_IS_OK(status)) {
1294 		TALLOC_FREE(frame);
1295 		return status;
1296 	}
1297 
1298 	TALLOC_FREE(frame);
1299 	return NT_STATUS_OK;
1300 }
1301 
1302 /****************************************************************
1303  Do the domain join
1304 ****************************************************************/
1305 
libnet_join_joindomain_rpc(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r,struct cli_state * cli)1306 static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
1307 					   struct libnet_JoinCtx *r,
1308 					   struct cli_state *cli)
1309 {
1310 	struct rpc_pipe_client *pipe_hnd = NULL;
1311 	struct policy_handle sam_pol, domain_pol, user_pol;
1312 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL, result;
1313 	char *acct_name;
1314 	struct lsa_String lsa_acct_name;
1315 	uint32_t user_rid;
1316 	uint32_t acct_flags = ACB_WSTRUST;
1317 	struct samr_Ids user_rids;
1318 	struct samr_Ids name_types;
1319 	union samr_UserInfo user_info;
1320 	struct dcerpc_binding_handle *b = NULL;
1321 	unsigned int old_timeout = 0;
1322 
1323 	DATA_BLOB session_key = data_blob_null;
1324 	struct samr_CryptPassword crypt_pwd;
1325 	struct samr_CryptPasswordEx crypt_pwd_ex;
1326 
1327 	ZERO_STRUCT(sam_pol);
1328 	ZERO_STRUCT(domain_pol);
1329 	ZERO_STRUCT(user_pol);
1330 
1331 	switch (r->in.secure_channel_type) {
1332 	case SEC_CHAN_WKSTA:
1333 		acct_flags = ACB_WSTRUST;
1334 		break;
1335 	case SEC_CHAN_BDC:
1336 		acct_flags = ACB_SVRTRUST;
1337 		break;
1338 	default:
1339 		return NT_STATUS_INVALID_PARAMETER;
1340 	}
1341 
1342 	if (!r->in.machine_password) {
1343 		int security = r->in.ads ? SEC_ADS : SEC_DOMAIN;
1344 
1345 		r->in.machine_password = trust_pw_new_value(mem_ctx,
1346 						r->in.secure_channel_type,
1347 						security);
1348 		NT_STATUS_HAVE_NO_MEMORY(r->in.machine_password);
1349 	}
1350 
1351 	/* Open the domain */
1352 
1353 	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
1354 					  &pipe_hnd);
1355 	if (!NT_STATUS_IS_OK(status)) {
1356 		DEBUG(0,("Error connecting to SAM pipe. Error was %s\n",
1357 			nt_errstr(status)));
1358 		goto done;
1359 	}
1360 
1361 	b = pipe_hnd->binding_handle;
1362 
1363 	status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
1364 	if (!NT_STATUS_IS_OK(status)) {
1365 		DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
1366 			nt_errstr(status)));
1367 		goto done;
1368 	}
1369 
1370 	status = dcerpc_samr_Connect2(b, mem_ctx,
1371 				      pipe_hnd->desthost,
1372 				      SAMR_ACCESS_ENUM_DOMAINS
1373 				      | SAMR_ACCESS_LOOKUP_DOMAIN,
1374 				      &sam_pol,
1375 				      &result);
1376 	if (!NT_STATUS_IS_OK(status)) {
1377 		goto done;
1378 	}
1379 	if (!NT_STATUS_IS_OK(result)) {
1380 		status = result;
1381 		goto done;
1382 	}
1383 
1384 	status = dcerpc_samr_OpenDomain(b, mem_ctx,
1385 					&sam_pol,
1386 					SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
1387 					| SAMR_DOMAIN_ACCESS_CREATE_USER
1388 					| SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
1389 					r->out.domain_sid,
1390 					&domain_pol,
1391 					&result);
1392 	if (!NT_STATUS_IS_OK(status)) {
1393 		goto done;
1394 	}
1395 	if (!NT_STATUS_IS_OK(result)) {
1396 		status = result;
1397 		goto done;
1398 	}
1399 
1400 	/* Create domain user */
1401 
1402 	acct_name = talloc_asprintf(mem_ctx, "%s$", r->in.machine_name);
1403 	if (!strlower_m(acct_name)) {
1404 		status = NT_STATUS_INVALID_PARAMETER;
1405 		goto done;
1406 	}
1407 
1408 	init_lsa_String(&lsa_acct_name, acct_name);
1409 
1410 	if (r->in.join_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE) {
1411 		uint32_t access_desired =
1412 			SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
1413 			SEC_STD_WRITE_DAC | SEC_STD_DELETE |
1414 			SAMR_USER_ACCESS_SET_PASSWORD |
1415 			SAMR_USER_ACCESS_GET_ATTRIBUTES |
1416 			SAMR_USER_ACCESS_SET_ATTRIBUTES;
1417 		uint32_t access_granted = 0;
1418 
1419 		DEBUG(10,("Creating account with desired access mask: %d\n",
1420 			access_desired));
1421 
1422 		status = dcerpc_samr_CreateUser2(b, mem_ctx,
1423 						 &domain_pol,
1424 						 &lsa_acct_name,
1425 						 acct_flags,
1426 						 access_desired,
1427 						 &user_pol,
1428 						 &access_granted,
1429 						 &user_rid,
1430 						 &result);
1431 		if (!NT_STATUS_IS_OK(status)) {
1432 			goto done;
1433 		}
1434 
1435 		status = result;
1436 		if (!NT_STATUS_IS_OK(status) &&
1437 		    !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
1438 
1439 			DEBUG(10,("Creation of workstation account failed: %s\n",
1440 				nt_errstr(status)));
1441 
1442 			/* If NT_STATUS_ACCESS_DENIED then we have a valid
1443 			   username/password combo but the user does not have
1444 			   administrator access. */
1445 
1446 			if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1447 				libnet_join_set_error_string(mem_ctx, r,
1448 					"User specified does not have "
1449 					"administrator privileges");
1450 			}
1451 
1452 			goto done;
1453 		}
1454 
1455 		if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
1456 			if (!(r->in.join_flags &
1457 			      WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED)) {
1458 				goto done;
1459 			}
1460 		}
1461 
1462 		/* We *must* do this.... don't ask... */
1463 
1464 		if (NT_STATUS_IS_OK(status)) {
1465 			dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1466 		}
1467 	}
1468 
1469 	status = dcerpc_samr_LookupNames(b, mem_ctx,
1470 					 &domain_pol,
1471 					 1,
1472 					 &lsa_acct_name,
1473 					 &user_rids,
1474 					 &name_types,
1475 					 &result);
1476 	if (!NT_STATUS_IS_OK(status)) {
1477 		goto done;
1478 	}
1479 	if (!NT_STATUS_IS_OK(result)) {
1480 		status = result;
1481 		goto done;
1482 	}
1483 	if (user_rids.count != 1) {
1484 		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1485 		goto done;
1486 	}
1487 	if (name_types.count != 1) {
1488 		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1489 		goto done;
1490 	}
1491 
1492 	if (name_types.ids[0] != SID_NAME_USER) {
1493 		DEBUG(0,("%s is not a user account (type=%d)\n",
1494 			acct_name, name_types.ids[0]));
1495 		status = NT_STATUS_INVALID_WORKSTATION;
1496 		goto done;
1497 	}
1498 
1499 	user_rid = user_rids.ids[0];
1500 
1501 	/* Open handle on user */
1502 
1503 	status = dcerpc_samr_OpenUser(b, mem_ctx,
1504 				      &domain_pol,
1505 				      SEC_FLAG_MAXIMUM_ALLOWED,
1506 				      user_rid,
1507 				      &user_pol,
1508 				      &result);
1509 	if (!NT_STATUS_IS_OK(status)) {
1510 		goto done;
1511 	}
1512 	if (!NT_STATUS_IS_OK(result)) {
1513 		status = result;
1514 		goto done;
1515 	}
1516 
1517 	/* Fill in the additional account flags now */
1518 
1519 	acct_flags |= ACB_PWNOEXP;
1520 
1521 	/* Set account flags on machine account */
1522 	ZERO_STRUCT(user_info.info16);
1523 	user_info.info16.acct_flags = acct_flags;
1524 
1525 	status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
1526 					  &user_pol,
1527 					  UserControlInformation,
1528 					  &user_info,
1529 					  &result);
1530 	if (!NT_STATUS_IS_OK(status)) {
1531 		dcerpc_samr_DeleteUser(b, mem_ctx,
1532 				       &user_pol,
1533 				       &result);
1534 
1535 		libnet_join_set_error_string(mem_ctx, r,
1536 			"Failed to set account flags for machine account (%s)\n",
1537 			nt_errstr(status));
1538 		goto done;
1539 	}
1540 
1541 	if (!NT_STATUS_IS_OK(result)) {
1542 		status = result;
1543 
1544 		dcerpc_samr_DeleteUser(b, mem_ctx,
1545 				       &user_pol,
1546 				       &result);
1547 
1548 		libnet_join_set_error_string(mem_ctx, r,
1549 			"Failed to set account flags for machine account (%s)\n",
1550 			nt_errstr(status));
1551 		goto done;
1552 	}
1553 
1554 	/* Set password on machine account - first try level 26 */
1555 
1556 	/*
1557 	 * increase the timeout as password filter modules on the DC
1558 	 * might delay the operation for a significant amount of time
1559 	 */
1560 	old_timeout = rpccli_set_timeout(pipe_hnd, 600000);
1561 
1562 	status = init_samr_CryptPasswordEx(r->in.machine_password,
1563 					   &session_key,
1564 					   &crypt_pwd_ex);
1565 	if (!NT_STATUS_IS_OK(status)) {
1566 		goto error;
1567 	}
1568 
1569 	user_info.info26.password = crypt_pwd_ex;
1570 	user_info.info26.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
1571 
1572 	status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
1573 					  &user_pol,
1574 					  UserInternal5InformationNew,
1575 					  &user_info,
1576 					  &result);
1577 
1578 	if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) {
1579 
1580 		/* retry with level 24 */
1581 
1582 		status = init_samr_CryptPassword(r->in.machine_password,
1583 						 &session_key,
1584 						 &crypt_pwd);
1585 		if (!NT_STATUS_IS_OK(status)) {
1586 			goto error;
1587 		}
1588 
1589 		user_info.info24.password = crypt_pwd;
1590 		user_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;
1591 
1592 		status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
1593 						  &user_pol,
1594 						  UserInternal5Information,
1595 						  &user_info,
1596 						  &result);
1597 	}
1598 
1599 error:
1600 	old_timeout = rpccli_set_timeout(pipe_hnd, old_timeout);
1601 
1602 	if (!NT_STATUS_IS_OK(status)) {
1603 
1604 		dcerpc_samr_DeleteUser(b, mem_ctx,
1605 				       &user_pol,
1606 				       &result);
1607 
1608 		libnet_join_set_error_string(mem_ctx, r,
1609 			"Failed to set password for machine account (%s)\n",
1610 			nt_errstr(status));
1611 		goto done;
1612 	}
1613 	if (!NT_STATUS_IS_OK(result)) {
1614 		status = result;
1615 
1616 		dcerpc_samr_DeleteUser(b, mem_ctx,
1617 				       &user_pol,
1618 				       &result);
1619 
1620 		libnet_join_set_error_string(mem_ctx, r,
1621 			"Failed to set password for machine account (%s)\n",
1622 			nt_errstr(status));
1623 		goto done;
1624 	}
1625 
1626 	status = NT_STATUS_OK;
1627 
1628  done:
1629 	if (!pipe_hnd) {
1630 		return status;
1631 	}
1632 
1633 	data_blob_clear_free(&session_key);
1634 
1635 	if (is_valid_policy_hnd(&sam_pol)) {
1636 		dcerpc_samr_Close(b, mem_ctx, &sam_pol, &result);
1637 	}
1638 	if (is_valid_policy_hnd(&domain_pol)) {
1639 		dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1640 	}
1641 	if (is_valid_policy_hnd(&user_pol)) {
1642 		dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1643 	}
1644 	TALLOC_FREE(pipe_hnd);
1645 
1646 	return status;
1647 }
1648 
1649 /****************************************************************
1650 ****************************************************************/
1651 
libnet_join_ok(struct messaging_context * msg_ctx,const char * netbios_domain_name,const char * dc_name,const bool use_kerberos)1652 NTSTATUS libnet_join_ok(struct messaging_context *msg_ctx,
1653 			const char *netbios_domain_name,
1654 			const char *dc_name,
1655 			const bool use_kerberos)
1656 {
1657 	TALLOC_CTX *frame = talloc_stackframe();
1658 	struct cli_state *cli = NULL;
1659 	struct rpc_pipe_client *netlogon_pipe = NULL;
1660 	struct cli_credentials *cli_creds = NULL;
1661 	struct netlogon_creds_cli_context *netlogon_creds = NULL;
1662 	struct netlogon_creds_CredentialState *creds = NULL;
1663 	uint32_t netlogon_flags = 0;
1664 	NTSTATUS status;
1665 	int flags = 0;
1666 
1667 	if (!dc_name) {
1668 		TALLOC_FREE(frame);
1669 		return NT_STATUS_INVALID_PARAMETER;
1670 	}
1671 
1672 	if (!secrets_init()) {
1673 		TALLOC_FREE(frame);
1674 		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1675 	}
1676 
1677 	status = pdb_get_trust_credentials(netbios_domain_name, NULL,
1678 					   frame, &cli_creds);
1679 	if (!NT_STATUS_IS_OK(status)) {
1680 		TALLOC_FREE(frame);
1681 		return status;
1682 	}
1683 
1684 	/* we don't want any old password */
1685 	cli_credentials_set_old_password(cli_creds, NULL, CRED_SPECIFIED);
1686 
1687 	if (use_kerberos) {
1688 		cli_credentials_set_kerberos_state(cli_creds,
1689 				CRED_MUST_USE_KERBEROS);
1690 	}
1691 
1692 	status = cli_full_connection_creds(&cli, NULL,
1693 					   dc_name,
1694 					   NULL, 0,
1695 					   "IPC$", "IPC",
1696 					   cli_creds,
1697 					   flags,
1698 					   SMB_SIGNING_IPC_DEFAULT);
1699 
1700 	if (!NT_STATUS_IS_OK(status)) {
1701 		status = cli_full_connection(&cli, NULL,
1702 					     dc_name,
1703 					     NULL, 0,
1704 					     "IPC$", "IPC",
1705 					     "",
1706 					     NULL,
1707 					     "",
1708 					     0,
1709 					     SMB_SIGNING_IPC_DEFAULT);
1710 	}
1711 
1712 	if (!NT_STATUS_IS_OK(status)) {
1713 		TALLOC_FREE(frame);
1714 		return status;
1715 	}
1716 
1717 	status = rpccli_create_netlogon_creds_ctx(cli_creds,
1718 						  dc_name,
1719 						  msg_ctx,
1720 						  frame,
1721 						  &netlogon_creds);
1722 	if (!NT_STATUS_IS_OK(status)) {
1723 		cli_shutdown(cli);
1724 		TALLOC_FREE(frame);
1725 		return status;
1726 	}
1727 
1728 	status = rpccli_setup_netlogon_creds(cli, NCACN_NP,
1729 					     netlogon_creds,
1730 					     true, /* force_reauth */
1731 					     cli_creds);
1732 	if (!NT_STATUS_IS_OK(status)) {
1733 		DEBUG(0,("connect_to_domain_password_server: "
1734 			 "unable to open the domain client session to "
1735 			 "machine %s. Flags[0x%08X] Error was : %s.\n",
1736 			 dc_name, (unsigned)netlogon_flags,
1737 			 nt_errstr(status)));
1738 		cli_shutdown(cli);
1739 		TALLOC_FREE(frame);
1740 		return status;
1741 	}
1742 
1743 	status = netlogon_creds_cli_get(netlogon_creds,
1744 					talloc_tos(),
1745 					&creds);
1746 	if (!NT_STATUS_IS_OK(status)) {
1747 		cli_shutdown(cli);
1748 		TALLOC_FREE(frame);
1749 		return status;
1750 	}
1751 	netlogon_flags = creds->negotiate_flags;
1752 	TALLOC_FREE(creds);
1753 
1754 	if (!(netlogon_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
1755 		cli_shutdown(cli);
1756 		TALLOC_FREE(frame);
1757 		return NT_STATUS_OK;
1758 	}
1759 
1760 	status = cli_rpc_pipe_open_schannel_with_creds(
1761 		cli, &ndr_table_netlogon, NCACN_NP,
1762 		netlogon_creds, &netlogon_pipe);
1763 
1764 	TALLOC_FREE(netlogon_pipe);
1765 
1766 	if (!NT_STATUS_IS_OK(status)) {
1767 		DEBUG(0,("libnet_join_ok: failed to open schannel session "
1768 			"on netlogon pipe to server %s for domain %s. "
1769 			"Error was %s\n",
1770 			smbXcli_conn_remote_name(cli->conn),
1771 			netbios_domain_name, nt_errstr(status)));
1772 		cli_shutdown(cli);
1773 		TALLOC_FREE(frame);
1774 		return status;
1775 	}
1776 
1777 	cli_shutdown(cli);
1778 	TALLOC_FREE(frame);
1779 	return NT_STATUS_OK;
1780 }
1781 
1782 /****************************************************************
1783 ****************************************************************/
1784 
libnet_join_post_verify(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)1785 static WERROR libnet_join_post_verify(TALLOC_CTX *mem_ctx,
1786 				      struct libnet_JoinCtx *r)
1787 {
1788 	NTSTATUS status;
1789 
1790 	status = libnet_join_ok(r->in.msg_ctx,
1791 				r->out.netbios_domain_name,
1792 				r->in.dc_name,
1793 				r->in.use_kerberos);
1794 	if (!NT_STATUS_IS_OK(status)) {
1795 		libnet_join_set_error_string(mem_ctx, r,
1796 			"failed to verify domain membership after joining: %s",
1797 			get_friendly_nt_error_msg(status));
1798 		return WERR_NERR_SETUPNOTJOINED;
1799 	}
1800 
1801 	return WERR_OK;
1802 }
1803 
1804 /****************************************************************
1805 ****************************************************************/
1806 
libnet_join_unjoindomain_remove_secrets(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)1807 static bool libnet_join_unjoindomain_remove_secrets(TALLOC_CTX *mem_ctx,
1808 						    struct libnet_UnjoinCtx *r)
1809 {
1810 	/*
1811 	 * TODO: use values from 'struct libnet_UnjoinCtx' ?
1812 	 */
1813 	return secrets_delete_machine_password_ex(lp_workgroup(), lp_realm());
1814 }
1815 
1816 /****************************************************************
1817 ****************************************************************/
1818 
libnet_join_unjoindomain_rpc(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)1819 static NTSTATUS libnet_join_unjoindomain_rpc(TALLOC_CTX *mem_ctx,
1820 					     struct libnet_UnjoinCtx *r)
1821 {
1822 	struct cli_state *cli = NULL;
1823 	struct rpc_pipe_client *pipe_hnd = NULL;
1824 	struct policy_handle sam_pol, domain_pol, user_pol;
1825 	NTSTATUS status = NT_STATUS_UNSUCCESSFUL, result;
1826 	char *acct_name;
1827 	uint32_t user_rid;
1828 	struct lsa_String lsa_acct_name;
1829 	struct samr_Ids user_rids;
1830 	struct samr_Ids name_types;
1831 	union samr_UserInfo *info = NULL;
1832 	struct dcerpc_binding_handle *b = NULL;
1833 
1834 	ZERO_STRUCT(sam_pol);
1835 	ZERO_STRUCT(domain_pol);
1836 	ZERO_STRUCT(user_pol);
1837 
1838 	status = libnet_join_connect_dc_ipc(r->in.dc_name,
1839 					    r->in.admin_account,
1840 					    r->in.admin_domain,
1841 					    r->in.admin_password,
1842 					    r->in.use_kerberos,
1843 					    &cli);
1844 	if (!NT_STATUS_IS_OK(status)) {
1845 		goto done;
1846 	}
1847 
1848 	/* Open the domain */
1849 
1850 	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
1851 					  &pipe_hnd);
1852 	if (!NT_STATUS_IS_OK(status)) {
1853 		DEBUG(0,("Error connecting to SAM pipe. Error was %s\n",
1854 			nt_errstr(status)));
1855 		goto done;
1856 	}
1857 
1858 	b = pipe_hnd->binding_handle;
1859 
1860 	status = dcerpc_samr_Connect2(b, mem_ctx,
1861 				      pipe_hnd->desthost,
1862 				      SEC_FLAG_MAXIMUM_ALLOWED,
1863 				      &sam_pol,
1864 				      &result);
1865 	if (!NT_STATUS_IS_OK(status)) {
1866 		goto done;
1867 	}
1868 	if (!NT_STATUS_IS_OK(result)) {
1869 		status = result;
1870 		goto done;
1871 	}
1872 
1873 	status = dcerpc_samr_OpenDomain(b, mem_ctx,
1874 					&sam_pol,
1875 					SEC_FLAG_MAXIMUM_ALLOWED,
1876 					r->in.domain_sid,
1877 					&domain_pol,
1878 					&result);
1879 	if (!NT_STATUS_IS_OK(status)) {
1880 		goto done;
1881 	}
1882 	if (!NT_STATUS_IS_OK(result)) {
1883 		status = result;
1884 		goto done;
1885 	}
1886 
1887 	/* Create domain user */
1888 
1889 	acct_name = talloc_asprintf(mem_ctx, "%s$", r->in.machine_name);
1890 	if (!strlower_m(acct_name)) {
1891 		status = NT_STATUS_INVALID_PARAMETER;
1892 		goto done;
1893 	}
1894 
1895 	init_lsa_String(&lsa_acct_name, acct_name);
1896 
1897 	status = dcerpc_samr_LookupNames(b, mem_ctx,
1898 					 &domain_pol,
1899 					 1,
1900 					 &lsa_acct_name,
1901 					 &user_rids,
1902 					 &name_types,
1903 					 &result);
1904 
1905 	if (!NT_STATUS_IS_OK(status)) {
1906 		goto done;
1907 	}
1908 	if (!NT_STATUS_IS_OK(result)) {
1909 		status = result;
1910 		goto done;
1911 	}
1912 	if (user_rids.count != 1) {
1913 		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1914 		goto done;
1915 	}
1916 	if (name_types.count != 1) {
1917 		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1918 		goto done;
1919 	}
1920 
1921 	if (name_types.ids[0] != SID_NAME_USER) {
1922 		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name,
1923 			name_types.ids[0]));
1924 		status = NT_STATUS_INVALID_WORKSTATION;
1925 		goto done;
1926 	}
1927 
1928 	user_rid = user_rids.ids[0];
1929 
1930 	/* Open handle on user */
1931 
1932 	status = dcerpc_samr_OpenUser(b, mem_ctx,
1933 				      &domain_pol,
1934 				      SEC_FLAG_MAXIMUM_ALLOWED,
1935 				      user_rid,
1936 				      &user_pol,
1937 				      &result);
1938 	if (!NT_STATUS_IS_OK(status)) {
1939 		goto done;
1940 	}
1941 	if (!NT_STATUS_IS_OK(result)) {
1942 		status = result;
1943 		goto done;
1944 	}
1945 
1946 	/* Get user info */
1947 
1948 	status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1949 					   &user_pol,
1950 					   16,
1951 					   &info,
1952 					   &result);
1953 	if (!NT_STATUS_IS_OK(status)) {
1954 		dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1955 		goto done;
1956 	}
1957 	if (!NT_STATUS_IS_OK(result)) {
1958 		status = result;
1959 		dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1960 		goto done;
1961 	}
1962 
1963 	/* now disable and setuser info */
1964 
1965 	info->info16.acct_flags |= ACB_DISABLED;
1966 
1967 	status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1968 					 &user_pol,
1969 					 16,
1970 					 info,
1971 					 &result);
1972 	if (!NT_STATUS_IS_OK(status)) {
1973 		dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1974 		goto done;
1975 	}
1976 	if (!NT_STATUS_IS_OK(result)) {
1977 		status = result;
1978 		dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1979 		goto done;
1980 	}
1981 	status = result;
1982 	dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1983 
1984 done:
1985 	if (pipe_hnd && b) {
1986 		if (is_valid_policy_hnd(&domain_pol)) {
1987 			dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1988 		}
1989 		if (is_valid_policy_hnd(&sam_pol)) {
1990 			dcerpc_samr_Close(b, mem_ctx, &sam_pol, &result);
1991 		}
1992 		TALLOC_FREE(pipe_hnd);
1993 	}
1994 
1995 	if (cli) {
1996 		cli_shutdown(cli);
1997 	}
1998 
1999 	return status;
2000 }
2001 
2002 /****************************************************************
2003 ****************************************************************/
2004 
do_join_modify_vals_config(struct libnet_JoinCtx * r)2005 static WERROR do_join_modify_vals_config(struct libnet_JoinCtx *r)
2006 {
2007 	WERROR werr = WERR_OK;
2008 	sbcErr err;
2009 	struct smbconf_ctx *ctx;
2010 
2011 	err = smbconf_init_reg(r, &ctx, NULL);
2012 	if (!SBC_ERROR_IS_OK(err)) {
2013 		werr = WERR_SERVICE_DOES_NOT_EXIST;
2014 		goto done;
2015 	}
2016 
2017 	if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE)) {
2018 
2019 		err = smbconf_set_global_parameter(ctx, "security", "user");
2020 		if (!SBC_ERROR_IS_OK(err)) {
2021 			werr = WERR_SERVICE_DOES_NOT_EXIST;
2022 			goto done;
2023 		}
2024 
2025 		err = smbconf_set_global_parameter(ctx, "workgroup",
2026 						   r->in.domain_name);
2027 		if (!SBC_ERROR_IS_OK(err)) {
2028 			werr = WERR_SERVICE_DOES_NOT_EXIST;
2029 			goto done;
2030 		}
2031 
2032 		smbconf_delete_global_parameter(ctx, "realm");
2033 		goto done;
2034 	}
2035 
2036 	err = smbconf_set_global_parameter(ctx, "security", "domain");
2037 	if (!SBC_ERROR_IS_OK(err)) {
2038 		werr = WERR_SERVICE_DOES_NOT_EXIST;
2039 		goto done;
2040 	}
2041 
2042 	err = smbconf_set_global_parameter(ctx, "workgroup",
2043 					   r->out.netbios_domain_name);
2044 	if (!SBC_ERROR_IS_OK(err)) {
2045 		werr = WERR_SERVICE_DOES_NOT_EXIST;
2046 		goto done;
2047 	}
2048 
2049 	if (r->out.domain_is_ad) {
2050 		err = smbconf_set_global_parameter(ctx, "security", "ads");
2051 		if (!SBC_ERROR_IS_OK(err)) {
2052 			werr = WERR_SERVICE_DOES_NOT_EXIST;
2053 			goto done;
2054 		}
2055 
2056 		err = smbconf_set_global_parameter(ctx, "realm",
2057 						   r->out.dns_domain_name);
2058 		if (!SBC_ERROR_IS_OK(err)) {
2059 			werr = WERR_SERVICE_DOES_NOT_EXIST;
2060 			goto done;
2061 		}
2062 	}
2063 
2064  done:
2065 	smbconf_shutdown(ctx);
2066 	return werr;
2067 }
2068 
2069 /****************************************************************
2070 ****************************************************************/
2071 
do_unjoin_modify_vals_config(struct libnet_UnjoinCtx * r)2072 static WERROR do_unjoin_modify_vals_config(struct libnet_UnjoinCtx *r)
2073 {
2074 	WERROR werr = WERR_OK;
2075 	sbcErr err;
2076 	struct smbconf_ctx *ctx;
2077 
2078 	err = smbconf_init_reg(r, &ctx, NULL);
2079 	if (!SBC_ERROR_IS_OK(err)) {
2080 		werr = WERR_SERVICE_DOES_NOT_EXIST;
2081 		goto done;
2082 	}
2083 
2084 	if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
2085 
2086 		err = smbconf_set_global_parameter(ctx, "security", "user");
2087 		if (!SBC_ERROR_IS_OK(err)) {
2088 			werr = WERR_SERVICE_DOES_NOT_EXIST;
2089 			goto done;
2090 		}
2091 
2092 		err = smbconf_delete_global_parameter(ctx, "workgroup");
2093 		if (!SBC_ERROR_IS_OK(err)) {
2094 			werr = WERR_SERVICE_DOES_NOT_EXIST;
2095 			goto done;
2096 		}
2097 
2098 		smbconf_delete_global_parameter(ctx, "realm");
2099 	}
2100 
2101  done:
2102 	smbconf_shutdown(ctx);
2103 	return werr;
2104 }
2105 
2106 /****************************************************************
2107 ****************************************************************/
2108 
do_JoinConfig(struct libnet_JoinCtx * r)2109 static WERROR do_JoinConfig(struct libnet_JoinCtx *r)
2110 {
2111 	WERROR werr;
2112 
2113 	if (!W_ERROR_IS_OK(r->out.result)) {
2114 		return r->out.result;
2115 	}
2116 
2117 	if (!r->in.modify_config) {
2118 		return WERR_OK;
2119 	}
2120 
2121 	werr = do_join_modify_vals_config(r);
2122 	if (!W_ERROR_IS_OK(werr)) {
2123 		return werr;
2124 	}
2125 
2126 	lp_load_global(get_dyn_CONFIGFILE());
2127 
2128 	r->out.modified_config = true;
2129 	r->out.result = werr;
2130 
2131 	return werr;
2132 }
2133 
2134 /****************************************************************
2135 ****************************************************************/
2136 
libnet_unjoin_config(struct libnet_UnjoinCtx * r)2137 static WERROR libnet_unjoin_config(struct libnet_UnjoinCtx *r)
2138 {
2139 	WERROR werr;
2140 
2141 	if (!W_ERROR_IS_OK(r->out.result)) {
2142 		return r->out.result;
2143 	}
2144 
2145 	if (!r->in.modify_config) {
2146 		return WERR_OK;
2147 	}
2148 
2149 	werr = do_unjoin_modify_vals_config(r);
2150 	if (!W_ERROR_IS_OK(werr)) {
2151 		return werr;
2152 	}
2153 
2154 	lp_load_global(get_dyn_CONFIGFILE());
2155 
2156 	r->out.modified_config = true;
2157 	r->out.result = werr;
2158 
2159 	return werr;
2160 }
2161 
2162 /****************************************************************
2163 ****************************************************************/
2164 
libnet_parse_domain_dc(TALLOC_CTX * mem_ctx,const char * domain_str,const char ** domain_p,const char ** dc_p)2165 static bool libnet_parse_domain_dc(TALLOC_CTX *mem_ctx,
2166 				   const char *domain_str,
2167 				   const char **domain_p,
2168 				   const char **dc_p)
2169 {
2170 	char *domain = NULL;
2171 	char *dc = NULL;
2172 	const char *p = NULL;
2173 
2174 	if (!domain_str || !domain_p || !dc_p) {
2175 		return false;
2176 	}
2177 
2178 	p = strchr_m(domain_str, '\\');
2179 
2180 	if (p != NULL) {
2181 		domain = talloc_strndup(mem_ctx, domain_str,
2182 					 PTR_DIFF(p, domain_str));
2183 		dc = talloc_strdup(mem_ctx, p+1);
2184 		if (!dc) {
2185 			return false;
2186 		}
2187 	} else {
2188 		domain = talloc_strdup(mem_ctx, domain_str);
2189 		dc = NULL;
2190 	}
2191 	if (!domain) {
2192 		return false;
2193 	}
2194 
2195 	*domain_p = domain;
2196 
2197 	if (!*dc_p && dc) {
2198 		*dc_p = dc;
2199 	}
2200 
2201 	return true;
2202 }
2203 
2204 /****************************************************************
2205 ****************************************************************/
2206 
libnet_join_pre_processing(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)2207 static WERROR libnet_join_pre_processing(TALLOC_CTX *mem_ctx,
2208 					 struct libnet_JoinCtx *r)
2209 {
2210 	if (!r->in.domain_name) {
2211 		libnet_join_set_error_string(mem_ctx, r,
2212 			"No domain name defined");
2213 		return WERR_INVALID_PARAMETER;
2214 	}
2215 
2216 	if (strlen(r->in.machine_name) > 15) {
2217 		libnet_join_set_error_string(mem_ctx, r,
2218 			"Our netbios name can be at most 15 chars long, "
2219                          "\"%s\" is %u chars long\n",
2220                          r->in.machine_name,
2221 			 (unsigned int)strlen(r->in.machine_name));
2222 		return WERR_INVALID_PARAMETER;
2223         }
2224 
2225 	r->out.account_name = talloc_asprintf(mem_ctx, "%s$",
2226 				       r->in.machine_name);
2227 	if (r->out.account_name == NULL) {
2228 		libnet_join_set_error_string(mem_ctx, r,
2229 			"Unable to construct r->out.account_name");
2230 		return WERR_NOT_ENOUGH_MEMORY;
2231 	}
2232 
2233 	if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name,
2234 				    &r->in.domain_name,
2235 				    &r->in.dc_name)) {
2236 		libnet_join_set_error_string(mem_ctx, r,
2237 			"Failed to parse domain name");
2238 		return WERR_INVALID_PARAMETER;
2239 	}
2240 
2241 	if (!r->in.admin_domain) {
2242 		char *admin_domain = NULL;
2243 		char *admin_account = NULL;
2244 		bool ok;
2245 
2246 		ok = split_domain_user(mem_ctx,
2247 				       r->in.admin_account,
2248 				       &admin_domain,
2249 				       &admin_account);
2250 		if (!ok) {
2251 			return WERR_NOT_ENOUGH_MEMORY;
2252 		}
2253 
2254 		if (admin_domain != NULL) {
2255 			r->in.admin_domain = admin_domain;
2256 		} else {
2257 			r->in.admin_domain = r->in.domain_name;
2258 		}
2259 		r->in.admin_account = admin_account;
2260 	}
2261 
2262 	if (!secrets_init()) {
2263 		libnet_join_set_error_string(mem_ctx, r,
2264 			"Unable to open secrets database");
2265 		return WERR_CAN_NOT_COMPLETE;
2266 	}
2267 
2268 	return WERR_OK;
2269 }
2270 
2271 /****************************************************************
2272 ****************************************************************/
2273 
libnet_join_add_dom_rids_to_builtins(struct dom_sid * domain_sid)2274 static void libnet_join_add_dom_rids_to_builtins(struct dom_sid *domain_sid)
2275 {
2276 	NTSTATUS status;
2277 
2278 	/* Try adding dom admins to builtin\admins. Only log failures. */
2279 	status = create_builtin_administrators(domain_sid);
2280 	if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
2281 		DEBUG(10,("Unable to auto-add domain administrators to "
2282 			  "BUILTIN\\Administrators during join because "
2283 			  "winbindd must be running.\n"));
2284 	} else if (!NT_STATUS_IS_OK(status)) {
2285 		DEBUG(5, ("Failed to auto-add domain administrators to "
2286 			  "BUILTIN\\Administrators during join: %s\n",
2287 			  nt_errstr(status)));
2288 	}
2289 
2290 	/* Try adding dom users to builtin\users. Only log failures. */
2291 	status = create_builtin_users(domain_sid);
2292 	if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
2293 		DEBUG(10,("Unable to auto-add domain users to BUILTIN\\users "
2294 			  "during join because winbindd must be running.\n"));
2295 	} else if (!NT_STATUS_IS_OK(status)) {
2296 		DEBUG(5, ("Failed to auto-add domain administrators to "
2297 			  "BUILTIN\\Administrators during join: %s\n",
2298 			  nt_errstr(status)));
2299 	}
2300 
2301 	/* Try adding dom guests to builtin\guests. Only log failures. */
2302 	status = create_builtin_guests(domain_sid);
2303 	if (NT_STATUS_EQUAL(status, NT_STATUS_PROTOCOL_UNREACHABLE)) {
2304 		DEBUG(10,("Unable to auto-add domain guests to "
2305 			  "BUILTIN\\Guests during join because "
2306 			  "winbindd must be running.\n"));
2307 	} else if (!NT_STATUS_IS_OK(status)) {
2308 		DEBUG(5, ("Failed to auto-add domain guests to "
2309 			  "BUILTIN\\Guests during join: %s\n",
2310 			  nt_errstr(status)));
2311 	}
2312 }
2313 
2314 /****************************************************************
2315 ****************************************************************/
2316 
libnet_join_post_processing(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)2317 static WERROR libnet_join_post_processing(TALLOC_CTX *mem_ctx,
2318 					  struct libnet_JoinCtx *r)
2319 {
2320 	WERROR werr;
2321 
2322 	if (!W_ERROR_IS_OK(r->out.result)) {
2323 		return r->out.result;
2324 	}
2325 
2326 	if (!(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE)) {
2327 		werr = do_JoinConfig(r);
2328 		if (!W_ERROR_IS_OK(werr)) {
2329 			return werr;
2330 		}
2331 
2332 		return WERR_OK;
2333 	}
2334 
2335 #ifdef HAVE_ADS
2336 	if (r->out.domain_is_ad &&
2337 	    !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
2338 		ADS_STATUS ads_status;
2339 
2340 		ads_status  = libnet_join_post_processing_ads_modify(mem_ctx, r);
2341 		if (!ADS_ERR_OK(ads_status)) {
2342 			return WERR_GEN_FAILURE;
2343 		}
2344 	}
2345 #endif /* HAVE_ADS */
2346 
2347 	saf_join_store(r->out.netbios_domain_name, r->in.dc_name);
2348 	if (r->out.dns_domain_name) {
2349 		saf_join_store(r->out.dns_domain_name, r->in.dc_name);
2350 	}
2351 
2352 	if (!libnet_join_joindomain_store_secrets(mem_ctx, r)) {
2353 		return WERR_NERR_SETUPNOTJOINED;
2354 	}
2355 
2356 	werr = do_JoinConfig(r);
2357 	if (!W_ERROR_IS_OK(werr)) {
2358 		return werr;
2359 	}
2360 
2361 #ifdef HAVE_ADS
2362 	if (r->out.domain_is_ad &&
2363 	    !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
2364 		ADS_STATUS ads_status;
2365 
2366 		ads_status  = libnet_join_post_processing_ads_sync(mem_ctx, r);
2367 		if (!ADS_ERR_OK(ads_status)) {
2368 			return WERR_GEN_FAILURE;
2369 		}
2370 	}
2371 #endif /* HAVE_ADS */
2372 
2373 	libnet_join_add_dom_rids_to_builtins(r->out.domain_sid);
2374 
2375 	return WERR_OK;
2376 }
2377 
2378 /****************************************************************
2379 ****************************************************************/
2380 
libnet_destroy_JoinCtx(struct libnet_JoinCtx * r)2381 static int libnet_destroy_JoinCtx(struct libnet_JoinCtx *r)
2382 {
2383 	if (r->in.ads) {
2384 		ads_destroy(&r->in.ads);
2385 	}
2386 
2387 	return 0;
2388 }
2389 
2390 /****************************************************************
2391 ****************************************************************/
2392 
libnet_destroy_UnjoinCtx(struct libnet_UnjoinCtx * r)2393 static int libnet_destroy_UnjoinCtx(struct libnet_UnjoinCtx *r)
2394 {
2395 	if (r->in.ads) {
2396 		ads_destroy(&r->in.ads);
2397 	}
2398 
2399 	return 0;
2400 }
2401 
2402 /****************************************************************
2403 ****************************************************************/
2404 
libnet_init_JoinCtx(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx ** r)2405 WERROR libnet_init_JoinCtx(TALLOC_CTX *mem_ctx,
2406 			   struct libnet_JoinCtx **r)
2407 {
2408 	struct libnet_JoinCtx *ctx;
2409 
2410 	ctx = talloc_zero(mem_ctx, struct libnet_JoinCtx);
2411 	if (!ctx) {
2412 		return WERR_NOT_ENOUGH_MEMORY;
2413 	}
2414 
2415 	talloc_set_destructor(ctx, libnet_destroy_JoinCtx);
2416 
2417 	ctx->in.machine_name = talloc_strdup(mem_ctx, lp_netbios_name());
2418 	W_ERROR_HAVE_NO_MEMORY(ctx->in.machine_name);
2419 
2420 	ctx->in.secure_channel_type = SEC_CHAN_WKSTA;
2421 
2422 	ctx->in.desired_encryption_types = ENC_CRC32 |
2423 					   ENC_RSA_MD5 |
2424 					   ENC_RC4_HMAC_MD5;
2425 #ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
2426 	ctx->in.desired_encryption_types |= ENC_HMAC_SHA1_96_AES128;
2427 #endif
2428 #ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
2429 	ctx->in.desired_encryption_types |= ENC_HMAC_SHA1_96_AES256;
2430 #endif
2431 
2432 	*r = ctx;
2433 
2434 	return WERR_OK;
2435 }
2436 
2437 /****************************************************************
2438 ****************************************************************/
2439 
libnet_init_UnjoinCtx(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx ** r)2440 WERROR libnet_init_UnjoinCtx(TALLOC_CTX *mem_ctx,
2441 			     struct libnet_UnjoinCtx **r)
2442 {
2443 	struct libnet_UnjoinCtx *ctx;
2444 
2445 	ctx = talloc_zero(mem_ctx, struct libnet_UnjoinCtx);
2446 	if (!ctx) {
2447 		return WERR_NOT_ENOUGH_MEMORY;
2448 	}
2449 
2450 	talloc_set_destructor(ctx, libnet_destroy_UnjoinCtx);
2451 
2452 	ctx->in.machine_name = talloc_strdup(mem_ctx, lp_netbios_name());
2453 	W_ERROR_HAVE_NO_MEMORY(ctx->in.machine_name);
2454 
2455 	*r = ctx;
2456 
2457 	return WERR_OK;
2458 }
2459 
2460 /****************************************************************
2461 ****************************************************************/
2462 
libnet_join_check_config(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)2463 static WERROR libnet_join_check_config(TALLOC_CTX *mem_ctx,
2464 				       struct libnet_JoinCtx *r)
2465 {
2466 	bool valid_security = false;
2467 	bool valid_workgroup = false;
2468 	bool valid_realm = false;
2469 	bool ignored_realm = false;
2470 
2471 	/* check if configuration is already set correctly */
2472 
2473 	valid_workgroup = strequal(lp_workgroup(), r->out.netbios_domain_name);
2474 
2475 	switch (r->out.domain_is_ad) {
2476 		case false:
2477 			valid_security = (lp_security() == SEC_DOMAIN)
2478 				|| (lp_server_role() == ROLE_DOMAIN_PDC)
2479 				|| (lp_server_role() == ROLE_DOMAIN_BDC);
2480 			if (valid_workgroup && valid_security) {
2481 				/* nothing to be done */
2482 				return WERR_OK;
2483 			}
2484 			break;
2485 		case true:
2486 			valid_realm = strequal(lp_realm(), r->out.dns_domain_name);
2487 			switch (lp_security()) {
2488 			case SEC_DOMAIN:
2489 				if (!valid_realm && lp_winbind_rpc_only()) {
2490 					valid_realm = true;
2491 					ignored_realm = true;
2492 				}
2493 
2494 				FALL_THROUGH;
2495 			case SEC_ADS:
2496 				valid_security = true;
2497 			}
2498 
2499 			if (valid_workgroup && valid_realm && valid_security) {
2500 				if (ignored_realm && !r->in.modify_config)
2501 				{
2502 					libnet_join_set_error_string(mem_ctx, r,
2503 						"Warning: ignoring realm when "
2504 						"joining AD domain with "
2505 						"'security=domain' and "
2506 						"'winbind rpc only = yes'. "
2507 						"(realm set to '%s', "
2508 						"should be '%s').", lp_realm(),
2509 						r->out.dns_domain_name);
2510 				}
2511 				/* nothing to be done */
2512 				return WERR_OK;
2513 			}
2514 			break;
2515 	}
2516 
2517 	/* check if we are supposed to manipulate configuration */
2518 
2519 	if (!r->in.modify_config) {
2520 
2521 		char *wrong_conf = talloc_strdup(mem_ctx, "");
2522 
2523 		if (!valid_workgroup) {
2524 			wrong_conf = talloc_asprintf_append(wrong_conf,
2525 				"\"workgroup\" set to '%s', should be '%s'",
2526 				lp_workgroup(), r->out.netbios_domain_name);
2527 			W_ERROR_HAVE_NO_MEMORY(wrong_conf);
2528 		}
2529 
2530 		if (!valid_realm) {
2531 			wrong_conf = talloc_asprintf_append(wrong_conf,
2532 				"\"realm\" set to '%s', should be '%s'",
2533 				lp_realm(), r->out.dns_domain_name);
2534 			W_ERROR_HAVE_NO_MEMORY(wrong_conf);
2535 		}
2536 
2537 		if (!valid_security) {
2538 			const char *sec = NULL;
2539 			switch (lp_security()) {
2540 			case SEC_USER:  sec = "user"; break;
2541 			case SEC_DOMAIN: sec = "domain"; break;
2542 			case SEC_ADS: sec = "ads"; break;
2543 			}
2544 			wrong_conf = talloc_asprintf_append(wrong_conf,
2545 				"\"security\" set to '%s', should be %s",
2546 				sec, r->out.domain_is_ad ?
2547 				"either 'domain' or 'ads'" : "'domain'");
2548 			W_ERROR_HAVE_NO_MEMORY(wrong_conf);
2549 		}
2550 
2551 		libnet_join_set_error_string(mem_ctx, r,
2552 			"Invalid configuration (%s) and configuration modification "
2553 			"was not requested", wrong_conf);
2554 		return WERR_CAN_NOT_COMPLETE;
2555 	}
2556 
2557 	/* check if we are able to manipulate configuration */
2558 
2559 	if (!lp_config_backend_is_registry()) {
2560 		libnet_join_set_error_string(mem_ctx, r,
2561 			"Configuration manipulation requested but not "
2562 			"supported by backend");
2563 		return WERR_NOT_SUPPORTED;
2564 	}
2565 
2566 	return WERR_OK;
2567 }
2568 
2569 /****************************************************************
2570 ****************************************************************/
2571 
libnet_DomainJoin(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)2572 static WERROR libnet_DomainJoin(TALLOC_CTX *mem_ctx,
2573 				struct libnet_JoinCtx *r)
2574 {
2575 	NTSTATUS status;
2576 	WERROR werr;
2577 	struct cli_state *cli = NULL;
2578 #ifdef HAVE_ADS
2579 	ADS_STATUS ads_status;
2580 #endif /* HAVE_ADS */
2581 	const char *pre_connect_realm = NULL;
2582 	const char *numeric_dcip = NULL;
2583 	const char *sitename = NULL;
2584 
2585 	/* Before contacting a DC, we can securely know
2586 	 * the realm only if the user specifies it.
2587 	 */
2588 	if (r->in.use_kerberos &&
2589 	    r->in.domain_name_type == JoinDomNameTypeDNS) {
2590 		pre_connect_realm = r->in.domain_name;
2591 	}
2592 
2593 	if (!r->in.dc_name) {
2594 		struct netr_DsRGetDCNameInfo *info;
2595 		const char *dc;
2596 		uint32_t name_type_flags = 0;
2597 		if (r->in.domain_name_type == JoinDomNameTypeDNS) {
2598 			name_type_flags = DS_IS_DNS_NAME;
2599 		} else if (r->in.domain_name_type == JoinDomNameTypeNBT) {
2600 			name_type_flags = DS_IS_FLAT_NAME;
2601 		}
2602 		status = dsgetdcname(mem_ctx,
2603 				     r->in.msg_ctx,
2604 				     r->in.domain_name,
2605 				     NULL,
2606 				     NULL,
2607 				     DS_FORCE_REDISCOVERY |
2608 				     DS_DIRECTORY_SERVICE_REQUIRED |
2609 				     DS_WRITABLE_REQUIRED |
2610 				     DS_RETURN_DNS_NAME |
2611 				     name_type_flags,
2612 				     &info);
2613 		if (!NT_STATUS_IS_OK(status)) {
2614 			libnet_join_set_error_string(mem_ctx, r,
2615 				"failed to find DC for domain %s - %s",
2616 				r->in.domain_name,
2617 				get_friendly_nt_error_msg(status));
2618 			return WERR_NERR_DCNOTFOUND;
2619 		}
2620 
2621 		dc = strip_hostname(info->dc_unc);
2622 		r->in.dc_name = talloc_strdup(mem_ctx, dc);
2623 		W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
2624 
2625 		if (info->dc_address == NULL || info->dc_address[0] != '\\' ||
2626 		    info->dc_address[1] != '\\') {
2627 			DBG_ERR("ill-formed DC address '%s'\n",
2628 				info->dc_address);
2629 			return WERR_NERR_DCNOTFOUND;
2630 		}
2631 
2632 		numeric_dcip = info->dc_address + 2;
2633 		sitename = info->dc_site_name;
2634 		/* info goes out of scope but the memory stays
2635 		   allocated on the talloc context */
2636 	}
2637 
2638 	if (pre_connect_realm != NULL) {
2639 		struct sockaddr_storage ss = {0};
2640 
2641 		if (numeric_dcip != NULL) {
2642 			if (!interpret_string_addr(&ss, numeric_dcip,
2643 						   AI_NUMERICHOST)) {
2644 				DBG_ERR(
2645 				    "cannot parse IP address '%s' of DC '%s'\n",
2646 				    numeric_dcip, r->in.dc_name);
2647 				return WERR_NERR_DCNOTFOUND;
2648 			}
2649 		} else {
2650 			if (!interpret_string_addr(&ss, r->in.dc_name, 0)) {
2651 				DBG_WARNING(
2652 				    "cannot resolve IP address of DC '%s'\n",
2653 				    r->in.dc_name);
2654 				return WERR_NERR_DCNOTFOUND;
2655 			}
2656 		}
2657 
2658 		/* The domain parameter is only used as modifier
2659 		 * to krb5.conf file name. _JOIN_ is is not a valid
2660 		 * NetBIOS name so it cannot clash with another domain
2661 		 * -- Uri.
2662 		 */
2663 		create_local_private_krb5_conf_for_domain(pre_connect_realm,
2664 							  "_JOIN_",
2665 							  sitename,
2666 							  &ss);
2667 	}
2668 
2669 	status = libnet_join_lookup_dc_rpc(mem_ctx, r, &cli);
2670 	if (!NT_STATUS_IS_OK(status)) {
2671 		libnet_join_set_error_string(mem_ctx, r,
2672 			"failed to lookup DC info for domain '%s' over rpc: %s",
2673 			r->in.domain_name, get_friendly_nt_error_msg(status));
2674 		return ntstatus_to_werror(status);
2675 	}
2676 
2677 	werr = libnet_join_check_config(mem_ctx, r);
2678 	if (!W_ERROR_IS_OK(werr)) {
2679 		goto done;
2680 	}
2681 
2682 #ifdef HAVE_ADS
2683 
2684 	if (r->out.domain_is_ad) {
2685 		create_local_private_krb5_conf_for_domain(
2686 			r->out.dns_domain_name, r->out.netbios_domain_name,
2687 			sitename, smbXcli_conn_remote_sockaddr(cli->conn));
2688 	}
2689 
2690 	if (r->out.domain_is_ad &&
2691 	    !(r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE)) {
2692 
2693 		const char *initial_account_ou = r->in.account_ou;
2694 
2695 		/*
2696 		 * we want to create the msDS-SupportedEncryptionTypes attribute
2697 		 * as early as possible so always try an LDAP create as the user
2698 		 * first. We copy r->in.account_ou because it may be changed
2699 		 * during the machine pre-creation.
2700 		 */
2701 
2702 		ads_status = libnet_join_connect_ads_user(mem_ctx, r);
2703 		if (!ADS_ERR_OK(ads_status)) {
2704 			libnet_join_set_error_string(mem_ctx, r,
2705 				"failed to connect to AD: %s",
2706 				ads_errstr(ads_status));
2707 			return WERR_NERR_DEFAULTJOINREQUIRED;
2708 		}
2709 
2710 		ads_status = libnet_join_precreate_machine_acct(mem_ctx, r);
2711 		if (ADS_ERR_OK(ads_status)) {
2712 
2713 			/*
2714 			 * LDAP object creation succeeded.
2715 			 */
2716 			r->in.join_flags &= ~WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE;
2717 
2718 			return WERR_OK;
2719 		}
2720 
2721 		if (initial_account_ou != NULL) {
2722 			libnet_join_set_error_string(mem_ctx, r,
2723 				"failed to precreate account in ou %s: %s",
2724 				r->in.account_ou,
2725 				ads_errstr(ads_status));
2726 			return WERR_NERR_DEFAULTJOINREQUIRED;
2727 		}
2728 
2729 		DBG_INFO("Failed to pre-create account in OU %s: %s\n",
2730 			 r->in.account_ou, ads_errstr(ads_status));
2731 	}
2732 #endif /* HAVE_ADS */
2733 
2734 	if ((r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_UNSECURE) &&
2735 	    (r->in.join_flags & WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED)) {
2736 		status = libnet_join_joindomain_rpc_unsecure(mem_ctx, r, cli);
2737 	} else {
2738 		status = libnet_join_joindomain_rpc(mem_ctx, r, cli);
2739 	}
2740 	if (!NT_STATUS_IS_OK(status)) {
2741 		libnet_join_set_error_string(mem_ctx, r,
2742 			"failed to join domain '%s' over rpc: %s",
2743 			r->in.domain_name, get_friendly_nt_error_msg(status));
2744 		if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
2745 			return WERR_NERR_SETUPALREADYJOINED;
2746 		}
2747 		werr = ntstatus_to_werror(status);
2748 		goto done;
2749 	}
2750 
2751 	werr = WERR_OK;
2752 
2753  done:
2754 	if (cli) {
2755 		cli_shutdown(cli);
2756 	}
2757 
2758 	return werr;
2759 }
2760 
2761 /****************************************************************
2762 ****************************************************************/
2763 
libnet_join_rollback(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)2764 static WERROR libnet_join_rollback(TALLOC_CTX *mem_ctx,
2765 				   struct libnet_JoinCtx *r)
2766 {
2767 	WERROR werr;
2768 	struct libnet_UnjoinCtx *u = NULL;
2769 
2770 	werr = libnet_init_UnjoinCtx(mem_ctx, &u);
2771 	if (!W_ERROR_IS_OK(werr)) {
2772 		return werr;
2773 	}
2774 
2775 	u->in.debug		= r->in.debug;
2776 	u->in.dc_name		= r->in.dc_name;
2777 	u->in.domain_name	= r->in.domain_name;
2778 	u->in.admin_account	= r->in.admin_account;
2779 	u->in.admin_password	= r->in.admin_password;
2780 	u->in.modify_config	= r->in.modify_config;
2781 	u->in.use_kerberos	= r->in.use_kerberos;
2782 	u->in.unjoin_flags	= WKSSVC_JOIN_FLAGS_JOIN_TYPE |
2783 				  WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
2784 
2785 	werr = libnet_Unjoin(mem_ctx, u);
2786 	TALLOC_FREE(u);
2787 
2788 	return werr;
2789 }
2790 
2791 /****************************************************************
2792 ****************************************************************/
2793 
libnet_Join(TALLOC_CTX * mem_ctx,struct libnet_JoinCtx * r)2794 WERROR libnet_Join(TALLOC_CTX *mem_ctx,
2795 		   struct libnet_JoinCtx *r)
2796 {
2797 	WERROR werr;
2798 
2799 	if (r->in.debug) {
2800 		LIBNET_JOIN_IN_DUMP_CTX(mem_ctx, r);
2801 	}
2802 
2803 	ZERO_STRUCT(r->out);
2804 
2805 	werr = libnet_join_pre_processing(mem_ctx, r);
2806 	if (!W_ERROR_IS_OK(werr)) {
2807 		goto done;
2808 	}
2809 
2810 	if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
2811 		werr = libnet_DomainJoin(mem_ctx, r);
2812 		if (!W_ERROR_IS_OK(werr)) {
2813 			goto done;
2814 		}
2815 	}
2816 
2817 	werr = libnet_join_post_processing(mem_ctx, r);
2818 	if (!W_ERROR_IS_OK(werr)) {
2819 		goto done;
2820 	}
2821 
2822 	if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
2823 		werr = libnet_join_post_verify(mem_ctx, r);
2824 		if (!W_ERROR_IS_OK(werr)) {
2825 			libnet_join_rollback(mem_ctx, r);
2826 		}
2827 	}
2828 
2829  done:
2830 	r->out.result = werr;
2831 
2832 	if (r->in.debug) {
2833 		LIBNET_JOIN_OUT_DUMP_CTX(mem_ctx, r);
2834 	}
2835 	return werr;
2836 }
2837 
2838 /****************************************************************
2839 ****************************************************************/
2840 
libnet_DomainUnjoin(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)2841 static WERROR libnet_DomainUnjoin(TALLOC_CTX *mem_ctx,
2842 				  struct libnet_UnjoinCtx *r)
2843 {
2844 	NTSTATUS status;
2845 
2846 	if (!r->in.domain_sid) {
2847 		struct dom_sid sid;
2848 		if (!secrets_fetch_domain_sid(lp_workgroup(), &sid)) {
2849 			libnet_unjoin_set_error_string(mem_ctx, r,
2850 				"Unable to fetch domain sid: are we joined?");
2851 			return WERR_NERR_SETUPNOTJOINED;
2852 		}
2853 		r->in.domain_sid = dom_sid_dup(mem_ctx, &sid);
2854 		W_ERROR_HAVE_NO_MEMORY(r->in.domain_sid);
2855 	}
2856 
2857 	if (!(r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE) &&
2858 	    !r->in.delete_machine_account) {
2859 		libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
2860 		return WERR_OK;
2861 	}
2862 
2863 	if (!r->in.dc_name) {
2864 		struct netr_DsRGetDCNameInfo *info;
2865 		const char *dc;
2866 		status = dsgetdcname(mem_ctx,
2867 				     r->in.msg_ctx,
2868 				     r->in.domain_name,
2869 				     NULL,
2870 				     NULL,
2871 				     DS_DIRECTORY_SERVICE_REQUIRED |
2872 				     DS_WRITABLE_REQUIRED |
2873 				     DS_RETURN_DNS_NAME,
2874 				     &info);
2875 		if (!NT_STATUS_IS_OK(status)) {
2876 			libnet_unjoin_set_error_string(mem_ctx, r,
2877 				"failed to find DC for domain %s - %s",
2878 				r->in.domain_name,
2879 				get_friendly_nt_error_msg(status));
2880 			return WERR_NERR_DCNOTFOUND;
2881 		}
2882 
2883 		dc = strip_hostname(info->dc_unc);
2884 		r->in.dc_name = talloc_strdup(mem_ctx, dc);
2885 		W_ERROR_HAVE_NO_MEMORY(r->in.dc_name);
2886 	}
2887 
2888 #ifdef HAVE_ADS
2889 	/* for net ads leave, try to delete the account.  If it works,
2890 	   no sense in disabling.  If it fails, we can still try to
2891 	   disable it. jmcd */
2892 
2893 	if (r->in.delete_machine_account) {
2894 		ADS_STATUS ads_status;
2895 		ads_status = libnet_unjoin_connect_ads(mem_ctx, r);
2896 		if (ADS_ERR_OK(ads_status)) {
2897 			/* dirty hack */
2898 			r->out.dns_domain_name =
2899 				talloc_strdup(mem_ctx,
2900 					      r->in.ads->server.realm);
2901 			ads_status =
2902 				libnet_unjoin_remove_machine_acct(mem_ctx, r);
2903 		}
2904 		if (!ADS_ERR_OK(ads_status)) {
2905 			libnet_unjoin_set_error_string(mem_ctx, r,
2906 				"failed to remove machine account from AD: %s",
2907 				ads_errstr(ads_status));
2908 		} else {
2909 			r->out.deleted_machine_account = true;
2910 			W_ERROR_HAVE_NO_MEMORY(r->out.dns_domain_name);
2911 			libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
2912 			return WERR_OK;
2913 		}
2914 	}
2915 #endif /* HAVE_ADS */
2916 
2917 	/* The WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE flag really means
2918 	   "disable".  */
2919 	if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE) {
2920 		status = libnet_join_unjoindomain_rpc(mem_ctx, r);
2921 		if (!NT_STATUS_IS_OK(status)) {
2922 			libnet_unjoin_set_error_string(mem_ctx, r,
2923 				"failed to disable machine account via rpc: %s",
2924 				get_friendly_nt_error_msg(status));
2925 			if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
2926 				return WERR_NERR_SETUPNOTJOINED;
2927 			}
2928 			return ntstatus_to_werror(status);
2929 		}
2930 
2931 		r->out.dns_domain_name = talloc_strdup(mem_ctx,
2932 				                      r->in.domain_name);
2933 		r->out.disabled_machine_account = true;
2934 	}
2935 
2936 	/* If disable succeeded or was not requested at all, we
2937 	   should be getting rid of our end of things */
2938 
2939 	libnet_join_unjoindomain_remove_secrets(mem_ctx, r);
2940 
2941 	return WERR_OK;
2942 }
2943 
2944 /****************************************************************
2945 ****************************************************************/
2946 
libnet_unjoin_pre_processing(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)2947 static WERROR libnet_unjoin_pre_processing(TALLOC_CTX *mem_ctx,
2948 					   struct libnet_UnjoinCtx *r)
2949 {
2950 	if (!r->in.domain_name) {
2951 		libnet_unjoin_set_error_string(mem_ctx, r,
2952 			"No domain name defined");
2953 		return WERR_INVALID_PARAMETER;
2954 	}
2955 
2956 	if (!libnet_parse_domain_dc(mem_ctx, r->in.domain_name,
2957 				    &r->in.domain_name,
2958 				    &r->in.dc_name)) {
2959 		libnet_unjoin_set_error_string(mem_ctx, r,
2960 			"Failed to parse domain name");
2961 		return WERR_INVALID_PARAMETER;
2962 	}
2963 
2964 	if (IS_DC) {
2965 		return WERR_NERR_SETUPDOMAINCONTROLLER;
2966 	}
2967 
2968 	if (!r->in.admin_domain) {
2969 		char *admin_domain = NULL;
2970 		char *admin_account = NULL;
2971 		bool ok;
2972 
2973 		ok = split_domain_user(mem_ctx,
2974 				       r->in.admin_account,
2975 				       &admin_domain,
2976 				       &admin_account);
2977 		if (!ok) {
2978 			return WERR_NOT_ENOUGH_MEMORY;
2979 		}
2980 
2981 		if (admin_domain != NULL) {
2982 			r->in.admin_domain = admin_domain;
2983 		} else {
2984 			r->in.admin_domain = r->in.domain_name;
2985 		}
2986 		r->in.admin_account = admin_account;
2987 	}
2988 
2989 	if (!secrets_init()) {
2990 		libnet_unjoin_set_error_string(mem_ctx, r,
2991 			"Unable to open secrets database");
2992 		return WERR_CAN_NOT_COMPLETE;
2993 	}
2994 
2995 	return WERR_OK;
2996 }
2997 
2998 /****************************************************************
2999 ****************************************************************/
3000 
libnet_unjoin_post_processing(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)3001 static WERROR libnet_unjoin_post_processing(TALLOC_CTX *mem_ctx,
3002 					    struct libnet_UnjoinCtx *r)
3003 {
3004 	saf_delete(r->out.netbios_domain_name);
3005 	saf_delete(r->out.dns_domain_name);
3006 
3007 	return libnet_unjoin_config(r);
3008 }
3009 
3010 /****************************************************************
3011 ****************************************************************/
3012 
libnet_Unjoin(TALLOC_CTX * mem_ctx,struct libnet_UnjoinCtx * r)3013 WERROR libnet_Unjoin(TALLOC_CTX *mem_ctx,
3014 		     struct libnet_UnjoinCtx *r)
3015 {
3016 	WERROR werr;
3017 
3018 	if (r->in.debug) {
3019 		LIBNET_UNJOIN_IN_DUMP_CTX(mem_ctx, r);
3020 	}
3021 
3022 	werr = libnet_unjoin_pre_processing(mem_ctx, r);
3023 	if (!W_ERROR_IS_OK(werr)) {
3024 		goto done;
3025 	}
3026 
3027 	if (r->in.unjoin_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
3028 		werr = libnet_DomainUnjoin(mem_ctx, r);
3029 		if (!W_ERROR_IS_OK(werr)) {
3030 			libnet_unjoin_config(r);
3031 			goto done;
3032 		}
3033 	}
3034 
3035 	werr = libnet_unjoin_post_processing(mem_ctx, r);
3036 	if (!W_ERROR_IS_OK(werr)) {
3037 		goto done;
3038 	}
3039 
3040  done:
3041 	r->out.result = werr;
3042 
3043 	if (r->in.debug) {
3044 		LIBNET_UNJOIN_OUT_DUMP_CTX(mem_ctx, r);
3045 	}
3046 
3047 	return werr;
3048 }
3049