From 7a4fbc070e7fc9e67a86af6cc70f84420f876a80 Mon Sep 17 00:00:00 2001
From: Zhanna Tsitkov <tsitkova@mit.edu>
Date: Mon, 17 Nov 2008 19:28:24 +0000
Subject: [PATCH] PERF: Introduced a new function krb5_is_permitted_enctype_ext
 to replace multiple calls to krb5_is_permitted_enctype

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21128 dc483132-0cff-0310-8789-dd5450dbe970
---
 src/configure.in              |  7 +-----
 src/include/k5-int.h          | 10 ++++++++
 src/lib/krb5/krb/init_ctx.c   | 32 ++++++++++++++++++++++++
 src/lib/krb5/krb/rd_req_dec.c | 47 ++++++++++++++++++++++++++++++++---
 4 files changed, 86 insertions(+), 10 deletions(-)

diff --git a/src/configure.in b/src/configure.in
index 174f7d97c..4d2b5b3bb 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -92,12 +92,7 @@ AC_CHECK_HEADERS(syslog.h stdarg.h sys/select.h sys/sockio.h ifaddrs.h unistd.h)
 AC_CHECK_FUNCS(openlog syslog closelog strftime vsprintf vasprintf vsnprintf)
 AC_CHECK_FUNCS(strlcpy)
 EXTRA_SUPPORT_SYMS=
-AC_CHECK_FUNC(strlcpy,
-[STRLCPY_ST_OBJ=
-STRLCPY_OBJ=],
-[STRLCPY_ST_OBJ=strlcpy.o
-STRLCPY_OBJ='$(OUTPRE)strlcpy.$(OBJEXT)'
-EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_strlcpy krb5int_strlcat"])
+AC_CHECK_FUNC(strlcpy, [STRLCPY_ST_OBJ= STRLCPY_OBJ=], [STRLCPY_ST_OBJ=strlcpy.o STRLCPY_OBJ='$(OUTPRE)strlcpy.$(OBJEXT)' EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_strlcpy krb5int_strlcat"])
 AC_SUBST(STRLCPY_OBJ)
 AC_SUBST(STRLCPY_ST_OBJ)
 AC_CHECK_FUNC(vasprintf,
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 3052d7be8..0fd5f5243 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2282,6 +2282,16 @@ void KRB5_CALLCONV krb5_free_ktypes
 krb5_boolean krb5_is_permitted_enctype
 	(krb5_context, krb5_enctype);
 
+typedef struct
+{
+        krb5_enctype *etype;
+        krb5_boolean *etype_ok;
+        krb5_int32 etype_count;
+} krb5_etypes_permitted;
+
+krb5_boolean krb5_is_permitted_enctype_ext 
+         ( krb5_context, krb5_etypes_permitted *);
+
 krb5_error_code krb5_kdc_rep_decrypt_proc
 	(krb5_context,
 		const krb5_keyblock *,
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index 467aec951..f916660f9 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -488,6 +488,38 @@ krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype)
     return(ret);
 }
 
+/* The same as krb5_is_permitted_enctype, but verifies multiple etype's
+ * Returns 0 is either the list of the permitted enc types is not available
+ * or all requested etypes are not permitted. Otherwise returns 1.
+ */
+
+krb5_boolean
+krb5_is_permitted_enctype_ext ( krb5_context context,
+                                krb5_etypes_permitted *etypes)
+{
+    krb5_enctype *list, *ptr;
+    krb5_boolean ret = 0;
+    int i = 0;
+
+    if (krb5_get_permitted_enctypes(context, &list))
+        return(0);
+
+    for ( i=0; i< etypes->etype_count; i++ )
+    {
+        for (ptr = list; *ptr; ptr++)
+        {
+            if (*ptr == etypes->etype[i])
+            {
+                etypes->etype_ok[i] =  TRUE;
+                ret = 1;
+            }
+        }
+    }
+    krb5_free_ktypes (context, list);
+
+    return(ret);
+}
+
 static krb5_error_code
 copy_ktypes(krb5_context ctx,
 	    unsigned int nktypes,
diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c
index e93551a54..3a92107a7 100644
--- a/src/lib/krb5/krb/rd_req_dec.c
+++ b/src/lib/krb5/krb/rd_req_dec.c
@@ -182,7 +182,6 @@ krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
 					&((*auth_context)->authentp),
 					check_valid_flag)))
 	goto cleanup;
-
     if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
 				req->ticket->enc_part2->client)) {
 	retval = KRB5KRB_AP_ERR_BADMATCH;
@@ -301,6 +300,26 @@ krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
 	/* no etype check needed */;
     } else if ((*auth_context)->permitted_etypes == NULL) {
 	int etype;
+        size_t size_etype_enc = 3 * sizeof(krb5_enctype); /*  upto three types */
+        size_t size_etype_bool = 3 * sizeof(krb5_boolean);
+        krb5_etypes_permitted etypes;
+        memset(&etypes, 0, sizeof etypes);
+
+        etypes.etype = (krb5_enctype*) malloc( size_etype_enc );
+        etypes.etype_ok = (krb5_boolean*) malloc( size_etype_bool );
+        memset(etypes.etype, 0, size_etype_enc );
+        memset(etypes.etype_ok, 0, size_etype_bool );
+
+        etypes.etype[etypes.etype_count++] = req->ticket->enc_part.enctype;
+        etypes.etype[etypes.etype_count++] = req->ticket->enc_part2->session->enctype;
+        if ( (*auth_context)->authentp->subkey) {
+            etypes.etype[etypes.etype_count++] = (*auth_context)->authentp->subkey->enctype;
+        }
+
+        retval = krb5_is_permitted_enctype_ext(context, &etypes);
+
+
+#if 0
 	/* check against the default set */
 	if ((!krb5_is_permitted_enctype(context,
 					etype = req->ticket->enc_part.enctype)) ||
@@ -309,8 +328,27 @@ krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
 	    (((*auth_context)->authentp->subkey) &&
 	     !krb5_is_permitted_enctype(context,
 					etype = (*auth_context)->authentp->subkey->enctype))) {
-	    char enctype_name[30];
-	    retval = KRB5_NOPERM_ETYPE;
+#endif
+        if  ( retval == 0  /* all etypes  are not permitted */ ||  
+              ( !etypes.etype_ok[0] || !etypes.etype_ok[1] ||
+              (((*auth_context)->authentp->subkey) && !etypes.etype_ok[etypes.etype_count-1])))
+        {
+            char enctype_name[30];
+            retval = KRB5_NOPERM_ETYPE;
+
+            if (  !etypes.etype_ok[0] )
+            {
+                etype =  etypes.etype[1];
+            }
+            else if (  !etypes.etype_ok[1] )
+            {
+                etype =  etypes.etype[1];
+            }
+            else
+            {
+                etype =  etypes.etype[2];
+            }
+
 	    if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0)
 		krb5_set_error_message(context, retval,
 				       "Encryption type %s not permitted",
@@ -453,7 +491,6 @@ krb5_rd_req_decoded_anyflag(krb5_context context,
 				   0); /* don't check_valid_flag */
   return retval;
 }
-
 static krb5_error_code
 decrypt_authenticator(krb5_context context, const krb5_ap_req *request,
 		      krb5_authenticator **authpp, int is_ap_req)
@@ -488,3 +525,5 @@ free(scratch.data);}
     clean_scratch();
     return retval;
 }
+
+
-- 
2.26.2