[Freeipa-devel] [PATCH] 0114 ipa-sam: fix setting encryption type for trust object already created

Alexander Bokovoy abokovoy at redhat.com
Thu Sep 5 14:44:06 UTC 2013


Hi!

Attached please find a patch to clean up a mess we have with SID
blacklist handling in ipa-sam. I noticed recently that Windows does not
show IPA trusts as having AES encryption enabled. When investigating why
is that happening, I've found out that there is a set of errors causing
that but most important ones are the following two:

  - Wrong handle type was used to modify trust object information, and

  - SID blacklist handling in ipa-sam prevented LDAP updates from being
    correct which led to rejecting them by the LDAP server.

Attached patch should fix the problem, more details are in the commit
message.

https://fedorahosted.org/freeipa/ticket/3898

-- 
/ Alexander Bokovoy
-------------- next part --------------
From aa63ab5d61d6f19401fa04d673095f14a1b5d0d3 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy at redhat.com>
Date: Thu, 5 Sep 2013 08:13:53 +0300
Subject: [PATCH 1/3] ipa-sam: fix setting encryption type for trust object
 already created

When trust is established, last step done by IPA framework is to set
encryption types associated with the trust. This operation fails due
to ipa-sam attempting to modify trust object improperly:

 - object classes were changed unconditionally on each update
 - ACI entry was missing permission to modify SID blacklists
 - SID blacklists were reset on each update of the trust object
   using incorrect method which caused LDAP parsing errors at the
   server side due to multiple removals of the same value
 - trust POSIX offset value was not initialized which caused errors
   when fetching the trusted domain object in PDB. We don't use it yet
   but should initialize it to some default value (0 for now).

Since the same code is used to create and update trusted domain object in LDAP,
care should be taken to not remove/override those attributes that are set
on the initialization of the trusted domain object but never touched by the ipa-sam
anymore. SID blacklists are initialized by ipa-sam but used by Kerberos DAL driver
and managed by IPA framework.

Additionally, wrong handle was used by dcerpc.py code when executing
SetInformationTrustedDomain() against IPA smbd which prevented even to
reach the point where ipa-sam would be asked to modify the trust object.

https://fedorahosted.org/freeipa/ticket/3898
---
 daemons/ipa-sam/ipa_sam.c        | 82 +++++++++++++++++++++++++++-------------
 install/updates/60-trusts.update |  1 +
 ipaserver/dcerpc.py              |  9 +++++
 3 files changed, 65 insertions(+), 27 deletions(-)

diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
index 4a2fca5..a1e00dc 100644
--- a/daemons/ipa-sam/ipa_sam.c
+++ b/daemons/ipa-sam/ipa_sam.c
@@ -2229,11 +2229,14 @@ static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
 	LDAPMod **mods;
 	bool res;
 	char *trusted_dn = NULL;
-	int ret, i;
+	int ret, i, count;
 	NTSTATUS status;
 	TALLOC_CTX *tmp_ctx;
 	char *trustpw;
 	char *sid;
+	char **in_blacklist = NULL;
+	char **out_blacklist = NULL;
+	uint32_t enctypes, trust_offset;
 
 	DEBUG(10, ("ipasam_set_trusted_domain called for domain %s\n", domain));
 
@@ -2250,10 +2253,12 @@ static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
 	}
 
 	mods = NULL;
-	smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
-			 LDAP_OBJ_TRUSTED_DOMAIN);
-	smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
-			 LDAP_OBJ_ID_OBJECT);
+	if (entry == NULL) {
+		smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
+				 LDAP_OBJ_TRUSTED_DOMAIN);
+		smbldap_make_mod(priv2ld(ldap_state), entry, &mods, "objectClass",
+				 LDAP_OBJ_ID_OBJECT);
+	}
 
 	if (entry != NULL) {
 		sid = get_single_attribute(tmp_ctx, priv2ld(ldap_state), entry,
@@ -2314,26 +2319,37 @@ static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
 		}
 	}
 
+	trust_offset = 0;
 	if (td->trust_posix_offset != NULL) {
-		res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
-						&mods,
-						LDAP_ATTRIBUTE_TRUST_POSIX_OFFSET,
-						*td->trust_posix_offset);
-		if (!res) {
-			status = NT_STATUS_UNSUCCESSFUL;
-			goto done;
-		}
+		trust_offset = *td->trust_posix_offset;
 	}
 
