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