summaryrefslogtreecommitdiffstats
path: root/ipaserver/dcerpc.py
diff options
context:
space:
mode:
authorAlexander Bokovoy <abokovoy@redhat.com>2016-06-06 08:55:44 +0300
committerMartin Basti <mbasti@redhat.com>2016-06-09 21:04:31 +0200
commit8ca7a4c94796afa280de7e7f5191b48ad667b219 (patch)
tree173c327c8c32ad790549af7973fa2052f9dcd379 /ipaserver/dcerpc.py
parent971b4bf009f051819d757d451e213c3c82de1c97 (diff)
downloadfreeipa-8ca7a4c94796afa280de7e7f5191b48ad667b219.tar.gz
freeipa-8ca7a4c94796afa280de7e7f5191b48ad667b219.tar.xz
freeipa-8ca7a4c94796afa280de7e7f5191b48ad667b219.zip
trusts: Add support for an external trust to Active Directory domain
External trust is a trust that can be created between Active Directory domains that are in different forests or between an Active Directory domain. Since FreeIPA does not support non-Kerberos means of communication, external trust to Windows NT 4.0 or earlier domains is not supported. The external trust is not transitive and can be established to any domain in another forest. This means no access beyond the external domain is possible via the trust link. Resolves: https://fedorahosted.org/freeipa/ticket/5743 Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
Diffstat (limited to 'ipaserver/dcerpc.py')
-rw-r--r--ipaserver/dcerpc.py50
1 files changed, 37 insertions, 13 deletions
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
index 25ffbfaea..e1921dc0c 100644
--- a/ipaserver/dcerpc.py
+++ b/ipaserver/dcerpc.py
@@ -77,6 +77,11 @@ and Samba4 python bindings.
TRUST_ONEWAY = 1
TRUST_BIDIRECTIONAL = 3
+# Trust join behavior
+# External trust -- allow creating trust to a non-root domain in the forest
+TRUST_JOIN_EXTERNAL = 1
+
+
def is_sid_valid(sid):
try:
security.dom_sid(sid)
@@ -1037,7 +1042,7 @@ class TrustDomainInstance(object):
# We can ignore the error here -- setting up name suffix routes may fail
pass
- def establish_trust(self, another_domain, trustdom_secret, trust_type='bidirectional'):
+ def establish_trust(self, another_domain, trustdom_secret, trust_type='bidirectional', trust_external=False):
"""
Establishes trust between our and another domain
Input: another_domain -- instance of TrustDomainInstance, initialized with #retrieve call
@@ -1060,6 +1065,8 @@ class TrustDomainInstance(object):
info.trust_direction |= lsa.LSA_TRUST_DIRECTION_OUTBOUND
info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
info.trust_attributes = 0
+ if trust_external:
+ info.trust_attributes |= lsa.LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
try:
dname = lsa.String()
@@ -1096,14 +1103,17 @@ class TrustDomainInstance(object):
# server as that one doesn't support AES encryption types
pass
- try:
- info = self._pipe.QueryTrustedDomainInfo(trustdom_handle, lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX)
- info.trust_attributes |= lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
- self._pipe.SetInformationTrustedDomain(trustdom_handle, lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX, info)
- except RuntimeError as e:
- root_logger.error('unable to set trust to transitive: %s' % (str(e)))
+ if not trust_external:
+ try:
+ info = self._pipe.QueryTrustedDomainInfo(trustdom_handle,
+ lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX)
+ info.trust_attributes |= lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
+ self._pipe.SetInformationTrustedDomain(trustdom_handle,
+ lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX, info)
+ except RuntimeError as e:
+ root_logger.error('unable to set trust transitivity status: %s' % (str(e)))
- if self.info['is_pdc']:
+ if self.info['is_pdc'] or trust_external:
self.update_ftinfo(another_domain)
def verify_trust(self, another_domain):
@@ -1262,6 +1272,7 @@ class TrustDomainJoins(object):
self.api = api
self.local_domain = None
self.remote_domain = None
+ self.__allow_behavior = 0
domain_validator = DomainValidator(api)
self.configured = domain_validator.is_configured()
@@ -1271,6 +1282,10 @@ class TrustDomainJoins(object):
self.local_dn = domain_validator.dn
self.__populate_local_domain()
+ def allow_behavior(self, *flags):
+ for f in flags:
+ self.__allow_behavior |= int(f)
+
def __populate_local_domain(self):
# Initialize local domain info using kerberos only
ld = TrustDomainInstance(self.local_flatname)
@@ -1358,14 +1373,19 @@ class TrustDomainJoins(object):
realm_passwd
)
+ trust_external = bool(self.__allow_behavior & TRUST_JOIN_EXTERNAL)
if self.remote_domain.info['dns_domain'] != self.remote_domain.info['dns_forest']:
- raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'], domain=self.remote_domain.info['dns_domain'])
+ if not trust_external:
+ raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'],
+ domain=self.remote_domain.info['dns_domain'])
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, trust_type)
- self.local_domain.establish_trust(self.remote_domain, trustdom_pass, trust_type)
+ self.remote_domain.establish_trust(self.local_domain,
+ trustdom_pass, trust_type, trust_external)
+ self.local_domain.establish_trust(self.remote_domain,
+ trustdom_pass, trust_type, trust_external)
# if trust is inbound, we don't need to verify it because AD DC will respond
# with WERR_NO_SUCH_DOMAIN -- in only does verification for outbound trusts.
result = True
@@ -1381,8 +1401,12 @@ class TrustDomainJoins(object):
if not(isinstance(self.remote_domain, TrustDomainInstance)):
self.populate_remote_domain(realm, realm_server, realm_passwd=None)
+ trust_external = bool(self.__allow_behavior & TRUST_JOIN_EXTERNAL)
if self.remote_domain.info['dns_domain'] != self.remote_domain.info['dns_forest']:
- raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'], domain=self.remote_domain.info['dns_domain'])
+ if not trust_external:
+ raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'],
+ domain=self.remote_domain.info['dns_domain'])
- self.local_domain.establish_trust(self.remote_domain, trustdom_passwd, trust_type)
+ self.local_domain.establish_trust(self.remote_domain,
+ trustdom_passwd, trust_type, trust_external)
return dict(local=self.local_domain, remote=self.remote_domain, verified=False)