+	res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
+					&mods,
+					LDAP_ATTRIBUTE_TRUST_POSIX_OFFSET,
+					trust_offset);
+	if (!res) {
+		status = NT_STATUS_UNSUCCESSFUL;
+		goto done;
+	}
+
+	enctypes = KERB_ENCTYPE_DES_CBC_CRC |
+		   KERB_ENCTYPE_DES_CBC_MD5 |
+		   KERB_ENCTYPE_RC4_HMAC_MD5 |
+		   KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 |
+		   KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96;
+
 	if (td->supported_enc_type != NULL) {
-		res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
-						&mods,
-						LDAP_ATTRIBUTE_SUPPORTED_ENC_TYPE,
-						*td->supported_enc_type);
-		if (!res) {
-			status = NT_STATUS_UNSUCCESSFUL;
-			goto done;
-		}
+		enctypes = *td->supported_enc_type;
+	}
+
+	res = smbldap_make_mod_uint32_t(priv2ld(ldap_state), entry,
+					&mods,
+					LDAP_ATTRIBUTE_SUPPORTED_ENC_TYPE,
+					enctypes);
+	if (!res) {
+		status = NT_STATUS_UNSUCCESSFUL;
+		goto done;
 	}
 
 	if (td->trust_auth_outgoing.data != NULL) {
@@ -2354,13 +2370,24 @@ static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
 				      &td->trust_forest_trust_info);
 	}
 
+
+	/* Only add default blacklists for incoming and outgoing SIDs but don't modify existing ones */
+	in_blacklist = get_attribute_values(tmp_ctx, ldap_state->smbldap_state->ldap_struct, entry,
+						LDAP_ATTRIBUTE_SID_BLACKLIST_INCOMING, &count);
+	out_blacklist = get_attribute_values(tmp_ctx, ldap_state->smbldap_state->ldap_struct, entry,
+						LDAP_ATTRIBUTE_SID_BLACKLIST_OUTGOING, &count);
+
 	for (i = 0; ipa_mspac_well_known_sids[i]; i++) {
-		smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
-				      LDAP_ATTRIBUTE_SID_BLACKLIST_INCOMING,
-				      ipa_mspac_well_known_sids[i]);
-		smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
-				      LDAP_ATTRIBUTE_SID_BLACKLIST_OUTGOING,
-				      ipa_mspac_well_known_sids[i]);
+		if (in_blacklist == NULL) {
+			smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+					      LDAP_ATTRIBUTE_SID_BLACKLIST_INCOMING,
+					      ipa_mspac_well_known_sids[i]);
+		}
+		if (out_blacklist == NULL) {
+			smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+					      LDAP_ATTRIBUTE_SID_BLACKLIST_OUTGOING,
+					      ipa_mspac_well_known_sids[i]);
+		}
 	}
 
 	smbldap_talloc_autofree_ldapmod(tmp_ctx, mods);
@@ -2370,6 +2397,7 @@ static NTSTATUS ipasam_set_trusted_domain(struct pdb_methods *methods,
 		status = NT_STATUS_NO_MEMORY;
 		goto done;
 	}
