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