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