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 : struct ForestTrustInfo *fti;
45 : 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 433 : 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 6260 : static NTSTATUS dsdb_trust_forest_record_to_lsa(TALLOC_CTX *mem_ctx,
144 : const struct ForestTrustInfoRecord *ftr,
145 : struct lsa_ForestTrustRecord **_lftr)
146 : {
147 6260 : struct lsa_ForestTrustRecord *lftr = NULL;
148 6260 : const struct ForestTrustString *str = NULL;
149 6260 : struct lsa_StringLarge *lstr = NULL;
150 6260 : const struct ForestTrustDataDomainInfo *info = NULL;
151 6260 : struct lsa_ForestTrustDomainInfo *linfo = NULL;
152 :
153 6260 : *_lftr = NULL;
154 :
155 6260 : lftr = talloc_zero(mem_ctx, struct lsa_ForestTrustRecord);
156 6260 : if (lftr == NULL) {
157 0 : return NT_STATUS_NO_MEMORY;
158 : }
159 :
160 6260 : lftr->flags = ftr->flags;
161 6260 : lftr->time = ftr->timestamp;
162 6260 : lftr->type = (enum lsa_ForestTrustRecordType)ftr->type;
163 :
164 6260 : switch (lftr->type) {
165 4755 : case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
166 4755 : lstr = &lftr->forest_trust_data.top_level_name;
167 4755 : str = &ftr->data.name;
168 :
169 4755 : lstr->string = talloc_strdup(mem_ctx, str->string);
170 4755 : if (lstr->string == NULL) {
171 0 : TALLOC_FREE(lftr);
172 0 : return NT_STATUS_NO_MEMORY;
173 : }
174 :
175 4755 : break;
176 :
177 46 : case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
178 46 : lstr = &lftr->forest_trust_data.top_level_name_ex;
179 46 : str = &ftr->data.name;
180 :
181 46 : lstr->string = talloc_strdup(mem_ctx, str->string);
182 46 : if (lstr->string == NULL) {
183 0 : TALLOC_FREE(lftr);
184 0 : return NT_STATUS_NO_MEMORY;
185 : }
186 :
187 46 : break;
188 :
189 1459 : case LSA_FOREST_TRUST_DOMAIN_INFO:
190 1459 : linfo = &lftr->forest_trust_data.domain_info;
191 1459 : info = &ftr->data.info;
192 :
193 1459 : linfo->domain_sid = dom_sid_dup(lftr, &info->sid);
194 1459 : if (linfo->domain_sid == NULL) {
195 0 : TALLOC_FREE(lftr);
196 0 : return NT_STATUS_NO_MEMORY;
197 : }
198 :
199 1459 : lstr = &linfo->dns_domain_name;
200 1459 : str = &info->dns_name;
201 1459 : lstr->string = talloc_strdup(mem_ctx, str->string);
202 1459 : if (lstr->string == NULL) {
203 0 : TALLOC_FREE(lftr);
204 0 : return NT_STATUS_NO_MEMORY;
205 : }
206 :
207 1459 : lstr = &linfo->netbios_domain_name;
208 1459 : str = &info->netbios_name;
209 1459 : lstr->string = talloc_strdup(mem_ctx, str->string);
210 1459 : if (lstr->string == NULL) {
211 0 : TALLOC_FREE(lftr);
212 0 : return NT_STATUS_NO_MEMORY;
213 : }
214 :
215 1459 : break;
216 :
217 0 : default:
218 0 : return NT_STATUS_NOT_SUPPORTED;
219 : }
220 :
221 6260 : *_lftr = lftr;
222 6260 : return NT_STATUS_OK;
223 : }
224 :
225 1459 : NTSTATUS dsdb_trust_forest_info_to_lsa(TALLOC_CTX *mem_ctx,
226 : const struct ForestTrustInfo *fti,
227 : struct lsa_ForestTrustInformation **_lfti)
228 : {
229 : struct lsa_ForestTrustInformation *lfti;
230 : uint32_t i;
231 :
232 1459 : *_lfti = NULL;
233 :
234 1459 : if (fti->version != 1) {
235 0 : return NT_STATUS_INVALID_PARAMETER;
236 : }
237 :
238 1459 : lfti = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
239 1459 : if (lfti == NULL) {
240 0 : return NT_STATUS_NO_MEMORY;
241 : }
242 :
243 1459 : lfti->count = fti->count;
244 1459 : lfti->entries = talloc_zero_array(mem_ctx,
245 : struct lsa_ForestTrustRecord *,
246 : lfti->count);
247 1459 : if (lfti->entries == NULL) {
248 0 : TALLOC_FREE(lfti);
249 0 : return NT_STATUS_NO_MEMORY;
250 : }
251 :
252 7719 : for (i = 0; i < fti->count; i++) {
253 6260 : struct ForestTrustInfoRecord *ftr = &fti->records[i].record;
254 6260 : struct lsa_ForestTrustRecord *lftr = NULL;
255 : NTSTATUS status;
256 :
257 6260 : status = dsdb_trust_forest_record_to_lsa(lfti->entries, ftr,
258 : &lftr);
259 6260 : if (!NT_STATUS_IS_OK(status)) {
260 0 : TALLOC_FREE(lfti);
261 0 : return NT_STATUS_NO_MEMORY;
262 : }
263 6260 : lfti->entries[i] = lftr;
264 : }
265 :
266 1459 : *_lfti = lfti;
267 1459 : return NT_STATUS_OK;
268 : }
269 :
270 48951 : static NTSTATUS dsdb_trust_forest_info_add_record(struct lsa_ForestTrustInformation *fti,
271 : const struct lsa_ForestTrustRecord *ftr)
272 : {
273 48951 : struct lsa_ForestTrustRecord **es = NULL;
274 48951 : struct lsa_ForestTrustRecord *e = NULL;
275 48951 : const struct lsa_StringLarge *dns1 = NULL;
276 48951 : struct lsa_StringLarge *dns2 = NULL;
277 48951 : const struct lsa_ForestTrustDomainInfo *d1 = NULL;
278 48951 : struct lsa_ForestTrustDomainInfo *d2 = NULL;
279 48951 : size_t len = 0;
280 :
281 48951 : es = talloc_realloc(fti, fti->entries,
282 : struct lsa_ForestTrustRecord *,
283 : fti->count + 1);
284 48951 : if (!es) {
285 0 : return NT_STATUS_NO_MEMORY;
286 : }
287 48951 : fti->entries = es;
288 :
289 48951 : e = talloc_zero(es, struct lsa_ForestTrustRecord);
290 48951 : if (e == NULL) {
291 0 : return NT_STATUS_NO_MEMORY;
292 : }
293 :
294 48951 : e->type = ftr->type;
295 48951 : e->flags = ftr->flags;
296 48951 : e->time = ftr->time;
297 :
298 48951 : switch (ftr->type) {
299 32718 : case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
300 32718 : dns1 = &ftr->forest_trust_data.top_level_name;
301 32718 : dns2 = &e->forest_trust_data.top_level_name;
302 32718 : 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 16201 : case LSA_FOREST_TRUST_DOMAIN_INFO:
310 16201 : dns1 = &ftr->forest_trust_data.domain_info.dns_domain_name;
311 16201 : dns2 = &e->forest_trust_data.domain_info.dns_domain_name;
312 16201 : d1 = &ftr->forest_trust_data.domain_info;
313 16201 : d2 = &e->forest_trust_data.domain_info;
314 16201 : break;
315 0 : default:
316 0 : return NT_STATUS_INVALID_PARAMETER;
317 : }
318 :
319 48951 : if (dns1->string == NULL) {
320 0 : TALLOC_FREE(e);
321 0 : return NT_STATUS_INVALID_PARAMETER;
322 : }
323 :
324 48951 : len = strlen(dns1->string);
325 48951 : if (len == 0) {
326 0 : TALLOC_FREE(e);
327 0 : return NT_STATUS_INVALID_PARAMETER;
328 : }
329 :
330 48951 : dns2->string = talloc_strdup(e, dns1->string);
331 48951 : if (dns2->string == NULL) {
332 0 : TALLOC_FREE(e);
333 0 : return NT_STATUS_NO_MEMORY;
334 : }
335 :
336 48951 : if (d1 != NULL) {
337 16201 : const struct lsa_StringLarge *nb1 = &d1->netbios_domain_name;
338 16201 : struct lsa_StringLarge *nb2 = &d2->netbios_domain_name;
339 :
340 16201 : if (nb1->string == NULL) {
341 0 : TALLOC_FREE(e);
342 0 : return NT_STATUS_INVALID_PARAMETER;
343 : }
344 :
345 16201 : len = strlen(nb1->string);
346 16201 : if (len == 0) {
347 0 : TALLOC_FREE(e);
348 0 : return NT_STATUS_INVALID_PARAMETER;
349 : }
350 16201 : if (len > 15) {
351 0 : TALLOC_FREE(e);
352 0 : return NT_STATUS_INVALID_PARAMETER;
353 : }
354 :
355 16201 : nb2->string = talloc_strdup(e, nb1->string);
356 16201 : if (nb2->string == NULL) {
357 0 : TALLOC_FREE(e);
358 0 : return NT_STATUS_NO_MEMORY;
359 : }
360 :
361 16201 : if (d1->domain_sid == NULL) {
362 0 : TALLOC_FREE(e);
363 0 : return NT_STATUS_INVALID_PARAMETER;
364 : }
365 :
366 16201 : d2->domain_sid = dom_sid_dup(e, d1->domain_sid);
367 16201 : if (d2->domain_sid == NULL) {
368 0 : TALLOC_FREE(e);
369 0 : return NT_STATUS_NO_MEMORY;
370 : }
371 : }
372 :
373 48951 : fti->entries[fti->count++] = e;
374 48951 : return NT_STATUS_OK;
375 : }
376 :
377 15986 : 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 15986 : TALLOC_CTX *frame = talloc_stackframe();
383 15986 : struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
384 15986 : const char *dns = NULL;
385 15986 : const char *netbios = NULL;
386 15986 : struct ldb_dn *nc_dn = NULL;
387 15986 : struct dom_sid sid = {
388 : .num_auths = 0,
389 : };
390 : NTSTATUS status;
391 :
392 15986 : *_tdo = NULL;
393 15986 : tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
394 15986 : if (tdo == NULL) {
395 0 : TALLOC_FREE(frame);
396 0 : return NT_STATUS_NO_MEMORY;
397 : }
398 15986 : talloc_steal(frame, tdo);
399 :
400 15986 : dns = ldb_msg_find_attr_as_string(msg, "dnsRoot", NULL);
401 15986 : if (dns == NULL) {
402 0 : TALLOC_FREE(frame);
403 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
404 : }
405 15986 : tdo->domain_name.string = talloc_strdup(tdo, dns);
406 15986 : if (tdo->domain_name.string == NULL) {
407 0 : TALLOC_FREE(frame);
408 0 : return NT_STATUS_NO_MEMORY;
409 : }
410 :
411 15986 : netbios = ldb_msg_find_attr_as_string(msg, "nETBIOSName", NULL);
412 15986 : if (netbios == NULL) {
413 0 : TALLOC_FREE(frame);
414 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
415 : }
416 15986 : tdo->netbios_name.string = talloc_strdup(tdo, netbios);
417 15986 : if (tdo->netbios_name.string == NULL) {
418 0 : TALLOC_FREE(frame);
419 0 : return NT_STATUS_NO_MEMORY;
420 : }
421 :
422 15986 : nc_dn = samdb_result_dn(sam_ctx, frame, msg, "ncName", NULL);
423 15986 : if (nc_dn == NULL) {
424 0 : TALLOC_FREE(frame);
425 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
426 : }
427 :
428 15986 : status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
429 15986 : if (!NT_STATUS_IS_OK(status)) {
430 0 : TALLOC_FREE(frame);
431 0 : return status;
432 : }
433 15986 : tdo->sid = dom_sid_dup(tdo, &sid);
434 15986 : if (tdo->sid == NULL) {
435 0 : TALLOC_FREE(frame);
436 0 : return NT_STATUS_NO_MEMORY;
437 : }
438 :
439 15986 : tdo->trust_type = LSA_TRUST_TYPE_UPLEVEL;
440 15986 : tdo->trust_direction = LSA_TRUST_DIRECTION_INBOUND |
441 : LSA_TRUST_DIRECTION_OUTBOUND;
442 15986 : tdo->trust_attributes = LSA_TRUST_ATTRIBUTE_WITHIN_FOREST;
443 :
444 15986 : *_tdo = talloc_move(mem_ctx, &tdo);
445 15986 : TALLOC_FREE(frame);
446 15986 : return NT_STATUS_OK;
447 : }
448 :
449 15986 : 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 15986 : TALLOC_CTX *frame = talloc_stackframe();
458 15986 : struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
459 15986 : struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
460 15986 : struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
461 15986 : struct ldb_dn *partitions_dn = NULL;
462 15986 : const char * const cross_attrs[] = {
463 : "dnsRoot",
464 : "nETBIOSName",
465 : "nCName",
466 : "rootTrust",
467 : "trustParent",
468 : NULL,
469 : };
470 15986 : struct ldb_result *cross_res = NULL;
471 15986 : struct ldb_message *msg = NULL;
472 15986 : struct ldb_dn *root_trust_dn = NULL;
473 15986 : struct ldb_dn *trust_parent_dn = NULL;
474 : NTSTATUS status;
475 : int ret;
476 :
477 15986 : if (extra_filter == NULL) {
478 15899 : extra_filter = "";
479 : }
480 :
481 15986 : *_tdo = NULL;
482 15986 : if (_root_trust_tdo != NULL) {
483 15773 : *_root_trust_tdo = NULL;
484 : }
485 15986 : if (_trust_parent_tdo != NULL) {
486 15773 : *_trust_parent_tdo = NULL;
487 : }
488 :
489 15986 : partitions_dn = samdb_partitions_dn(sam_ctx, frame);
490 15986 : if (partitions_dn == NULL) {
491 0 : TALLOC_FREE(frame);
492 0 : return NT_STATUS_NO_MEMORY;
493 : }
494 :
495 15986 : 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 15986 : if (ret != LDB_SUCCESS) {
511 0 : TALLOC_FREE(frame);
512 0 : return dsdb_ldb_err_to_ntstatus(ret);
513 : }
514 15986 : msg = cross_res->msgs[0];
515 :
516 15986 : status = dsdb_trust_parse_crossref_info(mem_ctx, sam_ctx, msg, &tdo);
517 15986 : if (!NT_STATUS_IS_OK(status)) {
518 0 : TALLOC_FREE(frame);
519 0 : return status;
520 : }
521 15986 : talloc_steal(frame, tdo);
522 :
523 15986 : if (_root_trust_tdo != NULL) {
524 15773 : root_trust_dn = samdb_result_dn(sam_ctx, frame, msg,
525 : "rootTrust", NULL);
526 : }
527 15986 : if (_trust_parent_tdo != NULL) {
528 15773 : trust_parent_dn = samdb_result_dn(sam_ctx, frame, msg,
529 : "trustParent", NULL);
530 : }
531 :
532 15986 : 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 15986 : 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 15986 : *_tdo = talloc_move(mem_ctx, &tdo);
591 15986 : if (_root_trust_tdo != NULL) {
592 15773 : *_root_trust_tdo = talloc_move(mem_ctx, &root_trust_tdo);
593 : }
594 15986 : if (_trust_parent_tdo != NULL) {
595 15773 : *_trust_parent_tdo = talloc_move(mem_ctx, &trust_parent_tdo);
596 : }
597 15986 : TALLOC_FREE(frame);
598 15986 : 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 130316 : static int dns_cmp(const char *s1, const char *s2)
624 : {
625 130316 : size_t l1 = 0;
626 130316 : const char *p1 = NULL;
627 130316 : size_t num_comp1 = 0;
628 130316 : uint16_t comp1[UINT8_MAX] = {0};
629 130316 : size_t l2 = 0;
630 130316 : const char *p2 = NULL;
631 130316 : size_t num_comp2 = 0;
632 130316 : uint16_t comp2[UINT8_MAX] = {0};
633 : size_t i;
634 :
635 130316 : if (s1 != NULL) {
636 130316 : l1 = strlen(s1);
637 : }
638 :
639 130316 : if (s2 != NULL) {
640 130316 : l2 = strlen(s2);
641 : }
642 :
643 : /*
644 : * trailing '.' are ignored.
645 : */
646 130316 : if (l1 > 1 && s1[l1 - 1] == '.') {
647 0 : l1--;
648 : }
649 130316 : if (l2 > 1 && s2[l2 - 1] == '.') {
650 0 : l2--;
651 : }
652 :
653 421460 : for (i = 0; i < ARRAY_SIZE(comp1); i++) {
654 : char *p;
655 :
656 421460 : if (i == 0) {
657 130316 : p1 = s1;
658 :
659 130316 : if (l1 == 0 || l1 >= UINT16_MAX) {
660 : /* just use one single component on overflow */
661 : break;
662 : }
663 : }
664 :
665 421460 : comp1[num_comp1++] = PTR_DIFF(p1, s1);
666 :
667 421460 : p = strchr_m(p1, '.');
668 421460 : if (p == NULL) {
669 126228 : p1 = NULL;
670 126228 : break;
671 : }
672 :
673 291144 : p1 = p + 1;
674 : }
675 :
676 130316 : 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 510119 : for (i = 0; i < ARRAY_SIZE(comp2); i++) {
684 : char *p;
685 :
686 510119 : if (i == 0) {
687 130316 : p2 = s2;
688 :
689 130316 : if (l2 == 0 || l2 >= UINT16_MAX) {
690 : /* just use one single component on overflow */
691 : break;
692 : }
693 : }
694 :
695 510119 : comp2[num_comp2++] = PTR_DIFF(p2, s2);
696 :
697 510119 : p = strchr_m(p2, '.');
698 510119 : if (p == NULL) {
699 126228 : p2 = NULL;
700 126228 : break;
701 : }
702 :
703 379803 : p2 = p + 1;
704 : }
705 :
706 130316 : 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 157806 : for (i = 0; i < UINT8_MAX; i++) {
714 : int cmp;
715 :
716 157806 : if (i < num_comp1) {
717 156863 : size_t idx = num_comp1 - (i + 1);
718 156863 : p1 = s1 + comp1[idx];
719 : } else {
720 943 : p1 = NULL;
721 : }
722 :
723 157806 : if (i < num_comp2) {
724 155268 : size_t idx = num_comp2 - (i + 1);
725 155268 : p2 = s2 + comp2[idx];
726 : } else {
727 2538 : p2 = NULL;
728 : }
729 :
730 157806 : if (p1 == NULL && p2 == NULL) {
731 943 : return DNS_CMP_MATCH;
732 : }
733 156863 : if (p1 != NULL && p2 == NULL) {
734 1595 : return DNS_CMP_FIRST_IS_CHILD;
735 : }
736 155268 : if (p1 == NULL && p2 != NULL) {
737 0 : return DNS_CMP_SECOND_IS_CHILD;
738 : }
739 :
740 155268 : cmp = strcasecmp_m(p1, p2);
741 155268 : if (cmp < 0) {
742 70867 : return DNS_CMP_FIRST_IS_LESS;
743 : }
744 81681 : if (cmp > 0) {
745 52823 : return DNS_CMP_SECOND_IS_LESS;
746 : }
747 : }
748 :
749 0 : smb_panic(__location__);
750 : return -1;
751 : }
752 :
753 49257 : static int dsdb_trust_find_tln_match_internal(const struct lsa_ForestTrustInformation *info,
754 : enum lsa_ForestTrustRecordType type,
755 : uint32_t disable_mask,
756 : const char *tln)
757 : {
758 : uint32_t i;
759 :
760 144731 : for (i = 0; i < info->count; i++) {
761 95526 : struct lsa_ForestTrustRecord *e = info->entries[i];
762 95526 : struct lsa_StringLarge *t = NULL;
763 : int cmp;
764 :
765 95526 : if (e == NULL) {
766 0 : continue;
767 : }
768 :
769 95526 : if (e->type != type) {
770 69719 : continue;
771 : }
772 :
773 25807 : if (e->flags & disable_mask) {
774 0 : continue;
775 : }
776 :
777 25807 : switch (type) {
778 25801 : case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
779 25801 : t = &e->forest_trust_data.top_level_name;
780 25801 : break;
781 6 : case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
782 6 : t = &e->forest_trust_data.top_level_name_ex;
783 6 : break;
784 0 : default:
785 0 : break;
786 : }
787 :
788 24781 : if (t == NULL) {
789 0 : continue;
790 : }
791 :
792 25807 : cmp = dns_cmp(tln, t->string);
793 25807 : switch (cmp) {
794 52 : case DNS_CMP_MATCH:
795 : case DNS_CMP_FIRST_IS_CHILD:
796 52 : return i;
797 : }
798 : }
799 :
800 47836 : return -1;
801 : }
802 :
803 30953 : static bool dsdb_trust_find_tln_match(const struct lsa_ForestTrustInformation *info,
804 : const char *tln)
805 : {
806 : int m;
807 :
808 31983 : m = dsdb_trust_find_tln_match_internal(info,
809 : LSA_FOREST_TRUST_TOP_LEVEL_NAME,
810 : LSA_TLN_DISABLED_MASK,
811 : tln);
812 31983 : if (m != -1) {
813 52 : return true;
814 : }
815 :
816 30901 : return false;
817 : }
818 :
819 16935 : static bool dsdb_trust_find_tln_ex_match(const struct lsa_ForestTrustInformation *info,
820 : const char *tln)
821 : {
822 : int m;
823 :
824 17274 : m = dsdb_trust_find_tln_match_internal(info,
825 : LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX,
826 : 0,
827 : tln);
828 17274 : if (m != -1) {
829 0 : return true;
830 : }
831 :
832 16935 : return false;
833 : }
834 :
835 126 : NTSTATUS dsdb_trust_local_tdo_info(TALLOC_CTX *mem_ctx,
836 : struct ldb_context *sam_ctx,
837 : struct lsa_TrustDomainInfoInfoEx **_tdo)
838 : {
839 126 : struct ldb_dn *domain_dn = NULL;
840 :
841 126 : domain_dn = ldb_get_default_basedn(sam_ctx);
842 126 : if (domain_dn == NULL) {
843 0 : return NT_STATUS_INTERNAL_ERROR;
844 : }
845 :
846 126 : 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 : 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 16085 : static int dsdb_trust_xref_sort_vals(struct ldb_val *v1,
913 : struct ldb_val *v2)
914 : {
915 16427 : const char *dns1 = (const char *)v1->data;
916 16427 : const char *dns2 = (const char *)v2->data;
917 :
918 16427 : return dns_cmp(dns1, dns2);
919 : }
920 :
921 16035 : NTSTATUS dsdb_trust_xref_forest_info(TALLOC_CTX *mem_ctx,
922 : struct ldb_context *sam_ctx,
923 : struct lsa_ForestTrustInformation **_info)
924 : {
925 16035 : TALLOC_CTX *frame = talloc_stackframe();
926 16035 : struct lsa_ForestTrustInformation *info = NULL;
927 16035 : struct ldb_dn *partitions_dn = NULL;
928 16035 : const char * const cross_attrs1[] = {
929 : "uPNSuffixes",
930 : "msDS-SPNSuffixes",
931 : NULL,
932 : };
933 16035 : struct ldb_result *cross_res1 = NULL;
934 16035 : struct ldb_message_element *upn_el = NULL;
935 16035 : struct ldb_message_element *spn_el = NULL;
936 16035 : struct ldb_message *tln_msg = NULL;
937 16035 : struct ldb_message_element *tln_el = NULL;
938 16035 : const char * const cross_attrs2[] = {
939 : "dnsRoot",
940 : "nETBIOSName",
941 : "nCName",
942 : "rootTrust",
943 : "trustParent",
944 : NULL,
945 : };
946 16035 : struct ldb_result *cross_res2 = NULL;
947 : int ret;
948 : unsigned int i;
949 16035 : bool restart = false;
950 :
951 16035 : *_info = NULL;
952 16035 : info = talloc_zero(mem_ctx, struct lsa_ForestTrustInformation);
953 16035 : if (info == NULL) {
954 0 : TALLOC_FREE(frame);
955 0 : return NT_STATUS_NO_MEMORY;
956 : }
957 16035 : talloc_steal(frame, info);
958 :
959 16035 : partitions_dn = samdb_partitions_dn(sam_ctx, frame);
960 16035 : if (partitions_dn == NULL) {
961 0 : TALLOC_FREE(frame);
962 0 : return NT_STATUS_NO_MEMORY;
963 : }
964 :
965 16035 : ret = dsdb_search_dn(sam_ctx, partitions_dn, &cross_res1,
966 : partitions_dn, cross_attrs1, 0);
967 16035 : if (ret != LDB_SUCCESS) {
968 0 : TALLOC_FREE(frame);
969 0 : return dsdb_ldb_err_to_ntstatus(ret);
970 : }
971 :
972 16035 : 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 16035 : 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 16035 : TYPESAFE_QSORT(cross_res2->msgs, cross_res2->count,
989 : dsdb_trust_xref_sort_msgs);
990 :
991 16035 : upn_el = ldb_msg_find_element(cross_res1->msgs[0], "uPNSuffixes");
992 16035 : if (upn_el != NULL) {
993 7509 : upn_el->name = "__tln__";
994 : }
995 16035 : spn_el = ldb_msg_find_element(cross_res1->msgs[0], "msDS-SPNSuffixes");
996 16035 : if (spn_el != NULL) {
997 7509 : spn_el->name = "__tln__";
998 : }
999 16035 : ret = ldb_msg_normalize(sam_ctx, frame, cross_res1->msgs[0], &tln_msg);
1000 16035 : if (ret != LDB_SUCCESS) {
1001 0 : TALLOC_FREE(frame);
1002 0 : return dsdb_ldb_err_to_ntstatus(ret);
1003 : }
1004 16035 : tln_el = ldb_msg_find_element(tln_msg, "__tln__");
1005 16035 : if (tln_el != NULL) {
1006 : /*
1007 : * Sort the domains as trees
1008 : */
1009 7509 : TYPESAFE_QSORT(tln_el->values, tln_el->num_values,
1010 : dsdb_trust_xref_sort_vals);
1011 : }
1012 :
1013 63384 : for (i=0; i < cross_res2->count; i++) {
1014 16035 : struct ldb_message *m = cross_res2->msgs[i];
1015 16035 : const char *dns = NULL;
1016 16035 : const char *netbios = NULL;
1017 16035 : struct ldb_dn *nc_dn = NULL;
1018 16035 : struct dom_sid sid = {
1019 : .num_auths = 0,
1020 : };
1021 16035 : struct lsa_ForestTrustRecord e = {
1022 : .flags = 0,
1023 : };
1024 16035 : struct lsa_ForestTrustDomainInfo *d = NULL;
1025 16035 : struct lsa_StringLarge *t = NULL;
1026 16035 : bool match = false;
1027 : NTSTATUS status;
1028 :
1029 16035 : dns = ldb_msg_find_attr_as_string(m, "dnsRoot", NULL);
1030 16035 : if (dns == NULL) {
1031 0 : TALLOC_FREE(frame);
1032 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1033 : }
1034 :
1035 16035 : netbios = ldb_msg_find_attr_as_string(m, "nETBIOSName", NULL);
1036 16035 : if (netbios == NULL) {
1037 0 : TALLOC_FREE(frame);
1038 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1039 : }
1040 :
1041 16035 : nc_dn = samdb_result_dn(sam_ctx, m, m, "ncName", NULL);
1042 16035 : if (nc_dn == NULL) {
1043 0 : TALLOC_FREE(frame);
1044 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1045 : }
1046 :
1047 16035 : status = dsdb_get_extended_dn_sid(nc_dn, &sid, "SID");
1048 16035 : if (!NT_STATUS_IS_OK(status)) {
1049 0 : TALLOC_FREE(frame);
1050 0 : return status;
1051 : }
1052 :
1053 16381 : match = dsdb_trust_find_tln_match(info, dns);
1054 15689 : if (!match) {
1055 : /*
1056 : * First the TOP_LEVEL_NAME, if required
1057 : */
1058 16035 : 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 16035 : t = &e.forest_trust_data.top_level_name;
1065 16035 : t->string = dns;
1066 :
1067 16035 : status = dsdb_trust_forest_info_add_record(info, &e);
1068 16035 : 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 16035 : 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 16035 : d = &e.forest_trust_data.domain_info;
1083 16035 : d->domain_sid = &sid;
1084 16035 : d->dns_domain_name.string = dns;
1085 16035 : d->netbios_domain_name.string = netbios;
1086 :
1087 16035 : status = dsdb_trust_forest_info_add_record(info, &e);
1088 16035 : if (!NT_STATUS_IS_OK(status)) {
1089 0 : TALLOC_FREE(frame);
1090 0 : return status;
1091 : }
1092 : }
1093 :
1094 31550 : for (i=0; (tln_el != NULL) && i < tln_el->num_values; i++) {
1095 15861 : const struct ldb_val *v = &tln_el->values[i];
1096 15861 : const char *dns = (const char *)v->data;
1097 15861 : struct lsa_ForestTrustRecord e = {
1098 : .flags = 0,
1099 : };
1100 15861 : struct lsa_StringLarge *t = NULL;
1101 15861 : bool match = false;
1102 : NTSTATUS status;
1103 :
1104 15861 : if (dns == NULL) {
1105 0 : TALLOC_FREE(frame);
1106 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1107 : }
1108 :
1109 16545 : match = dsdb_trust_find_tln_match(info, dns);
1110 15177 : if (match) {
1111 0 : continue;
1112 : }
1113 :
1114 : /*
1115 : * an additional the TOP_LEVEL_NAME
1116 : */
1117 15861 : 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 15861 : t = &e.forest_trust_data.top_level_name;
1123 15861 : t->string = dns;
1124 :
1125 15861 : status = dsdb_trust_forest_info_add_record(info, &e);
1126 15861 : if (!NT_STATUS_IS_OK(status)) {
1127 0 : TALLOC_FREE(frame);
1128 0 : return status;
1129 : }
1130 : }
1131 :
1132 63620 : for (i=0; i < info->count; restart ? i=0 : i++) {
1133 47931 : struct lsa_ForestTrustRecord *tr = info->entries[i];
1134 47931 : const struct lsa_StringLarge *ts = NULL;
1135 : uint32_t c;
1136 :
1137 47931 : restart = false;
1138 :
1139 47931 : if (tr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1140 16035 : continue;
1141 : }
1142 :
1143 31896 : ts = &tr->forest_trust_data.top_level_name;
1144 :
1145 73523 : for (c = i + 1; c < info->count; c++) {
1146 41627 : struct lsa_ForestTrustRecord *cr = info->entries[c];
1147 41627 : const struct lsa_StringLarge *cs = NULL;
1148 : uint32_t j;
1149 : int cmp;
1150 :
1151 41627 : if (cr->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
1152 16035 : continue;
1153 : }
1154 :
1155 25592 : cs = &cr->forest_trust_data.top_level_name;
1156 :
1157 25592 : cmp = dns_cmp(ts->string, cs->string);
1158 25592 : if (DNS_CMP_IS_NO_MATCH(cmp)) {
1159 25592 : 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 16035 : *_info = talloc_move(mem_ctx, &info);
1181 16035 : TALLOC_FREE(frame);
1182 16035 : return NT_STATUS_OK;
1183 : }
1184 :
1185 7841 : NTSTATUS dsdb_trust_parse_tdo_info(TALLOC_CTX *mem_ctx,
1186 : struct ldb_message *m,
1187 : struct lsa_TrustDomainInfoInfoEx **_tdo)
1188 : {
1189 7841 : struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
1190 7841 : const char *dns = NULL;
1191 7841 : const char *netbios = NULL;
1192 :
1193 7841 : *_tdo = NULL;
1194 :
1195 7841 : tdo = talloc_zero(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1196 7841 : if (tdo == NULL) {
1197 0 : return NT_STATUS_NO_MEMORY;
1198 : }
1199 :
1200 7841 : dns = ldb_msg_find_attr_as_string(m, "trustPartner", NULL);
1201 7841 : if (dns == NULL) {
1202 0 : TALLOC_FREE(tdo);
1203 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1204 : }
1205 7841 : tdo->domain_name.string = talloc_strdup(tdo, dns);
1206 7841 : if (tdo->domain_name.string == NULL) {
1207 0 : TALLOC_FREE(tdo);
1208 0 : return NT_STATUS_NO_MEMORY;
1209 : }
1210 :
1211 7841 : netbios = ldb_msg_find_attr_as_string(m, "flatName", NULL);
1212 7841 : if (netbios == NULL) {
1213 0 : TALLOC_FREE(tdo);
1214 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1215 : }
1216 7841 : tdo->netbios_name.string = talloc_strdup(tdo, netbios);
1217 7841 : if (tdo->netbios_name.string == NULL) {
1218 0 : TALLOC_FREE(tdo);
1219 0 : return NT_STATUS_NO_MEMORY;
1220 : }
1221 :
1222 7841 : tdo->sid = samdb_result_dom_sid(tdo, m, "securityIdentifier");
1223 7841 : if (tdo->sid == NULL) {
1224 0 : TALLOC_FREE(tdo);
1225 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1226 : }
1227 :
1228 7841 : tdo->trust_type = ldb_msg_find_attr_as_uint(m, "trustType", 0);
1229 7841 : tdo->trust_direction = ldb_msg_find_attr_as_uint(m, "trustDirection", 0);
1230 7841 : tdo->trust_attributes = ldb_msg_find_attr_as_uint(m, "trustAttributes", 0);
1231 :
1232 7841 : *_tdo = tdo;
1233 7841 : return NT_STATUS_OK;
1234 : }
1235 :
1236 1467 : NTSTATUS dsdb_trust_parse_forest_info(TALLOC_CTX *mem_ctx,
1237 : struct ldb_message *m,
1238 : struct ForestTrustInfo **_fti)
1239 : {
1240 1467 : const struct ldb_val *ft_blob = NULL;
1241 1467 : struct ForestTrustInfo *fti = NULL;
1242 : enum ndr_err_code ndr_err;
1243 :
1244 1467 : *_fti = NULL;
1245 :
1246 1467 : ft_blob = ldb_msg_find_ldb_val(m, "msDS-TrustForestTrustInfo");
1247 1467 : if (ft_blob == NULL) {
1248 8 : return NT_STATUS_NOT_FOUND;
1249 : }
1250 :
1251 1459 : fti = talloc_zero(mem_ctx, struct ForestTrustInfo);
1252 1459 : if (fti == NULL) {
1253 0 : return NT_STATUS_NO_MEMORY;
1254 : }
1255 :
1256 : /* ldb_val is equivalent to DATA_BLOB */
1257 1459 : ndr_err = ndr_pull_struct_blob_all(ft_blob, fti, fti,
1258 : (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1259 1459 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1260 0 : TALLOC_FREE(fti);
1261 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
1262 : }
1263 :
1264 1459 : *_fti = fti;
1265 1459 : 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 : struct lsa_ForestTrustInformation *nfti;
1274 : 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 dublicates. The first one wins and
1290 : * we keep 'count' as is. This is required in order to
1291 : * provide the correct index for collision records.
1292 : */
1293 942 : 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 : NTSTATUS status;
1301 538 : size_t len = 0;
1302 538 : char *p = NULL;
1303 : 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 : 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 : 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 : int cmp;
1454 :
1455 2910 : if (cftr == NULL) {
1456 1452 : 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 : uint32_t c;
1486 538 : bool found_tln = false;
1487 :
1488 538 : if (nftr == NULL) {
1489 266 : 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 : 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 : uint32_t c;
1540 538 : bool found_tln = false;
1541 :
1542 538 : if (nftr == NULL) {
1543 266 : 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 : 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 : struct lsa_ForestTrustInformation *nfti;
1604 : 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 : struct lsa_ForestTrustRecord tftr;
1625 482 : bool skip = false;
1626 : 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 : struct lsa_ForestTrustRecord tftr;
1666 482 : bool skip = false;
1667 : 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 : 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 : 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 : uint32_t r;
1756 : 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 : 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 246 : ntln->string = talloc_strdup(nftr,
1801 82 : 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 : 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 18 : 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 : uint32_t r;
1860 : 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 : 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 78 : ntln->string = talloc_strdup(nftr,
1965 26 : 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 : uint32_t ni;
2029 : uint32_t oi;
2030 : NTSTATUS status;
2031 : 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 : 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 : 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 : 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 : 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 1623 : 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 1623 : TALLOC_CTX *frame = talloc_stackframe();
2449 : int ret;
2450 1623 : struct ldb_dn *system_dn = NULL;
2451 1623 : char *netbios_encoded = NULL;
2452 1623 : char *dns_encoded = NULL;
2453 1623 : char *filter = NULL;
2454 :
2455 1623 : *msg = NULL;
2456 :
2457 1623 : if (netbios == NULL && dns == NULL) {
2458 0 : TALLOC_FREE(frame);
2459 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
2460 : }
2461 :
2462 1623 : system_dn = ldb_dn_copy(frame, ldb_get_default_basedn(sam_ctx));
2463 1623 : if (system_dn == NULL) {
2464 0 : TALLOC_FREE(frame);
2465 0 : return NT_STATUS_NO_MEMORY;
2466 : }
2467 :
2468 1623 : if (!ldb_dn_add_child_fmt(system_dn, "CN=System")) {
2469 0 : TALLOC_FREE(frame);
2470 0 : return NT_STATUS_NO_MEMORY;
2471 : }
2472 :
2473 1623 : if (netbios != NULL) {
2474 1376 : netbios_encoded = ldb_binary_encode_string(frame, netbios);
2475 1376 : if (netbios_encoded == NULL) {
2476 0 : TALLOC_FREE(frame);
2477 0 : return NT_STATUS_NO_MEMORY;
2478 : }
2479 : }
2480 :
2481 1623 : if (dns != NULL) {
2482 1418 : dns_encoded = ldb_binary_encode_string(frame, dns);
2483 1418 : if (dns_encoded == NULL) {
2484 0 : TALLOC_FREE(frame);
2485 0 : return NT_STATUS_NO_MEMORY;
2486 : }
2487 : }
2488 :
2489 1623 : if (netbios != NULL && dns != NULL) {
2490 1171 : filter = talloc_asprintf(frame,
2491 : "(&(objectClass=trustedDomain)"
2492 : "(|(trustPartner=%s)(flatName=%s))"
2493 : ")",
2494 : dns_encoded, netbios_encoded);
2495 2218 : if (filter == NULL) {
2496 0 : TALLOC_FREE(frame);
2497 0 : return NT_STATUS_NO_MEMORY;
2498 : }
2499 452 : } else if (netbios != NULL) {
2500 205 : filter = talloc_asprintf(frame,
2501 : "(&(objectClass=trustedDomain)(flatName=%s))",
2502 : netbios_encoded);
2503 205 : if (filter == NULL) {
2504 0 : TALLOC_FREE(frame);
2505 0 : return NT_STATUS_NO_MEMORY;
2506 : }
2507 247 : } else if (dns != NULL) {
2508 247 : filter = talloc_asprintf(frame,
2509 : "(&(objectClass=trustedDomain)(trustPartner=%s))",
2510 : dns_encoded);
2511 247 : if (filter == NULL) {
2512 0 : TALLOC_FREE(frame);
2513 0 : return NT_STATUS_NO_MEMORY;
2514 : }
2515 : }
2516 :
2517 1623 : ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2518 : system_dn,
2519 : LDB_SCOPE_ONELEVEL, attrs,
2520 : DSDB_SEARCH_NO_GLOBAL_CATALOG,
2521 : "%s", filter);
2522 1623 : if (ret != LDB_SUCCESS) {
2523 9 : NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2524 9 : DEBUG(3, ("Failed to search for %s: %s - %s\n",
2525 : filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2526 9 : TALLOC_FREE(frame);
2527 9 : return status;
2528 : }
2529 :
2530 1614 : TALLOC_FREE(frame);
2531 1614 : return NT_STATUS_OK;
2532 : }
2533 :
2534 146 : NTSTATUS dsdb_trust_search_tdo_by_type(struct ldb_context *sam_ctx,
2535 : enum netr_SchannelType type,
2536 : const char *name,
2537 : const char * const *attrs,
2538 : TALLOC_CTX *mem_ctx,
2539 : struct ldb_message **msg)
2540 : {
2541 146 : TALLOC_CTX *frame = talloc_stackframe();
2542 : NTSTATUS status;
2543 : size_t len;
2544 146 : char trailer = '$';
2545 146 : bool require_trailer = true;
2546 146 : char *encoded_name = NULL;
2547 146 : const char *netbios = NULL;
2548 146 : const char *dns = NULL;
2549 :
2550 146 : if (type != SEC_CHAN_DOMAIN && type != SEC_CHAN_DNS_DOMAIN) {
2551 0 : TALLOC_FREE(frame);
2552 0 : return NT_STATUS_INVALID_PARAMETER;
2553 : }
2554 :
2555 146 : if (type == SEC_CHAN_DNS_DOMAIN) {
2556 36 : trailer = '.';
2557 36 : require_trailer = false;
2558 : }
2559 :
2560 146 : encoded_name = ldb_binary_encode_string(frame, name);
2561 146 : if (encoded_name == NULL) {
2562 0 : TALLOC_FREE(frame);
2563 0 : return NT_STATUS_NO_MEMORY;
2564 : }
2565 :
2566 146 : len = strlen(encoded_name);
2567 146 : if (len < 2) {
2568 0 : TALLOC_FREE(frame);
2569 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2570 : }
2571 :
2572 146 : if (require_trailer && encoded_name[len - 1] != trailer) {
2573 0 : TALLOC_FREE(frame);
2574 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2575 : }
2576 146 : encoded_name[len - 1] = '\0';
2577 :
2578 146 : if (type == SEC_CHAN_DNS_DOMAIN) {
2579 36 : dns = encoded_name;
2580 : } else {
2581 110 : netbios = encoded_name;
2582 : }
2583 :
2584 146 : status = dsdb_trust_search_tdo(sam_ctx, netbios, dns,
2585 : attrs, mem_ctx, msg);
2586 146 : if (!NT_STATUS_IS_OK(status)) {
2587 0 : TALLOC_FREE(frame);
2588 0 : return status;
2589 : }
2590 :
2591 146 : TALLOC_FREE(frame);
2592 146 : return NT_STATUS_OK;
2593 : }
2594 :
2595 0 : NTSTATUS dsdb_trust_search_tdo_by_sid(struct ldb_context *sam_ctx,
2596 : const struct dom_sid *sid,
2597 : const char * const *attrs,
2598 : TALLOC_CTX *mem_ctx,
2599 : struct ldb_message **msg)
2600 : {
2601 0 : TALLOC_CTX *frame = talloc_stackframe();
2602 : int ret;
2603 0 : struct ldb_dn *system_dn = NULL;
2604 0 : char *encoded_sid = NULL;
2605 0 : char *filter = NULL;
2606 :
2607 0 : *msg = NULL;
2608 :
2609 0 : if (sid == NULL) {
2610 0 : TALLOC_FREE(frame);
2611 0 : return NT_STATUS_INVALID_PARAMETER_MIX;
2612 : }
2613 :
2614 0 : encoded_sid = ldap_encode_ndr_dom_sid(frame, sid);
2615 0 : if (encoded_sid == NULL) {
2616 0 : TALLOC_FREE(frame);
2617 0 : return NT_STATUS_NO_MEMORY;
2618 : }
2619 :
2620 0 : system_dn = ldb_dn_copy(frame, ldb_get_default_basedn(sam_ctx));
2621 0 : if (system_dn == NULL) {
2622 0 : TALLOC_FREE(frame);
2623 0 : return NT_STATUS_NO_MEMORY;
2624 : }
2625 :
2626 0 : if (!ldb_dn_add_child_fmt(system_dn, "CN=System")) {
2627 0 : TALLOC_FREE(frame);
2628 0 : return NT_STATUS_NO_MEMORY;
2629 : }
2630 :
2631 0 : filter = talloc_asprintf(frame,
2632 : "(&"
2633 : "(objectClass=trustedDomain)"
2634 : "(securityIdentifier=%s)"
2635 : ")",
2636 : encoded_sid);
2637 0 : if (filter == NULL) {
2638 0 : TALLOC_FREE(frame);
2639 0 : return NT_STATUS_NO_MEMORY;
2640 : }
2641 :
2642 0 : ret = dsdb_search_one(sam_ctx, mem_ctx, msg,
2643 : system_dn,
2644 : LDB_SCOPE_ONELEVEL, attrs,
2645 : DSDB_SEARCH_NO_GLOBAL_CATALOG,
2646 : "%s", filter);
2647 0 : if (ret != LDB_SUCCESS) {
2648 0 : NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2649 0 : DEBUG(3, ("Failed to search for %s: %s - %s\n",
2650 : filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2651 0 : TALLOC_FREE(frame);
2652 0 : return status;
2653 : }
2654 :
2655 0 : TALLOC_FREE(frame);
2656 0 : return NT_STATUS_OK;
2657 : }
2658 :
2659 354 : NTSTATUS dsdb_trust_get_incoming_passwords(struct ldb_message *msg,
2660 : TALLOC_CTX *mem_ctx,
2661 : struct samr_Password **_current,
2662 : struct samr_Password **_previous)
2663 : {
2664 354 : TALLOC_CTX *frame = talloc_stackframe();
2665 354 : struct samr_Password __current = {
2666 : .hash = {0},
2667 : };
2668 354 : struct samr_Password __previous = {
2669 : .hash = {0},
2670 : };
2671 354 : struct samr_Password *current = NULL;
2672 354 : struct samr_Password *previous = NULL;
2673 354 : const struct ldb_val *blob = NULL;
2674 : enum ndr_err_code ndr_err;
2675 354 : struct trustAuthInOutBlob incoming = {
2676 : .count = 0,
2677 : };
2678 : uint32_t i;
2679 :
2680 354 : if (_current != NULL) {
2681 354 : *_current = NULL;
2682 : }
2683 354 : if (_previous != NULL) {
2684 354 : *_previous = NULL;
2685 : }
2686 :
2687 354 : blob = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2688 354 : if (blob == NULL) {
2689 0 : TALLOC_FREE(frame);
2690 0 : return NT_STATUS_ACCOUNT_DISABLED;
2691 : }
2692 :
2693 : /* ldb_val is equivalent to DATA_BLOB */
2694 354 : ndr_err = ndr_pull_struct_blob_all(blob, frame, &incoming,
2695 : (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2696 354 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2697 0 : TALLOC_FREE(frame);
2698 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2699 : }
2700 :
2701 708 : for (i = 0; i < incoming.current.count; i++) {
2702 580 : struct AuthenticationInformation *a =
2703 580 : &incoming.current.array[i];
2704 :
2705 580 : if (current != NULL) {
2706 226 : break;
2707 : }
2708 :
2709 354 : switch (a->AuthType) {
2710 0 : case TRUST_AUTH_TYPE_NONE:
2711 : case TRUST_AUTH_TYPE_VERSION:
2712 0 : break;
2713 0 : case TRUST_AUTH_TYPE_NT4OWF:
2714 0 : current = &a->AuthInfo.nt4owf.password;
2715 0 : break;
2716 354 : case TRUST_AUTH_TYPE_CLEAR:
2717 652 : mdfour(__current.hash,
2718 354 : a->AuthInfo.clear.password,
2719 354 : a->AuthInfo.clear.size);
2720 354 : current = &__current;
2721 354 : break;
2722 : }
2723 : }
2724 :
2725 354 : if (current == NULL) {
2726 0 : TALLOC_FREE(frame);
2727 0 : return NT_STATUS_INTERNAL_DB_CORRUPTION;
2728 : }
2729 :
2730 708 : for (i = 0; i < incoming.previous.count; i++) {
2731 580 : struct AuthenticationInformation *a =
2732 580 : &incoming.previous.array[i];
2733 :
2734 580 : if (previous != NULL) {
2735 226 : break;
2736 : }
2737 :
2738 354 : switch (a->AuthType) {
2739 0 : case TRUST_AUTH_TYPE_NONE:
2740 : case TRUST_AUTH_TYPE_VERSION:
2741 0 : break;
2742 0 : case TRUST_AUTH_TYPE_NT4OWF:
2743 0 : previous = &a->AuthInfo.nt4owf.password;
2744 0 : break;
2745 354 : case TRUST_AUTH_TYPE_CLEAR:
2746 652 : mdfour(__previous.hash,
2747 354 : a->AuthInfo.clear.password,
2748 354 : a->AuthInfo.clear.size);
2749 354 : previous = &__previous;
2750 354 : break;
2751 : }
2752 : }
2753 :
2754 354 : if (previous == NULL) {
2755 0 : previous = current;
2756 : }
2757 :
2758 354 : if (_current != NULL) {
2759 354 : *_current = talloc(mem_ctx, struct samr_Password);
2760 354 : if (*_current == NULL) {
2761 0 : TALLOC_FREE(frame);
2762 0 : return NT_STATUS_NO_MEMORY;
2763 : }
2764 354 : **_current = *current;
2765 : }
2766 354 : if (_previous != NULL) {
2767 354 : *_previous = talloc(mem_ctx, struct samr_Password);
2768 354 : if (*_previous == NULL) {
2769 0 : if (_current != NULL) {
2770 0 : TALLOC_FREE(*_current);
2771 : }
2772 0 : TALLOC_FREE(frame);
2773 0 : return NT_STATUS_NO_MEMORY;
2774 : }
2775 354 : **_previous = *previous;
2776 : }
2777 354 : ZERO_STRUCTP(current);
2778 354 : ZERO_STRUCTP(previous);
2779 354 : TALLOC_FREE(frame);
2780 354 : return NT_STATUS_OK;
2781 : }
2782 :
2783 16191 : NTSTATUS dsdb_trust_search_tdos(struct ldb_context *sam_ctx,
2784 : const char *exclude,
2785 : const char * const *attrs,
2786 : TALLOC_CTX *mem_ctx,
2787 : struct ldb_result **res)
2788 : {
2789 16191 : TALLOC_CTX *frame = talloc_stackframe();
2790 : int ret;
2791 16191 : struct ldb_dn *system_dn = NULL;
2792 16191 : const char *filter = NULL;
2793 16191 : char *exclude_encoded = NULL;
2794 :
2795 16191 : *res = NULL;
2796 :
2797 16191 : system_dn = ldb_dn_copy(frame, ldb_get_default_basedn(sam_ctx));
2798 16191 : if (system_dn == NULL) {
2799 0 : TALLOC_FREE(frame);
2800 0 : return NT_STATUS_NO_MEMORY;
2801 : }
2802 :
2803 16191 : if (!ldb_dn_add_child_fmt(system_dn, "CN=System")) {
2804 0 : TALLOC_FREE(frame);
2805 0 : return NT_STATUS_NO_MEMORY;
2806 : }
2807 :
2808 16191 : if (exclude != NULL) {
2809 87 : exclude_encoded = ldb_binary_encode_string(frame, exclude);
2810 87 : if (exclude_encoded == NULL) {
2811 0 : TALLOC_FREE(frame);
2812 0 : return NT_STATUS_NO_MEMORY;
2813 : }
2814 :
2815 87 : filter = talloc_asprintf(frame,
2816 : "(&(objectClass=trustedDomain)"
2817 : "(!(|(trustPartner=%s)(flatName=%s)))"
2818 : ")",
2819 : exclude_encoded, exclude_encoded);
2820 87 : if (filter == NULL) {
2821 0 : TALLOC_FREE(frame);
2822 0 : return NT_STATUS_NO_MEMORY;
2823 : }
2824 : } else {
2825 15742 : filter = "(objectClass=trustedDomain)";
2826 : }
2827 :
2828 16191 : ret = dsdb_search(sam_ctx, mem_ctx, res,
2829 : system_dn,
2830 : LDB_SCOPE_ONELEVEL, attrs,
2831 : DSDB_SEARCH_NO_GLOBAL_CATALOG,
2832 : "%s", filter);
2833 16191 : if (ret != LDB_SUCCESS) {
2834 0 : NTSTATUS status = dsdb_ldb_err_to_ntstatus(ret);
2835 0 : DEBUG(3, ("Failed to search for %s: %s - %s\n",
2836 : filter, nt_errstr(status), ldb_errstring(sam_ctx)));
2837 0 : TALLOC_FREE(frame);
2838 0 : return status;
2839 : }
2840 :
2841 16191 : TALLOC_FREE(frame);
2842 16191 : return NT_STATUS_OK;
2843 : }
2844 :
2845 : struct dsdb_trust_routing_domain;
2846 :
2847 : struct dsdb_trust_routing_table {
2848 : struct dsdb_trust_routing_domain *domains;
2849 : };
2850 :
2851 : struct dsdb_trust_routing_domain {
2852 : struct dsdb_trust_routing_domain *prev, *next;
2853 :
2854 : struct lsa_TrustDomainInfoInfoEx *tdo;
2855 :
2856 : struct lsa_ForestTrustDomainInfo di;
2857 :
2858 : struct lsa_ForestTrustInformation *fti;
2859 : };
2860 :
2861 15773 : NTSTATUS dsdb_trust_routing_table_load(struct ldb_context *sam_ctx,
2862 : TALLOC_CTX *mem_ctx,
2863 : struct dsdb_trust_routing_table **_table)
2864 : {
2865 15773 : TALLOC_CTX *frame = talloc_stackframe();
2866 : struct dsdb_trust_routing_table *table;
2867 15773 : struct dsdb_trust_routing_domain *d = NULL;
2868 15773 : struct ldb_dn *domain_dn = NULL;
2869 15773 : struct lsa_TrustDomainInfoInfoEx *root_trust_tdo = NULL;
2870 15773 : struct lsa_TrustDomainInfoInfoEx *trust_parent_tdo = NULL;
2871 15773 : struct lsa_TrustDomainInfoInfoEx *root_direction_tdo = NULL;
2872 15773 : const char * const trusts_attrs[] = {
2873 : "securityIdentifier",
2874 : "flatName",
2875 : "trustPartner",
2876 : "trustAttributes",
2877 : "trustDirection",
2878 : "trustType",
2879 : "msDS-TrustForestTrustInfo",
2880 : NULL
2881 : };
2882 15773 : struct ldb_result *trusts_res = NULL;
2883 : unsigned int i;
2884 : NTSTATUS status;
2885 :
2886 15773 : *_table = NULL;
2887 :
2888 15773 : domain_dn = ldb_get_default_basedn(sam_ctx);
2889 15773 : if (domain_dn == NULL) {
2890 0 : TALLOC_FREE(frame);
2891 0 : return NT_STATUS_INTERNAL_ERROR;
2892 : }
2893 :
2894 15773 : table = talloc_zero(mem_ctx, struct dsdb_trust_routing_table);
2895 15773 : if (table == NULL) {
2896 0 : TALLOC_FREE(frame);
2897 0 : return NT_STATUS_NO_MEMORY;
2898 : }
2899 15773 : talloc_steal(frame, table);
2900 :
2901 15773 : d = talloc_zero(table, struct dsdb_trust_routing_domain);
2902 15773 : if (d == NULL) {
2903 0 : TALLOC_FREE(frame);
2904 0 : return NT_STATUS_NO_MEMORY;
2905 : }
2906 :
2907 15773 : status = dsdb_trust_crossref_tdo_info(d, sam_ctx,
2908 : domain_dn, NULL,
2909 : &d->tdo,
2910 : &root_trust_tdo,
2911 : &trust_parent_tdo);
2912 15773 : if (!NT_STATUS_IS_OK(status)) {
2913 0 : TALLOC_FREE(frame);
2914 0 : return status;
2915 : }
2916 :
2917 : /*
2918 : * d->tdo should not be NULL of status above is 'NT_STATUS_OK'
2919 : * check is needed to satisfy clang static checker
2920 : */
2921 15773 : if (d->tdo == NULL) {
2922 0 : TALLOC_FREE(frame);
2923 0 : return NT_STATUS_NO_MEMORY;
2924 : }
2925 15773 : d->di.domain_sid = d->tdo->sid;
2926 15773 : d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2927 15773 : d->di.dns_domain_name.string = d->tdo->domain_name.string;
2928 :
2929 15773 : if (root_trust_tdo != NULL) {
2930 0 : root_direction_tdo = root_trust_tdo;
2931 15773 : } else if (trust_parent_tdo != NULL) {
2932 0 : root_direction_tdo = trust_parent_tdo;
2933 : }
2934 :
2935 15434 : if (root_direction_tdo == NULL) {
2936 : /* we're the forest root */
2937 15773 : status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
2938 15773 : if (!NT_STATUS_IS_OK(status)) {
2939 0 : TALLOC_FREE(frame);
2940 0 : return status;
2941 : }
2942 : }
2943 :
2944 15773 : DLIST_ADD(table->domains, d);
2945 :
2946 15773 : status = dsdb_trust_search_tdos(sam_ctx, NULL, trusts_attrs,
2947 : frame, &trusts_res);
2948 15773 : if (!NT_STATUS_IS_OK(status)) {
2949 0 : TALLOC_FREE(frame);
2950 0 : return status;
2951 : }
2952 :
2953 22113 : for (i = 0; i < trusts_res->count; i++) {
2954 : bool ok;
2955 : int cmp;
2956 :
2957 6679 : d = talloc_zero(table, struct dsdb_trust_routing_domain);
2958 6679 : if (d == NULL) {
2959 0 : TALLOC_FREE(frame);
2960 0 : return NT_STATUS_NO_MEMORY;
2961 : }
2962 :
2963 13217 : status = dsdb_trust_parse_tdo_info(d,
2964 6679 : trusts_res->msgs[i],
2965 : &d->tdo);
2966 6679 : if (!NT_STATUS_IS_OK(status)) {
2967 0 : TALLOC_FREE(frame);
2968 0 : return status;
2969 : }
2970 :
2971 6679 : d->di.domain_sid = d->tdo->sid;
2972 6679 : d->di.netbios_domain_name.string = d->tdo->netbios_name.string;
2973 6679 : d->di.dns_domain_name.string = d->tdo->domain_name.string;
2974 :
2975 6679 : DLIST_ADD_END(table->domains, d);
2976 :
2977 6679 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2978 1303 : struct ForestTrustInfo *fti = NULL;
2979 :
2980 1303 : status = dsdb_trust_parse_forest_info(frame,
2981 1303 : trusts_res->msgs[i],
2982 : &fti);
2983 1303 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
2984 0 : fti = NULL;
2985 0 : status = NT_STATUS_OK;
2986 : }
2987 1303 : if (!NT_STATUS_IS_OK(status)) {
2988 0 : TALLOC_FREE(frame);
2989 0 : return status;
2990 : }
2991 :
2992 1303 : if (fti == NULL) {
2993 1303 : continue;
2994 : }
2995 :
2996 1303 : status = dsdb_trust_forest_info_to_lsa(d, fti, &d->fti);
2997 1303 : if (!NT_STATUS_IS_OK(status)) {
2998 0 : TALLOC_FREE(frame);
2999 0 : return status;
3000 : }
3001 :
3002 1303 : continue;
3003 : }
3004 :
3005 5376 : if (!(d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
3006 5376 : continue;
3007 : }
3008 :
3009 0 : if (root_direction_tdo == NULL) {
3010 0 : continue;
3011 : }
3012 :
3013 0 : ok = dom_sid_equal(root_direction_tdo->sid, d->tdo->sid);
3014 0 : if (!ok) {
3015 0 : continue;
3016 : }
3017 :
3018 0 : cmp = strcasecmp_m(root_direction_tdo->netbios_name.string,
3019 0 : d->tdo->netbios_name.string);
3020 0 : if (cmp != 0) {
3021 0 : continue;
3022 : }
3023 :
3024 0 : cmp = strcasecmp_m(root_direction_tdo->domain_name.string,
3025 0 : d->tdo->domain_name.string);
3026 0 : if (cmp != 0) {
3027 0 : continue;
3028 : }
3029 :
3030 : /* this our route to the forest root */
3031 0 : status = dsdb_trust_xref_forest_info(d, sam_ctx, &d->fti);
3032 0 : if (!NT_STATUS_IS_OK(status)) {
3033 0 : TALLOC_FREE(frame);
3034 0 : return status;
3035 : }
3036 : }
3037 :
3038 15773 : *_table = talloc_move(mem_ctx, &table);
3039 15773 : TALLOC_FREE(frame);
3040 15773 : return NT_STATUS_OK;
3041 : }
3042 :
3043 1566 : static void dsdb_trust_update_best_tln(
3044 : const struct dsdb_trust_routing_domain **best_d,
3045 : const char **best_tln,
3046 : const struct dsdb_trust_routing_domain *d,
3047 : const char *tln)
3048 : {
3049 : int cmp;
3050 :
3051 1566 : if (*best_tln == NULL) {
3052 1566 : *best_tln = tln;
3053 1566 : *best_d = d;
3054 1566 : return;
3055 : }
3056 :
3057 0 : cmp = dns_cmp(*best_tln, tln);
3058 0 : if (cmp != DNS_CMP_FIRST_IS_CHILD) {
3059 0 : return;
3060 : }
3061 :
3062 0 : *best_tln = tln;
3063 0 : *best_d = d;
3064 : }
3065 :
3066 15638 : const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_routing_by_name(
3067 : const struct dsdb_trust_routing_table *table,
3068 : const char *name)
3069 : {
3070 15638 : const struct dsdb_trust_routing_domain *best_d = NULL;
3071 15638 : const char *best_tln = NULL;
3072 15638 : const struct dsdb_trust_routing_domain *d = NULL;
3073 :
3074 15638 : if (name == NULL) {
3075 0 : return NULL;
3076 : }
3077 :
3078 35826 : for (d = table->domains; d != NULL; d = d->next) {
3079 20764 : bool transitive = false;
3080 20764 : bool allow_netbios = false;
3081 20764 : bool exclude = false;
3082 : uint32_t i;
3083 :
3084 20764 : if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3085 : /*
3086 : * Only uplevel trusts have top level names
3087 : */
3088 1008 : continue;
3089 : }
3090 :
3091 19756 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3092 15638 : transitive = true;
3093 : }
3094 :
3095 19756 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3096 1201 : transitive = true;
3097 : }
3098 :
3099 19756 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3100 0 : transitive = false;
3101 : }
3102 :
3103 19417 : if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3104 0 : transitive = false;
3105 : }
3106 :
3107 19417 : switch (d->tdo->trust_type) {
3108 19417 : case LSA_TRUST_TYPE_UPLEVEL:
3109 19756 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY) {
3110 0 : break;
3111 : }
3112 19756 : allow_netbios = true;
3113 19756 : break;
3114 0 : case LSA_TRUST_TYPE_DOWNLEVEL:
3115 0 : allow_netbios = true;
3116 0 : break;
3117 0 : default:
3118 0 : allow_netbios = false;
3119 0 : break;
3120 : }
3121 :
3122 19756 : if (!transitive || d->fti == NULL) {
3123 : int cmp;
3124 :
3125 2917 : if (allow_netbios) {
3126 2917 : cmp = dns_cmp(name, d->tdo->netbios_name.string);
3127 2917 : if (cmp == DNS_CMP_MATCH) {
3128 : /*
3129 : * exact match
3130 : */
3131 242 : return d->tdo;
3132 : }
3133 : }
3134 :
3135 2675 : cmp = dns_cmp(name, d->tdo->domain_name.string);
3136 2675 : if (cmp == DNS_CMP_MATCH) {
3137 : /*
3138 : * exact match
3139 : */
3140 322 : return d->tdo;
3141 : }
3142 2353 : if (cmp != DNS_CMP_FIRST_IS_CHILD) {
3143 2332 : continue;
3144 : }
3145 :
3146 21 : if (!transitive) {
3147 21 : continue;
3148 : }
3149 :
3150 0 : dsdb_trust_update_best_tln(&best_d, &best_tln, d,
3151 0 : d->tdo->domain_name.string);
3152 0 : continue;
3153 : }
3154 :
3155 16839 : exclude = dsdb_trust_find_tln_ex_match(d->fti, name);
3156 16500 : if (exclude) {
3157 0 : continue;
3158 : }
3159 :
3160 67589 : for (i = 0; i < d->fti->count; i++ ) {
3161 51101 : const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3162 51101 : const struct lsa_ForestTrustDomainInfo *di = NULL;
3163 51101 : const char *fti_nbt = NULL;
3164 : int cmp;
3165 :
3166 51101 : if (!allow_netbios) {
3167 0 : break;
3168 : }
3169 :
3170 51101 : if (f == NULL) {
3171 : /* broken record */
3172 0 : continue;
3173 : }
3174 :
3175 51101 : if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3176 34262 : continue;
3177 : }
3178 :
3179 16839 : if (f->flags & LSA_NB_DISABLED_MASK) {
3180 : /*
3181 : * any flag disables the entry.
3182 : */
3183 14 : continue;
3184 : }
3185 :
3186 16825 : di = &f->forest_trust_data.domain_info;
3187 16825 : fti_nbt = di->netbios_domain_name.string;
3188 16825 : if (fti_nbt == NULL) {
3189 : /* broken record */
3190 0 : continue;
3191 : }
3192 :
3193 16825 : cmp = dns_cmp(name, fti_nbt);
3194 16825 : if (cmp == DNS_CMP_MATCH) {
3195 : /*
3196 : * exact match
3197 : */
3198 12 : return d->tdo;
3199 : }
3200 : }
3201 :
3202 67541 : for (i = 0; i < d->fti->count; i++ ) {
3203 51053 : const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3204 51053 : const union lsa_ForestTrustData *u = NULL;
3205 51053 : const char *fti_tln = NULL;
3206 : int cmp;
3207 :
3208 51053 : if (f == NULL) {
3209 : /* broken record */
3210 0 : continue;
3211 : }
3212 :
3213 51053 : if (f->type != LSA_FOREST_TRUST_TOP_LEVEL_NAME) {
3214 16833 : continue;
3215 : }
3216 :
3217 34220 : if (f->flags & LSA_TLN_DISABLED_MASK) {
3218 : /*
3219 : * any flag disables the entry.
3220 : */
3221 75 : continue;
3222 : }
3223 :
3224 34145 : u = &f->forest_trust_data;
3225 34145 : fti_tln = u->top_level_name.string;
3226 34145 : if (fti_tln == NULL) {
3227 0 : continue;
3228 : }
3229 :
3230 34145 : cmp = dns_cmp(name, fti_tln);
3231 34145 : switch (cmp) {
3232 1566 : case DNS_CMP_MATCH:
3233 : case DNS_CMP_FIRST_IS_CHILD:
3234 1566 : dsdb_trust_update_best_tln(&best_d, &best_tln,
3235 : d, fti_tln);
3236 1566 : break;
3237 31566 : default:
3238 31566 : break;
3239 : }
3240 : }
3241 : }
3242 :
3243 15062 : if (best_d != NULL) {
3244 1566 : return best_d->tdo;
3245 : }
3246 :
3247 13157 : return NULL;
3248 : }
3249 :
3250 46 : const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_sid(
3251 : const struct dsdb_trust_routing_table *table,
3252 : const struct dom_sid *sid,
3253 : const struct lsa_ForestTrustDomainInfo **pdi)
3254 : {
3255 46 : const struct dsdb_trust_routing_domain *d = NULL;
3256 :
3257 46 : if (pdi != NULL) {
3258 31 : *pdi = NULL;
3259 : }
3260 :
3261 46 : if (sid == NULL) {
3262 0 : return NULL;
3263 : }
3264 :
3265 117 : for (d = table->domains; d != NULL; d = d->next) {
3266 100 : bool transitive = false;
3267 : uint32_t i;
3268 :
3269 100 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3270 46 : transitive = true;
3271 : }
3272 :
3273 100 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3274 27 : transitive = true;
3275 : }
3276 :
3277 100 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3278 0 : transitive = false;
3279 : }
3280 :
3281 100 : if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3282 0 : transitive = false;
3283 : }
3284 :
3285 100 : if (!transitive || d->fti == NULL) {
3286 27 : bool match = false;
3287 :
3288 27 : match = dom_sid_equal(d->di.domain_sid, sid);
3289 27 : if (match) {
3290 : /*
3291 : * exact match, it's the domain itself.
3292 : */
3293 13 : if (pdi != NULL) {
3294 6 : *pdi = &d->di;
3295 : }
3296 13 : return d->tdo;
3297 : }
3298 14 : continue;
3299 : }
3300 :
3301 335 : for (i = 0; i < d->fti->count; i++ ) {
3302 278 : const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3303 278 : const struct lsa_ForestTrustDomainInfo *di = NULL;
3304 278 : const struct dom_sid *fti_sid = NULL;
3305 278 : bool match = false;
3306 :
3307 278 : if (f == NULL) {
3308 : /* broken record */
3309 0 : continue;
3310 : }
3311 :
3312 278 : if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3313 205 : continue;
3314 : }
3315 :
3316 73 : if (f->flags & LSA_SID_DISABLED_MASK) {
3317 : /*
3318 : * any flag disables the entry.
3319 : */
3320 0 : continue;
3321 : }
3322 :
3323 73 : di = &f->forest_trust_data.domain_info;
3324 73 : fti_sid = di->domain_sid;
3325 73 : if (fti_sid == NULL) {
3326 : /* broken record */
3327 0 : continue;
3328 : }
3329 :
3330 73 : match = dom_sid_equal(fti_sid, sid);
3331 73 : if (match) {
3332 : /*
3333 : * exact match, it's a domain in the forest.
3334 : */
3335 16 : if (pdi != NULL) {
3336 12 : *pdi = di;
3337 : }
3338 16 : return d->tdo;
3339 : }
3340 : }
3341 : }
3342 :
3343 17 : return NULL;
3344 : }
3345 :
3346 137 : const struct lsa_TrustDomainInfoInfoEx *dsdb_trust_domain_by_name(
3347 : const struct dsdb_trust_routing_table *table,
3348 : const char *name,
3349 : const struct lsa_ForestTrustDomainInfo **pdi)
3350 : {
3351 137 : const struct dsdb_trust_routing_domain *d = NULL;
3352 :
3353 137 : if (pdi != NULL) {
3354 137 : *pdi = NULL;
3355 : }
3356 :
3357 137 : if (name == NULL) {
3358 0 : return NULL;
3359 : }
3360 :
3361 340 : for (d = table->domains; d != NULL; d = d->next) {
3362 313 : bool transitive = false;
3363 : uint32_t i;
3364 :
3365 313 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
3366 137 : transitive = true;
3367 : }
3368 :
3369 313 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
3370 84 : transitive = true;
3371 : }
3372 :
3373 313 : if (d->tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
3374 0 : transitive = false;
3375 : }
3376 :
3377 313 : if (d->tdo->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
3378 0 : transitive = false;
3379 : }
3380 :
3381 313 : if (!transitive || d->fti == NULL) {
3382 92 : bool match = false;
3383 :
3384 92 : match = strequal_m(d->di.netbios_domain_name.string,
3385 : name);
3386 92 : if (match) {
3387 : /*
3388 : * exact match for netbios name,
3389 : * it's the domain itself.
3390 : */
3391 28 : if (pdi != NULL) {
3392 28 : *pdi = &d->di;
3393 : }
3394 28 : return d->tdo;
3395 : }
3396 64 : match = strequal_m(d->di.dns_domain_name.string,
3397 : name);
3398 64 : if (match) {
3399 : /*
3400 : * exact match for dns name,
3401 : * it's the domain itself.
3402 : */
3403 28 : if (pdi != NULL) {
3404 28 : *pdi = &d->di;
3405 : }
3406 28 : return d->tdo;
3407 : }
3408 36 : continue;
3409 : }
3410 :
3411 987 : for (i = 0; i < d->fti->count; i++ ) {
3412 820 : const struct lsa_ForestTrustRecord *f = d->fti->entries[i];
3413 820 : const struct lsa_ForestTrustDomainInfo *di = NULL;
3414 820 : bool match = false;
3415 :
3416 820 : if (f == NULL) {
3417 : /* broken record */
3418 0 : continue;
3419 : }
3420 :
3421 820 : if (f->type != LSA_FOREST_TRUST_DOMAIN_INFO) {
3422 599 : continue;
3423 : }
3424 221 : di = &f->forest_trust_data.domain_info;
3425 :
3426 221 : if (!(f->flags & LSA_NB_DISABLED_MASK)) {
3427 221 : match = strequal_m(di->netbios_domain_name.string,
3428 : name);
3429 221 : if (match) {
3430 : /*
3431 : * exact match for netbios name,
3432 : * it's a domain in the forest.
3433 : */
3434 32 : if (pdi != NULL) {
3435 32 : *pdi = di;
3436 : }
3437 32 : return d->tdo;
3438 : }
3439 : }
3440 :
3441 189 : if (!(f->flags & LSA_TLN_DISABLED_MASK)) {
3442 189 : match = strequal_m(di->dns_domain_name.string,
3443 : name);
3444 189 : if (match) {
3445 : /*
3446 : * exact match for dns name,
3447 : * it's a domain in the forest.
3448 : */
3449 22 : if (pdi != NULL) {
3450 22 : *pdi = di;
3451 : }
3452 22 : return d->tdo;
3453 : }
3454 : }
3455 : }
3456 : }
3457 :
3458 27 : return NULL;
3459 : }
|