1 /*
2    Unix SMB/CIFS implementation.
3 
4    Copyright (C) Stefan Metzmacher 2015
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "includes.h"
21 #include "ldb.h"
22 #include "../lib/util/util_ldb.h"
23 #include "dsdb/samdb/samdb.h"
24 #include "libcli/security/security.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26 #include "librpc/gen_ndr/ndr_misc.h"
27 #include "../libds/common/flags.h"
28 #include "dsdb/common/proto.h"
29 #include "param/param.h"
30 #include "librpc/gen_ndr/ndr_drsblobs.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libds/common/flag_mapping.h"
34 #include "../lib/util/dlinklist.h"
35 #include "lib/crypto/md4.h"
36 #include "libcli/ldap/ldap_ndr.h"
37 
dsdb_trust_forest_info_from_lsa(TALLOC_CTX * mem_ctx,const struct lsa_ForestTrustInformation * lfti,struct ForestTrustInfo ** _fti)38 NTSTATUS dsdb_trust_forest_info_from_lsa(TALLOC_CTX *mem_ctx,
39 				const struct lsa_ForestTrustInformation *lfti,
40 				struct ForestTrustInfo **_fti)
41 {
42 	struct ForestTrustInfo *fti;
43 	uint32_t i;
44 
45 	*_fti = NULL;
46 
47 	fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
48 	if (fti == NULL) {
49 		return NT_STATUS_NO_MEMORY;
50 	}
51 
52 	fti->version = 1;
53 	fti->count = lfti->count;
54 	fti->records = talloc_zero_array(mem_ctx,
55 					 struct ForestTrustInfoRecordArmor,
56 					 fti->count);
57 	if (fti->records == NULL) {
58 		TALLOC_FREE(fti);
59 		return NT_STATUS_NO_MEMORY;
60 	}
61 
62 	for (i = 0; i < fti->count; i++) {
63 		const struct lsa_ForestTrustRecord *lftr = lfti->entries[i];
64 		struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
65 		struct ForestTrustString *str = NULL;
66 		const struct lsa_StringLarge *lstr = NULL;
67 		const struct lsa_ForestTrustDomainInfo *linfo = NULL;
68 		struct ForestTrustDataDomainInfo *info = NULL;
69 
70 		if (lftr == NULL) {
71 			TALLOC_FREE(fti);
72 			return NT_STATUS_INVALID_PARAMETER;
73 		}
74 
75 		ftr->flags = lftr->flags;
76 		ftr->timestamp = lftr->time;
77 		ftr->type = (enum ForestTrustInfoRecordType)lftr->type;
78 
79 		switch (lftr->type) {
80 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
81 			lstr = &lftr->forest_trust_data.top_level_name;
82 			str = &ftr->data.name;
83 
84 			str->string = talloc_strdup(mem_ctx, lstr->string);
85 			if (str->string == NULL) {
86 				TALLOC_FREE(fti);
87 				return NT_STATUS_NO_MEMORY;
88 			}
89 
90 			break;
91 
92 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
93 			lstr = &lftr->forest_trust_data.top_level_name_ex;
94 			str = &ftr->data.name;
95 
96 			str->string = talloc_strdup(mem_ctx, lstr->string);
97 			if (str->string == NULL) {
98 				TALLOC_FREE(fti);
99 				return NT_STATUS_NO_MEMORY;
100 			}
101 
102 			break;
103 
104 		case LSA_FOREST_TRUST_DOMAIN_INFO:
105 			linfo = &lftr->forest_trust_data.domain_info;
106 			info = &ftr->data.info;
107 
108 			if (linfo->domain_sid == NULL) {
109 				TALLOC_FREE(fti);
110 				return NT_STATUS_INVALID_PARAMETER;
111 			}
112 			info->sid = *linfo->domain_sid;
113 
114 			lstr = &linfo->dns_domain_name;
115 			str = &info->dns_name;
116 			str->string = talloc_strdup(mem_ctx, lstr->string);
117 			if (str->string == NULL) {
118 				TALLOC_FREE(fti);
119 				return NT_STATUS_NO_MEMORY;
120 			}
121 
122 			lstr = &linfo->netbios_domain_name;
123 			str = &info->netbios_name;
124 			str->string = talloc_strdup(mem_ctx, lstr->string);
125 			if (str->string == NULL) {
126 				TALLOC_FREE(fti);
127 				return NT_STATUS_NO_MEMORY;
128 			}
129 
130 			break;
131 
132 		default:
133 			return NT_STATUS_NOT_SUPPORTED;
134 		}
135 	}
136 
137 	*_fti = fti;
138 	return NT_STATUS_OK;
139 }
140 
dsdb_trust_forest_record_to_lsa(TALLOC_CTX * mem_ctx,const struct ForestTrustInfoRecord * ftr,struct lsa_ForestTrustRecord ** _lftr)141 static NTSTATUS dsdb_trust_forest_record_to_lsa(TALLOC_CTX *mem_ctx,
142 					 const struct ForestTrustInfoRecord *ftr,
143 					 struct lsa_ForestTrustRecord **_lftr)
144 {
145 	struct lsa_ForestTrustRecord *lftr = NULL;
146 	const struct ForestTrustString *str = NULL;
147 	struct lsa_StringLarge *lstr = NULL;
148 	const struct ForestTrustDataDomainInfo *info = NULL;
149 	struct lsa_ForestTrustDomainInfo *linfo = NULL;
150 
151 	*_lftr = NULL;
152 
153 	lftr = talloc_zero(mem_ctx, struct lsa_ForestTrustRecord);
154 	if (lftr == NULL) {
155 		return NT_STATUS_NO_MEMORY;
156 	}
157 
158 	lftr->flags = ftr->flags;
159 	lftr->time = ftr->timestamp;
160 	lftr->type = (enum lsa_ForestTrustRecordType)ftr->type;
161 
162 	switch (lftr->type) {
163 	case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
164 		lstr = &lftr->forest_trust_data.top_level_name;
165 		str = &ftr->data.name;
166 
167 		lstr->string = talloc_strdup(mem_ctx, str->string);
168 		if (lstr->string == NULL) {
169 			TALLOC_FREE(lftr);
170 			return NT_STATUS_NO_MEMORY;
171 		}
172 
173 		break;
174 
175 	case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
176 		lstr = &lftr->forest_trust_data.top_level_name_ex;
177 		str = &ftr->data.name;
178 
179 		lstr->string = talloc_strdup(mem_ctx, str->string);
180 		if (lstr->string == NULL) {
181 			TALLOC_FREE(lftr);
182 			return NT_STATUS_NO_MEMORY;
183 		}
184 
185 		break;
186 
187 	case LSA_FOREST_TRUST_DOMAIN_INFO:
188 		linfo = &lftr->forest_trust_data.domain_info;
189 		info = &ftr->data.info;
190 
191 		linfo->domain_sid = dom_sid_dup(lftr, &info->sid);
192 		if (linfo->domain_sid == NULL) {
193 			TALLOC_FREE(lftr);
194 			return NT_STATUS_NO_MEMORY;
195 		}
196 
197 		lstr = &linfo->dns_domain_name;
198 		str = &info->dns_name;
199 		lstr->string = talloc_strdup(mem_ctx, str->string);
200 		if (lstr->string == NULL) {
201 			TALLOC_FREE(lftr);
202 			return NT_STATUS_NO_MEMORY;
203 		}
204 
205 		lstr = &linfo->netbios_domain_name;
206 		str = &info->netbios_name;
207 		lstr->string = talloc_strdup(mem_ctx, str->string);
208 		if (lstr->string == NULL) {
209 			TALLOC_FREE(lftr);
210 			return NT_STATUS_NO_MEMORY;
211 		}
212 
213 		break;
214 
215 	default:
216 		return NT_STATUS_NOT_SUPPORTED;
217 	}
218 
219 	*_lftr = lftr;
220 	return NT_STATUS_OK;
221 }
222 
dsdb_trust_forest_info_to_lsa(TALLOC_CTX * mem_ctx,const struct ForestTrustInfo * fti,struct lsa_ForestTrustInformation ** _lfti)223 NTSTATUS dsdb_trust_forest_info_to_lsa(TALLOC_CTX *mem_ctx,
224 				       const struct ForestTrustInfo *fti,
225 				       struct lsa_ForestTrustInformation **_lfti)
226 {
227 	struct lsa_ForestTrustInformation *lfti;
228 	uint32_t i;
229 
230 	*_lfti = NULL;
231 
232 	if (fti->version != 1) {
233 		return NT_STATUS_INVALID_PARAMETER;
234 	}
235 
236 	lfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
237 	if (lfti == NULL) {
238 		return NT_STATUS_NO_MEMORY;
239 	}
240 
241 	lfti->count = fti->count;
242 	lfti->entries = talloc_zero_array(mem_ctx,
243 					  struct lsa_ForestTrustRecord *,
244 					  lfti->count);
245 	if (lfti->entries == NULL) {
246 		TALLOC_FREE(lfti);
247 		return NT_STATUS_NO_MEMORY;
248 	}
249 
250 	for (i = 0; i < fti->count; i++) {
251 		struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
252 		struct lsa_ForestTrustRecord *lftr = NULL;
253 		NTSTATUS status;
254 
255 		status = dsdb_trust_forest_record_to_lsa(lfti->entries, ftr,
256 							 &lftr);
257 		if (!NT_STATUS_IS_OK(status)) {
258 			TALLOC_FREE(lfti);
259 			return NT_STATUS_NO_MEMORY;
260 		}
261 		lfti->entries[i] = lftr;
262 	}
263 
264 	*_lfti = lfti;
265 	return NT_STATUS_OK;
266 }
267 
dsdb_trust_forest_info_add_record(struct lsa_ForestTrustInformation * fti,const struct lsa_ForestTrustRecord * ftr)268 static NTSTATUS dsdb_trust_forest_info_add_record(struct lsa_ForestTrustInformation *fti,
269 						  const struct lsa_ForestTrustRecord *ftr)
270 {
271 	struct lsa_ForestTrustRecord **es = NULL;
272 	struct lsa_ForestTrustRecord *e = NULL;
273 	const struct lsa_StringLarge *dns1 = NULL;
274 	struct lsa_StringLarge *dns2 = NULL;
275 	const struct lsa_ForestTrustDomainInfo *d1 = NULL;
276 	struct lsa_ForestTrustDomainInfo *d2 = NULL;
277 	size_t len = 0;
278 
279 	es = talloc_realloc(fti, fti->entries,
280 			    struct lsa_ForestTrustRecord *,
281 			    fti->count + 1);
282 	if (!es) {
283 		return NT_STATUS_NO_MEMORY;
284 	}
285 	fti->entries = es;
286 
287 	e = talloc_zero(es, struct lsa_ForestTrustRecord);
288 	if (e == NULL) {
289 		return NT_STATUS_NO_MEMORY;
290 	}
291 
292 	e->type = ftr->type;
293 	e->flags = ftr->flags;
294 	e->time = ftr->time;
295 
296 	switch (ftr->type) {
297 	case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
298 		dns1 = &ftr->forest_trust_data.top_level_name;
299 		dns2 = &e->forest_trust_data.top_level_name;
300 		break;
301 
302 	case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
303 		dns1 = &ftr->forest_trust_data.top_level_name_ex;
304 		dns2 = &e->forest_trust_data.top_level_name_ex;
305 		break;
306 
307 	case LSA_FOREST_TRUST_DOMAIN_INFO:
308 		dns1 = &ftr->forest_trust_data.domain_info.dns_domain_name;
309 		dns2 = &e->forest_trust_data.domain_info.dns_domain_name;
310 		d1 = &ftr->forest_trust_data.domain_info;
311 		d2 = &e->forest_trust_data.domain_info;
312 		break;
313 	default:
314 		return NT_STATUS_INVALID_PARAMETER;
315 	}
316 
317 	if (dns1->string == NULL) {
318 		TALLOC_FREE(e);
319 		return NT_STATUS_INVALID_PARAMETER;
320 	}
321 
322 	len = strlen(dns1->string);
323 	if (len == 0) {
324 		TALLOC_FREE(e);
325 		return NT_STATUS_INVALID_PARAMETER;
326 	}
327 
328 	dns2->string = talloc_strdup(e, dns1->string);
329 	if (dns2->string == NULL) {
330 		TALLOC_FREE(e);
331 		return NT_STATUS_NO_MEMORY;
332 	}
333 
334 	if (d1 != NULL) {
335 		const struct lsa_StringLarge *nb1 = &d1->netbios_domain_name;
336 		struct lsa_StringLarge *nb2 = &d2->netbios_domain_name;
337 
338 		if (nb1->string == NULL) {
339 			TALLOC_FREE(e);
340 			return NT_STATUS_INVALID_PARAMETER;
341 		}
342 
343 		len = strlen(nb1->string);
344 		if (len == 0) {
345 			TALLOC_FREE(e);
346 			return NT_STATUS_INVALID_PARAMETER;
347 		}
348 		if (len > 15) {
349 			TALLOC_FREE(e);
350 			return NT_STATUS_INVALID_PARAMETER;
351 		}
352 
353 		nb2->string = talloc_strdup(e, nb1->string);
354 		if (nb2->string == NULL) {
355 			TALLOC_FREE(e);
356 			return NT_STATUS_NO_MEMORY;
357 		}
358 
359 		if (d1->domain_sid == NULL) {
360 			TALLOC_FREE(e);
361 			return NT_STATUS_INVALID_PARAMETER;
362 		}
363 
364 		d2->domain_sid = dom_sid_dup(e, d1->domain_sid);
365 		if (d2->domain_sid == NULL) {
366 			TALLOC_FREE(e);
367 			return NT_STATUS_NO_MEMORY;
368 		}
369 	}
370 
371 	fti->entries[fti->count++] = e;
372 	return NT_STATUS_OK;
373 }
374 
dsdb_trust_parse_crossref_info(TALLOC_CTX * mem_ctx,struct ldb_context * sam_ctx,const struct ldb_message * msg,struct lsa_TrustDomainInfoInfoEx ** _tdo)375 static NTSTATUS dsdb_trust_parse_crossref_info(TALLOC_CTX *mem_ctx,
376 					struct ldb_context *sam_ctx,
377 					const struct ldb_message *msg,
378 					struct lsa_TrustDomainInfoInfoEx **_tdo)
379 {
380 	TALLOC_CTX *frame = talloc_stackframe();
381 	struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
382 	const char *dns = NULL;
383 	const char *netbios = NULL;
384 	struct ldb_dn *nc_dn = NULL;
385 	struct dom_sid sid = {
386 		.num_auths = 0,
387 	};
388 	NTSTATUS status;
389 
390 	*_tdo = NULL;
391 	tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
392 	if (tdo == NULL) {
393 		TALLOC_FREE(frame);
394 		return NT_STATUS_NO_MEMORY;
395 	}
396 	talloc_steal(frame, tdo);
397 
398 	dns = ldb_msg_find_attr_as_string(msg, "dnsRoot", NULL);
399 	if (dns == NULL) {
400 		TALLOC_FREE(frame);
401 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
402 	}
403 	tdo->domain_name.string = talloc_strdup(tdo, dns);
404 	if (tdo->domain_name.string == NULL) {
405 		TALLOC_FREE(frame);
406 		return NT_STATUS_NO_MEMORY;
407 	}
408 
409 	netbios = ldb_msg_find_attr_as_string(msg, "nETBIOSName", NULL);
410 	if (netbios == NULL) {
411 		TALLOC_FREE(frame);
412 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
413 	}
414 	tdo->netbios_name.string = talloc_strdup(tdo, netbios);
415 	if (tdo->netbios_name.string == NULL) {
416 		TALLOC_FREE(frame);
417 		return NT_STATUS_NO_MEMORY;
418 	}
419 
420 	nc_dn = samdb_result_dn(sam_ctx, frame, msg, "ncName", NULL);
421 	if (nc_dn == NULL) {
422 		TALLOC_FREE(frame);
423 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
424 	}
425 
426 	status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
427 	if (!NT_STATUS_IS_OK(status)) {
428 		TALLOC_FREE(frame);
429 		return status;
430 	}
431 	tdo->sid = dom_sid_dup(tdo, &sid);
432 	if (tdo->sid == NULL) {
433 		TALLOC_FREE(frame);
434 		return NT_STATUS_NO_MEMORY;
435 	}
436 
437 	tdo->trust_type = LSA_TRUST_TYPE_UPLEVEL;
438 	tdo->trust_direction = LSA_TRUST_DIRECTION_INBOUND |
439 			       LSA_TRUST_DIRECTION_OUTBOUND;
440 	tdo->trust_attributes = LSA_TRUST_ATTRIBUTE_WITHIN_FOREST;
441 
442 	*_tdo = talloc_move(mem_ctx, &tdo);
443 	TALLOC_FREE(frame);
444 	return NT_STATUS_OK;
445 }
446 
dsdb_trust_crossref_tdo_info(TALLOC_CTX * mem_ctx,struct ldb_context * sam_ctx,struct ldb_dn * domain_dn,const char * extra_filter,struct lsa_TrustDomainInfoInfoEx ** _tdo,struct lsa_TrustDomainInfoInfoEx ** _root_trust_tdo,struct lsa_TrustDomainInfoInfoEx ** _trust_parent_tdo)447 static NTSTATUS dsdb_trust_crossref_tdo_info(TALLOC_CTX *mem_ctx,
448 			struct ldb_context *sam_ctx,
449 			struct ldb_dn *domain_dn,
450 			const char *extra_filter,
451 			struct lsa_TrustDomainInfoInfoEx **_tdo,
452 			struct lsa_TrustDomainInfoInfoEx **_root_trust_tdo,
453 			struct lsa_TrustDomainInfoInfoEx **_trust_parent_tdo)
454 {
455 	TALLOC_CTX *frame = talloc_stackframe();
456 	struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
457 	struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
458 	struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
459 	struct ldb_dn *partitions_dn = NULL;
460 	const char * const cross_attrs[] = {
461 		"dnsRoot",
462 		"nETBIOSName",
463 		"nCName",
464 		"rootTrust",
465 		"trustParent",
466 		NULL,
467 	};
468 	struct ldb_result *cross_res = NULL;
469 	struct ldb_message *msg = NULL;
470 	struct ldb_dn *root_trust_dn = NULL;
471 	struct ldb_dn *trust_parent_dn = NULL;
472 	NTSTATUS status;
473 	int ret;
474 
475 	if (extra_filter == NULL) {
476 		extra_filter = "";
477 	}
478 
479 	*_tdo = NULL;
480 	if (_root_trust_tdo != NULL) {
481 		*_root_trust_tdo = NULL;
482 	}
483 	if (_trust_parent_tdo != NULL) {
484 		*_trust_parent_tdo = NULL;
485 	}
486 
487 	partitions_dn = samdb_partitions_dn(sam_ctx, frame);
488 	if (partitions_dn == NULL) {
489 		TALLOC_FREE(frame);
490 		return NT_STATUS_NO_MEMORY;
491 	}
492 
493 	ret = dsdb_search(sam_ctx, partitions_dn, &cross_res,
494 			  partitions_dn, LDB_SCOPE_ONELEVEL,
495 			  cross_attrs,
496 			  DSDB_SEARCH_ONE_ONLY |
497 			  DSDB_SEARCH_SHOW_EXTENDED_DN,
498 			  "(&"
499 			    "(ncName=%s)"
500 			    "(objectClass=crossRef)"
501 			    "(systemFlags:%s:=%u)"
502 			    "%s"
503 			  ")",
504 			  ldb_dn_get_linearized(domain_dn),
505 			  LDB_OID_COMPARATOR_AND,
506 			  SYSTEM_FLAG_CR_NTDS_DOMAIN,
507 			  extra_filter);
508 	if (ret != LDB_SUCCESS) {
509 		TALLOC_FREE(frame);
510 		return dsdb_ldb_err_to_ntstatus(ret);
511 	}
512 	msg = cross_res->msgs[0];
513 
514 	status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx, msg, &tdo);
515 	if (!NT_STATUS_IS_OK(status)) {
516 		TALLOC_FREE(frame);
517 		return status;
518 	}
519 	talloc_steal(frame, tdo);
520 
521 	if (_root_trust_tdo != NULL) {
522 		root_trust_dn = samdb_result_dn(sam_ctx, frame, msg,
523 						"rootTrust", NULL);
524 	}
525 	if (_trust_parent_tdo != NULL) {
526 		trust_parent_dn = samdb_result_dn(sam_ctx, frame, msg,
527 						   "trustParent", NULL);
528 	}
529 
530 	if (root_trust_dn != NULL) {
531 		struct ldb_message *root_trust_msg = NULL;
532 
533 		ret = dsdb_search_one(sam_ctx, frame,
534 				      &root_trust_msg,
535 				      root_trust_dn,
536 				      LDB_SCOPE_BASE,
537 				      cross_attrs,
538 				      DSDB_SEARCH_NO_GLOBAL_CATALOG,
539 				      "(objectClass=crossRef)");
540 		if (ret != LDB_SUCCESS) {
541 			status = dsdb_ldb_err_to_ntstatus(ret);
542 			DEBUG(3, ("Failed to search for %s: %s - %s\n",
543 				  ldb_dn_get_linearized(root_trust_dn),
544 				  nt_errstr(status), ldb_errstring(sam_ctx)));
545 			TALLOC_FREE(frame);
546 			return status;
547 		}
548 
549 		status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx,
550 							root_trust_msg,
551 							&root_trust_tdo);
552 		if (!NT_STATUS_IS_OK(status)) {
553 			TALLOC_FREE(frame);
554 			return status;
555 		}
556 		talloc_steal(frame, root_trust_tdo);
557 	}
558 
559 	if (trust_parent_dn != NULL) {
560 		struct ldb_message *trust_parent_msg = NULL;
561 
562 		ret = dsdb_search_one(sam_ctx, frame,
563 				      &trust_parent_msg,
564 				      trust_parent_dn,
565 				      LDB_SCOPE_BASE,
566 				      cross_attrs,
567 				      DSDB_SEARCH_NO_GLOBAL_CATALOG,
568 				      "(objectClass=crossRef)");
569 		if (ret != LDB_SUCCESS) {
570 			status = dsdb_ldb_err_to_ntstatus(ret);
571 			DEBUG(3, ("Failed to search for %s: %s - %s\n",
572 				  ldb_dn_get_linearized(trust_parent_dn),
573 				  nt_errstr(status), ldb_errstring(sam_ctx)));
574 			TALLOC_FREE(frame);
575 			return status;
576 		}
577 
578 		status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx,
579 							trust_parent_msg,
580 							&trust_parent_tdo);
581 		if (!NT_STATUS_IS_OK(status)) {
582 			TALLOC_FREE(frame);
583 			return status;
584 		}
585 		talloc_steal(frame, trust_parent_tdo);
586 	}
587 
588 	*_tdo = talloc_move(mem_ctx, &tdo);
589 	if (_root_trust_tdo != NULL) {
590 		*_root_trust_tdo = talloc_move(mem_ctx, &root_trust_tdo);
591 	}
592 	if (_trust_parent_tdo != NULL) {
593 		*_trust_parent_tdo = talloc_move(mem_ctx, &trust_parent_tdo);
594 	}
595 	TALLOC_FREE(frame);
596 	return NT_STATUS_OK;
597 }
598 
599 #define DNS_CMP_FIRST_IS_CHILD -2
600 #define DNS_CMP_FIRST_IS_LESS -1
601 #define DNS_CMP_MATCH 0
602 #define DNS_CMP_SECOND_IS_LESS 1
603 #define DNS_CMP_SECOND_IS_CHILD 2
604 
605 #define DNS_CMP_IS_NO_MATCH(__cmp) \
606 	((__cmp == DNS_CMP_FIRST_IS_LESS) || (__cmp == DNS_CMP_SECOND_IS_LESS))
607 
608 /*
609  * this function assumes names are well formed DNS names.
610  * it doesn't validate them
611  *
612  * It allows strings up to a length of UINT16_MAX - 1
613  * with up to UINT8_MAX components. On overflow this
614  * just returns the result of strcasecmp_m().
615  *
616  * Trailing dots (only one) are ignored.
617  *
618  * The DNS names are compared per component, starting from
619  * the last one.
620  */
dns_cmp(const char * s1,const char * s2)621 static int dns_cmp(const char *s1, const char *s2)
622 {
623 	size_t l1 = 0;
624 	const char *p1 = NULL;
625 	size_t num_comp1 = 0;
626 	uint16_t comp1[UINT8_MAX] = {0};
627 	size_t l2 = 0;
628 	const char *p2 = NULL;
629 	size_t num_comp2 = 0;
630 	uint16_t comp2[UINT8_MAX] = {0};
631 	size_t i;
632 
633 	if (s1 != NULL) {
634 		l1 = strlen(s1);
635 	}
636 
637 	if (s2 != NULL) {
638 		l2 = strlen(s2);
639 	}
640 
641 	/*
642 	 * trailing '.' are ignored.
643 	 */
644 	if (l1 > 1 && s1[l1 - 1] == '.') {
645 		l1--;
646 	}
647 	if (l2 > 1 && s2[l2 - 1] == '.') {
648 		l2--;
649 	}
650 
651 	for (i = 0; i < ARRAY_SIZE(comp1); i++) {
652 		char *p;
653 
654 		if (i == 0) {
655 			p1 = s1;
656 
657 			if (l1 == 0 || l1 >= UINT16_MAX) {
658 				/* just use one single component on overflow */
659 				break;
660 			}
661 		}
662 
663 		comp1[num_comp1++] = PTR_DIFF(p1, s1);
664 
665 		p = strchr_m(p1, '.');
666 		if (p == NULL) {
667 			p1 = NULL;
668 			break;
669 		}
670 
671 		p1 = p + 1;
672 	}
673 
674 	if (p1 != NULL) {
675 		/* just use one single component on overflow */
676 		num_comp1 = 0;
677 		comp1[num_comp1++] = 0;
678 		p1 = NULL;
679 	}
680 
681 	for (i = 0; i < ARRAY_SIZE(comp2); i++) {
682 		char *p;
683 
684 		if (i == 0) {
685 			p2 = s2;
686 
687 			if (l2 == 0 || l2 >= UINT16_MAX) {
688 				/* just use one single component on overflow */
689 				break;
690 			}
691 		}
692 
693 		comp2[num_comp2++] = PTR_DIFF(p2, s2);
694 
695 		p = strchr_m(p2, '.');
696 		if (p == NULL) {
697 			p2 = NULL;
698 			break;
699 		}
700 
701 		p2 = p + 1;
702 	}
703 
704 	if (p2 != NULL) {
705 		/* just use one single component on overflow */
706 		num_comp2 = 0;
707 		comp2[num_comp2++] = 0;
708 		p2 = NULL;
709 	}
710 
711 	for (i = 0; i < UINT8_MAX; i++) {
712 		int cmp;
713 
714 		if (i < num_comp1) {
715 			size_t idx = num_comp1 - (i + 1);
716 			p1 = s1 + comp1[idx];
717 		} else {
718 			p1 = NULL;
719 		}
720 
721 		if (i < num_comp2) {
722 			size_t idx = num_comp2 - (i + 1);
723 			p2 = s2 + comp2[idx];
724 		} else {
725 			p2 = NULL;
726 		}
727 
728 		if (p1 == NULL && p2 == NULL) {
729 			return DNS_CMP_MATCH;
730 		}
731 		if (p1 != NULL && p2 == NULL) {
732 			return DNS_CMP_FIRST_IS_CHILD;
733 		}
734 		if (p1 == NULL && p2 != NULL) {
735 			return DNS_CMP_SECOND_IS_CHILD;
736 		}
737 
738 		cmp = strcasecmp_m(p1, p2);
739 		if (cmp < 0) {
740 			return DNS_CMP_FIRST_IS_LESS;
741 		}
742 		if (cmp > 0) {
743 			return DNS_CMP_SECOND_IS_LESS;
744 		}
745 	}
746 
747 	smb_panic(__location__);
748 	return -1;
749 }
750 
dsdb_trust_find_tln_match_internal(const struct lsa_ForestTrustInformation * info,enum lsa_ForestTrustRecordType type,uint32_t disable_mask,const char * tln)751 static int dsdb_trust_find_tln_match_internal(const struct lsa_ForestTrustInformation *info,
752 					      enum lsa_ForestTrustRecordType type,
753 					      uint32_t disable_mask,
754 					      const char *tln)
755 {
756 	uint32_t i;
757 
758 	for (i = 0; i < info->count; i++) {
759 		struct lsa_ForestTrustRecord *e = info->entries[i];
760 		struct lsa_StringLarge *t = NULL;
761 		int cmp;
762 
763 		if (e == NULL) {
764 			continue;
765 		}
766 
767 		if (e->type != type) {
768 			continue;
769 		}
770 
771 		if (e->flags & disable_mask) {
772 			continue;
773 		}
774 
775 		switch (type) {
776 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
777 			t = &e->forest_trust_data.top_level_name;
778 			break;
779 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
780 			t = &e->forest_trust_data.top_level_name_ex;
781 			break;
782 		default:
783 			break;
784 		}
785 
786 		if (t == NULL) {
787 			continue;
788 		}
789 
790 		cmp = dns_cmp(tln, t->string);
791 		switch (cmp) {
792 		case DNS_CMP_MATCH:
793 		case DNS_CMP_FIRST_IS_CHILD:
794 			return i;
795 		}
796 	}
797 
798 	return -1;
799 }
800 
dsdb_trust_find_tln_match(const struct lsa_ForestTrustInformation * info,const char * tln)801 static bool dsdb_trust_find_tln_match(const struct lsa_ForestTrustInformation *info,
802 				      const char *tln)
803 {
804 	int m;
805 
806 	m = dsdb_trust_find_tln_match_internal(info,
807 					       LSA_FOREST_TRUST_TOP_LEVEL_NAME,
808 					       LSA_TLN_DISABLED_MASK,
809 					       tln);
810 	if (m != -1) {
811 		return true;
812 	}
813 
814 	return false;
815 }
816 
dsdb_trust_find_tln_ex_match(const struct lsa_ForestTrustInformation * info,const char * tln)817 static bool dsdb_trust_find_tln_ex_match(const struct lsa_ForestTrustInformation *info,
818 					 const char *tln)
819 {
820 	int m;
821 
822 	m = dsdb_trust_find_tln_match_internal(info,
823 					       LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX,
824 					       0,
825 					       tln);
826 	if (m != -1) {
827 		return true;
828 	}
829 
830 	return false;
831 }
832 
dsdb_trust_local_tdo_info(TALLOC_CTX * mem_ctx,struct ldb_context * sam_ctx,struct lsa_TrustDomainInfoInfoEx ** _tdo)833 NTSTATUS dsdb_trust_local_tdo_info(TALLOC_CTX *mem_ctx,
834 				   struct ldb_context *sam_ctx,
835 				   struct lsa_TrustDomainInfoInfoEx **_tdo)
836 {
837 	struct ldb_dn *domain_dn = NULL;
838 
839 	domain_dn = ldb_get_default_basedn(sam_ctx);
840 	if (domain_dn == NULL) {
841 		return NT_STATUS_INTERNAL_ERROR;
842 	}
843 
844 	return dsdb_trust_crossref_tdo_info(mem_ctx, sam_ctx,
845 					    domain_dn, NULL,
846 					    _tdo, NULL, NULL);
847 }
848 
dsdb_trust_xref_tdo_info(TALLOC_CTX * mem_ctx,struct ldb_context * sam_ctx,struct lsa_TrustDomainInfoInfoEx ** _tdo)849 NTSTATUS dsdb_trust_xref_tdo_info(TALLOC_CTX *mem_ctx,
850 				  struct ldb_context *sam_ctx,
851 				  struct lsa_TrustDomainInfoInfoEx **_tdo)
852 {
853 	/*
854 	 * The extra filter makes sure we only find the forest root domain
855 	 */
856 	const char *extra_filter = "(!(|(rootTrust=*)(trustParent=*)))";
857 	struct ldb_dn *domain_dn = NULL;
858 
859 	domain_dn = ldb_get_default_basedn(sam_ctx);
860 	if (domain_dn == NULL) {
861 		return NT_STATUS_INTERNAL_ERROR;
862 	}
863 
864 	return dsdb_trust_crossref_tdo_info(mem_ctx, sam_ctx,
865 					    domain_dn, extra_filter,
866 					    _tdo, NULL, NULL);
867 }
868 
dsdb_trust_xref_sort_msgs(struct ldb_message ** _m1,struct ldb_message ** _m2)869 static int dsdb_trust_xref_sort_msgs(struct ldb_message **_m1,
870 				     struct ldb_message **_m2)
871 {
872 	struct ldb_message *m1 = *_m1;
873 	struct ldb_message *m2 = *_m2;
874 	const char *dns1 = NULL;
875 	const char *dns2 = NULL;
876 	int cmp;
877 	struct ldb_message_element *rootTrust1 = NULL;
878 	struct ldb_message_element *trustParent1 = NULL;
879 	struct ldb_message_element *rootTrust2 = NULL;
880 	struct ldb_message_element *trustParent2 = NULL;
881 
882 	dns1 = ldb_msg_find_attr_as_string(m1, "dnsRoot", NULL);
883 	dns2 = ldb_msg_find_attr_as_string(m2, "dnsRoot", NULL);
884 
885 	cmp = dns_cmp(dns1, dns2);
886 	switch (cmp) {
887 	case DNS_CMP_FIRST_IS_CHILD:
888 		return -1;
889 	case DNS_CMP_SECOND_IS_CHILD:
890 		return 1;
891 	}
892 
893 	rootTrust1 = ldb_msg_find_element(m1, "rootTrust");
894 	trustParent1 = ldb_msg_find_element(m1, "trustParent");
895 	rootTrust2 = ldb_msg_find_element(m2, "rootTrust");
896 	trustParent2 = ldb_msg_find_element(m2, "trustParent");
897 
898 	if (rootTrust1 == NULL && trustParent1 == NULL) {
899 		/* m1 is the forest root */
900 		return -1;
901 	}
902 	if (rootTrust2 == NULL && trustParent2 == NULL) {
903 		/* m2 is the forest root */
904 		return 1;
905 	}
906 
907 	return cmp;
908 }
909 
dsdb_trust_xref_sort_vals(struct ldb_val * v1,struct ldb_val * v2)910 static int dsdb_trust_xref_sort_vals(struct ldb_val *v1,
911 				     struct ldb_val *v2)
912 {
913 	const char *dns1 = (const char *)v1->data;
914 	const char *dns2 = (const char *)v2->data;
915 
916 	return dns_cmp(dns1, dns2);
917 }
918 
dsdb_trust_xref_forest_info(TALLOC_CTX * mem_ctx,struct ldb_context * sam_ctx,struct lsa_ForestTrustInformation ** _info)919 NTSTATUS dsdb_trust_xref_forest_info(TALLOC_CTX *mem_ctx,
920 				     struct ldb_context *sam_ctx,
921 				     struct lsa_ForestTrustInformation **_info)
922 {
923 	TALLOC_CTX *frame = talloc_stackframe();
924 	struct lsa_ForestTrustInformation *info = NULL;
925 	struct ldb_dn *partitions_dn = NULL;
926 	const char * const cross_attrs1[] = {
927 		"uPNSuffixes",
928 		"msDS-SPNSuffixes",
929 		NULL,
930 	};
931 	struct ldb_result *cross_res1 = NULL;
932 	struct ldb_message_element *upn_el = NULL;
933 	struct ldb_message_element *spn_el = NULL;
934 	struct ldb_message *tln_msg = NULL;
935 	struct ldb_message_element *tln_el = NULL;
936 	const char * const cross_attrs2[] = {
937 		"dnsRoot",
938 		"nETBIOSName",
939 		"nCName",
940 		"rootTrust",
941 		"trustParent",
942 		NULL,
943 	};
944 	struct ldb_result *cross_res2 = NULL;
945 	int ret;
946 	unsigned int i;
947 	bool restart = false;
948 
949 	*_info = NULL;
950 	info = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
951 	if (info == NULL) {
952 		TALLOC_FREE(frame);
953 		return NT_STATUS_NO_MEMORY;
954 	}
955 	talloc_steal(frame, info);
956 
957 	partitions_dn = samdb_partitions_dn(sam_ctx, frame);
958 	if (partitions_dn == NULL) {
959 		TALLOC_FREE(frame);
960 		return NT_STATUS_NO_MEMORY;
961 	}
962 
963 	ret = dsdb_search_dn(sam_ctx, partitions_dn, &cross_res1,
964 			     partitions_dn, cross_attrs1, 0);
965 	if (ret != LDB_SUCCESS) {
966 		TALLOC_FREE(frame);
967 		return dsdb_ldb_err_to_ntstatus(ret);
968 	}
969 
970 	ret = dsdb_search(sam_ctx, partitions_dn, &cross_res2,
971 			  partitions_dn, LDB_SCOPE_ONELEVEL,
972 			  cross_attrs2,
973 			  DSDB_SEARCH_SHOW_EXTENDED_DN,
974 			  "(&(objectClass=crossRef)"
975 			   "(systemFlags:%s:=%u))",
976 			  LDB_OID_COMPARATOR_AND,
977 			  SYSTEM_FLAG_CR_NTDS_DOMAIN);
978 	if (ret != LDB_SUCCESS) {
979 		TALLOC_FREE(frame);
980 		return dsdb_ldb_err_to_ntstatus(ret);
981 	}
982 
983 	/*
984 	 * Sort the domains as trees, starting with the forest root
985 	 */
986 	TYPESAFE_QSORT(cross_res2->msgs, cross_res2->count,
987 		       dsdb_trust_xref_sort_msgs);
988 
989 	upn_el = ldb_msg_find_element(cross_res1->msgs[0], "uPNSuffixes");
990 	if (upn_el != NULL) {
991 		upn_el->name = "__tln__";
992 	}
993 	spn_el = ldb_msg_find_element(cross_res1->msgs[0], "msDS-SPNSuffixes");
994 	if (spn_el != NULL) {
995 		spn_el->name = "__tln__";
996 	}
997 	ret = ldb_msg_normalize(sam_ctx, frame, cross_res1->msgs[0], &tln_msg);
998 	if (ret != LDB_SUCCESS) {
999 		TALLOC_FREE(frame);
1000 		return dsdb_ldb_err_to_ntstatus(ret);
1001 	}
1002 	tln_el = ldb_msg_find_element(tln_msg, "__tln__");
1003 	if (tln_el != NULL) {
1004 		/*
1005 		 * Sort the domains as trees
1006 		 */
1007 		TYPESAFE_QSORT(tln_el->values, tln_el->num_values,
1008 			       dsdb_trust_xref_sort_vals);
1009 	}
1010 
1011 	for (i=0; i < cross_res2->count; i++) {
1012 		struct ldb_message *m = cross_res2->msgs[i];
1013 		const char *dns = NULL;
1014 		const char *netbios = NULL;
1015 		struct ldb_dn *nc_dn = NULL;
1016 		struct dom_sid sid = {
1017 			.num_auths = 0,
1018 		};
1019 		struct lsa_ForestTrustRecord e = {
1020 			.flags = 0,
1021 		};
1022 		struct lsa_ForestTrustDomainInfo *d = NULL;
1023 		struct lsa_StringLarge *t = NULL;
1024 		bool match = false;
1025 		NTSTATUS status;
1026 
1027 		dns = ldb_msg_find_attr_as_string(m, "dnsRoot", NULL);
1028 		if (dns == NULL) {
1029 			TALLOC_FREE(frame);
1030 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
1031 		}
1032 
1033 		netbios = ldb_msg_find_attr_as_string(m, "nETBIOSName", NULL);
1034 		if (netbios == NULL) {
1035 			TALLOC_FREE(frame);
1036 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
1037 		}
1038 
1039 		nc_dn = samdb_result_dn(sam_ctx, m, m, "ncName", NULL);
1040 		if (nc_dn == NULL) {
1041 			TALLOC_FREE(frame);
1042 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
1043 		}
1044 
1045 		status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
1046 		if (!NT_STATUS_IS_OK(status)) {
1047 			TALLOC_FREE(frame);
1048 			return status;
1049 		}
1050 
1051 		match = dsdb_trust_find_tln_match(info, dns);
1052 		if (!match) {
1053 			/*
1054 			 * First the TOP_LEVEL_NAME, if required
1055 			 */
1056 			e = (struct lsa_ForestTrustRecord) {
1057 				.flags = 0,
1058 				.type = LSA_FOREST_TRUST_TOP_LEVEL_NAME,
1059 				.time = 0, /* so far always 0 in traces. */
1060 			};
1061 
1062 			t = &e.forest_trust_data.top_level_name;
1063 			t->string = dns;
1064 
1065 			status = dsdb_trust_forest_info_add_record(info, &e);
1066 			if (!NT_STATUS_IS_OK(status)) {
1067 				TALLOC_FREE(frame);
1068 				return status;
1069 			}
1070 		}
1071 
1072 		/*
1073 		 * Then the DOMAIN_INFO
1074 		 */
1075 		e = (struct lsa_ForestTrustRecord) {
1076 			.flags = 0,
1077 			.type = LSA_FOREST_TRUST_DOMAIN_INFO,
1078 			.time = 0, /* so far always 0 in traces. */
1079 		};
1080 		d = &e.forest_trust_data.domain_info;
1081 		d->domain_sid = &sid;
1082 		d->dns_domain_name.string = dns;
1083 		d->netbios_domain_name.string = netbios;
1084 
1085 		status = dsdb_trust_forest_info_add_record(info, &e);
1086 		if (!NT_STATUS_IS_OK(status)) {
1087 			TALLOC_FREE(frame);
1088 			return status;
1089 		}
1090 	}
1091 
1092 	for (i=0; (tln_el != NULL) && i < tln_el->num_values; i++) {
1093 		const struct ldb_val *v = &tln_el->values[i];
1094 		const char *dns = (const char *)v->data;
1095 		struct lsa_ForestTrustRecord e = {
1096 			.flags = 0,
1097 		};
1098 		struct lsa_StringLarge *t = NULL;
1099 		bool match = false;
1100 		NTSTATUS status;
1101 
1102 		if (dns == NULL) {
1103 			TALLOC_FREE(frame);
1104 			return NT_STATUS_INTERNAL_DB_CORRUPTION;
1105 		}
1106 
1107 		match = dsdb_trust_find_tln_match(info, dns);
1108 		if (match) {
1109 			continue;
1110 		}
1111 
1112 		/*
1113 		 * an additional the TOP_LEVEL_NAME
1114 		 */
1115 		e = (struct lsa_ForestTrustRecord) {
1116 			.flags = 0,
1117 			.type = LSA_FOREST_TRUST_TOP_LEVEL_NAME,
1118 			.time = 0, /* so far always 0 in traces. */
1119 		};
1120 		t = &e.forest_trust_data.top_level_name;
1121 		t->string = dns;
1122 
1123 		status = dsdb_trust_forest_info_add_record(info, &e);
1124 		if (!NT_STATUS_IS_OK(status)) {
1125 			TALLOC_FREE(frame);
1126 			return status;
1127 		}
1128 	}
1129 
1130 	for (i=0; i < info->count; restart ? i=0 : i++) {
1131 		struct lsa_ForestTrustRecord *tr = info->entries[i];
1132 		const struct lsa_StringLarge *ts = NULL;
1133 		uint32_t c;
1134 
1135 		restart = false;
1136 
1137 		if (tr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1138 			continue;
1139 		}
1140 
1141 		ts = &tr->forest_trust_data.top_level_name;
1142 
1143 		for (c = i + 1; c < info->count; c++) {
1144 			struct lsa_ForestTrustRecord *cr = info->entries[c];
1145 			const struct lsa_StringLarge *cs = NULL;
1146 			uint32_t j;
1147 			int cmp;
1148 
1149 			if (cr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1150 				continue;
1151 			}
1152 
1153 			cs = &cr->forest_trust_data.top_level_name;
1154 
1155 			cmp = dns_cmp(ts->string, cs->string);
1156 			if (DNS_CMP_IS_NO_MATCH(cmp)) {
1157 				continue;
1158 			}
1159 			if (cmp != DNS_CMP_FIRST_IS_CHILD) {
1160 				/* can't happen ... */
1161 				continue;
1162 			}
1163 
1164 			ts = NULL;
1165 			tr = NULL;
1166 			TALLOC_FREE(info->entries[i]);
1167 			info->entries[i] = info->entries[c];
1168 
1169 			for (j = c + 1; j < info->count; j++) {
1170 				info->entries[j-1] = info->entries[j];
1171 			}
1172 			info->count -= 1;
1173 			restart = true;
1174 			break;
1175 		}
1176 	}
1177 
1178 	*_info = talloc_move(mem_ctx, &info);
1179 	TALLOC_FREE(frame);
1180 	return NT_STATUS_OK;
1181 }
1182 
dsdb_trust_parse_tdo_info(TALLOC_CTX * mem_ctx,struct ldb_message * m,struct lsa_TrustDomainInfoInfoEx ** _tdo)1183 NTSTATUS dsdb_trust_parse_tdo_info(TALLOC_CTX *mem_ctx,
1184 				   struct ldb_message *m,
1185 				   struct lsa_TrustDomainInfoInfoEx **_tdo)
1186 {
1187 	struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
1188 	const char *dns = NULL;
1189 	const char *netbios = NULL;
1190 
1191 	*_tdo = NULL;
1192 
1193 	tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1194 	if (tdo == NULL) {
1195 		return NT_STATUS_NO_MEMORY;
1196 	}
1197 
1198 	dns = ldb_msg_find_attr_as_string(m, "trustPartner", NULL);
1199 	if (dns == NULL) {
1200 		TALLOC_FREE(tdo);
1201 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
1202 	}
1203 	tdo->domain_name.string = talloc_strdup(tdo, dns);
1204 	if (tdo->domain_name.string == NULL) {
1205 		TALLOC_FREE(tdo);
1206 		return NT_STATUS_NO_MEMORY;
1207 	}
1208 
1209 	netbios = ldb_msg_find_attr_as_string(m, "flatName", NULL);
1210 	if (netbios == NULL) {
1211 		TALLOC_FREE(tdo);
1212 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
1213 	}
1214 	tdo->netbios_name.string = talloc_strdup(tdo, netbios);
1215 	if (tdo->netbios_name.string == NULL) {
1216 		TALLOC_FREE(tdo);
1217 		return NT_STATUS_NO_MEMORY;
1218 	}
1219 
1220 	tdo->sid = samdb_result_dom_sid(tdo, m, "securityIdentifier");
1221 	if (tdo->sid == NULL) {
1222 		TALLOC_FREE(tdo);
1223 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
1224 	}
1225 
1226 	tdo->trust_type = ldb_msg_find_attr_as_uint(m, "trustType", 0);
1227 	tdo->trust_direction = ldb_msg_find_attr_as_uint(m, "trustDirection", 0);
1228 	tdo->trust_attributes = ldb_msg_find_attr_as_uint(m, "trustAttributes", 0);
1229 
1230 	*_tdo = tdo;
1231 	return NT_STATUS_OK;
1232 }
1233 
dsdb_trust_parse_forest_info(TALLOC_CTX * mem_ctx,struct ldb_message * m,struct ForestTrustInfo ** _fti)1234 NTSTATUS dsdb_trust_parse_forest_info(TALLOC_CTX *mem_ctx,
1235 				      struct ldb_message *m,
1236 				      struct ForestTrustInfo **_fti)
1237 {
1238 	const struct ldb_val *ft_blob = NULL;
1239 	struct ForestTrustInfo *fti = NULL;
1240 	enum ndr_err_code ndr_err;
1241 
1242 	*_fti = NULL;
1243 
1244 	ft_blob = ldb_msg_find_ldb_val(m, "msDS-TrustForestTrustInfo");
1245 	if (ft_blob == NULL) {
1246 		return NT_STATUS_NOT_FOUND;
1247 	}
1248 
1249 	fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
1250 	if (fti == NULL) {
1251 		return NT_STATUS_NO_MEMORY;
1252 	}
1253 
1254 	/* ldb_val is equivalent to DATA_BLOB */
1255 	ndr_err = ndr_pull_struct_blob_all(ft_blob, fti, fti,
1256 				(ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1257 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1258 		TALLOC_FREE(fti);
1259 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
1260 	}
1261 
1262 	*_fti = fti;
1263 	return NT_STATUS_OK;
1264 }
1265 
dsdb_trust_normalize_forest_info_step1(TALLOC_CTX * mem_ctx,const struct lsa_ForestTrustInformation * gfti,struct lsa_ForestTrustInformation ** _nfti)1266 NTSTATUS dsdb_trust_normalize_forest_info_step1(TALLOC_CTX *mem_ctx,
1267 				const struct lsa_ForestTrustInformation *gfti,
1268 				struct lsa_ForestTrustInformation **_nfti)
1269 {
1270 	TALLOC_CTX *frame = talloc_stackframe();
1271 	struct lsa_ForestTrustInformation *nfti;
1272 	uint32_t n;
1273 
1274 	*_nfti = NULL;
1275 
1276 	nfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
1277 	if (nfti == NULL) {
1278 		TALLOC_FREE(frame);
1279 		return NT_STATUS_NO_MEMORY;
1280 	}
1281 	talloc_steal(frame, nfti);
1282 
1283 	/*
1284 	 * First we copy every record and remove possible trailing dots
1285 	 * from dns names.
1286 	 *
1287 	 * We also NULL out dublicates. The first one wins and
1288 	 * we keep 'count' as is. This is required in order to
1289 	 * provide the correct index for collision records.
1290 	 */
1291 	for (n = 0; n < gfti->count; n++) {
1292 		const struct lsa_ForestTrustRecord *gftr = gfti->entries[n];
1293 		struct lsa_ForestTrustRecord *nftr = NULL;
1294 		struct lsa_ForestTrustDomainInfo *ninfo = NULL;
1295 		struct lsa_StringLarge *ntln = NULL;
1296 		struct lsa_StringLarge *nnb = NULL;
1297 		struct dom_sid *nsid = NULL;
1298 		NTSTATUS status;
1299 		size_t len = 0;
1300 		char *p = NULL;
1301 		uint32_t c;
1302 
1303 		if (gftr == NULL) {
1304 			TALLOC_FREE(frame);
1305 			return NT_STATUS_INVALID_PARAMETER;
1306 		}
1307 
1308 		status = dsdb_trust_forest_info_add_record(nfti, gftr);
1309 		if (!NT_STATUS_IS_OK(status)) {
1310 			TALLOC_FREE(frame);
1311 			return status;
1312 		}
1313 
1314 		nftr = nfti->entries[n];
1315 
1316 		switch (nftr->type) {
1317 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1318 			ntln = &nftr->forest_trust_data.top_level_name;
1319 			break;
1320 
1321 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1322 			ntln = &nftr->forest_trust_data.top_level_name_ex;
1323 			break;
1324 
1325 		case LSA_FOREST_TRUST_DOMAIN_INFO:
1326 			ninfo = &nftr->forest_trust_data.domain_info;
1327 			ntln = &ninfo->dns_domain_name;
1328 			nnb = &ninfo->netbios_domain_name;
1329 			nsid = ninfo->domain_sid;
1330 			break;
1331 
1332 		default:
1333 			TALLOC_FREE(frame);
1334 			return NT_STATUS_INVALID_PARAMETER;
1335 		}
1336 
1337 		/*
1338 		 * We remove one trailing '.' before checking
1339 		 * for invalid dots.
1340 		 *
1341 		 * domain.com.  becomes domain.com
1342 		 * domain.com.. becomes domain.com.
1343 		 *
1344 		 * Then the following is invalid:
1345 		 *
1346 		 * domain..com
1347 		 * .domain.com
1348 		 * domain.com.
1349 		 */
1350 		len = strlen(ntln->string);
1351 		if (len > 1 && ntln->string[len - 1] == '.') {
1352 			const char *cp = &ntln->string[len - 1];
1353 			p = discard_const_p(char, cp);
1354 			*p= '\0';
1355 		}
1356 		if (ntln->string[0] == '.') {
1357 			TALLOC_FREE(frame);
1358 			return NT_STATUS_INVALID_PARAMETER;
1359 		}
1360 		p = strstr_m(ntln->string, "..");
1361 		if (p != NULL) {
1362 			TALLOC_FREE(frame);
1363 			return NT_STATUS_INVALID_PARAMETER;
1364 		}
1365 
1366 		for (c = 0; c < n; c++) {
1367 			const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
1368 			const struct lsa_ForestTrustDomainInfo *cinfo = NULL;
1369 			const struct lsa_StringLarge *ctln = NULL;
1370 			const struct lsa_StringLarge *cnb = NULL;
1371 			const struct dom_sid *csid = NULL;
1372 			int cmp;
1373 
1374 			if (cftr == NULL) {
1375 				continue;
1376 			}
1377 
1378 			if (cftr->type != nftr->type) {
1379 				continue;
1380 			}
1381 
1382 			switch (cftr->type) {
1383 			case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1384 				ctln = &cftr->forest_trust_data.top_level_name;
1385 				break;
1386 
1387 			case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1388 				ctln = &cftr->forest_trust_data.top_level_name_ex;
1389 				break;
1390 
1391 			case LSA_FOREST_TRUST_DOMAIN_INFO:
1392 				cinfo = &cftr->forest_trust_data.domain_info;
1393 				ctln = &cinfo->dns_domain_name;
1394 				cnb = &cinfo->netbios_domain_name;
1395 				csid = cinfo->domain_sid;
1396 				break;
1397 
1398 			default:
1399 				TALLOC_FREE(frame);
1400 				return NT_STATUS_INVALID_PARAMETER;
1401 			}
1402 
1403 			cmp = dns_cmp(ntln->string, ctln->string);
1404 			if (cmp == DNS_CMP_MATCH) {
1405 				nftr = NULL;
1406 				TALLOC_FREE(nfti->entries[n]);
1407 				break;
1408 			}
1409 
1410 			if (cinfo == NULL) {
1411 				continue;
1412 			}
1413 
1414 			cmp = strcasecmp_m(nnb->string, cnb->string);
1415 			if (cmp == 0) {
1416 				nftr = NULL;
1417 				TALLOC_FREE(nfti->entries[n]);
1418 				break;
1419 			}
1420 
1421 			cmp = dom_sid_compare(nsid, csid);
1422 			if (cmp == 0) {
1423 				nftr = NULL;
1424 				TALLOC_FREE(nfti->entries[n]);
1425 				break;
1426 			}
1427 		}
1428 	}
1429 
1430 	/*
1431 	 * Now we check that only true top level names are provided
1432 	 */
1433 	for (n = 0; n < nfti->count; n++) {
1434 		const struct lsa_ForestTrustRecord *nftr = nfti->entries[n];
1435 		const struct lsa_StringLarge *ntln = NULL;
1436 		uint32_t c;
1437 
1438 		if (nftr == NULL) {
1439 			continue;
1440 		}
1441 
1442 		if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1443 			continue;
1444 		}
1445 
1446 		ntln = &nftr->forest_trust_data.top_level_name;
1447 
1448 		for (c = 0; c < nfti->count; c++) {
1449 			const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
1450 			const struct lsa_StringLarge *ctln = NULL;
1451 			int cmp;
1452 
1453 			if (cftr == NULL) {
1454 				continue;
1455 			}
1456 
1457 			if (cftr == nftr) {
1458 				continue;
1459 			}
1460 
1461 			if (cftr->type != nftr->type) {
1462 				continue;
1463 			}
1464 
1465 			ctln = &cftr->forest_trust_data.top_level_name;
1466 
1467 			cmp = dns_cmp(ntln->string, ctln->string);
1468 			if (DNS_CMP_IS_NO_MATCH(cmp)) {
1469 				continue;
1470 			}
1471 
1472 			TALLOC_FREE(frame);
1473 			return NT_STATUS_INVALID_PARAMETER;
1474 		}
1475 	}
1476 
1477 	/*
1478 	 * Now we check that only true sub level excludes are provided
1479 	 */
1480 	for (n = 0; n < nfti->count; n++) {
1481 		const struct lsa_ForestTrustRecord *nftr = nfti->entries[n];
1482 		const struct lsa_StringLarge *ntln = NULL;
1483 		uint32_t c;
1484 		bool found_tln = false;
1485 
1486 		if (nftr == NULL) {
1487 			continue;
1488 		}
1489 
1490 		if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX) {
1491 			continue;
1492 		}
1493 
1494 		ntln = &nftr->forest_trust_data.top_level_name;
1495 
1496 		for (c = 0; c < nfti->count; c++) {
1497 			const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
1498 			const struct lsa_StringLarge *ctln = NULL;
1499 			int cmp;
1500 
1501 			if (cftr == NULL) {
1502 				continue;
1503 			}
1504 
1505 			if (cftr == nftr) {
1506 				continue;
1507 			}
1508 
1509 			if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1510 				continue;
1511 			}
1512 
1513 			ctln = &cftr->forest_trust_data.top_level_name;
1514 
1515 			cmp = dns_cmp(ntln->string, ctln->string);
1516 			if (cmp == DNS_CMP_FIRST_IS_CHILD) {
1517 				found_tln = true;
1518 				break;
1519 			}
1520 		}
1521 
1522 		if (found_tln) {
1523 			continue;
1524 		}
1525 
1526 		TALLOC_FREE(frame);
1527 		return NT_STATUS_INVALID_PARAMETER;
1528 	}
1529 
1530 	/*
1531 	 * Now we check that there's a top level name for each domain
1532 	 */
1533 	for (n = 0; n < nfti->count; n++) {
1534 		const struct lsa_ForestTrustRecord *nftr = nfti->entries[n];
1535 		const struct lsa_ForestTrustDomainInfo *ninfo = NULL;
1536 		const struct lsa_StringLarge *ntln = NULL;
1537 		uint32_t c;
1538 		bool found_tln = false;
1539 
1540 		if (nftr == NULL) {
1541 			continue;
1542 		}
1543 
1544 		if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1545 			continue;
1546 		}
1547 
1548 		ninfo = &nftr->forest_trust_data.domain_info;
1549 		ntln = &ninfo->dns_domain_name;
1550 
1551 		for (c = 0; c < nfti->count; c++) {
1552 			const struct lsa_ForestTrustRecord *cftr = nfti->entries[c];
1553 			const struct lsa_StringLarge *ctln = NULL;
1554 			int cmp;
1555 
1556 			if (cftr == NULL) {
1557 				continue;
1558 			}
1559 
1560 			if (cftr == nftr) {
1561 				continue;
1562 			}
1563 
1564 			if (cftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1565 				continue;
1566 			}
1567 
1568 			ctln = &cftr->forest_trust_data.top_level_name;
1569 
1570 			cmp = dns_cmp(ntln->string, ctln->string);
1571 			if (cmp == DNS_CMP_MATCH) {
1572 				found_tln = true;
1573 				break;
1574 			}
1575 			if (cmp == DNS_CMP_FIRST_IS_CHILD) {
1576 				found_tln = true;
1577 				break;
1578 			}
1579 		}
1580 
1581 		if (found_tln) {
1582 			continue;
1583 		}
1584 
1585 		TALLOC_FREE(frame);
1586 		return NT_STATUS_INVALID_PARAMETER;
1587 	}
1588 
1589 	*_nfti = talloc_move(mem_ctx, &nfti);
1590 	TALLOC_FREE(frame);
1591 	return NT_STATUS_OK;
1592 }
1593 
dsdb_trust_normalize_forest_info_step2(TALLOC_CTX * mem_ctx,const struct lsa_ForestTrustInformation * gfti,struct lsa_ForestTrustInformation ** _nfti)1594 NTSTATUS dsdb_trust_normalize_forest_info_step2(TALLOC_CTX *mem_ctx,
1595 				const struct lsa_ForestTrustInformation *gfti,
1596 				struct lsa_ForestTrustInformation **_nfti)
1597 {
1598 	TALLOC_CTX *frame = talloc_stackframe();
1599 	struct timeval tv = timeval_current();
1600 	NTTIME now = timeval_to_nttime(&tv);
1601 	struct lsa_ForestTrustInformation *nfti;
1602 	uint32_t g;
1603 
1604 	*_nfti = NULL;
1605 
1606 	nfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
1607 	if (nfti == NULL) {
1608 		TALLOC_FREE(frame);
1609 		return NT_STATUS_NO_MEMORY;
1610 	}
1611 	talloc_steal(frame, nfti);
1612 
1613 	/*
1614 	 * Now we add TOP_LEVEL_NAME[_EX] in reverse order
1615 	 * followed by LSA_FOREST_TRUST_DOMAIN_INFO in reverse order.
1616 	 *
1617 	 * This also removes the possible NULL entries generated in step1.
1618 	 */
1619 
1620 	for (g = 0; g < gfti->count; g++) {
1621 		const struct lsa_ForestTrustRecord *gftr = gfti->entries[gfti->count - (g+1)];
1622 		struct lsa_ForestTrustRecord tftr;
1623 		bool skip = false;
1624 		NTSTATUS status;
1625 
1626 		if (gftr == NULL) {
1627 			continue;
1628 		}
1629 
1630 		switch (gftr->type) {
1631 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1632 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1633 			break;
1634 
1635 		case LSA_FOREST_TRUST_DOMAIN_INFO:
1636 			skip = true;
1637 			break;
1638 
1639 		default:
1640 			TALLOC_FREE(frame);
1641 			return NT_STATUS_INVALID_PARAMETER;
1642 		}
1643 
1644 		if (skip) {
1645 			continue;
1646 		}
1647 
1648 		/* make a copy in order to update the time. */
1649 		tftr = *gftr;
1650 		if (tftr.time == 0) {
1651 			tftr.time = now;
1652 		}
1653 
1654 		status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1655 		if (!NT_STATUS_IS_OK(status)) {
1656 			TALLOC_FREE(frame);
1657 			return status;
1658 		}
1659 	}
1660 
1661 	for (g = 0; g < gfti->count; g++) {
1662 		const struct lsa_ForestTrustRecord *gftr = gfti->entries[gfti->count - (g+1)];
1663 		struct lsa_ForestTrustRecord tftr;
1664 		bool skip = false;
1665 		NTSTATUS status;
1666 
1667 		if (gftr == NULL) {
1668 			continue;
1669 		}
1670 
1671 		switch (gftr->type) {
1672 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1673 		case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
1674 			skip = true;
1675 			break;
1676 
1677 		case LSA_FOREST_TRUST_DOMAIN_INFO:
1678 			break;
1679 
1680 		default:
1681 			TALLOC_FREE(frame);
1682 			return NT_STATUS_INVALID_PARAMETER;
1683 		}
1684 
1685 		if (skip) {
1686 			continue;
1687 		}
1688 
1689 		/* make a copy in order to update the time. */
1690 		tftr = *gftr;
1691 		if (tftr.time == 0) {
1692 			tftr.time = now;
1693 		}
1694 
1695 		status = dsdb_trust_forest_info_add_record(nfti, &tftr);
1696 		if (!NT_STATUS_IS_OK(status)) {
1697 			TALLOC_FREE(frame);
1698 			return status;
1699 		}
1700 	}
1701 
1702 	*_nfti = talloc_move(mem_ctx, &nfti);
1703 	TALLOC_FREE(frame);
1704 	return NT_STATUS_OK;
1705 }
1706 
dsdb_trust_add_collision(struct lsa_ForestTrustCollisionInfo * c_info,enum lsa_ForestTrustCollisionRecordType type,uint32_t idx,uint32_t flags,const char * tdo_name)1707 static NTSTATUS dsdb_trust_add_collision(
1708 			struct lsa_ForestTrustCollisionInfo *c_info,
1709 			enum lsa_ForestTrustCollisionRecordType type,
1710 			uint32_t idx, uint32_t flags,
1711 			const char *tdo_name)
1712 {
1713 	struct lsa_ForestTrustCollisionRecord **es;
1714 	uint32_t i = c_info->count;
1715 
1716 	es = talloc_realloc(c_info, c_info->entries,
1717 			    struct lsa_ForestTrustCollisionRecord *, i + 1);
1718 	if (es == NULL) {
1719 		return NT_STATUS_NO_MEMORY;
1720 	}
1721 	c_info->entries = es;
1722 	c_info->count = i + 1;
1723 
1724 	es[i] = talloc_zero(es, struct lsa_ForestTrustCollisionRecord);
1725 	if (es[i] == NULL) {
1726 		return NT_STATUS_NO_MEMORY;
1727 	}
1728 
1729 	es[i]->index = idx;
1730 	es[i]->type = type;
1731 	es[i]->flags = flags;
1732 	es[i]->name.string = talloc_strdup(es[i], tdo_name);
1733 	if (es[i]->name.string == NULL) {
1734 		return NT_STATUS_NO_MEMORY;
1735 	}
1736 
1737 	return NT_STATUS_OK;
1738 }
1739 
dsdb_trust_verify_forest_info(const struct lsa_TrustDomainInfoInfoEx * ref_tdo,const struct lsa_ForestTrustInformation * ref_fti,enum lsa_ForestTrustCollisionRecordType collision_type,struct lsa_ForestTrustCollisionInfo * c_info,struct lsa_ForestTrustInformation * new_fti)1740 NTSTATUS dsdb_trust_verify_forest_info(const struct lsa_TrustDomainInfoInfoEx *ref_tdo,
1741 				const struct lsa_ForestTrustInformation *ref_fti,
1742 				enum lsa_ForestTrustCollisionRecordType collision_type,
1743 				struct lsa_ForestTrustCollisionInfo *c_info,
1744 				struct lsa_ForestTrustInformation *new_fti)
1745 {
1746 	uint32_t n;
1747 
1748 	for (n = 0; n < new_fti->count; n++) {
1749 		struct lsa_ForestTrustRecord *nftr = new_fti->entries[n];
1750 		struct lsa_StringLarge *ntln = NULL;
1751 		bool ntln_excluded = false;
1752 		uint32_t flags = 0;
1753 		uint32_t r;
1754 		NTSTATUS status;
1755 
1756 		if (nftr == NULL) {
1757 			continue;
1758 		}
1759 
1760 		if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1761 			continue;
1762 		}
1763 
1764 		ntln = &nftr->forest_trust_data.top_level_name;
1765 		if (ntln->string == NULL) {
1766 			return NT_STATUS_INVALID_PARAMETER;
1767 		}
1768 
1769 		ntln_excluded = dsdb_trust_find_tln_ex_match(ref_fti,
1770 							     ntln->string);
1771 
1772 		/* check if this is already taken and not excluded */
1773 		for (r = 0; r < ref_fti->count; r++) {
1774 			const struct lsa_ForestTrustRecord *rftr =
1775 				ref_fti->entries[r];
1776 			const struct lsa_StringLarge *rtln = NULL;
1777 			int cmp;
1778 
1779 			if (rftr == NULL) {
1780 				continue;
1781 			}
1782 
1783 			if (rftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1784 				continue;
1785 			}
1786 
1787 			rtln = &rftr->forest_trust_data.top_level_name;
1788 			if (rtln->string == NULL) {
1789 				continue;
1790 			}
1791 
1792 			cmp = dns_cmp(ntln->string, rtln->string);
1793 			if (DNS_CMP_IS_NO_MATCH(cmp)) {
1794 				continue;
1795 			}
1796 			if (cmp == DNS_CMP_MATCH) {
1797 				/* We need to normalize the string */
1798 				ntln->string = talloc_strdup(nftr,
1799 							     rtln->string);
1800 				if (ntln->string == NULL) {
1801 					return NT_STATUS_NO_MEMORY;
1802 				}
1803 			}
1804 
1805 			if (ntln_excluded) {
1806 				continue;
1807 			}
1808 
1809 			if (rftr->flags & LSA_TLN_DISABLED_MASK) {
1810 				continue;
1811 			}
1812 
1813 			if (nftr->flags & LSA_TLN_DISABLED_MASK) {
1814 				continue;
1815 			}
1816 
1817 			if (cmp == DNS_CMP_SECOND_IS_CHILD) {
1818 				bool m;
1819 
1820 				/*
1821 				 * If the conflicting tln is a child, check if
1822 				 * we have an exclusion record for it.
1823 				 */
1824 				m = dsdb_trust_find_tln_ex_match(new_fti,
1825 								 rtln->string);
1826 				if (m) {
1827 					continue;
1828 				}
1829 			}
1830 
1831 			flags |= LSA_TLN_DISABLED_CONFLICT;
1832 		}
1833 
1834 		if (flags == 0) {
1835 			continue;
1836 		}
1837 
1838 		nftr->flags |= flags;
1839 
1840 		status = dsdb_trust_add_collision(c_info,
1841 						  collision_type,
1842 						  n, nftr->flags,
1843 						  ref_tdo->domain_name.string);
1844 		if (!NT_STATUS_IS_OK(status)) {
1845 			return status;
1846 		}
1847 	}
1848 
1849 	for (n = 0; n < new_fti->count; n++) {
1850 		struct lsa_ForestTrustRecord *nftr = new_fti->entries[n];
1851 		struct lsa_ForestTrustDomainInfo *ninfo = NULL;
1852 		struct lsa_StringLarge *ntln = NULL;
1853 		struct lsa_StringLarge *nnb = NULL;
1854 		struct dom_sid *nsid = NULL;
1855 		bool ntln_found = false;
1856 		uint32_t flags = 0;
1857 		uint32_t r;
1858 		NTSTATUS status;
1859 
1860 		if (nftr == NULL) {
1861 			continue;
1862 		}
1863 
1864 		if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
1865 			continue;
1866 		}
1867 
1868 		ninfo = &nftr->forest_trust_data.domain_info;
1869 		ntln = &ninfo->dns_domain_name;
1870 		if (ntln->string == NULL) {
1871 			return NT_STATUS_INVALID_PARAMETER;
1872 		}
1873 		nnb = &ninfo->netbios_domain_name;
1874 		if (nnb->string == NULL) {
1875 			return NT_STATUS_INVALID_PARAMETER;
1876 		}
1877 		nsid = ninfo->domain_sid;
1878 		if (nsid == NULL) {
1879 			return NT_STATUS_INVALID_PARAMETER;
1880 		}
1881 
1882 		ntln_found = dsdb_trust_find_tln_match(ref_fti, ntln->string);
1883 
1884 		/* check if this is already taken and not excluded */
1885 		for (r = 0; r < ref_fti->count; r++) {
1886 			const struct lsa_ForestTrustRecord *rftr =
1887 				ref_fti->entries[r];
1888 			const struct lsa_ForestTrustDomainInfo *rinfo = NULL;
1889 			const struct lsa_StringLarge *rtln = NULL;
1890 			const struct lsa_StringLarge *rnb = NULL;
1891 			const struct dom_sid *rsid = NULL;
1892 			bool nb_possible = true;
1893 			bool sid_possible = true;
1894 			int cmp;
1895 
1896 			if (rftr == NULL) {
1897 				continue;
1898 			}
1899 
1900 			if (!ntln_found) {
1901 				/*
1902 				 * If the dns name doesn't match any existing
1903 				 * tln any conflict is ignored, but name
1904 				 * normalization still happens.
1905 				 *
1906 				 * I guess that's a bug in Windows
1907 				 * (tested with Windows 2012r2).
1908 				 */
1909 				nb_possible = false;
1910 				sid_possible = false;
1911 			}
1912 
1913 			if (nftr->flags & LSA_SID_DISABLED_MASK) {
1914 				sid_possible = false;
1915 			}
1916 
1917 			if (nftr->flags & LSA_NB_DISABLED_MASK) {
1918 				nb_possible = false;
1919 			}
1920 
1921 			switch (rftr->type) {
1922 			case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
1923 				rtln = &rftr->forest_trust_data.top_level_name;
1924 				nb_possible = false;
1925 				sid_possible = false;
1926 				break;
1927 
1928 			case LSA_FOREST_TRUST_DOMAIN_INFO:
1929 				rinfo = &rftr->forest_trust_data.domain_info;
1930 				rtln = &rinfo->dns_domain_name;
1931 				rnb = &rinfo->netbios_domain_name;
1932 				rsid = rinfo->domain_sid;
1933 
1934 				if (rftr->flags & LSA_SID_DISABLED_MASK) {
1935 					sid_possible = false;
1936 				}
1937 
1938 				if (rftr->flags & LSA_NB_DISABLED_MASK) {
1939 					nb_possible = false;
1940 				}
1941 				break;
1942 
1943 			default:
1944 				break;
1945 			}
1946 
1947 			if (rtln == NULL) {
1948 				continue;
1949 			}
1950 
1951 			if (rtln->string == NULL) {
1952 				continue;
1953 			}
1954 
1955 			cmp = dns_cmp(ntln->string, rtln->string);
1956 			if (DNS_CMP_IS_NO_MATCH(cmp)) {
1957 				nb_possible = false;
1958 				sid_possible = false;
1959 			}
1960 			if (cmp == DNS_CMP_MATCH) {
1961 				/* We need to normalize the string */
1962 				ntln->string = talloc_strdup(nftr,
1963 							     rtln->string);
1964 				if (ntln->string == NULL) {
1965 					return NT_STATUS_NO_MEMORY;
1966 				}
1967 			}
1968 
1969 			if (rinfo == NULL) {
1970 				continue;
1971 			}
1972 
1973 			if (rsid != NULL) {
1974 				cmp = dom_sid_compare(nsid, rsid);
1975 			} else {
1976 				cmp = -1;
1977 			}
1978 			if (cmp == 0) {
1979 				if (sid_possible) {
1980 					flags |= LSA_SID_DISABLED_CONFLICT;
1981 				}
1982 			}
1983 
1984 			if (rnb->string != NULL) {
1985 				cmp = strcasecmp_m(nnb->string, rnb->string);
1986 			} else {
1987 				cmp = -1;
1988 			}
1989 			if (cmp == 0) {
1990 				nnb->string = talloc_strdup(nftr, rnb->string);
1991 				if (nnb->string == NULL) {
1992 					return NT_STATUS_NO_MEMORY;
1993 				}
1994 				if (nb_possible) {
1995 					flags |= LSA_NB_DISABLED_CONFLICT;
1996 				}
1997 			}
1998 		}
1999 
2000 		if (flags == 0) {
2001 			continue;
2002 		}
2003 
2004 		nftr->flags |= flags;
2005 
2006 		status = dsdb_trust_add_collision(c_info,
2007 						  collision_type,
2008 						  n, nftr->flags,
2009 						  ref_tdo->domain_name.string);
2010 		if (!NT_STATUS_IS_OK(status)) {
2011 			return status;
2012 		}
2013 	}
2014 
2015 	return NT_STATUS_OK;
2016 }
2017 
dsdb_trust_merge_forest_info(TALLOC_CTX * mem_ctx,const struct lsa_TrustDomainInfoInfoEx * tdo,const struct lsa_ForestTrustInformation * ofti,const struct lsa_ForestTrustInformation * nfti,struct lsa_ForestTrustInformation ** _mfti)2018 NTSTATUS dsdb_trust_merge_forest_info(TALLOC_CTX *mem_ctx,
2019 				const struct lsa_TrustDomainInfoInfoEx *tdo,
2020 				const struct lsa_ForestTrustInformation *ofti,
2021 				const struct lsa_ForestTrustInformation *nfti,
2022 				struct lsa_ForestTrustInformation **_mfti)
2023 {
2024 	TALLOC_CTX *frame = talloc_stackframe();
2025 	struct lsa_ForestTrustInformation *mfti = NULL;
2026 	uint32_t ni;
2027 	uint32_t oi;
2028 	NTSTATUS status;
2029 	int cmp;
2030 
2031 	*_mfti = NULL;
2032 	mfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
2033 	if (mfti == NULL) {
2034 		TALLOC_FREE(frame);
2035 		return NT_STATUS_NO_MEMORY;
2036 	}
2037 	talloc_steal(frame, mfti);
2038 
2039 	/*
2040 	 * First we add all top unique level names.
2041 	 *
2042 	 * The one matching the tdo dns name, will be
2043 	 * added without further checking. All others
2044 	 * may keep the flags and time values.
2045 	 */
2046 	for (ni = 0; ni < nfti->count; ni++) {
2047 		const struct lsa_ForestTrustRecord *nftr = nfti->entries[ni];
2048 		struct lsa_ForestTrustRecord tftr = {
2049 			.flags = 0,
2050 		};
2051 		const char *ndns = NULL;
2052 		bool ignore_new = false;
2053 		bool found_old = false;
2054 		uint32_t mi;
2055 
2056 		if (nftr == NULL) {
2057 			TALLOC_FREE(frame);
2058 			return NT_STATUS_INVALID_PARAMETER;
2059 		}
2060 
2061 		if (nftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
2062 			continue;
2063 		}
2064 
2065 		ndns = nftr->forest_trust_data.top_level_name.string;
2066 		if (ndns == NULL) {
2067 			TALLOC_FREE(frame);
2068 			return NT_STATUS_INVALID_PARAMETER;
2069 		}
2070 
2071 		cmp = dns_cmp(tdo->domain_name.string, ndns);
2072 		if (cmp == DNS_CMP_MATCH) {
2073 			status = dsdb_trust_forest_info_add_record(mfti, nftr);
2074 			if (!NT_STATUS_IS_OK(status)) {
2075 				TALLOC_FREE(frame);
2076 				return status;
2077 			}
2078 		}
2079 
2080 		for (mi = 0; mi < mfti->count; mi++) {
2081 			const struct lsa_ForestTrustRecord *mftr =
2082 				mfti->entries[mi];
2083 			const char *mdns = NULL;
2084 
2085 			/*
2086 			 * we just added this above, so we're sure to have a
2087 			 * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME record
2088 			 */
2089 			mdns = mftr->forest_trust_data.top_level_name.string;
2090 
2091 			cmp = dns_cmp(mdns, ndns);
2092 			switch (cmp) {
2093 			case DNS_CMP_MATCH:
2094 			case DNS_CMP_SECOND_IS_CHILD:
2095 				ignore_new = true;
2096 				break;
2097 			}
2098 
2099 			if (ignore_new) {
2100 				break;
2101 			}
2102 		}
2103 
2104 		if (ignore_new) {
2105 			continue;
2106 		}
2107 
2108 		/*
2109 		 * make a temporary copy where we can change time and flags
2110 		 */
2111 		tftr = *nftr;
2112 
2113 		for (oi = 0; oi < ofti->count; oi++) {
2114 			const struct lsa_ForestTrustRecord *oftr =
2115 				ofti->entries[oi];
2116 			const char *odns = NULL;
2117 
2118 			if (oftr == NULL) {
2119 				/*
2120 				 * broken record => ignore...
2121 				 */
2122 				continue;
2123 			}
2124 
2125 			if (oftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
2126 				continue;
2127 			}
2128 
2129 			odns = oftr->forest_trust_data.top_level_name.string;
2130 			if (odns == NULL) {
2131 				/*
2132 				 * broken record => ignore...
2133 				 */
2134 				continue;
2135 			}
2136 
2137 			cmp = dns_cmp(odns, ndns);
2138 			if (cmp != DNS_CMP_MATCH) {
2139 				continue;
2140 			}
2141 
2142 			found_old = true;
2143 			tftr.flags = oftr->flags;
2144 			tftr.time = oftr->time;
2145 		}
2146 
2147 		if (!found_old) {
2148 			tftr.flags = LSA_TLN_DISABLED_NEW;
2149 			tftr.time = 0;
2150 		}
2151 
2152 		status = dsdb_trust_forest_info_add_record(mfti, &tftr);
2153 		if (!NT_STATUS_IS_OK(status)) {
2154 			TALLOC_FREE(frame);
2155 			return status;
2156 		}
2157 	}
2158 
2159 	/*
2160 	 * Now we add all unique (based on their SID) domains
2161 	 * and may keep the flags and time values.
2162 	 */
2163 	for (ni = 0; ni < nfti->count; ni++) {
2164 		const struct lsa_ForestTrustRecord *nftr = nfti->entries[ni];
2165 		struct lsa_ForestTrustRecord tftr = {
2166 			.flags = 0,
2167 		};
2168 		const struct lsa_ForestTrustDomainInfo *nd = NULL;
2169 		const char *ndns = NULL;
2170 		const char *nnbt = NULL;
2171 		bool ignore_new = false;
2172 		bool found_old = false;
2173 		uint32_t mi;
2174 
2175 		if (nftr == NULL) {
2176 			TALLOC_FREE(frame);
2177 			return NT_STATUS_INVALID_PARAMETER;
2178 		}
2179 
2180 		if (nftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2181 			continue;
2182 		}
2183 
2184 		nd = &nftr->forest_trust_data.domain_info;
2185 		if (nd->domain_sid == NULL) {
2186 			TALLOC_FREE(frame);
2187 			return NT_STATUS_INVALID_PARAMETER;
2188 		}
2189 		ndns = nd->dns_domain_name.string;
2190 		if (ndns == NULL) {
2191 			TALLOC_FREE(frame);
2192 			return NT_STATUS_INVALID_PARAMETER;
2193 		}
2194 		nnbt = nd->netbios_domain_name.string;
2195 		if (nnbt == NULL) {
2196 			TALLOC_FREE(frame);
2197 			return NT_STATUS_INVALID_PARAMETER;
2198 		}
2199 
2200 		for (mi = 0; mi < mfti->count; mi++) {
2201 			const struct lsa_ForestTrustRecord *mftr =
2202 				mfti->entries[mi];
2203 			const struct lsa_ForestTrustDomainInfo *md = NULL;
2204 
2205 			if (mftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2206 				continue;
2207 			}
2208 
2209 			/*
2210 			 * we just added this above, so we're sure to have a
2211 			 * valid LSA_FOREST_TRUST_DOMAIN_INFO record
2212 			 */
2213 			md = &mftr->forest_trust_data.domain_info;
2214 
2215 			cmp = dom_sid_compare(nd->domain_sid, md->domain_sid);
2216 			if (cmp == 0) {
2217 				ignore_new = true;
2218 				break;
2219 			}
2220 		}
2221 
2222 		if (ignore_new) {
2223 			continue;
2224 		}
2225 
2226 		/*
2227 		 * make a temporary copy where we can change time and flags
2228 		 */
2229 		tftr = *nftr;
2230 
2231 		for (oi = 0; oi < ofti->count; oi++) {
2232 			const struct lsa_ForestTrustRecord *oftr =
2233 				ofti->entries[oi];
2234 			const struct lsa_ForestTrustDomainInfo *od = NULL;
2235 			const char *onbt = NULL;
2236 
2237 			if (oftr == NULL) {
2238 				/*
2239 				 * broken record => ignore...
2240 				 */
2241 				continue;
2242 			}
2243 
2244 			if (oftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2245 				continue;
2246 			}
2247 
2248 			od = &oftr->forest_trust_data.domain_info;
2249 			onbt = od->netbios_domain_name.string;
2250 			if (onbt == NULL) {
2251 				/*
2252 				 * broken record => ignore...
2253 				 */
2254 				continue;
2255 			}
2256 
2257 			cmp = strcasecmp(onbt, nnbt);
2258 			if (cmp != 0) {
2259 				continue;
2260 			}
2261 
2262 			found_old = true;
2263 			tftr.flags = oftr->flags;
2264 			tftr.time = oftr->time;
2265 		}
2266 
2267 		if (!found_old) {
2268 			tftr.flags = 0;
2269 			tftr.time = 0;
2270 		}
2271 
2272 		status = dsdb_trust_forest_info_add_record(mfti, &tftr);
2273 		if (!NT_STATUS_IS_OK(status)) {
2274 			TALLOC_FREE(frame);
2275 			return status;
2276 		}
2277 	}
2278 
2279 	/*
2280 	 * We keep old domain records disabled by the admin
2281 	 * if not already in the list.
2282 	 */
2283 	for (oi = 0; oi < ofti->count; oi++) {
2284 		const struct lsa_ForestTrustRecord *oftr =
2285 			ofti->entries[oi];
2286 		const struct lsa_ForestTrustDomainInfo *od = NULL;
2287 		const char *odns = NULL;
2288 		const char *onbt = NULL;
2289 		bool ignore_old = true;
2290 		uint32_t mi;
2291 
2292 		if (oftr == NULL) {
2293 			/*
2294 			 * broken record => ignore...
2295 			 */
2296 			continue;
2297 		}
2298 
2299 		if (oftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2300 			continue;
2301 		}
2302 
2303 		od = &oftr->forest_trust_data.domain_info;
2304 		odns = od->dns_domain_name.string;
2305 		if (odns == NULL) {
2306 			/*
2307 			 * broken record => ignore...
2308 			 */
2309 			continue;
2310 		}
2311 		onbt = od->netbios_domain_name.string;
2312 		if (onbt == NULL) {
2313 			/*
2314 			 * broken record => ignore...
2315 			 */
2316 			continue;
2317 		}
2318 		if (od->domain_sid == NULL) {
2319 			/*
2320 			 * broken record => ignore...
2321 			 */
2322 			continue;
2323 		}
2324 
2325 		if (oftr->flags & LSA_NB_DISABLED_ADMIN) {
2326 			ignore_old = false;
2327 		} else if (oftr->flags & LSA_SID_DISABLED_ADMIN) {
2328 			ignore_old = false;
2329 		}
2330 
2331 		for (mi = 0; mi < mfti->count; mi++) {
2332 			const struct lsa_ForestTrustRecord *mftr =
2333 				mfti->entries[mi];
2334 			const struct lsa_ForestTrustDomainInfo *md = NULL;
2335 
2336 			if (mftr->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
2337 				continue;
2338 			}
2339 
2340 			/*
2341 			 * we just added this above, so we're sure to have a
2342 			 * valid LSA_FOREST_TRUST_DOMAIN_INFO record
2343 			 */
2344 			md = &mftr->forest_trust_data.domain_info;
2345 
2346 			cmp = dom_sid_compare(od->domain_sid, md->domain_sid);
2347 			if (cmp == 0) {
2348 				ignore_old = true;
2349 				break;
2350 			}
2351 		}
2352 
2353 		if (ignore_old) {
2354 			continue;
2355 		}
2356 
2357 		status = dsdb_trust_forest_info_add_record(mfti, oftr);
2358 		if (!NT_STATUS_IS_OK(status)) {
2359 			TALLOC_FREE(frame);
2360 			return status;
2361 		}
2362 	}
2363 
2364 	/*
2365 	 * Finally we readd top level exclusions,
2366 	 * if they still match a top level name.
2367 	 */
2368 	for (oi = 0; oi < ofti->count; oi++) {
2369 		const struct lsa_ForestTrustRecord *oftr =
2370 			ofti->entries[oi];
2371 		const char *odns = NULL;
2372 		bool ignore_old = false;
2373 		uint32_t mi;
2374 
2375 		if (oftr == NULL) {
2376 			/*
2377 			 * broken record => ignore...
2378 			 */
2379 			continue;
2380 		}
2381 
2382 		if (oftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX) {
2383 			continue;
2384 		}
2385 
2386 		odns = oftr->forest_trust_data.top_level_name_ex.string;
2387 		if (odns == NULL) {
2388 			/*
2389 			 * broken record => ignore...
2390 			 */
2391 			continue;
2392 		}
2393 
2394 		for (mi = 0; mi < mfti->count; mi++) {
2395 			const struct lsa_ForestTrustRecord *mftr =
2396 				mfti->entries[mi];
2397 			const char *mdns = NULL;
2398 
2399 			if (mftr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
2400 				continue;
2401 			}
2402 
2403 			/*
2404 			 * we just added this above, so we're sure to have a
2405 			 * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME.
2406 			 */
2407 			mdns = mftr->forest_trust_data.top_level_name.string;
2408 
2409 			cmp = dns_cmp(mdns, odns);
2410 			switch (cmp) {
2411 			case DNS_CMP_MATCH:
2412 			case DNS_CMP_SECOND_IS_CHILD:
2413 				break;
2414 			default:
2415 				ignore_old = true;
2416 				break;
2417 			}
2418 
2419 			if (ignore_old) {
2420 				break;
2421 			}
2422 		}
2423 
2424 		if (ignore_old) {
2425 			continue;
2426 		}
2427 
2428 		status = dsdb_trust_forest_info_add_record(mfti, oftr);
2429 		if (!NT_STATUS_IS_OK(status)) {
2430 			TALLOC_FREE(frame);
2431 			return status;
2432 		}
2433 	}
2434 
2435 	*_mfti = talloc_move(mem_ctx, &mfti);
2436 	TALLOC_FREE(frame);
2437 	return NT_STATUS_OK;
2438 }
2439 
dsdb_trust_search_tdo(struct ldb_context * sam_ctx,const char * netbios,const char * dns,const char * const * attrs,TALLOC_CTX * mem_ctx,struct ldb_message ** msg)2440 NTSTATUS dsdb_trust_search_tdo(struct ldb_context *sam_ctx,
2441 			       const char *netbios, const char *dns,
2442 			       const char * const *attrs,
2443 			       TALLOC_CTX *mem_ctx,
2444 			       struct ldb_message **msg)
2445 {
2446 	TALLOC_CTX *frame = talloc_stackframe();
2447 	int ret;
2448 	struct ldb_dn *system_dn = NULL;
2449 	char *netbios_encoded = NULL;
2450 	char *dns_encoded = NULL;
2451 	char *filter = NULL;
2452 
2453 	*msg = NULL;
2454 
2455 	if (netbios == NULL && dns == NULL) {
2456 		TALLOC_FREE(frame);
2457 		return NT_STATUS_INVALID_PARAMETER_MIX;
2458 	}
2459 
2460 	system_dn = ldb_dn_copy(frame, ldb_get_default_basedn(sam_ctx));
2461 	if (system_dn == NULL) {
2462 		TALLOC_FREE(frame);
2463 		return NT_STATUS_NO_MEMORY;
2464 	}
2465 
2466 	if (!ldb_dn_add_child_fmt(system_dn, "CN=System")) {
2467 		TALLOC_FREE(frame);
2468 		return NT_STATUS_NO_MEMORY;
2469 	}
2470 
2471 	if (netbios != NULL) {
2472 		netbios_encoded = ldb_binary_encode_string(frame, netbios);
2473 		if (netbios_encoded == NULL) {
2474 			TALLOC_FREE(frame);
2475 			return NT_STATUS_NO_MEMORY;
2476 		}
2477 	}
2478 
2479 	if (dns != NULL) {
2480 		dns_encoded = ldb_binary_encode_string(frame, dns);
2481 		if (dns_encoded == NULL) {
2482 			TALLOC_FREE(frame);
2483 			return NT_STATUS_NO_MEMORY;
2484 		}
2485 	}
2486 
2487 	if (netbios != NULL && dns != NULL) {
2488 		filter = talloc_asprintf(frame,
2489 				"(&(objectClass=trustedDomain)"
2490 				  "(|(trustPartner=%s)(flatName=%s))"
2491 				")",
2492 				dns_encoded, netbios_encoded);
2493 		if (filter == NULL) {
2494 			TALLOC_FREE(frame);
2495 			return NT_STATUS_NO_MEMORY;
2496 		}
2497 	} else if (netbios != NULL) {
2498 		filter = talloc_asprintf(frame,
2499 				"(&(objectClass=trustedDomain)(flatName=%s))",
2500 				netbios_encoded);
2501 		if (filter == NULL) {
2502 			TALLOC_FREE(frame);
2503 			return NT_STATUS_NO_MEMORY;
2504 		}
2505 	} else if (dns != NULL) {
2506 		filter = talloc_asprintf(frame,
2507 				"(&(objectClass=trustedDomain)(trustPartner=%s))",
2508 				dns_encoded);
2509 		if (filter == NULL) {
2510 			TALLOC_FREE(frame);
2511 			return NT_STATUS_NO_MEMORY;
2512 		}
2513 	}
2514 
2515 	ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2516 			      system_dn,
2517 			      LDB_SCOPE_ONELEVEL, attrs,
2518 			      DSDB_SEARCH_NO_GLOBAL_CATALOG,
2519 			      "%s", filter);
2520 	if (ret != LDB_SUCCESS) {
2521 		NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2522 		DEBUG(3, ("Failed to search for %s: %s - %s\n",
2523 			  filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2524 		TALLOC_FREE(frame);
2525 		return status;
2526 	}
2527 
2528 	TALLOC_FREE(frame);
2529 	return NT_STATUS_OK;
2530 }
2531 
dsdb_trust_search_tdo_by_type(struct ldb_context * sam_ctx,enum netr_SchannelType type,const char * name,const char * const * attrs,TALLOC_CTX * mem_ctx,struct ldb_message ** msg)2532 NTSTATUS dsdb_trust_search_tdo_by_type(struct ldb_context *sam_ctx,
2533 				       enum netr_SchannelType type,
2534 				       const char *name,
2535 				       const char * const *attrs,
2536 				       TALLOC_CTX *mem_ctx,
2537 				       struct ldb_message **msg)
2538 {
2539 	TALLOC_CTX *frame = talloc_stackframe();
2540 	NTSTATUS status;
2541 	size_t len;
2542 	char trailer = '$';
2543 	bool require_trailer = true;
2544 	char *encoded_name = NULL;
2545 	const char *netbios = NULL;
2546 	const char *dns = NULL;
2547 
2548 	if (type != SEC_CHAN_DOMAIN && type != SEC_CHAN_DNS_DOMAIN) {
2549 		TALLOC_FREE(frame);
2550 		return NT_STATUS_INVALID_PARAMETER;
2551 	}
2552 
2553 	if (type == SEC_CHAN_DNS_DOMAIN) {
2554 		trailer = '.';
2555 		require_trailer = false;
2556 	}
2557 
2558 	encoded_name = ldb_binary_encode_string(frame, name);
2559 	if (encoded_name == NULL) {
2560 		TALLOC_FREE(frame);
2561 		return NT_STATUS_NO_MEMORY;
2562 	}
2563 
2564 	len = strlen(encoded_name);
2565 	if (len < 2) {
2566 		TALLOC_FREE(frame);
2567 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2568 	}
2569 
2570 	if (require_trailer && encoded_name[len - 1] != trailer) {
2571 		TALLOC_FREE(frame);
2572 		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2573 	}
2574 	encoded_name[len - 1] = '\0';
2575 
2576 	if (type == SEC_CHAN_DNS_DOMAIN) {
2577 		dns = encoded_name;
2578 	} else {
2579 		netbios = encoded_name;
2580 	}
2581 
2582 	status = dsdb_trust_search_tdo(sam_ctx, netbios, dns,
2583 				       attrs, mem_ctx, msg);
2584 	if (!NT_STATUS_IS_OK(status)) {
2585 		TALLOC_FREE(frame);
2586 		return status;
2587 	}
2588 
2589 	TALLOC_FREE(frame);
2590 	return NT_STATUS_OK;
2591 }
2592 
dsdb_trust_search_tdo_by_sid(struct ldb_context * sam_ctx,const struct dom_sid * sid,const char * const * attrs,TALLOC_CTX * mem_ctx,struct ldb_message ** msg)2593 NTSTATUS dsdb_trust_search_tdo_by_sid(struct ldb_context *sam_ctx,
2594 				      const struct dom_sid *sid,
2595 				      const char * const *attrs,
2596 				      TALLOC_CTX *mem_ctx,
2597 				      struct ldb_message **msg)
2598 {
2599 	TALLOC_CTX *frame = talloc_stackframe();
2600 	int ret;
2601 	struct ldb_dn *system_dn = NULL;
2602 	char *encoded_sid = NULL;
2603 	char *filter = NULL;
2604 
2605 	*msg = NULL;
2606 
2607 	if (sid == NULL) {
2608 		TALLOC_FREE(frame);
2609 		return NT_STATUS_INVALID_PARAMETER_MIX;
2610 	}
2611 
2612 	encoded_sid = ldap_encode_ndr_dom_sid(frame, sid);
2613 	if (encoded_sid == NULL) {
2614 		TALLOC_FREE(frame);
2615 		return NT_STATUS_NO_MEMORY;
2616 	}
2617 
2618 	system_dn = ldb_dn_copy(frame, ldb_get_default_basedn(sam_ctx));
2619 	if (system_dn == NULL) {
2620 		TALLOC_FREE(frame);
2621 		return NT_STATUS_NO_MEMORY;
2622 	}
2623 
2624 	if (!ldb_dn_add_child_fmt(system_dn, "CN=System")) {
2625 		TALLOC_FREE(frame);
2626 		return NT_STATUS_NO_MEMORY;
2627 	}
2628 
2629 	filter = talloc_asprintf(frame,
2630 				"(&"
2631 				  "(objectClass=trustedDomain)"
2632 				  "(securityIdentifier=%s)"
2633 				")",
2634 				encoded_sid);
2635 	if (filter == NULL) {
2636 		TALLOC_FREE(frame);
2637 		return NT_STATUS_NO_MEMORY;
2638 	}
2639 
2640 	ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2641 			      system_dn,
2642 			      LDB_SCOPE_ONELEVEL, attrs,
2643 			      DSDB_SEARCH_NO_GLOBAL_CATALOG,
2644 			      "%s", filter);
2645 	if (ret != LDB_SUCCESS) {
2646 		NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2647 		DEBUG(3, ("Failed to search for %s: %s - %s\n",
2648 			  filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2649 		TALLOC_FREE(frame);
2650 		return status;
2651 	}
2652 
2653 	TALLOC_FREE(frame);
2654 	return NT_STATUS_OK;
2655 }
2656 
dsdb_trust_get_incoming_passwords(struct ldb_message * msg,TALLOC_CTX * mem_ctx,struct samr_Password ** _current,struct samr_Password ** _previous)2657 NTSTATUS dsdb_trust_get_incoming_passwords(struct ldb_message *msg,
2658 					   TALLOC_CTX *mem_ctx,
2659 					   struct samr_Password **_current,
2660 					   struct samr_Password **_previous)
2661 {
2662 	TALLOC_CTX *frame = talloc_stackframe();
2663 	struct samr_Password __current = {
2664 		.hash = {0},
2665 	};
2666 	struct samr_Password __previous = {
2667 		.hash = {0},
2668 	};
2669 	struct samr_Password *current = NULL;
2670 	struct samr_Password *previous = NULL;
2671 	const struct ldb_val *blob = NULL;
2672 	enum ndr_err_code ndr_err;
2673 	struct trustAuthInOutBlob incoming = {
2674 		.count = 0,
2675 	};
2676 	uint32_t i;
2677 
2678 	if (_current != NULL) {
2679 		*_current = NULL;
2680 	}
2681 	if (_previous != NULL) {
2682 		*_previous = NULL;
2683 	}
2684 
2685 	blob = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2686 	if (blob == NULL) {
2687 		TALLOC_FREE(frame);
2688 		return NT_STATUS_ACCOUNT_DISABLED;
2689 	}
2690 
2691 	/* ldb_val is equivalent to DATA_BLOB */
2692 	ndr_err = ndr_pull_struct_blob_all(blob, frame, &incoming,
2693 				(ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2694 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2695 		TALLOC_FREE(frame);
2696 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
2697 	}
2698 
2699 	for (i = 0; i < incoming.current.count; i++) {
2700 		struct AuthenticationInformation *a =
2701 			&incoming.current.array[i];
2702 
2703 		if (current != NULL) {
2704 			break;
2705 		}
2706 
2707 		switch (a->AuthType) {
2708 		case TRUST_AUTH_TYPE_NONE:
2709 		case TRUST_AUTH_TYPE_VERSION:
2710 			break;
2711 		case TRUST_AUTH_TYPE_NT4OWF:
2712 			current = &a->AuthInfo.nt4owf.password;
2713 			break;
2714 		case TRUST_AUTH_TYPE_CLEAR:
2715 			mdfour(__current.hash,
2716 			       a->AuthInfo.clear.password,
2717 			       a->AuthInfo.clear.size);
2718 			current = &__current;
2719 			break;
2720 		}
2721 	}
2722 
2723 	if (current == NULL) {
2724 		TALLOC_FREE(frame);
2725 		return NT_STATUS_INTERNAL_DB_CORRUPTION;
2726 	}
2727 
2728 	for (i = 0; i < incoming.previous.count; i++) {
2729 		struct AuthenticationInformation *a =
2730 			&incoming.previous.array[i];
2731 
2732 		if (previous != NULL) {
2733 			break;
2734 		}
2735 
2736 		switch (a->AuthType) {
2737 		case TRUST_AUTH_TYPE_NONE:
2738 		case TRUST_AUTH_TYPE_VERSION:
2739 			break;
2740 		case TRUST_AUTH_TYPE_NT4OWF:
2741 			previous = &a->AuthInfo.nt4owf.password;
2742 			break;
2743 		case TRUST_AUTH_TYPE_CLEAR:
2744 			mdfour(__previous.hash,
2745 			       a->AuthInfo.clear.password,
2746 			       a->AuthInfo.clear.size);
2747 			previous = &__previous;
2748 			break;
2749 		}
2750 	}
2751 
2752 	if (previous == NULL) {
2753 		previous = current;
2754 	}
2755 
2756 	if (_current != NULL) {
2757 		*_current = talloc(mem_ctx, struct samr_Password);
2758 		if (*_current == NULL) {
2759 			TALLOC_FREE(frame);
2760 			return NT_STATUS_NO_MEMORY;
2761 		}
2762 		**_current = *current;
2763 	}
2764 	if (_previous != NULL) {
2765 		*_previous = talloc(mem_ctx, struct samr_Password);
2766 		if (*_previous == NULL) {
2767 			if (_current != NULL) {
2768 				TALLOC_FREE(*_current);
2769 			}
2770 			TALLOC_FREE(frame);
2771 			return NT_STATUS_NO_MEMORY;
2772 		}
2773 		**_previous = *previous;
2774 	}
2775 	ZERO_STRUCTP(current);
2776 	ZERO_STRUCTP(previous);
2777 	TALLOC_FREE(frame);
2778 	return NT_STATUS_OK;
2779 }
2780 
dsdb_trust_search_tdos(struct ldb_context * sam_ctx,const char * exclude,const char * const * attrs,TALLOC_CTX * mem_ctx,struct ldb_result ** res)2781 NTSTATUS dsdb_trust_search_tdos(struct ldb_context *sam_ctx,
2782 				const char *exclude,
2783 				const char * const *attrs,
2784 				TALLOC_CTX *mem_ctx,
2785 				struct ldb_result **res)
2786 {
2787 	TALLOC_CTX *frame = talloc_stackframe();
2788 	int ret;
2789 	struct ldb_dn *system_dn = NULL;
2790 	const char *filter = NULL;
2791 	char *exclude_encoded = NULL;
2792 
2793 	*res = NULL;
2794 
2795 	system_dn = ldb_dn_copy(frame, ldb_get_default_basedn(sam_ctx));
2796 	if (system_dn == NULL) {
2797 		TALLOC_FREE(frame);
2798 		return NT_STATUS_NO_MEMORY;
2799 	}
2800 
2801 	if (!ldb_dn_add_child_fmt(system_dn, "CN=System")) {
2802 		TALLOC_FREE(frame);
2803 		return NT_STATUS_NO_MEMORY;
2804 	}
2805 
2806 	if (exclude != NULL) {
2807 		exclude_encoded = ldb_binary_encode_string(frame, exclude);
2808 		if (exclude_encoded == NULL) {
2809 			TALLOC_FREE(frame);
2810 			return NT_STATUS_NO_MEMORY;
2811 		}
2812 
2813 		filter = talloc_asprintf(frame,
2814 				"(&(objectClass=trustedDomain)"
2815 				  "(!(|(trustPartner=%s)(flatName=%s)))"
2816 				")",
2817 				exclude_encoded, exclude_encoded);
2818 		if (filter == NULL) {
2819 			TALLOC_FREE(frame);
2820 			return NT_STATUS_NO_MEMORY;
2821 		}
2822 	} else {
2823 		filter = "(objectClass=trustedDomain)";
2824 	}
2825 
2826 	ret = dsdb_search(sam_ctx, mem_ctx, res,
2827 			  system_dn,
2828 			  LDB_SCOPE_ONELEVEL, attrs,
2829 			  DSDB_SEARCH_NO_GLOBAL_CATALOG,
2830 			  "%s", filter);
2831 	if (ret != LDB_SUCCESS) {
2832 		NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2833 		DEBUG(3, ("Failed to search for %s: %s - %s\n",
2834 			  filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2835 		TALLOC_FREE(frame);
2836 		return status;
2837 	}
2838 
2839 	TALLOC_FREE(frame);
2840 	return NT_STATUS_OK;
2841 }
2842 
2843 struct dsdb_trust_routing_domain;
2844 
2845 struct dsdb_trust_routing_table {
2846 	struct dsdb_trust_routing_domain *domains;
2847 };
2848 
2849 struct dsdb_trust_routing_domain {
2850 	struct dsdb_trust_routing_domain *prev, *next;
2851 
2852 	struct lsa_TrustDomainInfoInfoEx *tdo;
2853 
2854 	struct lsa_ForestTrustDomainInfo di;
2855 
2856 	struct lsa_ForestTrustInformation *fti;
2857 };
2858 
dsdb_trust_routing_table_load(struct ldb_context * sam_ctx,TALLOC_CTX * mem_ctx,struct dsdb_trust_routing_table ** _table)2859 NTSTATUS dsdb_trust_routing_table_load(struct ldb_context *sam_ctx,
2860 				       TALLOC_CTX *mem_ctx,
2861 				       struct dsdb_trust_routing_table **_table)
2862 {
2863 	TALLOC_CTX *frame = talloc_stackframe();
2864 	struct dsdb_trust_routing_table *table;
2865 	struct dsdb_trust_routing_domain *d = NULL;
2866 	struct ldb_dn *domain_dn = NULL;
2867 	struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
2868 	struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
2869 	struct lsa_TrustDomainInfoInfoEx *root_direction_tdo = NULL;
2870 	const char * const trusts_attrs[] = {
2871 		"securityIdentifier",
2872 		"flatName",
2873 		"trustPartner",
2874 		"trustAttributes",
2875 		"trustDirection",
2876 		"trustType",
2877 		"msDS-TrustForestTrustInfo",
2878 		NULL
2879 	};
2880 	struct ldb_result *trusts_res = NULL;
2881 	unsigned int i;
2882 	NTSTATUS status;
2883 
2884 	*_table = NULL;
2885 
2886 	domain_dn = ldb_get_default_basedn(sam_ctx);
2887 	if (domain_dn == NULL) {
2888 		TALLOC_FREE(frame);
2889 		return NT_STATUS_INTERNAL_ERROR;
2890 	}
2891 
2892 	table = talloc_zero(mem_ctx, struct dsdb_trust_routing_table);
2893 	if (table == NULL) {
2894 		TALLOC_FREE(frame);
2895 		return NT_STATUS_NO_MEMORY;
2896 	}
2897 	talloc_steal(frame, table);
2898 
2899 	d = talloc_zero(table, struct dsdb_trust_routing_domain);
2900 	if (d == NULL) {
2901 		TALLOC_FREE(frame);
2902 		return NT_STATUS_NO_MEMORY;
2903 	}
2904 
2905 	status = dsdb_trust_crossref_tdo_info(d, sam_ctx,
2906 					      domain_dn, NULL,
2907 					      &d->tdo,
2908 					      &root_trust_tdo,
2909 					      &trust_parent_tdo);
2910 	if (!NT_STATUS_IS_OK(status)) {
2911 		TALLOC_FREE(frame);
2912 		return status;
2913 	}
2914 
2915 	/*
2916 	 * d->tdo should not be NULL of status above is 'NT_STATUS_OK'
2917 	 * check is needed to satisfy clang static checker
2918 	*/
2919 	if (d->tdo == NULL) {
2920 		TALLOC_FREE(frame);
2921 		return NT_STATUS_NO_MEMORY;
2922 	}
2923 	d->di.domain_sid = d->tdo->sid;
2924 	d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2925 	d->di.dns_domain_name.string = d->tdo->domain_name.string;
2926 
2927 	if (root_trust_tdo != NULL) {
2928 		root_direction_tdo = root_trust_tdo;
2929 	} else if (trust_parent_tdo != NULL) {
2930 		root_direction_tdo = trust_parent_tdo;
2931 	}
2932 
2933 	if (root_direction_tdo == NULL) {
2934 		/* we're the forest root */
2935 		status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
2936 		if (!NT_STATUS_IS_OK(status)) {
2937 			TALLOC_FREE(frame);
2938 			return status;
2939 		}
2940 	}
2941 
2942 	DLIST_ADD(table->domains, d);
2943 
2944 	status = dsdb_trust_search_tdos(sam_ctx, NULL, trusts_attrs,
2945 					frame, &trusts_res);
2946 	if (!NT_STATUS_IS_OK(status)) {
2947 		TALLOC_FREE(frame);
2948 		return status;
2949 	}
2950 
2951 	for (i = 0; i < trusts_res->count; i++) {
2952 		bool ok;
2953 		int cmp;
2954 
2955 		d = talloc_zero(table, struct dsdb_trust_routing_domain);
2956 		if (d == NULL) {
2957 			TALLOC_FREE(frame);
2958 			return NT_STATUS_NO_MEMORY;
2959 		}
2960 
2961 		status = dsdb_trust_parse_tdo_info(d,
2962 						   trusts_res->msgs[i],
2963 						   &d->tdo);
2964 		if (!NT_STATUS_IS_OK(status)) {
2965 			TALLOC_FREE(frame);
2966 			return status;
2967 		}
2968 
2969 		d->di.domain_sid = d->tdo->sid;
2970 		d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2971 		d->di.dns_domain_name.string = d->tdo->domain_name.string;
2972 
2973 		DLIST_ADD_END(table->domains, d);
2974 
2975 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2976 			struct ForestTrustInfo *fti = NULL;
2977 
2978 			status = dsdb_trust_parse_forest_info(frame,
2979 							      trusts_res->msgs[i],
2980 							      &fti);
2981 			if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
2982 				fti = NULL;
2983 				status = NT_STATUS_OK;
2984 			}
2985 			if (!NT_STATUS_IS_OK(status)) {
2986 				TALLOC_FREE(frame);
2987 				return status;
2988 			}
2989 
2990 			if (fti == NULL) {
2991 				continue;
2992 			}
2993 
2994 			status = dsdb_trust_forest_info_to_lsa(d, fti, &d->fti);
2995 			if (!NT_STATUS_IS_OK(status)) {
2996 				TALLOC_FREE(frame);
2997 				return status;
2998 			}
2999 
3000 			continue;
3001 		}
3002 
3003 		if (!(d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
3004 			continue;
3005 		}
3006 
3007 		if (root_direction_tdo == NULL) {
3008 			continue;
3009 		}
3010 
3011 		ok = dom_sid_equal(root_direction_tdo->sid, d->tdo->sid);
3012 		if (!ok) {
3013 			continue;
3014 		}
3015 
3016 		cmp = strcasecmp_m(root_direction_tdo->netbios_name.string,
3017 				   d->tdo->netbios_name.string);
3018 		if (cmp != 0) {
3019 			continue;
3020 		}
3021 
3022 		cmp = strcasecmp_m(root_direction_tdo->domain_name.string,
3023 				   d->tdo->domain_name.string);
3024 		if (cmp != 0) {
3025 			continue;
3026 		}
3027 
3028 		/* this our route to the forest root */
3029 		status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
3030 		if (!NT_STATUS_IS_OK(status)) {
3031 			TALLOC_FREE(frame);
3032 			return status;
3033 		}
3034 	}
3035 
3036 	*_table = talloc_move(mem_ctx, &table);
3037 	TALLOC_FREE(frame);
3038 	return NT_STATUS_OK;
3039 }
3040 
dsdb_trust_update_best_tln(const struct dsdb_trust_routing_domain ** best_d,const char ** best_tln,const struct dsdb_trust_routing_domain * d,const char * tln)3041 static void dsdb_trust_update_best_tln(
3042 	const struct dsdb_trust_routing_domain **best_d,
3043 	const char **best_tln,
3044 	const struct dsdb_trust_routing_domain *d,
3045 	const char *tln)
3046 {
3047 	int cmp;
3048 
3049 	if (*best_tln == NULL) {
3050 		*best_tln = tln;
3051 		*best_d = d;
3052 		return;
3053 	}
3054 
3055 	cmp = dns_cmp(*best_tln, tln);
3056 	if (cmp != DNS_CMP_FIRST_IS_CHILD) {
3057 		return;
3058 	}
3059 
3060 	*best_tln = tln;
3061 	*best_d = d;
3062 }
3063 
dsdb_trust_routing_by_name(const struct dsdb_trust_routing_table * table,const char * name)3064 const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name(
3065 		const struct dsdb_trust_routing_table *table,
3066 		const char *name)
3067 {
3068 	const struct dsdb_trust_routing_domain *best_d = NULL;
3069 	const char *best_tln = NULL;
3070 	const struct dsdb_trust_routing_domain *d = NULL;
3071 
3072 	if (name == NULL) {
3073 		return NULL;
3074 	}
3075 
3076 	for (d = table->domains; d != NULL; d = d->next) {
3077 		bool transitive = false;
3078 		bool allow_netbios = false;
3079 		bool exclude = false;
3080 		uint32_t i;
3081 
3082 		if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3083 			/*
3084 			 * Only uplevel trusts have top level names
3085 			 */
3086 			continue;
3087 		}
3088 
3089 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3090 			transitive = true;
3091 		}
3092 
3093 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3094 			transitive = true;
3095 		}
3096 
3097 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3098 			transitive = false;
3099 		}
3100 
3101 		if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3102 			transitive = false;
3103 		}
3104 
3105 		switch (d->tdo->trust_type) {
3106 		case LSA_TRUST_TYPE_UPLEVEL:
3107 			if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY) {
3108 				break;
3109 			}
3110 			allow_netbios = true;
3111 			break;
3112 		case LSA_TRUST_TYPE_DOWNLEVEL:
3113 			allow_netbios = true;
3114 			break;
3115 		default:
3116 			allow_netbios = false;
3117 			break;
3118 		}
3119 
3120 		if (!transitive || d->fti == NULL) {
3121 			int cmp;
3122 
3123 			if (allow_netbios) {
3124 				cmp = dns_cmp(name, d->tdo->netbios_name.string);
3125 				if (cmp == DNS_CMP_MATCH) {
3126 					/*
3127 					 * exact match
3128 					 */
3129 					return d->tdo;
3130 				}
3131 			}
3132 
3133 			cmp = dns_cmp(name, d->tdo->domain_name.string);
3134 			if (cmp == DNS_CMP_MATCH) {
3135 				/*
3136 				 * exact match
3137 				 */
3138 				return d->tdo;
3139 			}
3140 			if (cmp != DNS_CMP_FIRST_IS_CHILD) {
3141 				continue;
3142 			}
3143 
3144 			if (!transitive) {
3145 				continue;
3146 			}
3147 
3148 			dsdb_trust_update_best_tln(&best_d, &best_tln, d,
3149 						   d->tdo->domain_name.string);
3150 			continue;
3151 		}
3152 
3153 		exclude = dsdb_trust_find_tln_ex_match(d->fti, name);
3154 		if (exclude) {
3155 			continue;
3156 		}
3157 
3158 		for (i = 0; i < d->fti->count; i++ ) {
3159 			const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3160 			const struct lsa_ForestTrustDomainInfo *di = NULL;
3161 			const char *fti_nbt = NULL;
3162 			int cmp;
3163 
3164 			if (!allow_netbios) {
3165 				break;
3166 			}
3167 
3168 			if (f == NULL) {
3169 				/* broken record */
3170 				continue;
3171 			}
3172 
3173 			if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3174 				continue;
3175 			}
3176 
3177 			if (f->flags & LSA_NB_DISABLED_MASK) {
3178 				/*
3179 				 * any flag disables the entry.
3180 				 */
3181 				continue;
3182 			}
3183 
3184 			di = &f->forest_trust_data.domain_info;
3185 			fti_nbt = di->netbios_domain_name.string;
3186 			if (fti_nbt == NULL) {
3187 				/* broken record */
3188 				continue;
3189 			}
3190 
3191 			cmp = dns_cmp(name, fti_nbt);
3192 			if (cmp == DNS_CMP_MATCH) {
3193 				/*
3194 				 * exact match
3195 				 */
3196 				return d->tdo;
3197 			}
3198 		}
3199 
3200 		for (i = 0; i < d->fti->count; i++ ) {
3201 			const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3202 			const union lsa_ForestTrustData *u = NULL;
3203 			const char *fti_tln = NULL;
3204 			int cmp;
3205 
3206 			if (f == NULL) {
3207 				/* broken record */
3208 				continue;
3209 			}
3210 
3211 			if (f->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
3212 				continue;
3213 			}
3214 
3215 			if (f->flags & LSA_TLN_DISABLED_MASK) {
3216 				/*
3217 				 * any flag disables the entry.
3218 				 */
3219 				continue;
3220 			}
3221 
3222 			u = &f->forest_trust_data;
3223 			fti_tln = u->top_level_name.string;
3224 			if (fti_tln == NULL) {
3225 				continue;
3226 			}
3227 
3228 			cmp = dns_cmp(name, fti_tln);
3229 			switch (cmp) {
3230 			case DNS_CMP_MATCH:
3231 			case DNS_CMP_FIRST_IS_CHILD:
3232 				dsdb_trust_update_best_tln(&best_d, &best_tln,
3233 							   d, fti_tln);
3234 				break;
3235 			default:
3236 				break;
3237 			}
3238 		}
3239 	}
3240 
3241 	if (best_d != NULL) {
3242 		return best_d->tdo;
3243 	}
3244 
3245 	return NULL;
3246 }
3247 
dsdb_trust_domain_by_sid(const struct dsdb_trust_routing_table * table,const struct dom_sid * sid,const struct lsa_ForestTrustDomainInfo ** pdi)3248 const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_sid(
3249 		const struct dsdb_trust_routing_table *table,
3250 		const struct dom_sid *sid,
3251 		const struct lsa_ForestTrustDomainInfo **pdi)
3252 {
3253 	const struct dsdb_trust_routing_domain *d = NULL;
3254 
3255 	if (pdi != NULL) {
3256 		*pdi = NULL;
3257 	}
3258 
3259 	if (sid == NULL) {
3260 		return NULL;
3261 	}
3262 
3263 	for (d = table->domains; d != NULL; d = d->next) {
3264 		bool transitive = false;
3265 		uint32_t i;
3266 
3267 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3268 			transitive = true;
3269 		}
3270 
3271 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3272 			transitive = true;
3273 		}
3274 
3275 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3276 			transitive = false;
3277 		}
3278 
3279 		if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3280 			transitive = false;
3281 		}
3282 
3283 		if (!transitive || d->fti == NULL) {
3284 			bool match = false;
3285 
3286 			match = dom_sid_equal(d->di.domain_sid, sid);
3287 			if (match) {
3288 				/*
3289 				 * exact match, it's the domain itself.
3290 				 */
3291 				if (pdi != NULL) {
3292 					*pdi = &d->di;
3293 				}
3294 				return d->tdo;
3295 			}
3296 			continue;
3297 		}
3298 
3299 		for (i = 0; i < d->fti->count; i++ ) {
3300 			const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3301 			const struct lsa_ForestTrustDomainInfo *di = NULL;
3302 			const struct dom_sid *fti_sid = NULL;
3303 			bool match = false;
3304 
3305 			if (f == NULL) {
3306 				/* broken record */
3307 				continue;
3308 			}
3309 
3310 			if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3311 				continue;
3312 			}
3313 
3314 			if (f->flags & LSA_SID_DISABLED_MASK) {
3315 				/*
3316 				 * any flag disables the entry.
3317 				 */
3318 				continue;
3319 			}
3320 
3321 			di = &f->forest_trust_data.domain_info;
3322 			fti_sid = di->domain_sid;
3323 			if (fti_sid == NULL) {
3324 				/* broken record */
3325 				continue;
3326 			}
3327 
3328 			match = dom_sid_equal(fti_sid, sid);
3329 			if (match) {
3330 				/*
3331 				 * exact match, it's a domain in the forest.
3332 				 */
3333 				if (pdi != NULL) {
3334 					*pdi = di;
3335 				}
3336 				return d->tdo;
3337 			}
3338 		}
3339 	}
3340 
3341 	return NULL;
3342 }
3343 
dsdb_trust_domain_by_name(const struct dsdb_trust_routing_table * table,const char * name,const struct lsa_ForestTrustDomainInfo ** pdi)3344 const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_name(
3345 		const struct dsdb_trust_routing_table *table,
3346 		const char *name,
3347 		const struct lsa_ForestTrustDomainInfo **pdi)
3348 {
3349 	const struct dsdb_trust_routing_domain *d = NULL;
3350 
3351 	if (pdi != NULL) {
3352 		*pdi = NULL;
3353 	}
3354 
3355 	if (name == NULL) {
3356 		return NULL;
3357 	}
3358 
3359 	for (d = table->domains; d != NULL; d = d->next) {
3360 		bool transitive = false;
3361 		uint32_t i;
3362 
3363 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3364 			transitive = true;
3365 		}
3366 
3367 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3368 			transitive = true;
3369 		}
3370 
3371 		if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3372 			transitive = false;
3373 		}
3374 
3375 		if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3376 			transitive = false;
3377 		}
3378 
3379 		if (!transitive || d->fti == NULL) {
3380 			bool match = false;
3381 
3382 			match = strequal_m(d->di.netbios_domain_name.string,
3383 					   name);
3384 			if (match) {
3385 				/*
3386 				 * exact match for netbios name,
3387 				 * it's the domain itself.
3388 				 */
3389 				if (pdi != NULL) {
3390 					*pdi = &d->di;
3391 				}
3392 				return d->tdo;
3393 			}
3394 			match = strequal_m(d->di.dns_domain_name.string,
3395 					   name);
3396 			if (match) {
3397 				/*
3398 				 * exact match for dns name,
3399 				 * it's the domain itself.
3400 				 */
3401 				if (pdi != NULL) {
3402 					*pdi = &d->di;
3403 				}
3404 				return d->tdo;
3405 			}
3406 			continue;
3407 		}
3408 
3409 		for (i = 0; i < d->fti->count; i++ ) {
3410 			const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3411 			const struct lsa_ForestTrustDomainInfo *di = NULL;
3412 			bool match = false;
3413 
3414 			if (f == NULL) {
3415 				/* broken record */
3416 				continue;
3417 			}
3418 
3419 			if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3420 				continue;
3421 			}
3422 			di = &f->forest_trust_data.domain_info;
3423 
3424 			if (!(f->flags & LSA_NB_DISABLED_MASK)) {
3425 				match = strequal_m(di->netbios_domain_name.string,
3426 						   name);
3427 				if (match) {
3428 					/*
3429 					 * exact match for netbios name,
3430 					 * it's a domain in the forest.
3431 					 */
3432 					if (pdi != NULL) {
3433 						*pdi = di;
3434 					}
3435 					return d->tdo;
3436 				}
3437 			}
3438 
3439 			if (!(f->flags & LSA_TLN_DISABLED_MASK)) {
3440 				match = strequal_m(di->dns_domain_name.string,
3441 						   name);
3442 				if (match) {
3443 					/*
3444 					 * exact match for dns name,
3445 					 * it's a domain in the forest.
3446 					 */
3447 					if (pdi != NULL) {
3448 						*pdi = di;
3449 					}
3450 					return d->tdo;
3451 				}
3452 			}
3453 		}
3454 	}
3455 
3456 	return NULL;
3457 }
3458