[3154] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

krb5-libs/786: Keytab code should cache last-read key

daemon@ATHENA.MIT.EDU (Jonathan Kamens)
Tue Nov 23 18:49:33 1999

Resent-From: gnats@rt-11.MIT.EDU (GNATS Management)
Resent-To: krb5-unassigned@RT-11.MIT.EDU
Resent-Reply-To: krb5-bugs@MIT.EDU, jik@kamens.brookline.ma.us
Message-Id: <199911232148.QAA20937@jik2.kamens.brookline.ma.us>
Date: Tue, 23 Nov 1999 16:48:23 -0500
From: Jonathan Kamens <jik@kamens.brookline.ma.us>
Reply-To: jik@kamens.brookline.ma.us
To: krb5-bugs@MIT.EDU
Cc: jik@kamens.brookline.ma.us


>Number:         786
>Category:       krb5-libs
>Synopsis:       Keytab code should cache last-read key
>Confidential:   yes
>Severity:       non-critical
>Priority:       medium
>Responsible:    krb5-unassigned
>State:          open
>Class:          change-request
>Submitter-Id:   unknown
>Arrival-Date:   Tue Nov 23 16:49:00 EST 1999
>Last-Modified:
>Originator:     Jonathan Kamens
>Organization:
	
>Release:        krb5-1.1
>Environment:
	
System: Linux jik2 2.2.12-20 #14 Thu Nov 18 20:57:02 EST 1999 i686 unknown
Architecture: i686

>Description:
	Every time a Kerberos application server gets a request, it
	has to read its ticket file to process the request.  For a
	very busy server, this is very inefficient.  It's also
	unnecessary, since the vast majority of servers receive
	requests for the same service principal over and over.

	The patch below caches the last key read from the keytab, so
	that the keytab does not have to be read over and over as long
	as requests keep coming in for the same service principal.

	Note that these patches were previously submitted against krb5
	1.0.  I tested them pretty extensively before submitting them
	against 1.0, but I have *not* tested them extensively against
	1.1, since I'm not currently using any krb5 application
	servers.  I've simply merged my changes from 1.0 into a
	current 1.1 tree, which required some additional changes since
	the 1.1 code in question had changed a bit.

	Therefore, somebody who is more actively involved in doing
	krb5 development than I am right now should test these
	changes before committing and releasing them.
>How-To-Repeat:
	
>Fix:
Index: ./src/lib/krb5/keytab/file/ktf_close.c
--- ktf_close.c	1999/11/23 20:25:26	1.1.1.1
+++ ktf_close.c	1999/11/23 21:37:04	1.3
@@ -44,6 +44,8 @@
    */
 {
     krb5_xfree(KTFILENAME(id));
+    if (KTCACHE(id).magic)
+      krb5_kt_free_entry(context, &KTCACHE(id));
     krb5_xfree(id->data);
     id->ops = 0;
     krb5_xfree(id);
Index: ./src/lib/krb5/keytab/file/ktf_g_ent.c
--- ktf_g_ent.c	1999/11/23 20:25:26	1.1.1.1
+++ ktf_g_ent.c	1999/11/23 21:37:04	1.3
@@ -45,11 +45,11 @@
     krb5_error_code kerror = 0;
     int found_wrong_kvno = 0;
     krb5_boolean similar;
+    /* 0 - haven't checked the cache yet
+       1 - checked the cache, but haven't opened the ticket file yet
+       2 - opened the ticket file */
+    int checking_state = 0;
 
-    /* Open the keyfile for reading */
-    if ((kerror = krb5_ktfileint_openr(context, id)))
-	return(kerror);
-    
     /* 
      * For efficiency and simplicity, we'll use a while true that 
      * is exited with a break statement.
@@ -59,8 +59,28 @@
     cur_entry.key.contents = 0;
 
     while (TRUE) {
-	if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry)))
+	if (checking_state == 0) {
+	  checking_state++;
+	  if (! KTCACHE(id).magic)
+	    continue;
+	  krb5_ktfileint_copy_entry(context, &KTCACHE(id), &new_entry);
+	}
+	else {
+	  if (checking_state == 1) {
+	    /* Free the cache entry, if there is one */
+	    if (KTCACHE(id).magic) {
+	      krb5_kt_free_entry(context, &KTCACHE(id));
+	      KTCACHE(id).magic = 0;
+	    }
+	    /* Open the keyfile for reading */
+	    if ((kerror = krb5_ktfileint_openr(context, id)))
+	      return(kerror);
+	    checking_state++;
+	  }
+
+	  if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry)))
 	    break;
