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