[1199] in Kerberos-V5-bugs
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)