The first patch is preparatory and is needed in general now that we want
top allow alias and use krbCanonicalName as the canonical name when
multiple values are avilable in krbPrincipalName.

The second patch changes slightly how the interdomain trust account is
created so that the getkeytab control can generate the proper key (with
the right salt) for interop reasons with AD. The change should be
upgrade safe because keys are generate at account creation so older
accounts lacking the alias won't be a problem.

Fixes ##5495

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York
From e13bb47a9e3673bb7af627bfb2bc59476552947e Mon Sep 17 00:00:00 2001
From: Simo Sorce <s...@redhat.com>
Date: Wed, 2 Dec 2015 15:20:42 -0500
Subject: [PATCH 1/2] Improve keytab code to select the right principal.

Whe requesting a keytab the salt used is the NORMAL type (for backwards and AD
compatibility), however since we added alias support we need to search for the
krbCanonicalName in preference, hen nothing is specified, and for the requested
principal name when a getkeytab operation is performed. This is so that the
correct salt can be applied. (Windows AD uses some peculiar aliases for some
special accounts to generate the salt).

Signed-off-by: Simo Sorce <s...@redhat.com>
---
 daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c | 23 +++++++++++++++-------
 .../ipa-pwd-extop/ipa_pwd_extop.c                  |  3 ++-
 daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h   |  1 +
 daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c  |  2 +-
 4 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c
index 5ca155dcf49923b06bdd1ea56c5fba8fff5e410e..9c62f0560aa999b2179a7767040047dfa89288e0 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c
@@ -104,6 +104,7 @@ void ipapwd_keyset_free(struct ipapwd_keyset **pkset)
 
 Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
                                         struct ipapwd_data *data,
+                                        char *preferred_principal,
                                         int num_encsalts,
                                         krb5_key_salt_tuple *encsalts,
                                         char **errMesg)
@@ -128,12 +129,20 @@ Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
 
     kvno = ipapwd_get_cur_kvno(data->target);
 
-    krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
-                                                    "krbPrincipalName");
-    if (!krbPrincipalName) {
-        *errMesg = "no krbPrincipalName present in this entry\n";
-        LOG_FATAL("%s", *errMesg);
-        goto enc_error;
+    if (preferred_principal) {
+        krbPrincipalName = slapi_ch_strdup(preferred_principal);
+    } else {
+        krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
+                                                        "krbCanonicalName");
+        if (!krbPrincipalName) {
+            krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
+                                                        "krbPrincipalName");
+        }
+        if (!krbPrincipalName) {
+            *errMesg = "no krbPrincipalName present in this entry\n";
+            LOG_FATAL("%s", *errMesg);
+            goto enc_error;
+        }
     }
 
     krberr = krb5_parse_name(krbctx, krbPrincipalName, &princ);
