2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2015
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.
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.
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/>.
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"
40 NTSTATUS
dsdb_trust_forest_info_from_lsa(TALLOC_CTX
*mem_ctx
,
41 const struct lsa_ForestTrustInformation
*lfti
,
42 struct ForestTrustInfo
**_fti
)
44 struct ForestTrustInfo
*fti
;
49 fti
= talloc_zero(mem_ctx
, struct ForestTrustInfo
);
51 return NT_STATUS_NO_MEMORY
;
55 fti
->count
= lfti
->count
;
56 fti
->records
= talloc_zero_array(mem_ctx
,
57 struct ForestTrustInfoRecordArmor
,
59 if (fti
->records
== NULL
) {
61 return NT_STATUS_NO_MEMORY
;
64 for (i
= 0; i
< fti
->count
; i
++) {
65 const struct lsa_ForestTrustRecord
*lftr
= lfti
->entries
[i
];
66 struct ForestTrustInfoRecord
*ftr
= &fti
->records
[i
].record
;
67 struct ForestTrustString
*str
= NULL
;
68 const struct lsa_StringLarge
*lstr
= NULL
;
69 const struct lsa_ForestTrustDomainInfo
*linfo
= NULL
;
70 struct ForestTrustDataDomainInfo
*info
= NULL
;
74 return NT_STATUS_INVALID_PARAMETER
;
77 ftr
->flags
= lftr
->flags
;
78 ftr
->timestamp
= lftr
->time
;
79 ftr
->type
= (enum ForestTrustInfoRecordType
)lftr
->type
;
82 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
83 lstr
= &lftr
->forest_trust_data
.top_level_name
;
84 str
= &ftr
->data
.name
;
86 str
->string
= talloc_strdup(mem_ctx
, lstr
->string
);
87 if (str
->string
== NULL
) {
89 return NT_STATUS_NO_MEMORY
;
94 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
95 lstr
= &lftr
->forest_trust_data
.top_level_name_ex
;
96 str
= &ftr
->data
.name
;
98 str
->string
= talloc_strdup(mem_ctx
, lstr
->string
);
99 if (str
->string
== NULL
) {
101 return NT_STATUS_NO_MEMORY
;
106 case LSA_FOREST_TRUST_DOMAIN_INFO
:
107 linfo
= &lftr
->forest_trust_data
.domain_info
;
108 info
= &ftr
->data
.info
;
110 if (linfo
->domain_sid
== NULL
) {
112 return NT_STATUS_INVALID_PARAMETER
;
114 info
->sid
= *linfo
->domain_sid
;
116 lstr
= &linfo
->dns_domain_name
;
117 str
= &info
->dns_name
;
118 str
->string
= talloc_strdup(mem_ctx
, lstr
->string
);
119 if (str
->string
== NULL
) {
121 return NT_STATUS_NO_MEMORY
;
124 lstr
= &linfo
->netbios_domain_name
;
125 str
= &info
->netbios_name
;
126 str
->string
= talloc_strdup(mem_ctx
, lstr
->string
);
127 if (str
->string
== NULL
) {
129 return NT_STATUS_NO_MEMORY
;
135 return NT_STATUS_NOT_SUPPORTED
;
143 static NTSTATUS
dsdb_trust_forest_record_to_lsa(TALLOC_CTX
*mem_ctx
,
144 const struct ForestTrustInfoRecord
*ftr
,
145 struct lsa_ForestTrustRecord
**_lftr
)
147 struct lsa_ForestTrustRecord
*lftr
= NULL
;
148 const struct ForestTrustString
*str
= NULL
;
149 struct lsa_StringLarge
*lstr
= NULL
;
150 const struct ForestTrustDataDomainInfo
*info
= NULL
;
151 struct lsa_ForestTrustDomainInfo
*linfo
= NULL
;
155 lftr
= talloc_zero(mem_ctx
, struct lsa_ForestTrustRecord
);
157 return NT_STATUS_NO_MEMORY
;
160 lftr
->flags
= ftr
->flags
;
161 lftr
->time
= ftr
->timestamp
;
162 lftr
->type
= (enum lsa_ForestTrustRecordType
)ftr
->type
;
164 switch (lftr
->type
) {
165 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
166 lstr
= &lftr
->forest_trust_data
.top_level_name
;
167 str
= &ftr
->data
.name
;
169 lstr
->string
= talloc_strdup(mem_ctx
, str
->string
);
170 if (lstr
->string
== NULL
) {
172 return NT_STATUS_NO_MEMORY
;
177 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
178 lstr
= &lftr
->forest_trust_data
.top_level_name_ex
;
179 str
= &ftr
->data
.name
;
181 lstr
->string
= talloc_strdup(mem_ctx
, str
->string
);
182 if (lstr
->string
== NULL
) {
184 return NT_STATUS_NO_MEMORY
;
189 case LSA_FOREST_TRUST_DOMAIN_INFO
:
190 linfo
= &lftr
->forest_trust_data
.domain_info
;
191 info
= &ftr
->data
.info
;
193 linfo
->domain_sid
= dom_sid_dup(lftr
, &info
->sid
);
194 if (linfo
->domain_sid
== NULL
) {
196 return NT_STATUS_NO_MEMORY
;
199 lstr
= &linfo
->dns_domain_name
;
200 str
= &info
->dns_name
;
201 lstr
->string
= talloc_strdup(mem_ctx
, str
->string
);
202 if (lstr
->string
== NULL
) {
204 return NT_STATUS_NO_MEMORY
;
207 lstr
= &linfo
->netbios_domain_name
;
208 str
= &info
->netbios_name
;
209 lstr
->string
= talloc_strdup(mem_ctx
, str
->string
);
210 if (lstr
->string
== NULL
) {
212 return NT_STATUS_NO_MEMORY
;
218 return NT_STATUS_NOT_SUPPORTED
;
225 NTSTATUS
dsdb_trust_forest_info_to_lsa(TALLOC_CTX
*mem_ctx
,
226 const struct ForestTrustInfo
*fti
,
227 struct lsa_ForestTrustInformation
**_lfti
)
229 struct lsa_ForestTrustInformation
*lfti
;
234 if (fti
->version
!= 1) {
235 return NT_STATUS_INVALID_PARAMETER
;
238 lfti
= talloc_zero(mem_ctx
, struct lsa_ForestTrustInformation
);
240 return NT_STATUS_NO_MEMORY
;
243 lfti
->count
= fti
->count
;
244 lfti
->entries
= talloc_zero_array(mem_ctx
,
245 struct lsa_ForestTrustRecord
*,
247 if (lfti
->entries
== NULL
) {
249 return NT_STATUS_NO_MEMORY
;
252 for (i
= 0; i
< fti
->count
; i
++) {
253 struct ForestTrustInfoRecord
*ftr
= &fti
->records
[i
].record
;
254 struct lsa_ForestTrustRecord
*lftr
= NULL
;
257 status
= dsdb_trust_forest_record_to_lsa(lfti
->entries
, ftr
,
259 if (!NT_STATUS_IS_OK(status
)) {
261 return NT_STATUS_NO_MEMORY
;
263 lfti
->entries
[i
] = lftr
;
270 static NTSTATUS
dsdb_trust_forest_info_add_record(struct lsa_ForestTrustInformation
*fti
,
271 const struct lsa_ForestTrustRecord
*ftr
)
273 struct lsa_ForestTrustRecord
**es
= NULL
;
274 struct lsa_ForestTrustRecord
*e
= NULL
;
275 const struct lsa_StringLarge
*dns1
= NULL
;
276 struct lsa_StringLarge
*dns2
= NULL
;
277 const struct lsa_ForestTrustDomainInfo
*d1
= NULL
;
278 struct lsa_ForestTrustDomainInfo
*d2
= NULL
;
281 es
= talloc_realloc(fti
, fti
->entries
,
282 struct lsa_ForestTrustRecord
*,
285 return NT_STATUS_NO_MEMORY
;
289 e
= talloc_zero(es
, struct lsa_ForestTrustRecord
);
291 return NT_STATUS_NO_MEMORY
;
295 e
->flags
= ftr
->flags
;
299 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
300 dns1
= &ftr
->forest_trust_data
.top_level_name
;
301 dns2
= &e
->forest_trust_data
.top_level_name
;
304 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
305 dns1
= &ftr
->forest_trust_data
.top_level_name_ex
;
306 dns2
= &e
->forest_trust_data
.top_level_name_ex
;
309 case LSA_FOREST_TRUST_DOMAIN_INFO
:
310 dns1
= &ftr
->forest_trust_data
.domain_info
.dns_domain_name
;
311 dns2
= &e
->forest_trust_data
.domain_info
.dns_domain_name
;
312 d1
= &ftr
->forest_trust_data
.domain_info
;
313 d2
= &e
->forest_trust_data
.domain_info
;
316 return NT_STATUS_INVALID_PARAMETER
;
319 if (dns1
->string
== NULL
) {
321 return NT_STATUS_INVALID_PARAMETER
;
324 len
= strlen(dns1
->string
);
327 return NT_STATUS_INVALID_PARAMETER
;
330 dns2
->string
= talloc_strdup(e
, dns1
->string
);
331 if (dns2
->string
== NULL
) {
333 return NT_STATUS_NO_MEMORY
;
337 const struct lsa_StringLarge
*nb1
= &d1
->netbios_domain_name
;
338 struct lsa_StringLarge
*nb2
= &d2
->netbios_domain_name
;
340 if (nb1
->string
== NULL
) {
342 return NT_STATUS_INVALID_PARAMETER
;
345 len
= strlen(nb1
->string
);
348 return NT_STATUS_INVALID_PARAMETER
;
352 return NT_STATUS_INVALID_PARAMETER
;
355 nb2
->string
= talloc_strdup(e
, nb1
->string
);
356 if (nb2
->string
== NULL
) {
358 return NT_STATUS_NO_MEMORY
;
361 if (d1
->domain_sid
== NULL
) {
363 return NT_STATUS_INVALID_PARAMETER
;
366 d2
->domain_sid
= dom_sid_dup(e
, d1
->domain_sid
);
367 if (d2
->domain_sid
== NULL
) {
369 return NT_STATUS_NO_MEMORY
;
373 fti
->entries
[fti
->count
++] = e
;
377 static NTSTATUS
dsdb_trust_parse_crossref_info(TALLOC_CTX
*mem_ctx
,
378 struct ldb_context
*sam_ctx
,
379 const struct ldb_message
*msg
,
380 struct lsa_TrustDomainInfoInfoEx
**_tdo
)
382 TALLOC_CTX
*frame
= talloc_stackframe();
383 struct lsa_TrustDomainInfoInfoEx
*tdo
= NULL
;
384 const char *dns
= NULL
;
385 const char *netbios
= NULL
;
386 struct ldb_dn
*nc_dn
= NULL
;
387 struct dom_sid sid
= {
393 tdo
= talloc_zero(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
);
396 return NT_STATUS_NO_MEMORY
;
398 talloc_steal(frame
, tdo
);
400 dns
= ldb_msg_find_attr_as_string(msg
, "dnsRoot", NULL
);
403 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
405 tdo
->domain_name
.string
= talloc_strdup(tdo
, dns
);
406 if (tdo
->domain_name
.string
== NULL
) {
408 return NT_STATUS_NO_MEMORY
;
411 netbios
= ldb_msg_find_attr_as_string(msg
, "nETBIOSName", NULL
);
412 if (netbios
== NULL
) {
414 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
416 tdo
->netbios_name
.string
= talloc_strdup(tdo
, netbios
);
417 if (tdo
->netbios_name
.string
== NULL
) {
419 return NT_STATUS_NO_MEMORY
;
422 nc_dn
= samdb_result_dn(sam_ctx
, frame
, msg
, "ncName", NULL
);
425 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
428 status
= dsdb_get_extended_dn_sid(nc_dn
, &sid
, "SID");
429 if (!NT_STATUS_IS_OK(status
)) {
433 tdo
->sid
= dom_sid_dup(tdo
, &sid
);
434 if (tdo
->sid
== NULL
) {
436 return NT_STATUS_NO_MEMORY
;
439 tdo
->trust_type
= LSA_TRUST_TYPE_UPLEVEL
;
440 tdo
->trust_direction
= LSA_TRUST_DIRECTION_INBOUND
|
441 LSA_TRUST_DIRECTION_OUTBOUND
;
442 tdo
->trust_attributes
= LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
;
444 *_tdo
= talloc_move(mem_ctx
, &tdo
);
449 static NTSTATUS
dsdb_trust_crossref_tdo_info(TALLOC_CTX
*mem_ctx
,
450 struct ldb_context
*sam_ctx
,
451 struct ldb_dn
*domain_dn
,
452 const char *extra_filter
,
453 struct lsa_TrustDomainInfoInfoEx
**_tdo
,
454 struct lsa_TrustDomainInfoInfoEx
**_root_trust_tdo
,
455 struct lsa_TrustDomainInfoInfoEx
**_trust_parent_tdo
)
457 TALLOC_CTX
*frame
= talloc_stackframe();
458 struct lsa_TrustDomainInfoInfoEx
*tdo
= NULL
;
459 struct lsa_TrustDomainInfoInfoEx
*root_trust_tdo
= NULL
;
460 struct lsa_TrustDomainInfoInfoEx
*trust_parent_tdo
= NULL
;
461 struct ldb_dn
*partitions_dn
= NULL
;
462 const char * const cross_attrs
[] = {
470 struct ldb_result
*cross_res
= NULL
;
471 struct ldb_message
*msg
= NULL
;
472 struct ldb_dn
*root_trust_dn
= NULL
;
473 struct ldb_dn
*trust_parent_dn
= NULL
;
477 if (extra_filter
== NULL
) {
482 if (_root_trust_tdo
!= NULL
) {
483 *_root_trust_tdo
= NULL
;
485 if (_trust_parent_tdo
!= NULL
) {
486 *_trust_parent_tdo
= NULL
;
489 partitions_dn
= samdb_partitions_dn(sam_ctx
, frame
);
490 if (partitions_dn
== NULL
) {
492 return NT_STATUS_NO_MEMORY
;
495 ret
= dsdb_search(sam_ctx
, partitions_dn
, &cross_res
,
496 partitions_dn
, LDB_SCOPE_ONELEVEL
,
498 DSDB_SEARCH_ONE_ONLY
|
499 DSDB_SEARCH_SHOW_EXTENDED_DN
,
502 "(objectClass=crossRef)"
503 "(systemFlags:%s:=%u)"
506 ldb_dn_get_linearized(domain_dn
),
507 LDB_OID_COMPARATOR_AND
,
508 SYSTEM_FLAG_CR_NTDS_DOMAIN
,
510 if (ret
!= LDB_SUCCESS
) {
512 return dsdb_ldb_err_to_ntstatus(ret
);
514 msg
= cross_res
->msgs
[0];
516 status
= dsdb_trust_parse_crossref_info(mem_ctx
, sam_ctx
, msg
, &tdo
);
517 if (!NT_STATUS_IS_OK(status
)) {
521 talloc_steal(frame
, tdo
);
523 if (_root_trust_tdo
!= NULL
) {
524 root_trust_dn
= samdb_result_dn(sam_ctx
, frame
, msg
,
527 if (_trust_parent_tdo
!= NULL
) {
528 trust_parent_dn
= samdb_result_dn(sam_ctx
, frame
, msg
,
529 "trustParent", NULL
);
532 if (root_trust_dn
!= NULL
) {
533 struct ldb_message
*root_trust_msg
= NULL
;
535 ret
= dsdb_search_one(sam_ctx
, frame
,
540 DSDB_SEARCH_NO_GLOBAL_CATALOG
,
541 "(objectClass=crossRef)");
542 if (ret
!= LDB_SUCCESS
) {
543 status
= dsdb_ldb_err_to_ntstatus(ret
);
544 DEBUG(3, ("Failed to search for %s: %s - %s\n",
545 ldb_dn_get_linearized(root_trust_dn
),
546 nt_errstr(status
), ldb_errstring(sam_ctx
)));
551 status
= dsdb_trust_parse_crossref_info(mem_ctx
, sam_ctx
,
554 if (!NT_STATUS_IS_OK(status
)) {
558 talloc_steal(frame
, root_trust_tdo
);
561 if (trust_parent_dn
!= NULL
) {
562 struct ldb_message
*trust_parent_msg
= NULL
;
564 ret
= dsdb_search_one(sam_ctx
, frame
,
569 DSDB_SEARCH_NO_GLOBAL_CATALOG
,
570 "(objectClass=crossRef)");
571 if (ret
!= LDB_SUCCESS
) {
572 status
= dsdb_ldb_err_to_ntstatus(ret
);
573 DEBUG(3, ("Failed to search for %s: %s - %s\n",
574 ldb_dn_get_linearized(trust_parent_dn
),
575 nt_errstr(status
), ldb_errstring(sam_ctx
)));
580 status
= dsdb_trust_parse_crossref_info(mem_ctx
, sam_ctx
,
583 if (!NT_STATUS_IS_OK(status
)) {
587 talloc_steal(frame
, trust_parent_tdo
);
590 *_tdo
= talloc_move(mem_ctx
, &tdo
);
591 if (_root_trust_tdo
!= NULL
) {
592 *_root_trust_tdo
= talloc_move(mem_ctx
, &root_trust_tdo
);
594 if (_trust_parent_tdo
!= NULL
) {
595 *_trust_parent_tdo
= talloc_move(mem_ctx
, &trust_parent_tdo
);
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
607 #define DNS_CMP_IS_NO_MATCH(__cmp) \
608 ((__cmp == DNS_CMP_FIRST_IS_LESS) || (__cmp == DNS_CMP_SECOND_IS_LESS))
611 * this function assumes names are well formed DNS names.
612 * it doesn't validate them
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().
618 * Trailing dots (only one) are ignored.
620 * The DNS names are compared per component, starting from
623 static int dns_cmp(const char *s1
, const char *s2
)
626 const char *p1
= NULL
;
627 size_t num_comp1
= 0;
628 uint16_t comp1
[UINT8_MAX
] = {0};
630 const char *p2
= NULL
;
631 size_t num_comp2
= 0;
632 uint16_t comp2
[UINT8_MAX
] = {0};
644 * trailing '.' are ignored.
646 if (l1
> 1 && s1
[l1
- 1] == '.') {
649 if (l2
> 1 && s2
[l2
- 1] == '.') {
653 for (i
= 0; i
< ARRAY_SIZE(comp1
); i
++) {
659 if (l1
== 0 || l1
>= UINT16_MAX
) {
660 /* just use one single component on overflow */
665 comp1
[num_comp1
++] = PTR_DIFF(p1
, s1
);
667 p
= strchr_m(p1
, '.');
677 /* just use one single component on overflow */
679 comp1
[num_comp1
++] = 0;
683 for (i
= 0; i
< ARRAY_SIZE(comp2
); i
++) {
689 if (l2
== 0 || l2
>= UINT16_MAX
) {
690 /* just use one single component on overflow */
695 comp2
[num_comp2
++] = PTR_DIFF(p2
, s2
);
697 p
= strchr_m(p2
, '.');
707 /* just use one single component on overflow */
709 comp2
[num_comp2
++] = 0;
713 for (i
= 0; i
< UINT8_MAX
; i
++) {
717 size_t idx
= num_comp1
- (i
+ 1);
718 p1
= s1
+ comp1
[idx
];
724 size_t idx
= num_comp2
- (i
+ 1);
725 p2
= s2
+ comp2
[idx
];
730 if (p1
== NULL
&& p2
== NULL
) {
731 return DNS_CMP_MATCH
;
733 if (p1
!= NULL
&& p2
== NULL
) {
734 return DNS_CMP_FIRST_IS_CHILD
;
736 if (p1
== NULL
&& p2
!= NULL
) {
737 return DNS_CMP_SECOND_IS_CHILD
;
740 cmp
= strcasecmp_m(p1
, p2
);
742 return DNS_CMP_FIRST_IS_LESS
;
745 return DNS_CMP_SECOND_IS_LESS
;
749 smb_panic(__location__
);
753 static int dsdb_trust_find_tln_match_internal(const struct lsa_ForestTrustInformation
*info
,
754 enum lsa_ForestTrustRecordType type
,
755 uint32_t disable_mask
,
760 for (i
= 0; i
< info
->count
; i
++) {
761 struct lsa_ForestTrustRecord
*e
= info
->entries
[i
];
762 struct lsa_StringLarge
*t
= NULL
;
769 if (e
->type
!= type
) {
773 if (e
->flags
& disable_mask
) {
778 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
779 t
= &e
->forest_trust_data
.top_level_name
;
781 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
782 t
= &e
->forest_trust_data
.top_level_name_ex
;
792 cmp
= dns_cmp(tln
, t
->string
);
795 case DNS_CMP_FIRST_IS_CHILD
:
803 static bool dsdb_trust_find_tln_match(const struct lsa_ForestTrustInformation
*info
,
808 m
= dsdb_trust_find_tln_match_internal(info
,
809 LSA_FOREST_TRUST_TOP_LEVEL_NAME
,
810 LSA_TLN_DISABLED_MASK
,
819 static bool dsdb_trust_find_tln_ex_match(const struct lsa_ForestTrustInformation
*info
,
824 m
= dsdb_trust_find_tln_match_internal(info
,
825 LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
,
835 NTSTATUS
dsdb_trust_local_tdo_info(TALLOC_CTX
*mem_ctx
,
836 struct ldb_context
*sam_ctx
,
837 struct lsa_TrustDomainInfoInfoEx
**_tdo
)
839 struct ldb_dn
*domain_dn
= NULL
;
841 domain_dn
= ldb_get_default_basedn(sam_ctx
);
842 if (domain_dn
== NULL
) {
843 return NT_STATUS_INTERNAL_ERROR
;
846 return dsdb_trust_crossref_tdo_info(mem_ctx
, sam_ctx
,
851 NTSTATUS
dsdb_trust_xref_tdo_info(TALLOC_CTX
*mem_ctx
,
852 struct ldb_context
*sam_ctx
,
853 struct lsa_TrustDomainInfoInfoEx
**_tdo
)
856 * The extra filter makes sure we only find the forest root domain
858 const char *extra_filter
= "(!(|(rootTrust=*)(trustParent=*)))";
859 struct ldb_dn
*domain_dn
= NULL
;
861 domain_dn
= ldb_get_default_basedn(sam_ctx
);
862 if (domain_dn
== NULL
) {
863 return NT_STATUS_INTERNAL_ERROR
;
866 return dsdb_trust_crossref_tdo_info(mem_ctx
, sam_ctx
,
867 domain_dn
, extra_filter
,
871 static int dsdb_trust_xref_sort_msgs(struct ldb_message
**_m1
,
872 struct ldb_message
**_m2
)
874 struct ldb_message
*m1
= *_m1
;
875 struct ldb_message
*m2
= *_m2
;
876 const char *dns1
= NULL
;
877 const char *dns2
= NULL
;
879 struct ldb_message_element
*rootTrust1
= NULL
;
880 struct ldb_message_element
*trustParent1
= NULL
;
881 struct ldb_message_element
*rootTrust2
= NULL
;
882 struct ldb_message_element
*trustParent2
= NULL
;
884 dns1
= ldb_msg_find_attr_as_string(m1
, "dnsRoot", NULL
);
885 dns2
= ldb_msg_find_attr_as_string(m2
, "dnsRoot", NULL
);
887 cmp
= dns_cmp(dns1
, dns2
);
889 case DNS_CMP_FIRST_IS_CHILD
:
891 case DNS_CMP_SECOND_IS_CHILD
:
895 rootTrust1
= ldb_msg_find_element(m1
, "rootTrust");
896 trustParent1
= ldb_msg_find_element(m1
, "trustParent");
897 rootTrust2
= ldb_msg_find_element(m2
, "rootTrust");
898 trustParent2
= ldb_msg_find_element(m2
, "trustParent");
900 if (rootTrust1
== NULL
&& trustParent1
== NULL
) {
901 /* m1 is the forest root */
904 if (rootTrust2
== NULL
&& trustParent2
== NULL
) {
905 /* m2 is the forest root */
912 static int dsdb_trust_xref_sort_vals(struct ldb_val
*v1
,
915 const char *dns1
= (const char *)v1
->data
;
916 const char *dns2
= (const char *)v2
->data
;
918 return dns_cmp(dns1
, dns2
);
921 NTSTATUS
dsdb_trust_xref_forest_info(TALLOC_CTX
*mem_ctx
,
922 struct ldb_context
*sam_ctx
,
923 struct lsa_ForestTrustInformation
**_info
)
925 TALLOC_CTX
*frame
= talloc_stackframe();
926 struct lsa_ForestTrustInformation
*info
= NULL
;
927 struct ldb_dn
*partitions_dn
= NULL
;
928 const char * const cross_attrs1
[] = {
933 struct ldb_result
*cross_res1
= NULL
;
934 struct ldb_message_element
*upn_el
= NULL
;
935 struct ldb_message_element
*spn_el
= NULL
;
936 struct ldb_message
*tln_msg
= NULL
;
937 struct ldb_message_element
*tln_el
= NULL
;
938 const char * const cross_attrs2
[] = {
946 struct ldb_result
*cross_res2
= NULL
;
949 bool restart
= false;
952 info
= talloc_zero(mem_ctx
, struct lsa_ForestTrustInformation
);
955 return NT_STATUS_NO_MEMORY
;
957 talloc_steal(frame
, info
);
959 partitions_dn
= samdb_partitions_dn(sam_ctx
, frame
);
960 if (partitions_dn
== NULL
) {
962 return NT_STATUS_NO_MEMORY
;
965 ret
= dsdb_search_dn(sam_ctx
, partitions_dn
, &cross_res1
,
966 partitions_dn
, cross_attrs1
, 0);
967 if (ret
!= LDB_SUCCESS
) {
969 return dsdb_ldb_err_to_ntstatus(ret
);
972 ret
= dsdb_search(sam_ctx
, partitions_dn
, &cross_res2
,
973 partitions_dn
, LDB_SCOPE_ONELEVEL
,
975 DSDB_SEARCH_SHOW_EXTENDED_DN
,
976 "(&(objectClass=crossRef)"
977 "(systemFlags:%s:=%u))",
978 LDB_OID_COMPARATOR_AND
,
979 SYSTEM_FLAG_CR_NTDS_DOMAIN
);
980 if (ret
!= LDB_SUCCESS
) {
982 return dsdb_ldb_err_to_ntstatus(ret
);
986 * Sort the domains as trees, starting with the forest root
988 TYPESAFE_QSORT(cross_res2
->msgs
, cross_res2
->count
,
989 dsdb_trust_xref_sort_msgs
);
991 upn_el
= ldb_msg_find_element(cross_res1
->msgs
[0], "uPNSuffixes");
992 if (upn_el
!= NULL
) {
993 upn_el
->name
= "__tln__";
995 spn_el
= ldb_msg_find_element(cross_res1
->msgs
[0], "msDS-SPNSuffixes");
996 if (spn_el
!= NULL
) {
997 spn_el
->name
= "__tln__";
999 ret
= ldb_msg_normalize(sam_ctx
, frame
, cross_res1
->msgs
[0], &tln_msg
);
1000 if (ret
!= LDB_SUCCESS
) {
1002 return dsdb_ldb_err_to_ntstatus(ret
);
1004 tln_el
= ldb_msg_find_element(tln_msg
, "__tln__");
1005 if (tln_el
!= NULL
) {
1007 * Sort the domains as trees
1009 TYPESAFE_QSORT(tln_el
->values
, tln_el
->num_values
,
1010 dsdb_trust_xref_sort_vals
);
1013 for (i
=0; i
< cross_res2
->count
; i
++) {
1014 struct ldb_message
*m
= cross_res2
->msgs
[i
];
1015 const char *dns
= NULL
;
1016 const char *netbios
= NULL
;
1017 struct ldb_dn
*nc_dn
= NULL
;
1018 struct dom_sid sid
= {
1021 struct lsa_ForestTrustRecord e
= {
1024 struct lsa_ForestTrustDomainInfo
*d
= NULL
;
1025 struct lsa_StringLarge
*t
= NULL
;
1029 dns
= ldb_msg_find_attr_as_string(m
, "dnsRoot", NULL
);
1032 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1035 netbios
= ldb_msg_find_attr_as_string(m
, "nETBIOSName", NULL
);
1036 if (netbios
== NULL
) {
1038 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1041 nc_dn
= samdb_result_dn(sam_ctx
, m
, m
, "ncName", NULL
);
1042 if (nc_dn
== NULL
) {
1044 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1047 status
= dsdb_get_extended_dn_sid(nc_dn
, &sid
, "SID");
1048 if (!NT_STATUS_IS_OK(status
)) {
1053 match
= dsdb_trust_find_tln_match(info
, dns
);
1056 * First the TOP_LEVEL_NAME, if required
1058 e
= (struct lsa_ForestTrustRecord
) {
1060 .type
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
,
1061 .time
= 0, /* so far always 0 in traces. */
1064 t
= &e
.forest_trust_data
.top_level_name
;
1067 status
= dsdb_trust_forest_info_add_record(info
, &e
);
1068 if (!NT_STATUS_IS_OK(status
)) {
1075 * Then the DOMAIN_INFO
1077 e
= (struct lsa_ForestTrustRecord
) {
1079 .type
= LSA_FOREST_TRUST_DOMAIN_INFO
,
1080 .time
= 0, /* so far always 0 in traces. */
1082 d
= &e
.forest_trust_data
.domain_info
;
1083 d
->domain_sid
= &sid
;
1084 d
->dns_domain_name
.string
= dns
;
1085 d
->netbios_domain_name
.string
= netbios
;
1087 status
= dsdb_trust_forest_info_add_record(info
, &e
);
1088 if (!NT_STATUS_IS_OK(status
)) {
1094 for (i
=0; (tln_el
!= NULL
) && i
< tln_el
->num_values
; i
++) {
1095 const struct ldb_val
*v
= &tln_el
->values
[i
];
1096 const char *dns
= (const char *)v
->data
;
1097 struct lsa_ForestTrustRecord e
= {
1100 struct lsa_StringLarge
*t
= NULL
;
1106 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1109 match
= dsdb_trust_find_tln_match(info
, dns
);
1115 * an additional the TOP_LEVEL_NAME
1117 e
= (struct lsa_ForestTrustRecord
) {
1119 .type
= LSA_FOREST_TRUST_TOP_LEVEL_NAME
,
1120 .time
= 0, /* so far always 0 in traces. */
1122 t
= &e
.forest_trust_data
.top_level_name
;
1125 status
= dsdb_trust_forest_info_add_record(info
, &e
);
1126 if (!NT_STATUS_IS_OK(status
)) {
1132 for (i
=0; i
< info
->count
; restart
? i
=0 : i
++) {
1133 struct lsa_ForestTrustRecord
*tr
= info
->entries
[i
];
1134 const struct lsa_StringLarge
*ts
= NULL
;
1139 if (tr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
1143 ts
= &tr
->forest_trust_data
.top_level_name
;
1145 for (c
= i
+ 1; c
< info
->count
; c
++) {
1146 struct lsa_ForestTrustRecord
*cr
= info
->entries
[c
];
1147 const struct lsa_StringLarge
*cs
= NULL
;
1151 if (cr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
1155 cs
= &cr
->forest_trust_data
.top_level_name
;
1157 cmp
= dns_cmp(ts
->string
, cs
->string
);
1158 if (DNS_CMP_IS_NO_MATCH(cmp
)) {
1161 if (cmp
!= DNS_CMP_FIRST_IS_CHILD
) {
1162 /* can't happen ... */
1168 TALLOC_FREE(info
->entries
[i
]);
1169 info
->entries
[i
] = info
->entries
[c
];
1171 for (j
= c
+ 1; j
< info
->count
; j
++) {
1172 info
->entries
[j
-1] = info
->entries
[j
];
1180 *_info
= talloc_move(mem_ctx
, &info
);
1182 return NT_STATUS_OK
;
1185 NTSTATUS
dsdb_trust_parse_tdo_info(TALLOC_CTX
*mem_ctx
,
1186 struct ldb_message
*m
,
1187 struct lsa_TrustDomainInfoInfoEx
**_tdo
)
1189 struct lsa_TrustDomainInfoInfoEx
*tdo
= NULL
;
1190 const char *dns
= NULL
;
1191 const char *netbios
= NULL
;
1195 tdo
= talloc_zero(mem_ctx
, struct lsa_TrustDomainInfoInfoEx
);
1197 return NT_STATUS_NO_MEMORY
;
1200 dns
= ldb_msg_find_attr_as_string(m
, "trustPartner", NULL
);
1203 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1205 tdo
->domain_name
.string
= talloc_strdup(tdo
, dns
);
1206 if (tdo
->domain_name
.string
== NULL
) {
1208 return NT_STATUS_NO_MEMORY
;
1211 netbios
= ldb_msg_find_attr_as_string(m
, "flatName", NULL
);
1212 if (netbios
== NULL
) {
1214 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1216 tdo
->netbios_name
.string
= talloc_strdup(tdo
, netbios
);
1217 if (tdo
->netbios_name
.string
== NULL
) {
1219 return NT_STATUS_NO_MEMORY
;
1222 tdo
->sid
= samdb_result_dom_sid(tdo
, m
, "securityIdentifier");
1223 if (tdo
->sid
== NULL
) {
1225 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1228 tdo
->trust_type
= ldb_msg_find_attr_as_uint(m
, "trustType", 0);
1229 tdo
->trust_direction
= ldb_msg_find_attr_as_uint(m
, "trustDirection", 0);
1230 tdo
->trust_attributes
= ldb_msg_find_attr_as_uint(m
, "trustAttributes", 0);
1233 return NT_STATUS_OK
;
1236 NTSTATUS
dsdb_trust_parse_forest_info(TALLOC_CTX
*mem_ctx
,
1237 struct ldb_message
*m
,
1238 struct ForestTrustInfo
**_fti
)
1240 const struct ldb_val
*ft_blob
= NULL
;
1241 struct ForestTrustInfo
*fti
= NULL
;
1242 enum ndr_err_code ndr_err
;
1246 ft_blob
= ldb_msg_find_ldb_val(m
, "msDS-TrustForestTrustInfo");
1247 if (ft_blob
== NULL
) {
1248 return NT_STATUS_NOT_FOUND
;
1251 fti
= talloc_zero(mem_ctx
, struct ForestTrustInfo
);
1253 return NT_STATUS_NO_MEMORY
;
1256 /* ldb_val is equivalent to DATA_BLOB */
1257 ndr_err
= ndr_pull_struct_blob_all(ft_blob
, fti
, fti
,
1258 (ndr_pull_flags_fn_t
)ndr_pull_ForestTrustInfo
);
1259 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
1261 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
1265 return NT_STATUS_OK
;
1268 NTSTATUS
dsdb_trust_normalize_forest_info_step1(TALLOC_CTX
*mem_ctx
,
1269 const struct lsa_ForestTrustInformation
*gfti
,
1270 struct lsa_ForestTrustInformation
**_nfti
)
1272 TALLOC_CTX
*frame
= talloc_stackframe();
1273 struct lsa_ForestTrustInformation
*nfti
;
1278 nfti
= talloc_zero(mem_ctx
, struct lsa_ForestTrustInformation
);
1281 return NT_STATUS_NO_MEMORY
;
1283 talloc_steal(frame
, nfti
);
1286 * First we copy every record and remove possible trailing dots
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.
1293 for (n
= 0; n
< gfti
->count
; n
++) {
1294 const struct lsa_ForestTrustRecord
*gftr
= gfti
->entries
[n
];
1295 struct lsa_ForestTrustRecord
*nftr
= NULL
;
1296 struct lsa_ForestTrustDomainInfo
*ninfo
= NULL
;
1297 struct lsa_StringLarge
*ntln
= NULL
;
1298 struct lsa_StringLarge
*nnb
= NULL
;
1299 struct dom_sid
*nsid
= NULL
;
1307 return NT_STATUS_INVALID_PARAMETER
;
1310 status
= dsdb_trust_forest_info_add_record(nfti
, gftr
);
1311 if (!NT_STATUS_IS_OK(status
)) {
1316 nftr
= nfti
->entries
[n
];
1318 switch (nftr
->type
) {
1319 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
1320 ntln
= &nftr
->forest_trust_data
.top_level_name
;
1323 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
1324 ntln
= &nftr
->forest_trust_data
.top_level_name_ex
;
1327 case LSA_FOREST_TRUST_DOMAIN_INFO
:
1328 ninfo
= &nftr
->forest_trust_data
.domain_info
;
1329 ntln
= &ninfo
->dns_domain_name
;
1330 nnb
= &ninfo
->netbios_domain_name
;
1331 nsid
= ninfo
->domain_sid
;
1336 return NT_STATUS_INVALID_PARAMETER
;
1340 * We remove one trailing '.' before checking
1343 * domain.com. becomes domain.com
1344 * domain.com.. becomes domain.com.
1346 * Then the following is invalid:
1352 len
= strlen(ntln
->string
);
1353 if (len
> 1 && ntln
->string
[len
- 1] == '.') {
1354 const char *cp
= &ntln
->string
[len
- 1];
1355 p
= discard_const_p(char, cp
);
1358 if (ntln
->string
[0] == '.') {
1360 return NT_STATUS_INVALID_PARAMETER
;
1362 p
= strstr_m(ntln
->string
, "..");
1365 return NT_STATUS_INVALID_PARAMETER
;
1368 for (c
= 0; c
< n
; c
++) {
1369 const struct lsa_ForestTrustRecord
*cftr
= nfti
->entries
[c
];
1370 const struct lsa_ForestTrustDomainInfo
*cinfo
= NULL
;
1371 const struct lsa_StringLarge
*ctln
= NULL
;
1372 const struct lsa_StringLarge
*cnb
= NULL
;
1373 const struct dom_sid
*csid
= NULL
;
1380 if (cftr
->type
!= nftr
->type
) {
1384 switch (cftr
->type
) {
1385 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
1386 ctln
= &cftr
->forest_trust_data
.top_level_name
;
1389 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
1390 ctln
= &cftr
->forest_trust_data
.top_level_name_ex
;
1393 case LSA_FOREST_TRUST_DOMAIN_INFO
:
1394 cinfo
= &cftr
->forest_trust_data
.domain_info
;
1395 ctln
= &cinfo
->dns_domain_name
;
1396 cnb
= &cinfo
->netbios_domain_name
;
1397 csid
= cinfo
->domain_sid
;
1402 return NT_STATUS_INVALID_PARAMETER
;
1405 cmp
= dns_cmp(ntln
->string
, ctln
->string
);
1406 if (cmp
== DNS_CMP_MATCH
) {
1408 TALLOC_FREE(nfti
->entries
[n
]);
1412 if (cinfo
== NULL
) {
1416 cmp
= strcasecmp_m(nnb
->string
, cnb
->string
);
1419 TALLOC_FREE(nfti
->entries
[n
]);
1423 cmp
= dom_sid_compare(nsid
, csid
);
1426 TALLOC_FREE(nfti
->entries
[n
]);
1433 * Now we check that only true top level names are provided
1435 for (n
= 0; n
< nfti
->count
; n
++) {
1436 const struct lsa_ForestTrustRecord
*nftr
= nfti
->entries
[n
];
1437 const struct lsa_StringLarge
*ntln
= NULL
;
1444 if (nftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
1448 ntln
= &nftr
->forest_trust_data
.top_level_name
;
1450 for (c
= 0; c
< nfti
->count
; c
++) {
1451 const struct lsa_ForestTrustRecord
*cftr
= nfti
->entries
[c
];
1452 const struct lsa_StringLarge
*ctln
= NULL
;
1463 if (cftr
->type
!= nftr
->type
) {
1467 ctln
= &cftr
->forest_trust_data
.top_level_name
;
1469 cmp
= dns_cmp(ntln
->string
, ctln
->string
);
1470 if (DNS_CMP_IS_NO_MATCH(cmp
)) {
1475 return NT_STATUS_INVALID_PARAMETER
;
1480 * Now we check that only true sub level excludes are provided
1482 for (n
= 0; n
< nfti
->count
; n
++) {
1483 const struct lsa_ForestTrustRecord
*nftr
= nfti
->entries
[n
];
1484 const struct lsa_StringLarge
*ntln
= NULL
;
1486 bool found_tln
= false;
1492 if (nftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
) {
1496 ntln
= &nftr
->forest_trust_data
.top_level_name
;
1498 for (c
= 0; c
< nfti
->count
; c
++) {
1499 const struct lsa_ForestTrustRecord
*cftr
= nfti
->entries
[c
];
1500 const struct lsa_StringLarge
*ctln
= NULL
;
1511 if (cftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
1515 ctln
= &cftr
->forest_trust_data
.top_level_name
;
1517 cmp
= dns_cmp(ntln
->string
, ctln
->string
);
1518 if (cmp
== DNS_CMP_FIRST_IS_CHILD
) {
1529 return NT_STATUS_INVALID_PARAMETER
;
1533 * Now we check that there's a top level name for each domain
1535 for (n
= 0; n
< nfti
->count
; n
++) {
1536 const struct lsa_ForestTrustRecord
*nftr
= nfti
->entries
[n
];
1537 const struct lsa_ForestTrustDomainInfo
*ninfo
= NULL
;
1538 const struct lsa_StringLarge
*ntln
= NULL
;
1540 bool found_tln
= false;
1546 if (nftr
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
1550 ninfo
= &nftr
->forest_trust_data
.domain_info
;
1551 ntln
= &ninfo
->dns_domain_name
;
1553 for (c
= 0; c
< nfti
->count
; c
++) {
1554 const struct lsa_ForestTrustRecord
*cftr
= nfti
->entries
[c
];
1555 const struct lsa_StringLarge
*ctln
= NULL
;
1566 if (cftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
1570 ctln
= &cftr
->forest_trust_data
.top_level_name
;
1572 cmp
= dns_cmp(ntln
->string
, ctln
->string
);
1573 if (cmp
== DNS_CMP_MATCH
) {
1577 if (cmp
== DNS_CMP_FIRST_IS_CHILD
) {
1588 return NT_STATUS_INVALID_PARAMETER
;
1591 *_nfti
= talloc_move(mem_ctx
, &nfti
);
1593 return NT_STATUS_OK
;
1596 NTSTATUS
dsdb_trust_normalize_forest_info_step2(TALLOC_CTX
*mem_ctx
,
1597 const struct lsa_ForestTrustInformation
*gfti
,
1598 struct lsa_ForestTrustInformation
**_nfti
)
1600 TALLOC_CTX
*frame
= talloc_stackframe();
1601 struct timeval tv
= timeval_current();
1602 NTTIME now
= timeval_to_nttime(&tv
);
1603 struct lsa_ForestTrustInformation
*nfti
;
1608 nfti
= talloc_zero(mem_ctx
, struct lsa_ForestTrustInformation
);
1611 return NT_STATUS_NO_MEMORY
;
1613 talloc_steal(frame
, nfti
);
1616 * Now we add TOP_LEVEL_NAME[_EX] in reverse order
1617 * followed by LSA_FOREST_TRUST_DOMAIN_INFO in reverse order.
1619 * This also removes the possible NULL entries generated in step1.
1622 for (g
= 0; g
< gfti
->count
; g
++) {
1623 const struct lsa_ForestTrustRecord
*gftr
= gfti
->entries
[gfti
->count
- (g
+1)];
1624 struct lsa_ForestTrustRecord tftr
;
1632 switch (gftr
->type
) {
1633 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
1634 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
1637 case LSA_FOREST_TRUST_DOMAIN_INFO
:
1643 return NT_STATUS_INVALID_PARAMETER
;
1650 /* make a copy in order to update the time. */
1652 if (tftr
.time
== 0) {
1656 status
= dsdb_trust_forest_info_add_record(nfti
, &tftr
);
1657 if (!NT_STATUS_IS_OK(status
)) {
1663 for (g
= 0; g
< gfti
->count
; g
++) {
1664 const struct lsa_ForestTrustRecord
*gftr
= gfti
->entries
[gfti
->count
- (g
+1)];
1665 struct lsa_ForestTrustRecord tftr
;
1673 switch (gftr
->type
) {
1674 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
1675 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
:
1679 case LSA_FOREST_TRUST_DOMAIN_INFO
:
1684 return NT_STATUS_INVALID_PARAMETER
;
1691 /* make a copy in order to update the time. */
1693 if (tftr
.time
== 0) {
1697 status
= dsdb_trust_forest_info_add_record(nfti
, &tftr
);
1698 if (!NT_STATUS_IS_OK(status
)) {
1704 *_nfti
= talloc_move(mem_ctx
, &nfti
);
1706 return NT_STATUS_OK
;
1709 static NTSTATUS
dsdb_trust_add_collision(
1710 struct lsa_ForestTrustCollisionInfo
*c_info
,
1711 enum lsa_ForestTrustCollisionRecordType type
,
1712 uint32_t idx
, uint32_t flags
,
1713 const char *tdo_name
)
1715 struct lsa_ForestTrustCollisionRecord
**es
;
1716 uint32_t i
= c_info
->count
;
1718 es
= talloc_realloc(c_info
, c_info
->entries
,
1719 struct lsa_ForestTrustCollisionRecord
*, i
+ 1);
1721 return NT_STATUS_NO_MEMORY
;
1723 c_info
->entries
= es
;
1724 c_info
->count
= i
+ 1;
1726 es
[i
] = talloc_zero(es
, struct lsa_ForestTrustCollisionRecord
);
1727 if (es
[i
] == NULL
) {
1728 return NT_STATUS_NO_MEMORY
;
1733 es
[i
]->flags
= flags
;
1734 es
[i
]->name
.string
= talloc_strdup(es
[i
], tdo_name
);
1735 if (es
[i
]->name
.string
== NULL
) {
1736 return NT_STATUS_NO_MEMORY
;
1739 return NT_STATUS_OK
;
1742 NTSTATUS
dsdb_trust_verify_forest_info(const struct lsa_TrustDomainInfoInfoEx
*ref_tdo
,
1743 const struct lsa_ForestTrustInformation
*ref_fti
,
1744 enum lsa_ForestTrustCollisionRecordType collision_type
,
1745 struct lsa_ForestTrustCollisionInfo
*c_info
,
1746 struct lsa_ForestTrustInformation
*new_fti
)
1750 for (n
= 0; n
< new_fti
->count
; n
++) {
1751 struct lsa_ForestTrustRecord
*nftr
= new_fti
->entries
[n
];
1752 struct lsa_StringLarge
*ntln
= NULL
;
1753 bool ntln_excluded
= false;
1762 if (nftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
1766 ntln
= &nftr
->forest_trust_data
.top_level_name
;
1767 if (ntln
->string
== NULL
) {
1768 return NT_STATUS_INVALID_PARAMETER
;
1771 ntln_excluded
= dsdb_trust_find_tln_ex_match(ref_fti
,
1774 /* check if this is already taken and not excluded */
1775 for (r
= 0; r
< ref_fti
->count
; r
++) {
1776 const struct lsa_ForestTrustRecord
*rftr
=
1777 ref_fti
->entries
[r
];
1778 const struct lsa_StringLarge
*rtln
= NULL
;
1785 if (rftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
1789 rtln
= &rftr
->forest_trust_data
.top_level_name
;
1790 if (rtln
->string
== NULL
) {
1794 cmp
= dns_cmp(ntln
->string
, rtln
->string
);
1795 if (DNS_CMP_IS_NO_MATCH(cmp
)) {
1798 if (cmp
== DNS_CMP_MATCH
) {
1799 /* We need to normalize the string */
1800 ntln
->string
= talloc_strdup(nftr
,
1802 if (ntln
->string
== NULL
) {
1803 return NT_STATUS_NO_MEMORY
;
1807 if (ntln_excluded
) {
1811 if (rftr
->flags
& LSA_TLN_DISABLED_MASK
) {
1815 if (nftr
->flags
& LSA_TLN_DISABLED_MASK
) {
1819 if (cmp
== DNS_CMP_SECOND_IS_CHILD
) {
1823 * If the conflicting tln is a child, check if
1824 * we have an exclusion record for it.
1826 m
= dsdb_trust_find_tln_ex_match(new_fti
,
1833 flags
|= LSA_TLN_DISABLED_CONFLICT
;
1840 nftr
->flags
|= flags
;
1842 status
= dsdb_trust_add_collision(c_info
,
1845 ref_tdo
->domain_name
.string
);
1846 if (!NT_STATUS_IS_OK(status
)) {
1851 for (n
= 0; n
< new_fti
->count
; n
++) {
1852 struct lsa_ForestTrustRecord
*nftr
= new_fti
->entries
[n
];
1853 struct lsa_ForestTrustDomainInfo
*ninfo
= NULL
;
1854 struct lsa_StringLarge
*ntln
= NULL
;
1855 struct lsa_StringLarge
*nnb
= NULL
;
1856 struct dom_sid
*nsid
= NULL
;
1857 bool ntln_found
= false;
1866 if (nftr
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
1870 ninfo
= &nftr
->forest_trust_data
.domain_info
;
1871 ntln
= &ninfo
->dns_domain_name
;
1872 if (ntln
->string
== NULL
) {
1873 return NT_STATUS_INVALID_PARAMETER
;
1875 nnb
= &ninfo
->netbios_domain_name
;
1876 if (nnb
->string
== NULL
) {
1877 return NT_STATUS_INVALID_PARAMETER
;
1879 nsid
= ninfo
->domain_sid
;
1881 return NT_STATUS_INVALID_PARAMETER
;
1884 ntln_found
= dsdb_trust_find_tln_match(ref_fti
, ntln
->string
);
1886 /* check if this is already taken and not excluded */
1887 for (r
= 0; r
< ref_fti
->count
; r
++) {
1888 const struct lsa_ForestTrustRecord
*rftr
=
1889 ref_fti
->entries
[r
];
1890 const struct lsa_ForestTrustDomainInfo
*rinfo
= NULL
;
1891 const struct lsa_StringLarge
*rtln
= NULL
;
1892 const struct lsa_StringLarge
*rnb
= NULL
;
1893 const struct dom_sid
*rsid
= NULL
;
1894 bool nb_possible
= true;
1895 bool sid_possible
= true;
1904 * If the dns name doesn't match any existing
1905 * tln any conflict is ignored, but name
1906 * normalization still happens.
1908 * I guess that's a bug in Windows
1909 * (tested with Windows 2012r2).
1911 nb_possible
= false;
1912 sid_possible
= false;
1915 if (nftr
->flags
& LSA_SID_DISABLED_MASK
) {
1916 sid_possible
= false;
1919 if (nftr
->flags
& LSA_NB_DISABLED_MASK
) {
1920 nb_possible
= false;
1923 switch (rftr
->type
) {
1924 case LSA_FOREST_TRUST_TOP_LEVEL_NAME
:
1925 rtln
= &rftr
->forest_trust_data
.top_level_name
;
1926 nb_possible
= false;
1927 sid_possible
= false;
1930 case LSA_FOREST_TRUST_DOMAIN_INFO
:
1931 rinfo
= &rftr
->forest_trust_data
.domain_info
;
1932 rtln
= &rinfo
->dns_domain_name
;
1933 rnb
= &rinfo
->netbios_domain_name
;
1934 rsid
= rinfo
->domain_sid
;
1936 if (rftr
->flags
& LSA_SID_DISABLED_MASK
) {
1937 sid_possible
= false;
1940 if (rftr
->flags
& LSA_NB_DISABLED_MASK
) {
1941 nb_possible
= false;
1953 if (rtln
->string
== NULL
) {
1957 cmp
= dns_cmp(ntln
->string
, rtln
->string
);
1958 if (DNS_CMP_IS_NO_MATCH(cmp
)) {
1959 nb_possible
= false;
1960 sid_possible
= false;
1962 if (cmp
== DNS_CMP_MATCH
) {
1963 /* We need to normalize the string */
1964 ntln
->string
= talloc_strdup(nftr
,
1966 if (ntln
->string
== NULL
) {
1967 return NT_STATUS_NO_MEMORY
;
1971 if (rinfo
== NULL
) {
1976 cmp
= dom_sid_compare(nsid
, rsid
);
1982 flags
|= LSA_SID_DISABLED_CONFLICT
;
1986 if (rnb
->string
!= NULL
) {
1987 cmp
= strcasecmp_m(nnb
->string
, rnb
->string
);
1992 nnb
->string
= talloc_strdup(nftr
, rnb
->string
);
1993 if (nnb
->string
== NULL
) {
1994 return NT_STATUS_NO_MEMORY
;
1997 flags
|= LSA_NB_DISABLED_CONFLICT
;
2006 nftr
->flags
|= flags
;
2008 status
= dsdb_trust_add_collision(c_info
,
2011 ref_tdo
->domain_name
.string
);
2012 if (!NT_STATUS_IS_OK(status
)) {
2017 return NT_STATUS_OK
;
2020 NTSTATUS
dsdb_trust_merge_forest_info(TALLOC_CTX
*mem_ctx
,
2021 const struct lsa_TrustDomainInfoInfoEx
*tdo
,
2022 const struct lsa_ForestTrustInformation
*ofti
,
2023 const struct lsa_ForestTrustInformation
*nfti
,
2024 struct lsa_ForestTrustInformation
**_mfti
)
2026 TALLOC_CTX
*frame
= talloc_stackframe();
2027 struct lsa_ForestTrustInformation
*mfti
= NULL
;
2034 mfti
= talloc_zero(mem_ctx
, struct lsa_ForestTrustInformation
);
2037 return NT_STATUS_NO_MEMORY
;
2039 talloc_steal(frame
, mfti
);
2042 * First we add all top unique level names.
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.
2048 for (ni
= 0; ni
< nfti
->count
; ni
++) {
2049 const struct lsa_ForestTrustRecord
*nftr
= nfti
->entries
[ni
];
2050 struct lsa_ForestTrustRecord tftr
= {
2053 const char *ndns
= NULL
;
2054 bool ignore_new
= false;
2055 bool found_old
= false;
2060 return NT_STATUS_INVALID_PARAMETER
;
2063 if (nftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
2067 ndns
= nftr
->forest_trust_data
.top_level_name
.string
;
2070 return NT_STATUS_INVALID_PARAMETER
;
2073 cmp
= dns_cmp(tdo
->domain_name
.string
, ndns
);
2074 if (cmp
== DNS_CMP_MATCH
) {
2075 status
= dsdb_trust_forest_info_add_record(mfti
, nftr
);
2076 if (!NT_STATUS_IS_OK(status
)) {
2082 for (mi
= 0; mi
< mfti
->count
; mi
++) {
2083 const struct lsa_ForestTrustRecord
*mftr
=
2085 const char *mdns
= NULL
;
2088 * we just added this above, so we're sure to have a
2089 * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME record
2091 mdns
= mftr
->forest_trust_data
.top_level_name
.string
;
2093 cmp
= dns_cmp(mdns
, ndns
);
2096 case DNS_CMP_SECOND_IS_CHILD
:
2111 * make a temporary copy where we can change time and flags
2115 for (oi
= 0; oi
< ofti
->count
; oi
++) {
2116 const struct lsa_ForestTrustRecord
*oftr
=
2118 const char *odns
= NULL
;
2122 * broken record => ignore...
2127 if (oftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
2131 odns
= oftr
->forest_trust_data
.top_level_name
.string
;
2134 * broken record => ignore...
2139 cmp
= dns_cmp(odns
, ndns
);
2140 if (cmp
!= DNS_CMP_MATCH
) {
2145 tftr
.flags
= oftr
->flags
;
2146 tftr
.time
= oftr
->time
;
2150 tftr
.flags
= LSA_TLN_DISABLED_NEW
;
2154 status
= dsdb_trust_forest_info_add_record(mfti
, &tftr
);
2155 if (!NT_STATUS_IS_OK(status
)) {
2162 * Now we add all unique (based on their SID) domains
2163 * and may keep the flags and time values.
2165 for (ni
= 0; ni
< nfti
->count
; ni
++) {
2166 const struct lsa_ForestTrustRecord
*nftr
= nfti
->entries
[ni
];
2167 struct lsa_ForestTrustRecord tftr
= {
2170 const struct lsa_ForestTrustDomainInfo
*nd
= NULL
;
2171 const char *ndns
= NULL
;
2172 const char *nnbt
= NULL
;
2173 bool ignore_new
= false;
2174 bool found_old
= false;
2179 return NT_STATUS_INVALID_PARAMETER
;
2182 if (nftr
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
2186 nd
= &nftr
->forest_trust_data
.domain_info
;
2187 if (nd
->domain_sid
== NULL
) {
2189 return NT_STATUS_INVALID_PARAMETER
;
2191 ndns
= nd
->dns_domain_name
.string
;
2194 return NT_STATUS_INVALID_PARAMETER
;
2196 nnbt
= nd
->netbios_domain_name
.string
;
2199 return NT_STATUS_INVALID_PARAMETER
;
2202 for (mi
= 0; mi
< mfti
->count
; mi
++) {
2203 const struct lsa_ForestTrustRecord
*mftr
=
2205 const struct lsa_ForestTrustDomainInfo
*md
= NULL
;
2207 if (mftr
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
2212 * we just added this above, so we're sure to have a
2213 * valid LSA_FOREST_TRUST_DOMAIN_INFO record
2215 md
= &mftr
->forest_trust_data
.domain_info
;
2217 cmp
= dom_sid_compare(nd
->domain_sid
, md
->domain_sid
);
2229 * make a temporary copy where we can change time and flags
2233 for (oi
= 0; oi
< ofti
->count
; oi
++) {
2234 const struct lsa_ForestTrustRecord
*oftr
=
2236 const struct lsa_ForestTrustDomainInfo
*od
= NULL
;
2237 const char *onbt
= NULL
;
2241 * broken record => ignore...
2246 if (oftr
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
2250 od
= &oftr
->forest_trust_data
.domain_info
;
2251 onbt
= od
->netbios_domain_name
.string
;
2254 * broken record => ignore...
2259 cmp
= strcasecmp(onbt
, nnbt
);
2265 tftr
.flags
= oftr
->flags
;
2266 tftr
.time
= oftr
->time
;
2274 status
= dsdb_trust_forest_info_add_record(mfti
, &tftr
);
2275 if (!NT_STATUS_IS_OK(status
)) {
2282 * We keep old domain records disabled by the admin
2283 * if not already in the list.
2285 for (oi
= 0; oi
< ofti
->count
; oi
++) {
2286 const struct lsa_ForestTrustRecord
*oftr
=
2288 const struct lsa_ForestTrustDomainInfo
*od
= NULL
;
2289 const char *odns
= NULL
;
2290 const char *onbt
= NULL
;
2291 bool ignore_old
= true;
2296 * broken record => ignore...
2301 if (oftr
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
2305 od
= &oftr
->forest_trust_data
.domain_info
;
2306 odns
= od
->dns_domain_name
.string
;
2309 * broken record => ignore...
2313 onbt
= od
->netbios_domain_name
.string
;
2316 * broken record => ignore...
2320 if (od
->domain_sid
== NULL
) {
2322 * broken record => ignore...
2327 if (oftr
->flags
& LSA_NB_DISABLED_ADMIN
) {
2329 } else if (oftr
->flags
& LSA_SID_DISABLED_ADMIN
) {
2333 for (mi
= 0; mi
< mfti
->count
; mi
++) {
2334 const struct lsa_ForestTrustRecord
*mftr
=
2336 const struct lsa_ForestTrustDomainInfo
*md
= NULL
;
2338 if (mftr
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
2343 * we just added this above, so we're sure to have a
2344 * valid LSA_FOREST_TRUST_DOMAIN_INFO record
2346 md
= &mftr
->forest_trust_data
.domain_info
;
2348 cmp
= dom_sid_compare(od
->domain_sid
, md
->domain_sid
);
2359 status
= dsdb_trust_forest_info_add_record(mfti
, oftr
);
2360 if (!NT_STATUS_IS_OK(status
)) {
2367 * Finally we readd top level exclusions,
2368 * if they still match a top level name.
2370 for (oi
= 0; oi
< ofti
->count
; oi
++) {
2371 const struct lsa_ForestTrustRecord
*oftr
=
2373 const char *odns
= NULL
;
2374 bool ignore_old
= false;
2379 * broken record => ignore...
2384 if (oftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
) {
2388 odns
= oftr
->forest_trust_data
.top_level_name_ex
.string
;
2391 * broken record => ignore...
2396 for (mi
= 0; mi
< mfti
->count
; mi
++) {
2397 const struct lsa_ForestTrustRecord
*mftr
=
2399 const char *mdns
= NULL
;
2401 if (mftr
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
2406 * we just added this above, so we're sure to have a
2407 * valid LSA_FOREST_TRUST_TOP_LEVEL_NAME.
2409 mdns
= mftr
->forest_trust_data
.top_level_name
.string
;
2411 cmp
= dns_cmp(mdns
, odns
);
2414 case DNS_CMP_SECOND_IS_CHILD
:
2430 status
= dsdb_trust_forest_info_add_record(mfti
, oftr
);
2431 if (!NT_STATUS_IS_OK(status
)) {
2437 *_mfti
= talloc_move(mem_ctx
, &mfti
);
2439 return NT_STATUS_OK
;
2442 NTSTATUS
dsdb_trust_search_tdo(struct ldb_context
*sam_ctx
,
2443 const char *netbios
, const char *dns
,
2444 const char * const *attrs
,
2445 TALLOC_CTX
*mem_ctx
,
2446 struct ldb_message
**msg
)
2448 TALLOC_CTX
*frame
= talloc_stackframe();
2450 struct ldb_dn
*system_dn
= NULL
;
2451 char *netbios_encoded
= NULL
;
2452 char *dns_encoded
= NULL
;
2453 char *filter
= NULL
;
2457 if (netbios
== NULL
&& dns
== NULL
) {
2459 return NT_STATUS_INVALID_PARAMETER_MIX
;
2462 system_dn
= ldb_dn_copy(frame
, ldb_get_default_basedn(sam_ctx
));
2463 if (system_dn
== NULL
) {
2465 return NT_STATUS_NO_MEMORY
;
2468 if (!ldb_dn_add_child_fmt(system_dn
, "CN=System")) {
2470 return NT_STATUS_NO_MEMORY
;
2473 if (netbios
!= NULL
) {
2474 netbios_encoded
= ldb_binary_encode_string(frame
, netbios
);
2475 if (netbios_encoded
== NULL
) {
2477 return NT_STATUS_NO_MEMORY
;
2482 dns_encoded
= ldb_binary_encode_string(frame
, dns
);
2483 if (dns_encoded
== NULL
) {
2485 return NT_STATUS_NO_MEMORY
;
2489 if (netbios
!= NULL
&& dns
!= NULL
) {
2490 filter
= talloc_asprintf(frame
,
2491 "(&(objectClass=trustedDomain)"
2492 "(|(trustPartner=%s)(flatName=%s))"
2494 dns_encoded
, netbios_encoded
);
2495 if (filter
== NULL
) {
2497 return NT_STATUS_NO_MEMORY
;
2499 } else if (netbios
!= NULL
) {
2500 filter
= talloc_asprintf(frame
,
2501 "(&(objectClass=trustedDomain)(flatName=%s))",
2503 if (filter
== NULL
) {
2505 return NT_STATUS_NO_MEMORY
;
2507 } else if (dns
!= NULL
) {
2508 filter
= talloc_asprintf(frame
,
2509 "(&(objectClass=trustedDomain)(trustPartner=%s))",
2511 if (filter
== NULL
) {
2513 return NT_STATUS_NO_MEMORY
;
2517 ret
= dsdb_search_one(sam_ctx
, mem_ctx
, msg
,
2519 LDB_SCOPE_ONELEVEL
, attrs
,
2520 DSDB_SEARCH_NO_GLOBAL_CATALOG
,
2522 if (ret
!= LDB_SUCCESS
) {
2523 NTSTATUS status
= dsdb_ldb_err_to_ntstatus(ret
);
2524 DEBUG(3, ("Failed to search for %s: %s - %s\n",
2525 filter
, nt_errstr(status
), ldb_errstring(sam_ctx
)));
2531 return NT_STATUS_OK
;
2534 NTSTATUS
dsdb_trust_search_tdo_by_type(struct ldb_context
*sam_ctx
,
2535 enum netr_SchannelType type
,
2537 const char * const *attrs
,
2538 TALLOC_CTX
*mem_ctx
,
2539 struct ldb_message
**msg
)
2541 TALLOC_CTX
*frame
= talloc_stackframe();
2545 bool require_trailer
= true;
2546 char *encoded_name
= NULL
;
2547 const char *netbios
= NULL
;
2548 const char *dns
= NULL
;
2550 if (type
!= SEC_CHAN_DOMAIN
&& type
!= SEC_CHAN_DNS_DOMAIN
) {
2552 return NT_STATUS_INVALID_PARAMETER
;
2555 if (type
== SEC_CHAN_DNS_DOMAIN
) {
2557 require_trailer
= false;
2560 encoded_name
= ldb_binary_encode_string(frame
, name
);
2561 if (encoded_name
== NULL
) {
2563 return NT_STATUS_NO_MEMORY
;
2566 len
= strlen(encoded_name
);
2569 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2572 if (require_trailer
&& encoded_name
[len
- 1] != trailer
) {
2574 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
2576 encoded_name
[len
- 1] = '\0';
2578 if (type
== SEC_CHAN_DNS_DOMAIN
) {
2581 netbios
= encoded_name
;
2584 status
= dsdb_trust_search_tdo(sam_ctx
, netbios
, dns
,
2585 attrs
, mem_ctx
, msg
);
2586 if (!NT_STATUS_IS_OK(status
)) {
2592 return NT_STATUS_OK
;
2595 NTSTATUS
dsdb_trust_search_tdo_by_sid(struct ldb_context
*sam_ctx
,
2596 const struct dom_sid
*sid
,
2597 const char * const *attrs
,
2598 TALLOC_CTX
*mem_ctx
,
2599 struct ldb_message
**msg
)
2601 TALLOC_CTX
*frame
= talloc_stackframe();
2603 struct ldb_dn
*system_dn
= NULL
;
2604 char *encoded_sid
= NULL
;
2605 char *filter
= NULL
;
2611 return NT_STATUS_INVALID_PARAMETER_MIX
;
2614 encoded_sid
= ldap_encode_ndr_dom_sid(frame
, sid
);
2615 if (encoded_sid
== NULL
) {
2617 return NT_STATUS_NO_MEMORY
;
2620 system_dn
= ldb_dn_copy(frame
, ldb_get_default_basedn(sam_ctx
));
2621 if (system_dn
== NULL
) {
2623 return NT_STATUS_NO_MEMORY
;
2626 if (!ldb_dn_add_child_fmt(system_dn
, "CN=System")) {
2628 return NT_STATUS_NO_MEMORY
;
2631 filter
= talloc_asprintf(frame
,
2633 "(objectClass=trustedDomain)"
2634 "(securityIdentifier=%s)"
2637 if (filter
== NULL
) {
2639 return NT_STATUS_NO_MEMORY
;
2642 ret
= dsdb_search_one(sam_ctx
, mem_ctx
, msg
,
2644 LDB_SCOPE_ONELEVEL
, attrs
,
2645 DSDB_SEARCH_NO_GLOBAL_CATALOG
,
2647 if (ret
!= LDB_SUCCESS
) {
2648 NTSTATUS status
= dsdb_ldb_err_to_ntstatus(ret
);
2649 DEBUG(3, ("Failed to search for %s: %s - %s\n",
2650 filter
, nt_errstr(status
), ldb_errstring(sam_ctx
)));
2656 return NT_STATUS_OK
;
2659 NTSTATUS
dsdb_trust_get_incoming_passwords(struct ldb_message
*msg
,
2660 TALLOC_CTX
*mem_ctx
,
2661 struct samr_Password
**_current
,
2662 struct samr_Password
**_previous
)
2664 TALLOC_CTX
*frame
= talloc_stackframe();
2665 struct samr_Password __current
= {
2668 struct samr_Password __previous
= {
2671 struct samr_Password
*current
= NULL
;
2672 struct samr_Password
*previous
= NULL
;
2673 const struct ldb_val
*blob
= NULL
;
2674 enum ndr_err_code ndr_err
;
2675 struct trustAuthInOutBlob incoming
= {
2680 if (_current
!= NULL
) {
2683 if (_previous
!= NULL
) {
2687 blob
= ldb_msg_find_ldb_val(msg
, "trustAuthIncoming");
2690 return NT_STATUS_ACCOUNT_DISABLED
;
2693 /* ldb_val is equivalent to DATA_BLOB */
2694 ndr_err
= ndr_pull_struct_blob_all(blob
, frame
, &incoming
,
2695 (ndr_pull_flags_fn_t
)ndr_pull_trustAuthInOutBlob
);
2696 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2698 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2701 for (i
= 0; i
< incoming
.current
.count
; i
++) {
2702 struct AuthenticationInformation
*a
=
2703 &incoming
.current
.array
[i
];
2705 if (current
!= NULL
) {
2709 switch (a
->AuthType
) {
2710 case TRUST_AUTH_TYPE_NONE
:
2711 case TRUST_AUTH_TYPE_VERSION
:
2713 case TRUST_AUTH_TYPE_NT4OWF
:
2714 current
= &a
->AuthInfo
.nt4owf
.password
;
2716 case TRUST_AUTH_TYPE_CLEAR
:
2717 mdfour(__current
.hash
,
2718 a
->AuthInfo
.clear
.password
,
2719 a
->AuthInfo
.clear
.size
);
2720 current
= &__current
;
2725 if (current
== NULL
) {
2727 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
2730 for (i
= 0; i
< incoming
.previous
.count
; i
++) {
2731 struct AuthenticationInformation
*a
=
2732 &incoming
.previous
.array
[i
];
2734 if (previous
!= NULL
) {
2738 switch (a
->AuthType
) {
2739 case TRUST_AUTH_TYPE_NONE
:
2740 case TRUST_AUTH_TYPE_VERSION
:
2742 case TRUST_AUTH_TYPE_NT4OWF
:
2743 previous
= &a
->AuthInfo
.nt4owf
.password
;
2745 case TRUST_AUTH_TYPE_CLEAR
:
2746 mdfour(__previous
.hash
,
2747 a
->AuthInfo
.clear
.password
,
2748 a
->AuthInfo
.clear
.size
);
2749 previous
= &__previous
;
2754 if (previous
== NULL
) {
2758 if (_current
!= NULL
) {
2759 *_current
= talloc(mem_ctx
, struct samr_Password
);
2760 if (*_current
== NULL
) {
2762 return NT_STATUS_NO_MEMORY
;
2764 **_current
= *current
;
2766 if (_previous
!= NULL
) {
2767 *_previous
= talloc(mem_ctx
, struct samr_Password
);
2768 if (*_previous
== NULL
) {
2769 if (_current
!= NULL
) {
2770 TALLOC_FREE(*_current
);
2773 return NT_STATUS_NO_MEMORY
;
2775 **_previous
= *previous
;
2777 ZERO_STRUCTP(current
);
2778 ZERO_STRUCTP(previous
);
2780 return NT_STATUS_OK
;
2783 NTSTATUS
dsdb_trust_search_tdos(struct ldb_context
*sam_ctx
,
2784 const char *exclude
,
2785 const char * const *attrs
,
2786 TALLOC_CTX
*mem_ctx
,
2787 struct ldb_result
**res
)
2789 TALLOC_CTX
*frame
= talloc_stackframe();
2791 struct ldb_dn
*system_dn
= NULL
;
2792 const char *filter
= NULL
;
2793 char *exclude_encoded
= NULL
;
2797 system_dn
= ldb_dn_copy(frame
, ldb_get_default_basedn(sam_ctx
));
2798 if (system_dn
== NULL
) {
2800 return NT_STATUS_NO_MEMORY
;
2803 if (!ldb_dn_add_child_fmt(system_dn
, "CN=System")) {
2805 return NT_STATUS_NO_MEMORY
;
2808 if (exclude
!= NULL
) {
2809 exclude_encoded
= ldb_binary_encode_string(frame
, exclude
);
2810 if (exclude_encoded
== NULL
) {
2812 return NT_STATUS_NO_MEMORY
;
2815 filter
= talloc_asprintf(frame
,
2816 "(&(objectClass=trustedDomain)"
2817 "(!(|(trustPartner=%s)(flatName=%s)))"
2819 exclude_encoded
, exclude_encoded
);
2820 if (filter
== NULL
) {
2822 return NT_STATUS_NO_MEMORY
;
2825 filter
= "(objectClass=trustedDomain)";
2828 ret
= dsdb_search(sam_ctx
, mem_ctx
, res
,
2830 LDB_SCOPE_ONELEVEL
, attrs
,
2831 DSDB_SEARCH_NO_GLOBAL_CATALOG
,
2833 if (ret
!= LDB_SUCCESS
) {
2834 NTSTATUS status
= dsdb_ldb_err_to_ntstatus(ret
);
2835 DEBUG(3, ("Failed to search for %s: %s - %s\n",
2836 filter
, nt_errstr(status
), ldb_errstring(sam_ctx
)));
2842 return NT_STATUS_OK
;
2845 struct dsdb_trust_routing_domain
;
2847 struct dsdb_trust_routing_table
{
2848 struct dsdb_trust_routing_domain
*domains
;
2851 struct dsdb_trust_routing_domain
{
2852 struct dsdb_trust_routing_domain
*prev
, *next
;
2854 struct lsa_TrustDomainInfoInfoEx
*tdo
;
2856 struct lsa_ForestTrustDomainInfo di
;
2858 struct lsa_ForestTrustInformation
*fti
;
2861 NTSTATUS
dsdb_trust_routing_table_load(struct ldb_context
*sam_ctx
,
2862 TALLOC_CTX
*mem_ctx
,
2863 struct dsdb_trust_routing_table
**_table
)
2865 TALLOC_CTX
*frame
= talloc_stackframe();
2866 struct dsdb_trust_routing_table
*table
;
2867 struct dsdb_trust_routing_domain
*d
= NULL
;
2868 struct ldb_dn
*domain_dn
= NULL
;
2869 struct lsa_TrustDomainInfoInfoEx
*root_trust_tdo
= NULL
;
2870 struct lsa_TrustDomainInfoInfoEx
*trust_parent_tdo
= NULL
;
2871 struct lsa_TrustDomainInfoInfoEx
*root_direction_tdo
= NULL
;
2872 const char * const trusts_attrs
[] = {
2873 "securityIdentifier",
2879 "msDS-TrustForestTrustInfo",
2882 struct ldb_result
*trusts_res
= NULL
;
2888 domain_dn
= ldb_get_default_basedn(sam_ctx
);
2889 if (domain_dn
== NULL
) {
2891 return NT_STATUS_INTERNAL_ERROR
;
2894 table
= talloc_zero(mem_ctx
, struct dsdb_trust_routing_table
);
2895 if (table
== NULL
) {
2897 return NT_STATUS_NO_MEMORY
;
2899 talloc_steal(frame
, table
);
2901 d
= talloc_zero(table
, struct dsdb_trust_routing_domain
);
2904 return NT_STATUS_NO_MEMORY
;
2907 status
= dsdb_trust_crossref_tdo_info(d
, sam_ctx
,
2912 if (!NT_STATUS_IS_OK(status
)) {
2918 * d->tdo should not be NULL of status above is 'NT_STATUS_OK'
2919 * check is needed to satisfy clang static checker
2921 if (d
->tdo
== NULL
) {
2923 return NT_STATUS_NO_MEMORY
;
2925 d
->di
.domain_sid
= d
->tdo
->sid
;
2926 d
->di
.netbios_domain_name
.string
= d
->tdo
->netbios_name
.string
;
2927 d
->di
.dns_domain_name
.string
= d
->tdo
->domain_name
.string
;
2929 if (root_trust_tdo
!= NULL
) {
2930 root_direction_tdo
= root_trust_tdo
;
2931 } else if (trust_parent_tdo
!= NULL
) {
2932 root_direction_tdo
= trust_parent_tdo
;
2935 if (root_direction_tdo
== NULL
) {
2936 /* we're the forest root */
2937 status
= dsdb_trust_xref_forest_info(d
, sam_ctx
, &d
->fti
);
2938 if (!NT_STATUS_IS_OK(status
)) {
2944 DLIST_ADD(table
->domains
, d
);
2946 status
= dsdb_trust_search_tdos(sam_ctx
, NULL
, trusts_attrs
,
2947 frame
, &trusts_res
);
2948 if (!NT_STATUS_IS_OK(status
)) {
2953 for (i
= 0; i
< trusts_res
->count
; i
++) {
2957 d
= talloc_zero(table
, struct dsdb_trust_routing_domain
);
2960 return NT_STATUS_NO_MEMORY
;
2963 status
= dsdb_trust_parse_tdo_info(d
,
2964 trusts_res
->msgs
[i
],
2966 if (!NT_STATUS_IS_OK(status
)) {
2971 d
->di
.domain_sid
= d
->tdo
->sid
;
2972 d
->di
.netbios_domain_name
.string
= d
->tdo
->netbios_name
.string
;
2973 d
->di
.dns_domain_name
.string
= d
->tdo
->domain_name
.string
;
2975 DLIST_ADD_END(table
->domains
, d
);
2977 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
2978 struct ForestTrustInfo
*fti
= NULL
;
2980 status
= dsdb_trust_parse_forest_info(frame
,
2981 trusts_res
->msgs
[i
],
2983 if (NT_STATUS_EQUAL(status
, NT_STATUS_NOT_FOUND
)) {
2985 status
= NT_STATUS_OK
;
2987 if (!NT_STATUS_IS_OK(status
)) {
2996 status
= dsdb_trust_forest_info_to_lsa(d
, fti
, &d
->fti
);
2997 if (!NT_STATUS_IS_OK(status
)) {
3005 if (!(d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
)) {
3009 if (root_direction_tdo
== NULL
) {
3013 ok
= dom_sid_equal(root_direction_tdo
->sid
, d
->tdo
->sid
);
3018 cmp
= strcasecmp_m(root_direction_tdo
->netbios_name
.string
,
3019 d
->tdo
->netbios_name
.string
);
3024 cmp
= strcasecmp_m(root_direction_tdo
->domain_name
.string
,
3025 d
->tdo
->domain_name
.string
);
3030 /* this our route to the forest root */
3031 status
= dsdb_trust_xref_forest_info(d
, sam_ctx
, &d
->fti
);
3032 if (!NT_STATUS_IS_OK(status
)) {
3038 *_table
= talloc_move(mem_ctx
, &table
);
3040 return NT_STATUS_OK
;
3043 static void dsdb_trust_update_best_tln(
3044 const struct dsdb_trust_routing_domain
**best_d
,
3045 const char **best_tln
,
3046 const struct dsdb_trust_routing_domain
*d
,
3051 if (*best_tln
== NULL
) {
3057 cmp
= dns_cmp(*best_tln
, tln
);
3058 if (cmp
!= DNS_CMP_FIRST_IS_CHILD
) {
3066 const struct lsa_TrustDomainInfoInfoEx
*dsdb_trust_routing_by_name(
3067 const struct dsdb_trust_routing_table
*table
,
3070 const struct dsdb_trust_routing_domain
*best_d
= NULL
;
3071 const char *best_tln
= NULL
;
3072 const struct dsdb_trust_routing_domain
*d
= NULL
;
3078 for (d
= table
->domains
; d
!= NULL
; d
= d
->next
) {
3079 bool transitive
= false;
3080 bool allow_netbios
= false;
3081 bool exclude
= false;
3084 if (d
->tdo
->trust_type
!= LSA_TRUST_TYPE_UPLEVEL
) {
3086 * Only uplevel trusts have top level names
3091 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
3095 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
3099 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
) {
3103 if (d
->tdo
->trust_type
!= LSA_TRUST_TYPE_UPLEVEL
) {
3107 switch (d
->tdo
->trust_type
) {
3108 case LSA_TRUST_TYPE_UPLEVEL
:
3109 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_UPLEVEL_ONLY
) {
3112 allow_netbios
= true;
3114 case LSA_TRUST_TYPE_DOWNLEVEL
:
3115 allow_netbios
= true;
3118 allow_netbios
= false;
3122 if (!transitive
|| d
->fti
== NULL
) {
3125 if (allow_netbios
) {
3126 cmp
= dns_cmp(name
, d
->tdo
->netbios_name
.string
);
3127 if (cmp
== DNS_CMP_MATCH
) {
3135 cmp
= dns_cmp(name
, d
->tdo
->domain_name
.string
);
3136 if (cmp
== DNS_CMP_MATCH
) {
3142 if (cmp
!= DNS_CMP_FIRST_IS_CHILD
) {
3150 dsdb_trust_update_best_tln(&best_d
, &best_tln
, d
,
3151 d
->tdo
->domain_name
.string
);
3155 exclude
= dsdb_trust_find_tln_ex_match(d
->fti
, name
);
3160 for (i
= 0; i
< d
->fti
->count
; i
++ ) {
3161 const struct lsa_ForestTrustRecord
*f
= d
->fti
->entries
[i
];
3162 const struct lsa_ForestTrustDomainInfo
*di
= NULL
;
3163 const char *fti_nbt
= NULL
;
3166 if (!allow_netbios
) {
3175 if (f
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
3179 if (f
->flags
& LSA_NB_DISABLED_MASK
) {
3181 * any flag disables the entry.
3186 di
= &f
->forest_trust_data
.domain_info
;
3187 fti_nbt
= di
->netbios_domain_name
.string
;
3188 if (fti_nbt
== NULL
) {
3193 cmp
= dns_cmp(name
, fti_nbt
);
3194 if (cmp
== DNS_CMP_MATCH
) {
3202 for (i
= 0; i
< d
->fti
->count
; i
++ ) {
3203 const struct lsa_ForestTrustRecord
*f
= d
->fti
->entries
[i
];
3204 const union lsa_ForestTrustData
*u
= NULL
;
3205 const char *fti_tln
= NULL
;
3213 if (f
->type
!= LSA_FOREST_TRUST_TOP_LEVEL_NAME
) {
3217 if (f
->flags
& LSA_TLN_DISABLED_MASK
) {
3219 * any flag disables the entry.
3224 u
= &f
->forest_trust_data
;
3225 fti_tln
= u
->top_level_name
.string
;
3226 if (fti_tln
== NULL
) {
3230 cmp
= dns_cmp(name
, fti_tln
);
3233 case DNS_CMP_FIRST_IS_CHILD
:
3234 dsdb_trust_update_best_tln(&best_d
, &best_tln
,
3243 if (best_d
!= NULL
) {
3250 const struct lsa_TrustDomainInfoInfoEx
*dsdb_trust_domain_by_sid(
3251 const struct dsdb_trust_routing_table
*table
,
3252 const struct dom_sid
*sid
,
3253 const struct lsa_ForestTrustDomainInfo
**pdi
)
3255 const struct dsdb_trust_routing_domain
*d
= NULL
;
3265 for (d
= table
->domains
; d
!= NULL
; d
= d
->next
) {
3266 bool transitive
= false;
3269 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
3273 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
3277 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
) {
3281 if (d
->tdo
->trust_type
!= LSA_TRUST_TYPE_UPLEVEL
) {
3285 if (!transitive
|| d
->fti
== NULL
) {
3288 match
= dom_sid_equal(d
->di
.domain_sid
, sid
);
3291 * exact match, it's the domain itself.
3301 for (i
= 0; i
< d
->fti
->count
; i
++ ) {
3302 const struct lsa_ForestTrustRecord
*f
= d
->fti
->entries
[i
];
3303 const struct lsa_ForestTrustDomainInfo
*di
= NULL
;
3304 const struct dom_sid
*fti_sid
= NULL
;
3312 if (f
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
3316 if (f
->flags
& LSA_SID_DISABLED_MASK
) {
3318 * any flag disables the entry.
3323 di
= &f
->forest_trust_data
.domain_info
;
3324 fti_sid
= di
->domain_sid
;
3325 if (fti_sid
== NULL
) {
3330 match
= dom_sid_equal(fti_sid
, sid
);
3333 * exact match, it's a domain in the forest.
3346 const struct lsa_TrustDomainInfoInfoEx
*dsdb_trust_domain_by_name(
3347 const struct dsdb_trust_routing_table
*table
,
3349 const struct lsa_ForestTrustDomainInfo
**pdi
)
3351 const struct dsdb_trust_routing_domain
*d
= NULL
;
3361 for (d
= table
->domains
; d
!= NULL
; d
= d
->next
) {
3362 bool transitive
= false;
3365 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
3369 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
3373 if (d
->tdo
->trust_attributes
& LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
) {
3377 if (d
->tdo
->trust_type
!= LSA_TRUST_TYPE_UPLEVEL
) {
3381 if (!transitive
|| d
->fti
== NULL
) {
3384 match
= strequal_m(d
->di
.netbios_domain_name
.string
,
3388 * exact match for netbios name,
3389 * it's the domain itself.
3396 match
= strequal_m(d
->di
.dns_domain_name
.string
,
3400 * exact match for dns name,
3401 * it's the domain itself.
3411 for (i
= 0; i
< d
->fti
->count
; i
++ ) {
3412 const struct lsa_ForestTrustRecord
*f
= d
->fti
->entries
[i
];
3413 const struct lsa_ForestTrustDomainInfo
*di
= NULL
;
3421 if (f
->type
!= LSA_FOREST_TRUST_DOMAIN_INFO
) {
3424 di
= &f
->forest_trust_data
.domain_info
;
3426 if (!(f
->flags
& LSA_NB_DISABLED_MASK
)) {
3427 match
= strequal_m(di
->netbios_domain_name
.string
,
3431 * exact match for netbios name,
3432 * it's a domain in the forest.
3441 if (!(f
->flags
& LSA_TLN_DISABLED_MASK
)) {
3442 match
= strequal_m(di
->dns_domain_name
.string
,
3446 * exact match for dns name,
3447 * it's a domain in the forest.