e3ffab
From 6d3e68480293b50cf3ac40ad09f3ab48de764089 Mon Sep 17 00:00:00 2001
e3ffab
From: Alexander Bokovoy <abokovoy@redhat.com>
e3ffab
Date: Mon, 24 Nov 2014 15:07:49 +0200
e3ffab
Subject: [PATCH] AD trust: improve trust validation
e3ffab
e3ffab
Trust validation requires AD DC to contact IPA server to verify that trust account
e3ffab
actually works. It can fail due to DNS or firewall issue or if AD DC was able to
e3ffab
resolve IPA master(s) via SRV records, it still may contact a replica that has
e3ffab
no trust data replicated yet.
e3ffab
e3ffab
In case AD DC still returns 'access denied', wait 5 seconds and try validation again.
e3ffab
Repeat validation until we hit a limit of 10 attempts, at which point raise
e3ffab
exception telling what's happening.
e3ffab
e3ffab
https://fedorahosted.org/freeipa/ticket/4764
e3ffab
e3ffab
Reviewed-By: Tomas Babej <tbabej@redhat.com>
e3ffab
---
e3ffab
 ipaserver/dcerpc.py | 19 ++++++++++++++++---
e3ffab
 1 file changed, 16 insertions(+), 3 deletions(-)
e3ffab
e3ffab
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
e3ffab
index caeca3c4ab357193aef4d0e6a373240acfdf1993..e342c4973746a113c0ad4f15a1e6050583461ccf 100644
e3ffab
--- a/ipaserver/dcerpc.py
e3ffab
+++ b/ipaserver/dcerpc.py
e3ffab
@@ -58,6 +58,7 @@ import pysss
e3ffab
 from ipaplatform.paths import paths
e3ffab
 
e3ffab
 from ldap.filter import escape_filter_chars
e3ffab
+from time import sleep
e3ffab
 
e3ffab
 __doc__ = _("""
e3ffab
 Classes to manage trust joins using DCE-RPC calls
e3ffab
@@ -93,6 +94,8 @@ dcerpc_error_codes = {
e3ffab
 dcerpc_error_messages = {
e3ffab
     "NT_STATUS_OBJECT_NAME_NOT_FOUND":
e3ffab
          errors.NotFound(reason=_('Cannot find specified domain or server name')),
e3ffab
+    "WERR_NO_LOGON_SERVERS":
e3ffab
+         errors.RemoteRetrieveError(reason=_('AD DC was unable to reach any IPA domain controller. Most likely it is a DNS or firewall issue')),
e3ffab
     "NT_STATUS_INVALID_PARAMETER_MIX":
e3ffab
          errors.RequirementError(name=_('At least the domain or IP address should be specified')),
e3ffab
 }
e3ffab
@@ -699,6 +702,7 @@ class TrustDomainInstance(object):
e3ffab
         self._policy_handle = None
e3ffab
         self.read_only = False
e3ffab
         self.ftinfo_records = None
e3ffab
+        self.validation_attempts = 0
e3ffab
 
e3ffab
     def __gen_lsa_connection(self, binding):
e3ffab
        if self.creds is None:
e3ffab
@@ -1011,9 +1015,18 @@ class TrustDomainInstance(object):
e3ffab
                                           netlogon.NETLOGON_CONTROL_TC_VERIFY,
e3ffab
                                           another_domain.info['dns_domain'])
e3ffab
         if (result and (result.flags and netlogon.NETLOGON_VERIFY_STATUS_RETURNED)):
e3ffab
-            # netr_LogonControl2Ex() returns non-None result only if overall call
e3ffab
-            # result was WERR_OK which means verification was correct.
e3ffab
-            # We only check that it was indeed status for verification process
e3ffab
+            if (result.pdc_connection_status[0] != 0) and (result.tc_connection_status[0] != 0):
e3ffab
+                if result.pdc_connection_status[1] == "WERR_ACCESS_DENIED":
e3ffab
+                    # Most likely AD DC hit another IPA replica which yet has no trust secret replicated
e3ffab
+                    # Sleep and repeat again
e3ffab
+                    self.validation_attempts += 1
e3ffab
+                    if self.validation_attempts < 10:
e3ffab
+                        sleep(5)
e3ffab
+                        return self.verify_trust(another_domain)
e3ffab
+                    raise errors.ACIError(reason=_('IPA master denied trust validation requests from AD DC '
e3ffab
+                                                   '%(count)d times. Most likely AD DC contacted a replica '
e3ffab
+                                                   'that has no trust information replicated yet.' % (self.validation_attempts)))
e3ffab
+                raise assess_dcerpc_exception(*result.pdc_connection_status)
e3ffab
             return True
e3ffab
         return False
e3ffab
 
e3ffab
-- 
e3ffab
2.1.0
e3ffab