+	}
 
 	/* by the time this loop exits, it must either free cur_entry,
 	   and copy new_entry there, or free new_entry.  Otherwise, it
@@ -137,6 +157,8 @@
 	krb5_kt_free_entry(context, &cur_entry);
 	return kerror;
     }
+    if (checking_state == 2)
+      (void) krb5_ktfileint_copy_entry(context, &cur_entry, &KTCACHE(id));
     *entry = cur_entry;
     return 0;
 }
Index: ./src/lib/krb5/keytab/file/ktfile.h
--- ktfile.h	1999/11/23 20:25:26	1.1.1.1
+++ ktfile.h	1999/11/23 21:37:04	1.3
@@ -52,6 +52,7 @@
     char *name;			/* Name of the file */
     FILE *openf;		/* open file, if any. */
     int	version;		/* Version number of keytab */
+    krb5_keytab_entry cache;	/* Cached last keytab entry returned by get_entry */
 } krb5_ktfile_data;
 
 /*
@@ -61,6 +62,7 @@
 #define KTFILENAME(id) (((krb5_ktfile_data *)(id)->data)->name)
 #define KTFILEP(id) (((krb5_ktfile_data *)(id)->data)->openf)
 #define KTVERSION(id) (((krb5_ktfile_data *)(id)->data)->version)
+#define KTCACHE(id) (((krb5_ktfile_data *)(id)->data)->cache)
 
 extern struct _krb5_kt_ops krb5_ktf_ops;
 extern struct _krb5_kt_ops krb5_ktf_writable_ops;
@@ -163,6 +165,11 @@
 		   krb5_keytab,
                    krb5_int32 *,
                    krb5_int32 *));
+
+krb5_error_code krb5_ktfileint_copy_entry
+	PROTOTYPE((krb5_context,
+		   krb5_keytab_entry *,
+		   krb5_keytab_entry *));
 
 
 #endif /* KRB5_KTFILE__ */
Index: ./src/lib/krb5/keytab/file/ktf_resolv.c
--- ktf_resolv.c	1999/11/23 20:25:26	1.1.1.1
+++ ktf_resolv.c	1999/11/23 21:37:04	1.3
@@ -56,6 +56,7 @@
 
     (void) strcpy(data->name, name);
     data->openf = 0;
+    memset(&data->cache, 0, sizeof(data->cache));
     data->version = 0;
 
     (*id)->data = (krb5_pointer)data;
Index: ./src/lib/krb5/keytab/file/ktf_util.c
--- ktf_util.c	1999/11/23 20:25:26	1.1.1.1
+++ ktf_util.c	1999/11/23 21:37:04	1.3
@@ -774,3 +774,31 @@
     return 0;
 }
 
+/*
+ * Copy a keytab entry's data from an old structure into a new
+ * (already allocated) structure.
+ */
+
+krb5_error_code
+krb5_ktfileint_copy_entry(context, old_entry, new_entry)
+     krb5_context context;
+     krb5_keytab_entry *old_entry, *new_entry;
+{
+  krb5_error_code code;
+  krb5_keytab_entry tmp_entry;
+
+  tmp_entry = *old_entry;
+  
+  if ((code = krb5_copy_principal(context, old_entry->principal,
+				  &tmp_entry.principal)))
+    return code;
+
+  if ((code = krb5_copy_keyblock_contents(context, &old_entry->key,
+					  &tmp_entry.key))) {
+    (void) krb5_free_principal(context, tmp_entry.principal);
+    return code;
+  }
+
+  *new_entry = tmp_entry;
+  return 0;
+}
Index: ./src/lib/krb5/keytab/file/ktf_wreslv.c
--- ktf_wreslv.c	1999/11/23 20:25:26	1.1.1.1
+++ ktf_wreslv.c	1999/11/23 21:37:04	1.3
@@ -56,6 +56,7 @@
 
     (void) strcpy(data->name, name);
     data->openf = 0;
+    memset(&data->cache, 0, sizeof(data->cache));
     data->version = 0;
 
     (*id)->data = (krb5_pointer)data;
>Audit-Trail:
>Unformatted:

home help back first fref pref prev next nref lref last post