+
 	if (entry == NULL) {
 		ret = smbldap_add(ldap_state->smbldap_state, trusted_dn, mods);
 	} else {
diff --git a/install/updates/60-trusts.update b/install/updates/60-trusts.update
index 1b25115..46de01a 100644
--- a/install/updates/60-trusts.update
+++ b/install/updates/60-trusts.update
@@ -54,6 +54,7 @@ default: cn: trusts
 # 2. cn=trust admins,cn=groups,cn=accounts,$SUFFIX can manage trusts (via ipa tools)
 dn: cn=trusts,$SUFFIX
 add:aci: '(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "ipaNTTrustType || ipaNTTrustAttributes || ipaNTTrustDirection || ipaNTTrustPartner || ipaNTFlatName || ipaNTTrustAuthOutgoing || ipaNTTrustAuthIncoming || ipaNTSecurityIdentifier || ipaNTTrustForestTrustInfo || ipaNTTrustPosixOffset || ipaNTSupportedEncryptionTypes || krbPrincipalName || krbLastPwdChange || krbTicketFlags || krbLoginFailedCount || krbExtraData || krbPrincipalKey")(version 3.0;acl "Allow trust system user to create and delete trust accounts and cross realm principals"; allow (read,write,add,delete) groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";)'
+replace:aci:'(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "ipaNTTrustType || ipaNTTrustAttributes || ipaNTTrustDirection || ipaNTTrustPartner || ipaNTFlatName || ipaNTTrustAuthOutgoing || ipaNTTrustAuthIncoming || ipaNTSecurityIdentifier || ipaNTTrustForestTrustInfo || ipaNTTrustPosixOffset || ipaNTSupportedEncryptionTypes || krbPrincipalName || krbLastPwdChange || krbTicketFlags || krbLoginFailedCount || krbExtraData || krbPrincipalKey")(version 3.0;acl "Allow trust system user to create and delete trust accounts and cross realm principals"; allow (read,write,add,delete) groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";)::(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "ipaNTTrustType || ipaNTTrustAttributes || ipaNTTrustDirection || ipaNTTrustPartner || ipaNTFlatName || ipaNTTrustAuthOutgoing || ipaNTTrustAuthIncoming || ipaNTSecurityIdentifier || ipaNTTrustForestTrustInfo || ipaNTTrustPosixOffset || ipaNTSupportedEncryptionTypes || ipaNTSIDBlacklistIncoming || ipaNTSIDBlacklistOutgoing || krbPrincipalName || krbLastPwdChange || krbTicketFlags || krbLoginFailedCount || krbExtraData || krbPrincipalKey")(version 3.0;acl "Allow trust system user to create and delete trust accounts and cross realm principals"; allow (read,write,add,delete) groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";)'
 replace:aci:'(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "ipaNTTrustType || ipaNTTrustAttributes || ipaNTTrustDirection || ipaNTTrustPartner || ipaNTFlatName || ipaNTTrustAuthOutgoing || ipaNTTrustAuthIncoming || ipaNTSecurityIdentifier || ipaNTTrustForestTrustInfo || ipaNTTrustPosixOffset || ipaNTSupportedEncryptionTypes")(version 3.0;acl "Allow trust admins manage trust accounts"; allow (read,write,add,delete) groupdn="ldap:///cn=trust admins,cn=groups,cn=accounts,$SUFFIX";)::(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "ipaNTTrustType || ipaNTTrustAttributes || ipaNTTrustDirection || ipaNTTrustPartner || ipaNTFlatName || ipaNTTrustAuthOutgoing || ipaNTTrustAuthIncoming || ipaNTSecurityIdentifier || ipaNTTrustForestTrustInfo || ipaNTTrustPosixOffset || ipaNTSupportedEncryptionTypes || ipaNTSIDBlacklistIncoming || ipaNTSIDBlacklistOutgoing")(version 3.0;acl "Allow trust admins manage trust accounts"; allow (read,write,add,delete) groupdn="ldap:///cn=trust admins,cn=groups,cn=accounts,$SUFFIX";)'
 add:aci: '(target = "ldap:///cn=trusts,$SUFFIX")(targetattr = "ipaNTTrustType || ipaNTTrustAttributes || ipaNTTrustDirection || ipaNTTrustPartner || ipaNTFlatName || ipaNTTrustAuthOutgoing || ipaNTTrustAuthIncoming || ipaNTSecurityIdentifier || ipaNTTrustForestTrustInfo || ipaNTTrustPosixOffset || ipaNTSupportedEncryptionTypes || ipaNTSIDBlacklistIncoming || ipaNTSIDBlacklistOutgoing")(version 3.0;acl "Allow trust admins manage trust accounts"; allow (read,write,add,delete) groupdn="ldap:///cn=trust admins,cn=groups,cn=accounts,$SUFFIX";)'
 
diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py
index a27a64d..bd8f5aa 100644
--- a/ipaserver/dcerpc.py
+++ b/ipaserver/dcerpc.py
@@ -912,12 +912,21 @@ class TrustDomainInstance(object):
             raise assess_dcerpc_exception(num=num, message=message)
 
         try:
+            # We should use proper trustdom handle in order to modify the
+            # trust settings. Samba insists this has to be done with LSA
+            # OpenTrustedDomain* calls, it is not enough to have a handle
+            # returned by the CreateTrustedDomainEx2 call.
+            trustdom_handle = self._pipe.OpenTrustedDomainByName(self._policy_handle, dname, security.SEC_FLAG_MAXIMUM_ALLOWED)
             infoclass = lsa.TrustDomainInfoSupportedEncTypes()
             infoclass.enc_types = security.KERB_ENCTYPE_RC4_HMAC_MD5
             infoclass.enc_types |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96
             infoclass.enc_types |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96
             self._pipe.SetInformationTrustedDomain(trustdom_handle, lsa.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES, infoclass)
         except RuntimeError, e:
+            # We can ignore the error here -- changing enctypes is for
+            # improved security but the trust will work with default values as
+            # well. In particular, the call may fail against Windows 2003
+            # server as that one doesn't support AES encryption types
             pass
 
     def verify_trust(self, another_domain):
-- 
1.8.3.1



More information about the Freeipa-devel mailing list