8f4e66
From 41b252a5b47f57919bf98c41947d5927ed0d5aaf Mon Sep 17 00:00:00 2001
8f4e66
From: Alexander Bokovoy <abokovoy@redhat.com>
8f4e66
Date: Tue, 19 Aug 2014 16:21:21 +0300
8f4e66
Subject: [PATCH] ipaserver/dcerpc.py: make PDC discovery more robust
8f4e66
8f4e66
Certain operations against AD domain controller can only be done if its
8f4e66
FSMO role is primary domain controller. We need to use writable DC and
8f4e66
PDC when creating trust and updating name suffix routing information.
8f4e66
8f4e66
https://fedorahosted.org/freeipa/ticket/4479
8f4e66
8f4e66
Reviewed-By: Sumit Bose <sbose@redhat.com>
8f4e66
---
8f4e66
 ipaserver/dcerpc.py | 21 ++++++++++++++++-----
8f4e66
 1 file changed, 16 insertions(+), 5 deletions(-)
8f4e66
8f4e66
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
8f4e66
index b11476a262ccce4315131b9ffbd93b625de940e7..78bfc5dbefc778519c5db0ac12d6551710257ba9 100644
8f4e66
--- a/ipaserver/dcerpc.py
8f4e66
+++ b/ipaserver/dcerpc.py
8f4e66
@@ -706,16 +706,19 @@ class TrustDomainInstance(object):
8f4e66
         binding_template=lambda x,y,z: u'%s:%s[%s]' % (x, y, z)
8f4e66
         return [binding_template(t, remote_host, o) for t in transports for o in options]
8f4e66
 
8f4e66
-    def retrieve_anonymously(self, remote_host, discover_srv=False):
8f4e66
+    def retrieve_anonymously(self, remote_host, discover_srv=False, search_pdc=False):
8f4e66
         """
8f4e66
         When retrieving DC information anonymously, we can't get SID of the domain
8f4e66
         """
8f4e66
         netrc = net.Net(creds=self.creds, lp=self.parm)
8f4e66
+        flags = nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE
8f4e66
+        if search_pdc:
8f4e66
+            flags = flags | nbt.NBT_SERVER_PDC
8f4e66
         try:
8f4e66
             if discover_srv:
8f4e66
-                result = netrc.finddc(domain=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)
8f4e66
+                result = netrc.finddc(domain=remote_host, flags=flags)
8f4e66
             else:
8f4e66
-                result = netrc.finddc(address=remote_host, flags=nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS)
8f4e66
+                result = netrc.finddc(address=remote_host, flags=flags)
8f4e66
         except RuntimeError, e:
8f4e66
             raise assess_dcerpc_exception(message=str(e))
8f4e66
 
8f4e66
@@ -726,6 +729,7 @@ class TrustDomainInstance(object):
8f4e66
         self.info['dns_forest'] = unicode(result.forest)
8f4e66
         self.info['guid'] = unicode(result.domain_uuid)
8f4e66
         self.info['dc'] = unicode(result.pdc_dns_name)
8f4e66
+        self.info['is_pdc'] = (result.server_type & nbt.NBT_SERVER_PDC) != 0
8f4e66
 
8f4e66
         # Netlogon response doesn't contain SID of the domain.
8f4e66
         # We need to do rootDSE search with LDAP_SERVER_EXTENDED_DN_OID control to reveal the SID
8f4e66
@@ -774,6 +778,13 @@ class TrustDomainInstance(object):
8f4e66
         self.info['sid'] = unicode(result.sid)
8f4e66
         self.info['dc'] = remote_host
8f4e66
 
8f4e66
+        try:
8f4e66
+            result = self._pipe.QueryInfoPolicy2(self._policy_handle, lsa.LSA_POLICY_INFO_ROLE)
8f4e66
+        except RuntimeError, (num, message):
8f4e66
+            raise assess_dcerpc_exception(num=num, message=message)
8f4e66
+
8f4e66
+        self.info['is_pdc'] = (result.role == lsa.LSA_ROLE_PRIMARY)
8f4e66
+
8f4e66
     def generate_auth(self, trustdom_secret):
8f4e66
         def arcfour_encrypt(key, data):
8f4e66
             c = RC4.RC4(key)
8f4e66
@@ -1069,9 +1080,9 @@ class TrustDomainJoins(object):
8f4e66
         rd.creds.set_anonymous()
8f4e66
         rd.creds.set_workstation(self.local_domain.hostname)
8f4e66
         if realm_server is None:
8f4e66
-            rd.retrieve_anonymously(realm, discover_srv=True)
8f4e66
+            rd.retrieve_anonymously(realm, discover_srv=True, search_pdc=True)
8f4e66
         else:
8f4e66
-            rd.retrieve_anonymously(realm_server, discover_srv=False)
8f4e66
+            rd.retrieve_anonymously(realm_server, discover_srv=False, search_pdc=True)
8f4e66
         rd.read_only = True
8f4e66
         if realm_admin and realm_passwd:
8f4e66
             if 'name' in rd.info:
8f4e66
-- 
8f4e66
1.9.3
8f4e66