[1199] in Kerberos-V5-bugs

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

krb5b4pl3: lib/krb5/rcache/rc_io.c: should lock cache files

daemon@ATHENA.MIT.EDU (Jonathan I. Kamens)
Sun Mar 19 20:42:18 1995

From: "Jonathan I. Kamens" <jik@cam.ov.com>
Date: Sun, 19 Mar 1995 20:45:30 -0500
To: krb5-bugs@MIT.EDU

Replay cache files needs to be locked before they are written to.  To
not lock them is a security hole (which I'll gladly explain if you
call me or contact me via private E-mail).

Here's a patch:

--- lib/krb5/rcache/rc_io.c	1995/02/27 02:37:24	1.1
+++ lib/krb5/rcache/rc_io.c	1995/02/27 02:46:17
@@ -21,6 +21,9 @@
 #include "rc_io.h"
 #include <krb5/sysincl.h>
 #include <krb5/osconf.h>
+#include <krb5/libos.h> /* for KRB5_LOCKMODE_EXCLUSIVE */
+
+#define KRB5_RC_LOCK_TRIES 30	/* # of times to try locking */
 
 #ifdef KRB5_USE_INET
 #include <netinet/in.h>
@@ -64,6 +67,7 @@
  char *c;
  krb5_int16 rc_vno = htons(KRB5_RC_VNO);
  krb5_error_code retval;
+ int lock_count = 0;
 
  GETDIR;
  if (fn && *fn)
@@ -127,6 +131,17 @@
 	    retval = KRB5_RC_IO_UNKNOWN; goto fail;
     }
     }
+
+ if (! (d->file = fdopen(d->fd, "w")))
+     goto fail;
+ while (((retval = krb5_lock_file(d->file, d->fn, KRB5_LOCKMODE_EXCLUSIVE)) ==
+	 EAGAIN) && (++lock_count < KRB5_RC_LOCK_TRIES))
+     sleep(1);
+ if (retval) {
+     retval = KRB5_RC_IO_UNKNOWN;
+     goto fail;
+ }
+ 
     if ((retval = krb5_rc_io_write(d, (krb5_pointer)&rc_vno, sizeof(rc_vno))) ||
 	(retval = krb5_rc_io_sync(d)))
     {
@@ -134,6 +149,10 @@
      (void) unlink(d->fn);
      FREE(d->fn);
 	d->fn = NULL;
+     if (d->file)
+	 (void) fclose(d->file);
+     /* This is probably unnecessary, because the fclose() will close
+	the file descriptor too. */
      (void) close(d->fd);
      return retval;
  }
@@ -147,6 +166,7 @@
  krb5_int16 rc_vno;
  krb5_error_code retval;
  struct stat statb;
+ int lock_count = 0;
 
  GETDIR;
  if (!(d->fn = malloc(strlen(fn) + dirlen + 1)))
@@ -192,6 +212,18 @@
 	    goto fail;
     }
  }
+
+ if (! (d->file = fdopen(d->fd, "r+")))
+     goto unlk;
+
+ while (((retval = krb5_lock_file(d->file, d->fn, KRB5_LOCKMODE_EXCLUSIVE)) ==
+	 EAGAIN) && (++lock_count < KRB5_RC_LOCK_TRIES))
+     sleep(1);
+ if (retval) {
+     retval = KRB5_RC_IO_UNKNOWN;
+     goto unlk;
+ }
+
     if (retval = krb5_rc_io_read(d, (krb5_pointer) &rc_vno,  sizeof(rc_vno)))  
 	goto unlk;
 
@@ -202,6 +234,9 @@
     unlk:
 	unlink(d->fn);
     fail:
+	if (d->file)
+	    (void) fclose(d->file);
+	/* This probably isn't necessary (see above). */
      (void) close(d->fd);
      FREE(d->fn); 
 	d->fn = NULL;
@@ -219,6 +254,7 @@
  (void) krb5_rc_io_close(new);
  new->fn = old->fn;
  new->fd = old->fd;
+ new->file = old->file;
  return 0;
 }
 
@@ -277,11 +313,15 @@
 krb5_error_code krb5_rc_io_close (d)
 krb5_rc_iostuff *d;
 {
+    krb5_error_code retval;
+
+    retval = krb5_unlock_file(d->file, d->fn);
  FREE(d->fn);
  d->fn = NULL;
- if (close(d->fd) == -1) /* can't happen */
-   return KRB5_RC_IO_UNKNOWN;
- return 0;
+ if (fclose(d->file) && !retval)
+     retval = KRB5_RC_IO_UNKNOWN;
+    (void) close(d->fd);
+ return retval;
 }
 
 krb5_error_code krb5_rc_io_destroy (d)

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