mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ipaserver/dcerpc: fix exclusion entry with a forest trust domain info returned
When looking through the topology of a trusted forest, we should support all types of forest trust records. Since Samba Python bindings parse the data into a typed structure, a type of the record has to be taken into account or there will be type mismatch when accessing elements of the union: typedef [switch_type(lsa_ForestTrustRecordType)] union { [case(LSA_FOREST_TRUST_TOP_LEVEL_NAME)] lsa_StringLarge top_level_name; [case(LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX)] lsa_StringLarge top_level_name_ex; [case(LSA_FOREST_TRUST_DOMAIN_INFO)] lsa_ForestTrustDomainInfo domain_info; [default] lsa_ForestTrustBinaryData data; } lsa_ForestTrustData; typedef struct { lsa_ForestTrustRecordFlags flags; lsa_ForestTrustRecordType type; NTTIME_hyper time; [switch_is(type)] lsa_ForestTrustData forest_trust_data; } lsa_ForestTrustRecord; typedef [public] struct { [range(0,4000)] uint32 count; [size_is(count)] lsa_ForestTrustRecord **entries; } lsa_ForestTrustInformation; Each entry in the lsa_ForestTrustInformation has forest_trust_data member but its content depends on the value of a type member (forest_trust_data is a union of all possible structures). Previously we assumed only TLN or TLN exclusion record which were of the same type (lsa_StringLarge). Access to forest_trust_data.string fails when forest_trust_data's type is lsa_ForestTrustDomainInfo as it has no string member. Fix the code by properly accessing the dns_domain_name from the lsa_ForestTrustDomainInfo structure. Fixes: https://pagure.io/freeipa/issue/7828 Reviewed-By: Christian Heimes <cheimes@redhat.com>
This commit is contained in:
parent
3bed3d4ddb
commit
3c38aea6fc
@ -51,6 +51,7 @@ from samba.dcerpc import security, lsa, drsblobs, nbt, netlogon
|
||||
from samba.ndr import ndr_pack, ndr_print
|
||||
from samba import net
|
||||
from samba import arcfour_encrypt
|
||||
from samba import ntstatus
|
||||
import samba
|
||||
|
||||
import ldap as _ldap
|
||||
@ -1105,6 +1106,25 @@ class TrustDomainInstance:
|
||||
original forest.
|
||||
"""
|
||||
|
||||
def domain_name_from_ftinfo(ftinfo):
|
||||
"""
|
||||
Returns a domain name string from a ForestTrustRecord
|
||||
|
||||
:param ftinfo: LSA ForestTrustRecord to parse
|
||||
"""
|
||||
if ftinfo.type == lsa.LSA_FOREST_TRUST_DOMAIN_INFO:
|
||||
return ftinfo.forest_trust_data.dns_domain_name.string
|
||||
elif ftinfo.type == lsa.LSA_FOREST_TRUST_TOP_LEVEL_NAME:
|
||||
return ftinfo.forest_trust_data.string
|
||||
elif ftinfo.type == lsa.LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
|
||||
# We should ignore TLN exclusion record because it
|
||||
# is already an exclusion so we aren't going to
|
||||
# change anything here
|
||||
return None
|
||||
else:
|
||||
# Ignore binary blobs we don't know about
|
||||
return None
|
||||
|
||||
# List of entries for unsolved conflicts
|
||||
result = []
|
||||
|
||||
@ -1145,18 +1165,26 @@ class TrustDomainInstance:
|
||||
e1.time = e.time
|
||||
e1.forest_trust_data = e.forest_trust_data
|
||||
|
||||
# We either have a domain struct, a TLN name,
|
||||
# or a TLN exclusion name in the list.
|
||||
# The rest we should skip, those are binary blobs
|
||||
dns_domain_name = domain_name_from_ftinfo(e)
|
||||
|
||||
# Search for a match in the topology of another domain
|
||||
# if there is a match, we have to convert a record
|
||||
# into a TLN exclusion to allow its routing to the
|
||||
# another domain
|
||||
for r in another_domain.ftinfo_records:
|
||||
if r['rec_name'] == e.forest_trust_data.string:
|
||||
# r['rec_name'] cannot be None, thus we can ignore
|
||||
# the case when dns_domain_name is None
|
||||
if r['rec_name'] == dns_domain_name:
|
||||
is_our_record = True
|
||||
|
||||
# Convert e1 into an exclusion record
|
||||
e1.type = lsa.LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX
|
||||
e1.flags = 0
|
||||
e1.time = trust_timestamp
|
||||
e1.forest_trust_data.string = dns_domain_name
|
||||
break
|
||||
entries.append(e1)
|
||||
|
||||
@ -1180,11 +1208,29 @@ class TrustDomainInstance:
|
||||
# Update the forest trust information now
|
||||
ldname = lsa.StringLarge()
|
||||
ldname.string = rec.name.string
|
||||
cninfo = None
|
||||
try:
|
||||
cninfo = self._pipe.lsaRSetForestTrustInformation(
|
||||
self._policy_handle,
|
||||
ldname,
|
||||
lsa.LSA_FOREST_TRUST_DOMAIN_INFO,
|
||||
fti, 0)
|
||||
except samba.NTSTATUSError as error:
|
||||
# Handle NT_STATUS_INVALID_PARAMETER separately
|
||||
if ntstatus.NT_STATUS_INVALID_PARAMETER == error.args[0]:
|
||||
result.append(rec)
|
||||
logger.error("Unable to resolve conflict for "
|
||||
"DNS domain %s in the forest %s "
|
||||
"for in-forest domain %s. Trust cannot "
|
||||
"be established unless this conflict "
|
||||
"is fixed manually.",
|
||||
another_domain.info['dns_domain'],
|
||||
self.info['dns_domain'],
|
||||
rec.name.string)
|
||||
else:
|
||||
raise assess_dcerpc_error(error)
|
||||
|
||||
|
||||
if cninfo:
|
||||
result.append(rec)
|
||||
logger.error("When defining exception for DNS "
|
||||
@ -1213,7 +1259,7 @@ class TrustDomainInstance:
|
||||
# Otherwise, raise TrustTopologyConflictError() exception
|
||||
domains = [x.name.string for x in result]
|
||||
raise errors.TrustTopologyConflictError(
|
||||
target=self.info['dns_domain'],
|
||||
forest=self.info['dns_domain'],
|
||||
conflict=another_domain.info['dns_domain'],
|
||||
domains=domains)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user