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