@@ -215,7 +224,7 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
 
     if (is_krb) {
 
-        *svals = ipapwd_encrypt_encode_key(krbcfg, data,
+        *svals = ipapwd_encrypt_encode_key(krbcfg, data, NULL,
                                            krbcfg->num_pref_encsalts,
                                            krbcfg->pref_encsalts,
                                            errMesg);
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
index a910625cea711ca8c564f3c547a1d61788b071be..527238b1b710dfe63d90338ccf806c86c8d9cf6c 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
@@ -661,6 +661,7 @@ static Slapi_Entry *get_entry_by_principal(const char *principal)
     Slapi_PBlock *pb = NULL;
     char *attrlist[] = { "krbPrincipalKey", "krbLastPwdChange",
                          "userPassword", "krbPrincipalName",
+                         "krbCanonicalName",
                          "enrolledBy", "objectClass", NULL };
     Slapi_Entry **es = NULL;
     int res, ret, i;
@@ -1664,7 +1665,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
         data.target = target_entry;
         data.password = password;
 
-        svals = ipapwd_encrypt_encode_key(krbcfg, &data,
+        svals = ipapwd_encrypt_encode_key(krbcfg, &data, service_name,
                                           kenctypes ? num_kenctypes :
                                                 krbcfg->num_pref_encsalts,
                                           kenctypes ? kenctypes :
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
index 36366949633ab5faf331991f0e1994f7432b2f38..33c36fd39adae26069189ef2de48040eae178522 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
@@ -145,6 +145,7 @@ void ipapwd_keyset_free(struct ipapwd_keyset **pkset);
 
 Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
                                         struct ipapwd_data *data,
+                                        char *preferred_principal,
                                         int num_encsalts,
                                         krb5_key_salt_tuple *encsalts,
                                         char **errMesg);
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
index f830e3bfe14d025724d74b6890cca743c480f264..c1fc7fe3345e227054b8118b35d8f504fe957ea6 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
@@ -1386,7 +1386,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
     static const char *attrs_list[] = {
         SLAPI_USERPWD_ATTR, "ipaUserAuthType", "krbprincipalkey", "uid",
         "krbprincipalname", "objectclass", "passwordexpirationtime",
-        "passwordhistory", "krbprincipalexpiration",
+        "passwordhistory", "krbprincipalexpiration", "krbcanonicalname",
         NULL
     };
     struct berval *credentials = NULL;
-- 
2.5.0

From b384d65b20f88c11ac9dd637ea54ea35bbe636a6 Mon Sep 17 00:00:00 2001
From: Simo Sorce <s...@redhat.com>
Date: Tue, 1 Dec 2015 13:43:35 -0500
Subject: [PATCH 2/2] Convert ipa-sam to use the new getkeytab control

Signed-off-by: Simo Sorce <s...@redhat.com>

Ticket: https://fedorahosted.org/freeipa/ticket/5495
---
 daemons/ipa-sam/Makefile.am      |  3 ++
 daemons/ipa-sam/ipa_sam.c        | 81 ++++++++++++++--------------------------
 install/updates/60-trusts.update |  1 +
 3 files changed, 33 insertions(+), 52 deletions(-)

diff --git a/daemons/ipa-sam/Makefile.am b/daemons/ipa-sam/Makefile.am
index 46c813af5caf37b43fbdc3eef7189544e47cf357..ea14661b6eb5ef4fe3502a5a6a1fe59b37110aeb 100644
--- a/daemons/ipa-sam/Makefile.am
+++ b/daemons/ipa-sam/Makefile.am
@@ -8,10 +8,12 @@ SAMBA40EXTRA_LIBS = $(SAMBA40EXTRA_LIBPATH)	\
 
 KRB5_UTIL_DIR=../../util
 KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
+ASN1_UTIL_DIR=../../asn1
 
 AM_CPPFLAGS =						\
 	-I.						\
 	-I$(srcdir)					\
+	-I$(ASN1_UTIL_DIR)				\
 	-I/usr/include/samba-4.0			\
 	-DPREFIX=\""$(prefix)"\" 			\
 	-DBINDIR=\""$(bindir)"\"			\
@@ -54,6 +56,7 @@ ipasam_la_LIBADD = 		\
 	$(NDR_LIBS)		\
 	$(SAMBA40EXTRA_LIBS)	\
 	$(SSSIDMAP_LIBS)	\
+	$(ASN1_UTIL_DIR)/libipaasn1.la  \
 	$(NULL)
 
 EXTRA_DIST =			\
diff --git a/daemons/ipa-sam/ipa_sam.c b/daemons/ipa-sam/ipa_sam.c
index 7274d600b532f1066661e8a614a47eea7632ed70..ff053813f6d978aad02d95d47dd20b7e9adbef5f 100644
--- a/daemons/ipa-sam/ipa_sam.c
+++ b/daemons/ipa-sam/ipa_sam.c
@@ -31,7 +31,7 @@
 #include <sasl/sasl.h>
 #include <krb5/krb5.h>
 #include <sss_idmap.h>
-#include "ipa_krb5.h"
+#include "ipa_asn1.h"
 #include "ipa_pwd.h"
 #include "ipa_mspac.h"
 
@@ -146,6 +146,7 @@ void idmap_cache_set_sid2unixid(const struct dom_sid *sid, struct unixid *unix_i
 #define LDAP_OBJ_KRB_PRINCIPAL "krbPrincipal"
 #define LDAP_OBJ_KRB_PRINCIPAL_AUX "krbPrincipalAux"
 #define LDAP_OBJ_KRB_TICKET_POLICY_AUX "krbTicketPolicyAux"
+#define LDAP_ATTRIBUTE_KRB_CANONICAL "krbCanonicalName"
 #define LDAP_ATTRIBUTE_KRB_PRINCIPAL "krbPrincipalName"
 #define LDAP_ATTRIBUTE_KRB_TICKET_FLAGS "krbTicketFlags"
 #define LDAP_ATTRIBUTE_IPAOPALLOW "ipaAllowedToPerform;read_keys"
@@ -1686,66 +1687,41 @@ static bool search_krb_princ(struct ldapsam_privates *ldap_state,
 	return true;
 }
 
-#define KRB_PRINC_DEFAULT_ENCTYPES "aes256-cts-hmac-sha1-96,aes128-cts-hmac-sha1-96,arcfour-hmac"
+#define DEF_ENCTYPE_NUM 3
+long default_enctypes[DEF_ENCTYPE_NUM] = {
+    ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+    ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+    ENCTYPE_ARCFOUR_HMAC
+};
 
 static int set_cross_realm_pw(struct ldapsam_privates *ldap_state,
-			      TALLOC_CTX *mem_ctx,
 			      const char *princ,
-			      const char *saltprinc,
-			      const char *pwd,
-			      const char *base_dn)
+			      const char *pwd)
 {
-
 	int ret;
-	krb5_error_code krberr;
-	krb5_context krbctx;
-	krb5_principal service_princ;
-	struct keys_container keys = {0, NULL};
-	char *err_msg;
-	struct berval *reqdata = NULL;
+        size_t buflen;
+        void *buffer = NULL;
+	struct berval reqdata = { 0 };
 	struct berval *retdata = NULL;
         char *retoid;
 
-	krberr = krb5_init_context(&krbctx);
-	if (krberr != 0) {
-		DEBUG(1, ("krb5_init_context failed.\n"));
-		ret = krberr;
-		goto done;
-	}
+        ret = ipaasn1_enc_getkt(true, princ, pwd,
+                                default_enctypes, DEF_ENCTYPE_NUM,
+                                &buffer, &buflen);
+        if (!ret) goto done;
 
-	krberr = krb5_parse_name(krbctx, (saltprinc != NULL) ? saltprinc : princ, &service_princ);
-	if (krberr != 0) {
-		DEBUG(1, ("Invalid Service Principal Name [%s]\n", princ));
-		ret = krberr;
-		goto done;
-	}
-
-	ret = create_keys(krbctx, service_princ, discard_const(pwd), KRB_PRINC_DEFAULT_ENCTYPES,
-                          &keys, &err_msg);
-	krb5_free_principal(krbctx, service_princ);
-	if (!ret) {
-		if (err_msg != NULL) {
-			DEBUG(1, ("create_keys returned [%s]\n", err_msg));
-		}
-		goto done;
-	}
-
-	reqdata = create_key_control(&keys, princ);
-	if (reqdata == NULL) {
-		DEBUG(1, ("Failed to create reqdata!\n"));
-		ret= ENOMEM;
-		goto done;
-	}
+        reqdata.bv_len = buflen;
+        reqdata.bv_val = buffer;
 
 	ret = smbldap_extended_operation(ldap_state->smbldap_state,
-					 KEYTAB_SET_OID, reqdata, NULL, NULL,
+					 KEYTAB_GET_OID, &reqdata, NULL, NULL,
 					 &retoid, &retdata);
 	if (ret != LDAP_SUCCESS) {
 		DEBUG(1, ("smbldap_extended_operation failed!\n"));
 		goto done;
 	}
 
-	/* So far we do not care abot the result */
+	/* So far we do not care about the result */
 	ldap_memfree(retoid);
 	if (retdata != NULL) {
 		ber_bvfree(retdata);
@@ -1753,12 +1729,7 @@ static int set_cross_realm_pw(struct ldapsam_privates *ldap_state,
 
 	ret = 0;
 done:
-	if (reqdata != NULL) {
-	    ber_bvfree(reqdata);
-	}
-	free_keys_contents(krbctx, &keys);
-	krb5_free_context(krbctx);
-
+        free(buffer);
 	return ret;
 }
 
@@ -1822,8 +1793,14 @@ static bool set_krb_princ(struct ldapsam_privates *ldap_state,
 				LDAP_OBJ_KRB_TICKET_POLICY_AUX);
 	}
 
-	smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
+	smbldap_set_mod(&mods, LDAP_MOD_ADD,
+			 LDAP_ATTRIBUTE_KRB_CANONICAL, princ);
+	smbldap_set_mod(&mods, LDAP_MOD_ADD,
 			 LDAP_ATTRIBUTE_KRB_PRINCIPAL, princ);
+        if (saltprinc) {
+	    smbldap_set_mod(&mods, LDAP_MOD_ADD,
+			    LDAP_ATTRIBUTE_KRB_PRINCIPAL, saltprinc);
+        }
 
 	if ((create_flags & KRB_PRINC_CREATE_DISABLED)) {
 		smbldap_make_mod(priv2ld(ldap_state), entry, &mods,
@@ -1862,7 +1839,7 @@ static bool set_krb_princ(struct ldapsam_privates *ldap_state,
 		return false;
 	}
 
-	ret = set_cross_realm_pw(ldap_state, mem_ctx, princ, saltprinc, pwd, base_dn);
+	ret = set_cross_realm_pw(ldap_state, saltprinc ? saltprinc : princ, pwd);
 	if (ret != 0) {
 		DEBUG(1, ("set_cross_realm_pw failed.\n"));
 		return false;
diff --git a/install/updates/60-trusts.update b/install/updates/60-trusts.update
index df9468e406297876b26c1863d8ac1df1ef5976b1..04c85ba77389b12415849ed81b8131c07b1c7a32 100644
--- a/install/updates/60-trusts.update
+++ b/install/updates/60-trusts.update
@@ -28,6 +28,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: (targetattr="ipaProtectedOperation;read_keys")(version 3.0; acl "Allow trust agents to retrieve keytab keys for cross realm principals"; allow(read) userattr="ipaAllowedToPerform;read_keys#GROUPDN";)
+add:aci: (targetattr="ipaProtectedOperation;write_keys")(version 3.0; acl "Allow trust agents to set keys for cross realm principals"; allow(write) groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$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";)
-- 
2.5.0

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to