diff options
author | Alexander Bokovoy <abokovoy@redhat.com> | 2015-07-06 14:46:24 +0000 |
---|---|---|
committer | Tomas Babej <tbabej@redhat.com> | 2015-07-08 01:56:52 +0200 |
commit | 2dd5b46d257eb03188fcfb21997e9348bc0e3f4d (patch) | |
tree | e95ce08123cc28ff2369d50c8ad090289456f7a5 /ipaserver/dcerpc.py | |
parent | 5025204175fad221a74befa7dc52087fcd0751c6 (diff) | |
download | freeipa-2dd5b46d257eb03188fcfb21997e9348bc0e3f4d.tar.gz freeipa-2dd5b46d257eb03188fcfb21997e9348bc0e3f4d.tar.xz freeipa-2dd5b46d257eb03188fcfb21997e9348bc0e3f4d.zip |
trust: support retrieving POSIX IDs with one-way trust during trust-add
With one-way trust we cannot rely on cross-realm TGT as there will be none.
Thus, if we have AD administrator credentials we should reuse them.
Additionally, such use should be done over Kerberos.
Fixes:
https://fedorahosted.org/freeipa/ticket/4960
https://fedorahosted.org/freeipa/ticket/4959
Reviewed-By: Tomas Babej <tbabej@redhat.com>
Diffstat (limited to 'ipaserver/dcerpc.py')
-rw-r--r-- | ipaserver/dcerpc.py | 83 |
1 files changed, 65 insertions, 18 deletions
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py index bfdfe2c5d..a1da0a641 100644 --- a/ipaserver/dcerpc.py +++ b/ipaserver/dcerpc.py @@ -151,6 +151,7 @@ class DomainValidator(object): self._domains = None self._info = dict() self._creds = None + self._admin_creds = None self._parm = None def is_configured(self): @@ -565,6 +566,52 @@ class DomainValidator(object): % (stdout, stderr)) return (None, None) + def kinit_as_administrator(self, domain): + """ + Initializes ccache with http service credentials. + + Applies session code defaults for ccache directory and naming prefix. + Session code uses krbccache_prefix+<pid>, we use + krbccache_prefix+<TD>+<domain netbios name> so there is no clash. + + Returns tuple (ccache path, principal) where (None, None) signifes an + error on ccache initialization + """ + + if self._admin_creds == None: + return (None, None) + + domain_suffix = domain.replace('.', '-') + + ccache_name = "%sTDA%s" % (krbccache_prefix, domain_suffix) + ccache_path = os.path.join(krbccache_dir, ccache_name) + + (principal, password) = self._admin_creds.split('%', 1) + + # Destroy the contents of the ccache + root_logger.debug('Destroying the contents of the separate ccache') + + (stdout, stderr, returncode) = ipautil.run( + [paths.KDESTROY, '-A', '-c', ccache_path], + env={'KRB5CCNAME': ccache_path}, + raiseonerr=False) + + # Destroy the contents of the ccache + root_logger.debug('Running kinit with credentials of AD administrator') + + (stdout, stderr, returncode) = ipautil.run( + [paths.KINIT, principal], + env={'KRB5CCNAME': ccache_path}, + stdin=password, + raiseonerr=False) + + if returncode == 0: + return (ccache_path, principal) + else: + root_logger.debug('Kinit failed, stout: %s, stderr: %s' + % (stdout, stderr)) + return (None, None) + def search_in_dc(self, domain, filter, attrs, scope, basedn=None, quiet=False): """ @@ -597,7 +644,8 @@ class DomainValidator(object): Returns LDAP result or None. """ - (ccache_name, principal) = self.kinit_as_http(info['dns_domain']) + if self._admin_creds: + (ccache_name, principal) = self.kinit_as_administrator(info['dns_domain']) if ccache_name: with ipautil.private_ccache(path=ccache_name): @@ -1106,10 +1154,24 @@ def fetch_domains(api, mydomain, trustdomain, creds=None, server=None): raise assess_dcerpc_exception(message=str(e)) td.info['dc'] = unicode(result.pdc_dns_name) - if creds is None: + if type(creds) is bool: + # Rely on existing Kerberos credentials in the environment + td.creds = credentials.Credentials() + td.creds.set_kerberos_state(credentials.MUST_USE_KERBEROS) + td.creds.guess(td.parm) + td.creds.set_workstation(domain_validator.flatname) + domains = communicate(td) + else: # Attempt to authenticate as HTTP/ipa.master and use cross-forest trust + # or as passed-in user in case of a one-way trust domval = DomainValidator(api) - (ccache_name, principal) = domval.kinit_as_http(trustdomain) + ccache_name = None + principal = None + if creds: + domval._admin_creds = creds + (ccache_name, principal) = domval.kinit_as_administrator(trustdomain) + else: + (ccache_name, principal) = domval.kinit_as_http(trustdomain) td.creds = credentials.Credentials() td.creds.set_kerberos_state(credentials.MUST_USE_KERBEROS) if ccache_name: @@ -1117,21 +1179,6 @@ def fetch_domains(api, mydomain, trustdomain, creds=None, server=None): td.creds.guess(td.parm) td.creds.set_workstation(domain_validator.flatname) domains = communicate(td) - elif type(creds) is bool: - # Rely on existing Kerberos credentials in the environment - td.creds = credentials.Credentials() - td.creds.set_kerberos_state(credentials.MUST_USE_KERBEROS) - td.creds.guess(td.parm) - td.creds.set_workstation(domain_validator.flatname) - domains = communicate(td) - else: - # Assume we've got credentials as a string user%password - td.creds = credentials.Credentials() - td.creds.set_kerberos_state(credentials.DONT_USE_KERBEROS) - td.creds.guess(td.parm) - td.creds.parse_string(creds) - td.creds.set_workstation(domain_validator.flatname) - domains = communicate(td) if domains is None: return None |