summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Bokovoy <abokovoy@redhat.com>2015-08-13 17:18:57 +0300
committerMartin Basti <mbasti@redhat.com>2015-08-18 18:48:12 +0200
commitc30baa9bb9dfa5a5de7685e9203f3eae95dec22a (patch)
treefd5674e23740f4e77217519ad6a59a2522a93e29
parentbfe937715236e71037f05885293afb3d1c8d2227 (diff)
downloadfreeipa-c30baa9bb9dfa5a5de7685e9203f3eae95dec22a.tar.gz
freeipa-c30baa9bb9dfa5a5de7685e9203f3eae95dec22a.tar.xz
freeipa-c30baa9bb9dfa5a5de7685e9203f3eae95dec22a.zip
trusts: harden trust-fetch-domains oddjobd-based script
When ipa-getkeytab is used to fetch trusted domain object credentials, the fetched entry has always kvno 1. ipa-getkeytab always adds a key to keytab which means older key versions will be in the SSSD keytab and will confuse libkrb5 ccache initialization code as all kvno values are equal to 1. Wrong key is picked up then and kinit fails. To solve this problem, always remove existing /var/lib/sss/keytabs/forest.keytab before retrieving a new one. To make sure script's input cannot be used to define what should be removed (by passing a relative path), make sure we retrieve trusted forest name from LDAP. If it is not possible to retrieve, the script will issue an exception and quit. If abrtd is running, this will be recorded as a 'crash' and an attempt to use script by malicious user would be recorded as well in the abrtd journal. Additionally, as com.redhat.idm.trust-fetch-domains will create ID ranges for the domains of the trusted forest if they don't exist, it needs permissions to do so. The permission should be granted only to cifs/ipa.master@IPA.REALM services which means they must have krbprincipalname=cifs/*@IPA.REALM,cn=services,... DN and be members of cn=adtrust agents,cn=sysaccounts,... group. Solves https://bugzilla.redhat.com/show_bug.cgi?id=1250190 Ticket https://fedorahosted.org/freeipa/ticket/5182 Reviewed-By: Tomas Babej <tbabej@redhat.com>
-rwxr-xr-xinstall/oddjob/com.redhat.idm.trust-fetch-domains29
-rw-r--r--install/updates/20-aci.update4
2 files changed, 28 insertions, 5 deletions
diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains b/install/oddjob/com.redhat.idm.trust-fetch-domains
index e50c81e50..6a2171d5f 100755
--- a/install/oddjob/com.redhat.idm.trust-fetch-domains
+++ b/install/oddjob/com.redhat.idm.trust-fetch-domains
@@ -41,6 +41,9 @@ def retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal):
"-p", oneway_principal,
"-k", oneway_keytab_name,
"-r"]
+ if os.path.isfile(oneway_keytab_name):
+ os.unlink(oneway_keytab_name)
+
(stdout, stderr, retcode) = ipautil.run(getkeytab_args,
env={'KRB5CCNAME': ccache_name, 'LANG': 'C'},
raiseonerr=False)
@@ -111,7 +114,6 @@ from ipalib.plugins import trust
# retrieve the keys to oneway_keytab_name.
keytab_name = '/etc/samba/samba.keytab'
-oneway_keytab_name = '/var/lib/sss/keytabs/' + trusted_domain + '.keytab'
principal = str('cifs/' + api.env.host)
@@ -137,10 +139,20 @@ else:
old_ccache = os.environ.get('KRB5CCNAME')
api.Backend.ldap2.connect(ccache)
+# Retrieve own NetBIOS name and trusted forest's name.
+# We use script's input to retrieve the trusted forest's name to sanitize input
+# for file-level access as we might need to wipe out keytab in /var/lib/sss/keytabs
own_trust_dn = DN(('cn', api.env.domain),('cn','ad'), ('cn', 'etc'), api.env.basedn)
own_trust_entry = api.Backend.ldap2.get_entry(own_trust_dn, ['ipantflatname'])
-own_trust_flatname = own_trust_entry['ipantflatname'][0].upper()
+own_trust_flatname = own_trust_entry.single_value.get('ipantflatname').upper()
+trusted_domain_dn = DN(('cn', trusted_domain.lower()), api.env.container_adtrusts, api.env.basedn)
+trusted_domain_entry = api.Backend.ldap2.get_entry(trusted_domain_dn, ['cn'])
+trusted_domain = trusted_domain_entry.single_value.get('cn').lower()
+# At this point if we didn't find trusted forest name, an exception will be raised
+# and script will quit. This is actually intended.
+
+oneway_keytab_name = '/var/lib/sss/keytabs/' + trusted_domain + '.keytab'
oneway_principal = str('%s$@%s' % (own_trust_flatname, trusted_domain.upper()))
# If keytab does not exist, retrieve it
@@ -152,11 +164,18 @@ try:
# The keytab may have stale key material (from older trust-add run)
if not os.path.isfile(oneway_ccache_name):
oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
+ else:
+ oneway_ccache_check = KRB5_CCache(oneway_ccache_name)
+ if not oneway_ccache_check.credential_is_valid(oneway_principal):
+ # If credentials were invalid, obtain them again
+ oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
+ else:
+ oneway_ccache = oneway_ccache_check.ccache
except krbV.Krb5Error as e:
# If there was failure on using keytab, assume it is stale and retrieve again
retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal)
-if oneway_ccache:
+try:
# There wasn existing ccache, validate its content
oneway_ccache_check = KRB5_CCache(oneway_ccache_name)
if not oneway_ccache_check.credential_is_valid(oneway_principal):
@@ -164,7 +183,7 @@ if oneway_ccache:
oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
else:
oneway_ccache = oneway_ccache_check.ccache
-else:
+except krbV.Krb5Error as e:
oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name)
# We are done: we have ccache with TDO credentials and can fetch domains
@@ -193,7 +212,7 @@ if domains:
dom['range_type'] = u'ipa-ad-trust'
# Do not pass ipaserver.dcerpc.TrustInstance to trust.add_range
# to force it using existing credentials cache
- trust.add_range(None, range_name, dom['ipanttrusteddomainsid'],
+ trust.add_range(api, None, range_name, dom['ipanttrusteddomainsid'],
trusted_domain, name, **dom)
except errors.DuplicateEntry:
# Ignore updating duplicate entries
diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update
index 0bdeeb6ac..cba1897e1 100644
--- a/install/updates/20-aci.update
+++ b/install/updates/20-aci.update
@@ -87,3 +87,7 @@ add:aci:(targetattr = "usercertificate")(version 3.0;acl "selfservice:Users can
# Hosts can add their own services
dn: cn=services,cn=accounts,$SUFFIX
add:aci: (target = "ldap:///krbprincipalname=*/($$dn)@$REALM,cn=services,cn=accounts,$SUFFIX")(targetfilter = "(objectClass=ipaKrbPrincipal)")(version 3.0;acl "Hosts can add own services"; allow(add) userdn="ldap:///fqdn=($$dn),cn=computers,cn=accounts,$SUFFIX";)
+
+# CIFS service on the master can manage ID ranges
+dn: cn=ranges,cn=etc,$SUFFIX
+add:aci: (target = "ldap:///cn=*,cn=ranges,cn=etc,$SUFFIX")(targetfilter = "(objectClass=ipaIDrange)")(version 3.0;acl "CIFS service can manage ID ranges for trust"; allow(all) userdn="ldap:///krbprincipalname=cifs/*@$REALM,cn=services,cn=accounts,$SUFFIX" and groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";)