[Freeipa-devel] [PATCH] 0117 ipaserver/dcerpc.py: populate forest trust information

Alexander Bokovoy abokovoy at redhat.com
Thu Sep 19 19:18:57 UTC 2013


On Thu, 12 Sep 2013, Alexander Bokovoy wrote:
> Hi!
> 
> Attached patch does the magic of enabling all domains associated with
> our realm in AD when we establish the trust relationship.
> 
> LsarSetForestTrustInformation RPC call is used to set the forest trust
> information. Currently only top level names are exposed as we don't have
> any domain name/SID/NetBIOS exclusion support yet. I decided to avoid
> updating full TDO object as there is some problem with memory handling
> of a domain sid object in lsa.ForestTrustRecord Python binding for that
> type -- even assigned value gets immediately destroyed unless I
> ndr_print the record.
> 
> The patch also moves string_to_array() helper to the top level as it is
> useful for quite few RPC calls where instead of a structured record one
> needs to use ndr_pack() and string_to_array() of the result. While it is
> not used right now, there will be updates coming related to subdomains
> handling that will require it anyway.
> 
> https://fedorahosted.org/freeipa/ticket/3919
Patch updated with few more fixes found by pylint and code
simplification.


-- 
/ Alexander Bokovoy
-------------- next part --------------
>From d850941399811a98ed68e77438b3c67412f5e99d Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy at redhat.com>
Date: Wed, 11 Sep 2013 21:34:55 +0300
Subject: [PATCH 4/5] ipaserver/dcerpc.py: populate forest trust information
 using realmdomains

Use realmdomains information to prepopulate forest trust info. As result,
all additional domains should now be enabled from the beginning, unless they
really conflict with existing DNS domains on AD side.
---
 ipaserver/dcerpc.py | 72 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 65 insertions(+), 7 deletions(-)

diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
index bd8f5aa..33e7e07 100644
--- a/ipaserver/dcerpc.py
+++ b/ipaserver/dcerpc.py
@@ -698,6 +698,7 @@ class TrustDomainInstance(object):
         self._pipe = None
         self._policy_handle = None
         self.read_only = False
+        self.ftinfo_records = None
 
     def __gen_lsa_connection(self, binding):
        if self.creds is None:
@@ -876,6 +877,41 @@ class TrustDomainInstance(object):
         self.auth_info = auth_info
 
 
+    def generate_ftinfo(self, another_domain):
+        """
+        Generates TrustDomainInfoFullInfo2Internal structure
+        This structure allows to pass informationa bout all domains associated
+        with our realm.
+        """
+        info = lsa.TrustDomainInfoFullInfo2Internal()
+        info.info_ex.domain_name.string = another_domain.info['dns_domain']
+        info.info_ex.netbios_name.string = another_domain.info['name']
+        info.info_ex.sid = security.dom_sid(another_domain.info['sid'])
+        info.info_ex.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND
+        info.info_ex.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
+        info.info_ex.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
+
+        ftinfo = drsblobs.ForestTrustInfo()
+        ftinfo.version = 1
+        ftinfo_records = []
+
+        for rec in self.ftinfo_records:
+            record = drsblobs.ForestTrustInfoRecordArmor()
+            record.record.flags = 0
+            record.record.timestamp = 0
+            record.record.type = rec['rec_type']
+            if rec.rec_type in [1,2]:
+                record.record.data.name.string = rec['rec_name']
+            elif rec.rec_type == 2:
+                record.record.data.info.sid = rec['rec_sid']
+                record.record.data.info.dns_name.string = rec['rec_name']
+                record.record.data.info.netbios_name.string = rec['rec_nbtname']
+            ftinfo_records.append(record)
+
+        ftinfo.records = ftinfo_records
+        info.forest_trust_data = ndr_pack(ftinfo)
+        return info
+
 
     def establish_trust(self, another_domain, trustdom_secret):
         """
@@ -885,13 +921,17 @@ class TrustDomainInstance(object):
         """
         self.generate_auth(trustdom_secret)
 
-        info = lsa.TrustDomainInfoInfoEx()
-        info.domain_name.string = another_domain.info['dns_domain']
-        info.netbios_name.string = another_domain.info['name']
-        info.sid = security.dom_sid(another_domain.info['sid'])
-        info.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND
-        info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
-        info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
+
+        if self.ftinfo_records:
+            info = self.generate_ftinfo(another_domain)
+        else:
+            info = lsa.TrustDomainInfoInfoEx()
+            info.domain_name.string = another_domain.info['dns_domain']
+            info.netbios_name.string = another_domain.info['name']
+            info.sid = security.dom_sid(another_domain.info['sid'])
+            info.trust_direction = lsa.LSA_TRUST_DIRECTION_INBOUND | lsa.LSA_TRUST_DIRECTION_OUTBOUND
+            info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
+            info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
 
         if self.info['name'] == info.netbios_name.string:
             # Check that NetBIOS names do not clash
@@ -1016,6 +1056,23 @@ class TrustDomainJoins(object):
         # Otherwise, use anonymously obtained data
         self.remote_domain = rd
 
+    def get_realmdomains(self):
+        if self.remote_domain.read_only:
+            return
+        realm_domains = self.api.Command.realmdomains_show()['result']['associateddomain']
+        trustconfig = self.api.Command.trustconfig_show()['result']
+        for dom in realm_domains:
+            ftinfo = dict()
+            ftinfo['rec_name'] = dom
+            if dom == trustconfig['cn'][0]:
+                ftinfo['rec_type'] = drsblobs.FOREST_TRUST_DOMAIN_INFO
+                ftinfo['rec_sid'] = security.dom_sid(trustconfig['ipantsecurityidentifier'])
+                ftinfo['rec_nbtname'] = trustconfig['ipantflatname']
+            else:
+                ftinfo['rec_type'] = drsblobs.FOREST_TRUST_TOP_LEVEL_NAME
+            self.remote_domain.ftinfo_records.append(ftinfo)
+
+
     def join_ad_full_credentials(self, realm, realm_server, realm_admin, realm_passwd):
         if not self.configured:
             return None
@@ -1030,6 +1087,7 @@ class TrustDomainJoins(object):
 
         if not self.remote_domain.read_only:
             trustdom_pass = samba.generate_random_password(128, 128)
+            self.get_realmdomains()
             self.remote_domain.establish_trust(self.local_domain, trustdom_pass)
             self.local_domain.establish_trust(self.remote_domain, trustdom_pass)
             result = self.remote_domain.verify_trust(self.local_domain)
-- 
1.8.3.1



More information about the Freeipa-devel mailing list