Add verification of the AD trust

Since we only can perform verification when AD admin credentials are available,
report that trust should be verified from the AD side in other cases,
including unsuccessful verification.

Once trust is added, status of it is never stored anywhere.

https://fedorahosted.org/freeipa/ticket/2763
This commit is contained in:
Alexander Bokovoy
2012-09-13 20:01:55 +03:00
committed by Rob Crittenden
parent f0829efe1f
commit 7269687822
2 changed files with 35 additions and 8 deletions

View File

@@ -60,8 +60,8 @@ _trust_type_dict = {1 : _('Non-Active Directory domain'),
_trust_direction_dict = {1 : _('Trusting forest'),
2 : _('Trusted forest'),
3 : _('Two-way trust')}
_trust_status = {1 : _('Established and verified'),
2 : _('Waiting for confirmation by remote side')}
_trust_status_dict = {True : _('Established and verified'),
False : _('Waiting for confirmation by remote side')}
_trust_type_dict_unknown = _('Unknown')
def trust_type_string(level):
@@ -84,7 +84,7 @@ def trust_direction_string(level):
return unicode(string)
def trust_status_string(level):
string = _trust_direction_dict.get(int(level), _trust_type_dict_unknown)
string = _trust_status_dict.get(level, _trust_type_dict_unknown)
return unicode(string)
class trust(LDAPObject):
@@ -190,6 +190,8 @@ class trust_add(LDAPCreate):
result['result'] = trusts[0][1]
result['result']['trusttype'] = [trust_type_string(result['result']['ipanttrusttype'][0])]
result['result']['trustdirection'] = [trust_direction_string(result['result']['ipanttrustdirection'][0])]
result['result']['truststatus'] = [trust_status_string(result['verified'])]
del result['verified']
return result
@@ -272,14 +274,14 @@ class trust_add(LDAPCreate):
if result is None:
raise errors.ValidationError(name=_('AD Trust setup'), error=_('Unable to verify write permissions to the AD'))
return dict(result=dict(), value=trustinstance.remote_domain.info['dns_domain'])
return dict(value=trustinstance.remote_domain.info['dns_domain'], verified=result['verified'])
# 2. We don't have access to the remote domain and trustdom password
# is provided. Do the work on our side and inform what to do on remote
# side.
if 'trust_secret' in options:
result = trustinstance.join_ad_ipa_half(keys[-1], realm_server, options['trust_secret'])
return dict(result=dict(), value=trustinstance.remote_domain.info['dns_domain'])
return dict(value=trustinstance.remote_domain.info['dns_domain'], verified=result['verified'])
raise errors.ValidationError(name=_('AD Trust setup'), error=_('Not enough arguments specified to perform trust setup'))
class trust_del(LDAPDelete):

View File

@@ -35,7 +35,7 @@ import os, string, struct, copy
import uuid
from samba import param
from samba import credentials
from samba.dcerpc import security, lsa, drsblobs, nbt
from samba.dcerpc import security, lsa, drsblobs, nbt, netlogon
from samba.ndr import ndr_pack
from samba import net
import samba
@@ -217,6 +217,7 @@ class TrustDomainInstance(object):
if self._pipe is None:
raise errors.RemoteRetrieveError(
reason=_('Cannot establish LSA connection to %(host)s. Is CIFS server running?') % dict(host=remote_host))
self.binding = binding
def __gen_lsa_bindings(self, remote_host):
"""
@@ -251,6 +252,7 @@ class TrustDomainInstance(object):
self.info['dns_domain'] = unicode(result.dns_domain)
self.info['dns_forest'] = unicode(result.forest)
self.info['guid'] = unicode(result.domain_uuid)
self.info['dc'] = unicode(result.pdc_dns_name)
# Netlogon response doesn't contain SID of the domain.
# We need to do rootDSE search with LDAP_SERVER_EXTENDED_DN_OID control to reveal the SID
@@ -291,6 +293,7 @@ class TrustDomainInstance(object):
self.info['dns_forest'] = unicode(result.dns_forest.string)
self.info['guid'] = unicode(result.domain_guid)
self.info['sid'] = unicode(result.sid)
self.info['dc'] = remote_host
def generate_auth(self, trustdom_secret):
def arcfour_encrypt(key, data):
@@ -374,6 +377,27 @@ class TrustDomainInstance(object):
except RuntimeError, (num, message):
raise assess_dcerpc_exception(num=num, message=message)
def verify_trust(self, another_domain):
def retrieve_netlogon_info_2(domain, function_code, data):
try:
netr_pipe = netlogon.netlogon(domain.binding, domain.parm, domain.creds)
result = netr_pipe.netr_LogonControl2Ex(logon_server=None,
function_code=function_code,
level=2,
data=data
)
return result
except RuntimeError, (num, message):
raise assess_dcerpc_exception(num=num, message=message)
result = retrieve_netlogon_info_2(self,
netlogon.NETLOGON_CONTROL_TC_VERIFY,
another_domain.info['dns_domain'])
if (unicode(result.trusted_dc_name)[2:] == another_domain.info['dc'] and
result.tc_connection_status == (0, 'WERR_OK')):
return True
return False
class TrustDomainJoins(object):
def __init__(self, api):
self.api = api
@@ -447,7 +471,8 @@ class TrustDomainJoins(object):
trustdom_pass = samba.generate_random_password(128, 128)
self.remote_domain.establish_trust(self.local_domain, trustdom_pass)
self.local_domain.establish_trust(self.remote_domain, trustdom_pass)
return dict(local=self.local_domain, remote=self.remote_domain)
result = self.remote_domain.verify_trust(self.local_domain)
return dict(local=self.local_domain, remote=self.remote_domain, verified=result)
return None
def join_ad_ipa_half(self, realm, realm_server, trustdom_passwd):
@@ -456,4 +481,4 @@ class TrustDomainJoins(object):
self.__populate_remote_domain(realm, realm_server, realm_passwd=None)
self.local_domain.establish_trust(self.remote_domain, trustdom_passwd)
return dict(local=self.local_domain, remote=self.remote_domain)
return dict(local=self.local_domain, remote=self.remote_domain, verified=False)