krb5 commit: Use file2 replay cache by default
Greg Hudson
ghudson at mit.edu
Fri May 31 15:45:12 EDT 2019
https://github.com/krb5/krb5/commit/e8a35f6962ce2d048616fb7457bff2d90398ca48
commit e8a35f6962ce2d048616fb7457bff2d90398ca48
Author: Greg Hudson <ghudson at mit.edu>
Date: Wed May 15 01:01:34 2019 -0400
Use file2 replay cache by default
Remove the existing default replay cache implementation and replace it
with a wrapper around the file2 replay cache code. Change the
filename to krb5_EUID.rcache2, ignoring the residual (and therefore
the server principal name). On Windows, use the local appdata
directory if KRB5RCACHEDIR is not set in the environment.
ticket: 8786
doc/basic/rcache_def.rst | 27 +-
src/kadmin/testing/Makefile.in | 2 +-
src/lib/krb5/libkrb5.exports | 23 -
src/lib/krb5/rcache/Makefile.in | 6 -
src/lib/krb5/rcache/README | 82 ----
src/lib/krb5/rcache/deps | 40 +-
src/lib/krb5/rcache/rc_dfl.c | 927 ++++++---------------------------------
src/lib/krb5/rcache/rc_dfl.h | 48 --
src/lib/krb5/rcache/rc_io.c | 518 ----------------------
src/lib/krb5/rcache/rc_io.h | 60 ---
src/lib/krb5/rcache/rcdef.c | 45 --
11 files changed, 179 insertions(+), 1599 deletions(-)
diff --git a/doc/basic/rcache_def.rst b/doc/basic/rcache_def.rst
index 56d369d..5e550fc 100644
--- a/doc/basic/rcache_def.rst
+++ b/doc/basic/rcache_def.rst
@@ -71,21 +71,30 @@ are in lowercase. The following types are defined:
#. **dfl** is the default type if no environment variable or
configuration specifies a different type. It stores replay data in
- a file, occasionally rewriting it to purge old, expired entries.
+ a file2 replay cache with a filename based on the effective uid.
+ The residual value is ignored.
The default type can be overridden by the **KRB5RCACHETYPE**
environment variable.
-For the dfl type, the placement of the replay cache file is determined
-by the following:
+For the dfl type, the location of the replay cache file is determined
+as follows:
-#. The **KRB5RCACHEDIR** environment variable;
+#. The directory is taken from the **KRB5RCACHEDIR** environment
+ variable, or the **TMPDIR** environment variable, or a temporary
+ directory determined at configuration time such as ``/var/tmp``, in
+ descending order of preference.
-#. If KRB5RCACHEDIR is unspecified, on UNIX, the library
- will fall back to the environment variable **TMPDIR**, and then to
- a temporary directory determined at configuration time such as
- */tmp* or */var/tmp*; on Windows, it will check the environment
- variables *TEMP* and *TMP*, and fall back to the directory C:\\.
+#. The filename is ``krb5_EUID.rcache2`` where EUID is the effective
+ uid of the process.
+
+#. The file is opened without following symbolic links, and ownership
+ of the file is verified to match the effective uid.
+
+On Windows, the directory for the dfl type is the local appdata
+directory, unless overridden by the **KRB5RCACHEDIR** environment
+variable. The filename on Windows is ``krb5.rcache2``, and the file
+is opened normally.
Performance issues
------------------
diff --git a/src/kadmin/testing/Makefile.in b/src/kadmin/testing/Makefile.in
index e5bcc74..5b803cb 100644
--- a/src/kadmin/testing/Makefile.in
+++ b/src/kadmin/testing/Makefile.in
@@ -5,4 +5,4 @@ SUBDIRS = scripts util
all:
clean:
- -$(RM) -r krb5-test-root admin_* init-* kadmin_* kdc_rcache.* ovsec-*
+ -$(RM) -r krb5-test-root admin_* init-* *.rcache2 ovsec-*
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 038e4de..1f22498 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -503,35 +503,12 @@ krb5_rc_default
krb5_rc_default_name
krb5_rc_default_type
krb5_rc_destroy
-krb5_rc_dfl_close
-krb5_rc_dfl_close_no_free
-krb5_rc_dfl_destroy
-krb5_rc_dfl_expunge
-krb5_rc_dfl_get_name
-krb5_rc_dfl_get_span
-krb5_rc_dfl_init
-krb5_rc_dfl_ops
-krb5_rc_dfl_recover
-krb5_rc_dfl_resolve
-krb5_rc_dfl_store
krb5_rc_expunge
-krb5_rc_free_entry
krb5_rc_get_lifespan
krb5_rc_get_name
krb5_rc_get_type
krb5_rc_hash_message
krb5_rc_initialize
-krb5_rc_io_close
-krb5_rc_io_creat
-krb5_rc_io_destroy
-krb5_rc_io_mark
-krb5_rc_io_move
-krb5_rc_io_open
-krb5_rc_io_read
-krb5_rc_io_size
-krb5_rc_io_sync
-krb5_rc_io_unmark
-krb5_rc_io_write
krb5_rc_recover
krb5_rc_recover_or_initialize
krb5_rc_register_type
diff --git a/src/lib/krb5/rcache/Makefile.in b/src/lib/krb5/rcache/Makefile.in
index 0513937..441a6ca 100644
--- a/src/lib/krb5/rcache/Makefile.in
+++ b/src/lib/krb5/rcache/Makefile.in
@@ -10,8 +10,6 @@ STLIBOBJS = \
rc_base.o \
rc_dfl.o \
rc_file2.o \
- rc_io.o \
- rcdef.o \
rc_none.o \
rc_conv.o \
ser_rc.o \
@@ -22,8 +20,6 @@ OBJS= \
$(OUTPRE)rc_base.$(OBJEXT) \
$(OUTPRE)rc_dfl.$(OBJEXT) \
$(OUTPRE)rc_file2.$(OBJEXT) \
- $(OUTPRE)rc_io.$(OBJEXT) \
- $(OUTPRE)rcdef.$(OBJEXT) \
$(OUTPRE)rc_none.$(OBJEXT) \
$(OUTPRE)rc_conv.$(OBJEXT) \
$(OUTPRE)ser_rc.$(OBJEXT) \
@@ -34,8 +30,6 @@ SRCS= \
$(srcdir)/rc_base.c \
$(srcdir)/rc_dfl.c \
$(srcdir)/rc_file2.c \
- $(srcdir)/rc_io.c \
- $(srcdir)/rcdef.c \
$(srcdir)/rc_none.c \
$(srcdir)/rc_conv.c \
$(srcdir)/ser_rc.c \
diff --git a/src/lib/krb5/rcache/README b/src/lib/krb5/rcache/README
deleted file mode 100644
index 13a45a1..0000000
--- a/src/lib/krb5/rcache/README
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Copyright 1990, Daniel J. Bernstein. All rights reserved.
-
-Please address any questions or comments to the author at brnstnd at acf10.nyu.edu.
-*/
-
-The #include's should be rewritten.
-
-All functions return 0 on success.
-
-Environment variables: KRB5RCACHETYPE, KRB5RCACHENAME, KRB5RCACHEDIR,
-and TMPDIR. Obsolete: KRB5RCACHE.
-
-All header files are both ANSI-compatible and K&R-compatible. The .c files
-are only ANSI compatible. Everything passes gcc -Wall -ansi -pedantic.
-
-Strings are freed using FREE(), which is defined in terms of free().
-
-The error header files should be redone.
-
-The header files don't use __ because that's reserved.
-
-Each .c file assumes <malloc.h>. rc_io.c assumes fsync() and a gaggle of
-error codes. These assumptions are not as portable as the code itself.
-
-
-rcache.c:
-
-The rcache.c compatibility interface's type registration is a no-op; it
-simply passes the type name on to rc_base.h. rcache.h is obsolete; use
-rc_base.h if possible.
-
-There are some slight differences between rcache.c and the prototypes I
-saw in krb/func-proto.h. Don't look at me, it's your interface.
-
-rcache.c's get_name doesn't fill with zeros unless strncpy does.
-
-
-rc_base.c:
-
-It doesn't take linker magic to preregister types. Just change the
-typehead initialization in rc_base.c, with an appropriate include file
-setting the ops.
-
-
-rc_dfl.c:
-
-If NOIOSTUFF is defined when rc_dfl.c is compiled, all dfl rcaches will
-be per-process. This is untested.
-
-Provided that separate threads use separate rcaches, rc_dfl.c is safe
-for multithreading.
-
-Getting the name of a cache is only valid after it is created and before
-it is closed. Recovering a cache is only valid after it has been created.
-
-krb5_unparse_name had better produce a zero-terminated string.
-
-rc_dfl.c isn't smart enough to try expunge/retry upon a malloc error.
-Then again, such an error indicates that the whole system's about to die;
-without real memory management there's no good solution.
-
-HASHSIZE can be defined at compile time. It defaults to 997 in rc_dfl.c.
-EXCESSREPS can be defined at compile time. It defaults to 30 in rc_dfl.c.
-
-Hopefully adding a deltat to a time to compare to another time cannot
-overflow.
-
-In rc_dfl's struct dfl_data, the name field is never freed, even though
-it may be malloced by io_creat on a generate-name call. This should not
-be a problem: a single process should not be opening and closing many
-rcaches. One fix would be another field to indicate whether the string
-was malloced or not; normally this is an unstated characteristic of a
-char pointer, but here it would have to be explicit.
-
-
-rc_io.c:
-
-rc_io.c assumes that siginterrupt() is not set. If siginterrupt() is set
-and a signal occurs during, say, close(), then the close will fail.
-
-On a machine without fsync() you might as well not use the disk at all.
diff --git a/src/lib/krb5/rcache/deps b/src/lib/krb5/rcache/deps
index 445439a..a9ac7fd 100644
--- a/src/lib/krb5/rcache/deps
+++ b/src/lib/krb5/rcache/deps
@@ -26,37 +26,27 @@ rc_base.so rc_base.po $(OUTPRE)rc_base.$(OBJEXT): $(BUILDTOP)/include/autoconf.h
rc_base.h
rc_dfl.so rc_dfl.po $(OUTPRE)rc_dfl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
- $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h rc-int.h rc_base.h \
- rc_dfl.c rc_dfl.h rc_io.h
-rc_io.so rc_io.po $(OUTPRE)rc_io.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
- $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
- $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
- $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
- $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h \
+ $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h rc_base.h rc_dfl.h \
- rc_io.c rc_io.h
-rcdef.so rcdef.po $(OUTPRE)rcdef.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
- $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
- $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
- $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/socket-utils.h memrcache.h rc-int.h \
+ rc_dfl.c
+rc_file2.so rc_file2.po $(OUTPRE)rc_file2.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hashtab.h \
$(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
$(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h rc-int.h rc_dfl.h \
- rcdef.c
+ $(top_srcdir)/include/socket-utils.h rc-int.h rc_file2.c
rc_none.so rc_none.po $(OUTPRE)rc_none.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
index 1e0cb22..d7ea476 100644
--- a/src/lib/krb5/rcache/rc_dfl.c
+++ b/src/lib/krb5/rcache/rc_dfl.c
@@ -1,850 +1,213 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/rcache/rc_dfl.c */
+/* lib/krb5/rcache/rc_dfl.c - default replay cache type */
/*
- * This file of the Kerberos V5 software is derived from public-domain code
- * contributed by Daniel J. Bernstein, <brnstnd at acf10.nyu.edu>.
+ * Copyright (C) 2019 by the Massachusetts Institute of Technology.
+ * All rights reserved.
*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
- * An implementation for the default replay cache type.
+ * The dfl rcache type is a wrapper around the file2 rcache type, selecting a
+ * filename and (on Unix-like systems) applying open() safety appropriate for
+ * using a shared temporary directory.
*/
+
#include "k5-int.h"
-#include "rc_base.h"
-#include "rc_dfl.h"
-#include "rc_io.h"
#include "rc-int.h"
-
-/*
- * If NOIOSTUFF is defined at compile time, dfl rcaches will be per-process.
- */
-
-/*
- Local stuff:
-
- static int hash(krb5_donot_replay *rep, int hsize)
- returns hash value of *rep, between 0 and hsize - 1
- HASHSIZE
- size of hash table (constant), can be preset
- static int cmp(krb5_donot_replay *old, krb5_donot_replay *new, krb5_deltat t)
- compare old and new; return CMP_REPLAY or CMP_HOHUM
- static int alive(krb5_context, krb5_donot_replay *new, krb5_deltat t)
- see if new is still alive; return CMP_EXPIRED or CMP_HOHUM
- CMP_MALLOC, CMP_EXPIRED, CMP_REPLAY, CMP_HOHUM
- return codes from cmp(), alive(), and store()
- struct dfl_data
- data stored in this cache type, namely "dfl"
- struct authlist
- multilinked list of reps
- static int rc_store(context, krb5_rcache id, krb5_donot_replay *rep)
- store rep in cache id; return CMP_REPLAY if replay, else CMP_MALLOC/CMP_HOHUM
-
-*/
-
-#ifndef HASHSIZE
-#define HASHSIZE 997 /* a convenient prime */
-#endif
-
-#ifndef EXCESSREPS
-#define EXCESSREPS 30
+#ifdef _WIN32
+#include "../os/os-proto.h"
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
#endif
-/*
- * The rcache will be automatically expunged when the number of
- * expired krb5_donot_replays encountered incidentally in searching
- * exceeds the number of live krb5_donot_replays by EXCESSREPS. With
- * the defaults here, a typical cache might build up some 10K of
- * expired krb5_donot_replays before an automatic expunge, with the
- * waste basically independent of the number of stores per minute.
- *
- * The rcache will also automatically be expunged when it encounters
- * more than EXCESSREPS expired entries when recovering a cache in
- * dfl_recover.
- */
+#ifdef _WIN32
-static unsigned int
-hash(krb5_donot_replay *rep, unsigned int hsize)
+static krb5_error_code
+open_file(krb5_context context, int *fd_out)
{
- unsigned int h = rep->cusec + rep->ctime;
- h += *rep->server;
- h += *rep->client;
- return h % hsize;
-}
+ krb5_error_code ret;
+ char *fname;
+ const char *dir;
-#define CMP_MALLOC -3
-#define CMP_EXPIRED -2
-#define CMP_REPLAY -1
-#define CMP_HOHUM 0
+ *fd_out = -1;
-/*ARGSUSED*/
-static int
-cmp(krb5_donot_replay *old, krb5_donot_replay *new1, krb5_deltat t)
-{
- if ((old->cusec == new1->cusec) && /* most likely to distinguish */
- (old->ctime == new1->ctime) &&
- (strcmp(old->client, new1->client) == 0) &&
- (strcmp(old->server, new1->server) == 0)) { /* always true */
- /* If both records include message hashes, compare them as well. */
- if (old->msghash == NULL || new1->msghash == NULL ||
- strcmp(old->msghash, new1->msghash) == 0)
- return CMP_REPLAY;
+ dir = getenv("KRB5RCACHEDIR");
+ if (dir != NULL) {
+ if (asprintf(&fname, "%s\\krb5.rcache2") < 0)
+ return ENOMEM;
+ } else {
+ ret = k5_expand_path_tokens(context, "%{LOCAL_APPDATA}\\krb5.rcache2",
+ &fname);
+ if (ret)
+ return ret;
}
- return CMP_HOHUM;
-}
-static int
-alive(krb5_timestamp mytime, krb5_donot_replay *new1, krb5_deltat t)
-{
- if (mytime == 0)
- return CMP_HOHUM; /* who cares? */
- if (ts_after(mytime, ts_incr(new1->ctime, t)))
- return CMP_EXPIRED;
- return CMP_HOHUM;
+ *fd_out = open(O_CREAT | O_RDWR | O_BINARY, 0600);
+ ret = (*fd_out < 0) ? errno : 0;
+ if (ret) {
+ k5_setmsg(context, ret, "%s (filename: %s)",
+ error_message(ret), fname);
+ }
+ free(fname);
+ return ret;
}
-struct dfl_data
-{
- char *name;
- krb5_deltat lifespan;
- unsigned int hsize;
- int numhits;
- int nummisses;
- struct authlist **h;
- struct authlist *a;
-#ifndef NOIOSTUFF
- krb5_rc_iostuff d;
-#endif
- char recovering;
-};
-
-struct authlist
-{
- krb5_donot_replay rep;
- struct authlist *na;
- struct authlist *nh;
-};
+#else /* _WIN32 */
-/* of course, list is backwards from file */
-/* hash could be forwards since we have to search on match, but naaaah */
-
-static int
-rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep,
- krb5_timestamp now, krb5_boolean fromfile)
+static krb5_error_code
+open_file(krb5_context context, int *fd_out)
{
- struct dfl_data *t = (struct dfl_data *)id->data;
- unsigned int rephash;
- struct authlist *ta;
-
- rephash = hash(rep, t->hsize);
+ krb5_error_code ret;
+ int fd = -1;
+ char *fname = NULL;
+ const char *dir;
+ struct stat statbuf;
+ uid_t euid = geteuid();
+
+ *fd_out = -1;
+
+ dir = secure_getenv("KRB5RCACHEDIR");
+ if (dir == NULL) {
+ dir = secure_getenv("TMPDIR");
+ if (dir == NULL)
+ dir = RCTMPDIR;
+ }
+ if (asprintf(&fname, "%s/krb5_%lu.rcache2", dir, (unsigned long)euid) < 0)
+ return ENOMEM;
+
+ fd = open(fname, O_CREAT | O_RDWR | O_NOFOLLOW, 0600);
+ if (fd < 0) {
+ ret = errno;
+ k5_setmsg(context, ret, "%s (filename: %s)",
+ error_message(ret), fname);
+ goto cleanup;
+ }
- for (ta = t->h[rephash]; ta; ta = ta->nh) {
- switch(cmp(&ta->rep, rep, t->lifespan))
- {
- case CMP_REPLAY:
- if (fromfile) {
- /*
- * This is an expected collision between a hash
- * extension record and a normal-format record. Make
- * sure the message hash is included in the stored
- * record and carry on.
- */
- if (!ta->rep.msghash && rep->msghash) {
- if (!(ta->rep.msghash = strdup(rep->msghash)))
- return CMP_MALLOC;
- }
- return CMP_HOHUM;
- } else
- return CMP_REPLAY;
- case CMP_HOHUM:
- if (alive(now, &ta->rep, t->lifespan) == CMP_EXPIRED)
- t->nummisses++;
- else
- t->numhits++;
- break;
- default:
- ; /* wtf? */
- }
+ if (fstat(fd, &statbuf) < 0 || statbuf.st_uid != euid) {
+ ret = EIO;
+ k5_setmsg(context, ret, "Replay cache file %s is not owned by uid %lu",
+ fname, (unsigned long)euid);
+ goto cleanup;
}
- if (!(ta = (struct authlist *) malloc(sizeof(struct authlist))))
- return CMP_MALLOC;
- ta->rep = *rep;
- ta->rep.client = ta->rep.server = ta->rep.msghash = NULL;
- if (!(ta->rep.client = strdup(rep->client)))
- goto error;
- if (!(ta->rep.server = strdup(rep->server)))
- goto error;
- if (rep->msghash && !(ta->rep.msghash = strdup(rep->msghash)))
- goto error;
- ta->na = t->a; t->a = ta;
- ta->nh = t->h[rephash]; t->h[rephash] = ta;
- return CMP_HOHUM;
-error:
- if (ta->rep.client)
- free(ta->rep.client);
- if (ta->rep.server)
- free(ta->rep.server);
- if (ta->rep.msghash)
- free(ta->rep.msghash);
- free(ta);
- return CMP_MALLOC;
-}
+ *fd_out = fd;
+ fd = -1;
+ ret = 0;
-char * KRB5_CALLCONV
-krb5_rc_dfl_get_name(krb5_context context, krb5_rcache id)
-{
- return ((struct dfl_data *) (id->data))->name;
+cleanup:
+ if (fd != -1)
+ close(fd);
+ free(fname);
+ return ret;
}
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_get_span(krb5_context context, krb5_rcache id,
- krb5_deltat *lifespan)
-{
- struct dfl_data *t;
+#endif /* not _WIN32 */
- k5_mutex_lock(&id->lock);
- t = (struct dfl_data *) id->data;
- *lifespan = t->lifespan;
- k5_mutex_unlock(&id->lock);
- return 0;
+static char * KRB5_CALLCONV
+dfl_get_name(krb5_context context, krb5_rcache rc)
+{
+ return "";
}
static krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_init_locked(krb5_context context, krb5_rcache id, krb5_deltat lifespan)
+dfl_get_span(krb5_context context, krb5_rcache rc, krb5_deltat *lifespan)
{
- struct dfl_data *t = (struct dfl_data *)id->data;
- krb5_error_code retval;
-
- t->lifespan = lifespan ? lifespan : context->clockskew;
- /* default to clockskew from the context */
-#ifndef NOIOSTUFF
- if ((retval = krb5_rc_io_creat(context, &t->d, &t->name))) {
- return retval;
- }
- if ((krb5_rc_io_write(context, &t->d,
- (krb5_pointer) &t->lifespan, sizeof(t->lifespan))
- || krb5_rc_io_sync(context, &t->d))) {
- return KRB5_RC_IO;
- }
-#endif
+ *lifespan = context->clockskew;
return 0;
}
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_init(krb5_context context, krb5_rcache id, krb5_deltat lifespan)
-{
- krb5_error_code retval;
-
- k5_mutex_lock(&id->lock);
- retval = krb5_rc_dfl_init_locked(context, id, lifespan);
- k5_mutex_unlock(&id->lock);
- return retval;
-}
-
-/* Called with the mutex already locked. */
-krb5_error_code
-krb5_rc_dfl_close_no_free(krb5_context context, krb5_rcache id)
+static krb5_error_code KRB5_CALLCONV
+dfl_init(krb5_context context, krb5_rcache rc, krb5_deltat lifespan)
{
- struct dfl_data *t = (struct dfl_data *)id->data;
- struct authlist *q;
-
- free(t->h);
- if (t->name)
- free(t->name);
- while ((q = t->a))
- {
- t->a = q->na;
- free(q->rep.client);
- free(q->rep.server);
- if (q->rep.msghash)
- free(q->rep.msghash);
- free(q);
- }
-#ifndef NOIOSTUFF
- (void) krb5_rc_io_close(context, &t->d);
-#endif
- free(t);
return 0;
}
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_close(krb5_context context, krb5_rcache id)
+static krb5_error_code KRB5_CALLCONV
+dfl_close(krb5_context context, krb5_rcache rc)
{
- k5_mutex_lock(&id->lock);
- krb5_rc_dfl_close_no_free(context, id);
- k5_mutex_unlock(&id->lock);
- k5_mutex_destroy(&id->lock);
- free(id);
+ k5_mutex_destroy(&rc->lock);
+ free(rc);
return 0;
}
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_destroy(krb5_context context, krb5_rcache id)
-{
-#ifndef NOIOSTUFF
- if (krb5_rc_io_destroy(context, &((struct dfl_data *) (id->data))->d))
- return KRB5_RC_IO;
-#endif
- return krb5_rc_dfl_close(context, id);
-}
+#define dfl_destroy dfl_close
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_resolve(krb5_context context, krb5_rcache id, char *name)
+static krb5_error_code KRB5_CALLCONV
+dfl_resolve(krb5_context context, krb5_rcache rc, char *name)
{
- struct dfl_data *t = 0;
- krb5_error_code retval;
-
- /* allocate id? no */
- if (!(t = (struct dfl_data *) calloc(1, sizeof(struct dfl_data))))
- return KRB5_RC_MALLOC;
- id->data = (krb5_pointer) t;
- if (name) {
- t->name = strdup(name);
- if (!t->name) {
- retval = KRB5_RC_MALLOC;
- goto cleanup;
- }
- } else
- t->name = 0;
- t->numhits = t->nummisses = 0;
- t->hsize = HASHSIZE; /* no need to store---it's memory-only */
- t->h = (struct authlist **) malloc(t->hsize*sizeof(struct authlist *));
- if (!t->h) {
- retval = KRB5_RC_MALLOC;
- goto cleanup;
- }
- memset(t->h, 0, t->hsize*sizeof(struct authlist *));
- t->a = (struct authlist *) 0;
-#ifndef NOIOSTUFF
- t->d.fd = -1;
-#endif
- t->recovering = 0;
return 0;
-
-cleanup:
- if (t) {
- if (t->name)
- free(t->name);
- if (t->h)
- free(t->h);
- free(t);
- }
- return retval;
-}
-
-void
-krb5_rc_free_entry(krb5_context context, krb5_donot_replay **rep)
-{
- krb5_donot_replay *rp = *rep;
-
- *rep = NULL;
- if (rp)
- {
- if (rp->client)
- free(rp->client);
- if (rp->server)
- free(rp->server);
- if (rp->msghash)
- free(rp->msghash);
- rp->client = NULL;
- rp->server = NULL;
- rp->msghash = NULL;
- free(rp);
- }
}
-/*
- * Parse a string in the format <len>:<data>, with the length
- * represented in ASCII decimal. On parse failure, return 0 but set
- * *result to NULL.
- */
-static krb5_error_code
-parse_counted_string(char **strptr, char **result)
+static krb5_error_code KRB5_CALLCONV
+dfl_recover(krb5_context context, krb5_rcache rc)
{
- char *str = *strptr, *end;
- unsigned long len;
-
- *result = NULL;
-
- /* Parse the length, expecting a ':' afterwards. */
- errno = 0;
- len = strtoul(str, &end, 10);
- if (errno != 0 || *end != ':' || len > strlen(end + 1))
- return 0;
-
- /* Allocate space for *result and copy the data. */
- *result = malloc(len + 1);
- if (!*result)
- return KRB5_RC_MALLOC;
- memcpy(*result, end + 1, len);
- (*result)[len] = '\0';
- *strptr = end + 1 + len;
return 0;
}
-/*
- * Hash extension records have the format:
- * client = <empty string>
- * server = SHA256:<msghash> <clientlen>:<client> <serverlen>:<server>
- * Spaces in the client and server string are represented with
- * with backslashes. Client and server lengths are represented in
- * ASCII decimal (which is different from the 32-bit binary we use
- * elsewhere in the replay cache).
- *
- * On parse failure, we leave the record unmodified.
- */
-static krb5_error_code
-check_hash_extension(krb5_donot_replay *rep)
+static krb5_error_code KRB5_CALLCONV
+dfl_recover_or_init(krb5_context context, krb5_rcache rc, krb5_deltat lifespan)
{
- char *msghash = NULL, *client = NULL, *server = NULL, *str, *end;
- krb5_error_code retval = 0;
-
- /* Check if this appears to match the hash extension format. */
- if (*rep->client)
- return 0;
- if (strncmp(rep->server, "SHA256:", 7) != 0)
- return 0;
-
- /* Parse out the message hash. */
- str = rep->server + 7;
- end = strchr(str, ' ');
- if (!end)
- return 0;
- msghash = k5memdup0(str, end - str, &retval);
- if (!msghash)
- return KRB5_RC_MALLOC;
- str = end + 1;
-
- /* Parse out the client and server. */
- retval = parse_counted_string(&str, &client);
- if (retval != 0 || client == NULL)
- goto error;
- if (*str != ' ')
- goto error;
- str++;
- retval = parse_counted_string(&str, &server);
- if (retval != 0 || server == NULL)
- goto error;
- if (*str)
- goto error;
-
- free(rep->client);
- free(rep->server);
- rep->client = client;
- rep->server = server;
- rep->msghash = msghash;
return 0;
-
-error:
- if (msghash)
- free(msghash);
- if (client)
- free(client);
- if (server)
- free(server);
- return retval;
}
-static krb5_error_code
-krb5_rc_io_fetch(krb5_context context, struct dfl_data *t,
- krb5_donot_replay *rep, int maxlen)
-{
- int len2;
- unsigned int len;
- krb5_error_code retval;
-
- rep->client = rep->server = rep->msghash = NULL;
-
- retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len2,
- sizeof(len2));
- if (retval)
- return retval;
-
- if ((len2 <= 0) || (len2 >= maxlen))
- return KRB5_RC_IO_EOF;
-
- len = len2;
- rep->client = malloc (len);
- if (!rep->client)
- return KRB5_RC_MALLOC;
-
- retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) rep->client, len);
- if (retval)
- goto errout;
-
- retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len2,
- sizeof(len2));
- if (retval)
- goto errout;
-
- if ((len2 <= 0) || (len2 >= maxlen)) {
- retval = KRB5_RC_IO_EOF;
- goto errout;
- }
- len = len2;
-
- rep->server = malloc (len);
- if (!rep->server) {
- retval = KRB5_RC_MALLOC;
- goto errout;
- }
-
- retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) rep->server, len);
- if (retval)
- goto errout;
-
- retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &rep->cusec,
- sizeof(rep->cusec));
- if (retval)
- goto errout;
-
- retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &rep->ctime,
- sizeof(rep->ctime));
- if (retval)
- goto errout;
-
- retval = check_hash_extension(rep);
- if (retval)
- goto errout;
-
- return 0;
-
-errout:
- if (rep->client)
- free(rep->client);
- if (rep->server)
- free(rep->server);
- if (rep->msghash)
- free(rep->msghash);
- rep->client = rep->server = rep->msghash = NULL;
- return retval;
-}
-
-
-static krb5_error_code
-krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id);
-
-static krb5_error_code
-krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id)
-{
-#ifdef NOIOSTUFF
- return KRB5_RC_NOIO;
-#else
-
- struct dfl_data *t = (struct dfl_data *)id->data;
- krb5_donot_replay *rep = 0;
- krb5_error_code retval;
- long max_size;
- int expired_entries = 0;
- krb5_timestamp now;
-
- if ((retval = krb5_rc_io_open(context, &t->d, t->name))) {
- return retval;
- }
-
- t->recovering = 1;
-
- max_size = krb5_rc_io_size(context, &t->d);
-
- rep = NULL;
- if (krb5_rc_io_read(context, &t->d, (krb5_pointer) &t->lifespan,
- sizeof(t->lifespan))) {
- retval = KRB5_RC_IO;
- goto io_fail;
- }
-
- if (!(rep = (krb5_donot_replay *) malloc(sizeof(krb5_donot_replay)))) {
- retval = KRB5_RC_MALLOC;
- goto io_fail;
- }
- rep->client = rep->server = rep->msghash = NULL;
-
- if (krb5_timeofday(context, &now))
- now = 0;
-
- /* now read in each auth_replay and insert into table */
- for (;;) {
- if (krb5_rc_io_mark(context, &t->d)) {
- retval = KRB5_RC_IO;
- goto io_fail;
- }
-
- retval = krb5_rc_io_fetch(context, t, rep, (int) max_size);
-
- if (retval == KRB5_RC_IO_EOF)
- break;
- else if (retval != 0)
- goto io_fail;
-
- if (alive(now, rep, t->lifespan) != CMP_EXPIRED) {
- if (rc_store(context, id, rep, now, TRUE) == CMP_MALLOC) {
- retval = KRB5_RC_MALLOC; goto io_fail;
- }
- } else {
- expired_entries++;
- }
-
- /*
- * free fields allocated by rc_io_fetch
- */
- free(rep->server);
- free(rep->client);
- if (rep->msghash)
- free(rep->msghash);
- rep->client = rep->server = rep->msghash = NULL;
- }
- retval = 0;
- krb5_rc_io_unmark(context, &t->d);
- /*
- * An automatic expunge here could remove the need for
- * mark/unmark but that would be inefficient.
- */
-io_fail:
- krb5_rc_free_entry(context, &rep);
- if (retval)
- krb5_rc_io_close(context, &t->d);
- else if (expired_entries > EXCESSREPS)
- retval = krb5_rc_dfl_expunge_locked(context, id);
- t->recovering = 0;
- return retval;
-
-#endif
-}
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_recover(krb5_context context, krb5_rcache id)
-{
- krb5_error_code ret;
-
- k5_mutex_lock(&id->lock);
- ret = krb5_rc_dfl_recover_locked(context, id);
- k5_mutex_unlock(&id->lock);
- return ret;
-}
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_recover_or_init(krb5_context context, krb5_rcache id,
- krb5_deltat lifespan)
-{
- krb5_error_code retval;
-
- k5_mutex_lock(&id->lock);
- retval = krb5_rc_dfl_recover_locked(context, id);
- if (retval)
- retval = krb5_rc_dfl_init_locked(context, id, lifespan);
- k5_mutex_unlock(&id->lock);
- return retval;
-}
-
-static krb5_error_code
-krb5_rc_io_store(krb5_context context, struct dfl_data *t,
- krb5_donot_replay *rep)
-{
- size_t clientlen, serverlen;
- unsigned int len;
- krb5_error_code ret;
- struct k5buf buf, extbuf;
- char *extstr;
-
- clientlen = strlen(rep->client);
- serverlen = strlen(rep->server);
-
- if (rep->msghash) {
- /*
- * Write a hash extension record, to be followed by a record
- * in regular format (without the message hash) for the
- * benefit of old implementations.
- */
-
- /* Format the extension value so we know its length. */
- k5_buf_init_dynamic(&extbuf);
- k5_buf_add_fmt(&extbuf, "SHA256:%s %lu:%s %lu:%s", rep->msghash,
- (unsigned long)clientlen, rep->client,
- (unsigned long)serverlen, rep->server);
- if (k5_buf_status(&extbuf) != 0)
- return KRB5_RC_MALLOC;
- extstr = extbuf.data;
-
- /*
- * Put the extension value into the server field of a
- * regular-format record, with an empty client field.
- */
- k5_buf_init_dynamic(&buf);
- len = 1;
- k5_buf_add_len(&buf, (char *)&len, sizeof(len));
- k5_buf_add_len(&buf, "", 1);
- len = strlen(extstr) + 1;
- k5_buf_add_len(&buf, (char *)&len, sizeof(len));
- k5_buf_add_len(&buf, extstr, len);
- k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec));
- k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime));
- free(extstr);
- } else /* No extension record needed. */
- k5_buf_init_dynamic(&buf);
-
- len = clientlen + 1;
- k5_buf_add_len(&buf, (char *)&len, sizeof(len));
- k5_buf_add_len(&buf, rep->client, len);
- len = serverlen + 1;
- k5_buf_add_len(&buf, (char *)&len, sizeof(len));
- k5_buf_add_len(&buf, rep->server, len);
- k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec));
- k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime));
-
- if (k5_buf_status(&buf) != 0)
- return KRB5_RC_MALLOC;
-
- ret = krb5_rc_io_write(context, &t->d, buf.data, buf.len);
- k5_buf_free(&buf);
- return ret;
-}
-
-static krb5_error_code krb5_rc_dfl_expunge_locked(krb5_context, krb5_rcache);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
+static krb5_error_code KRB5_CALLCONV
+dfl_store(krb5_context context, krb5_rcache rc, krb5_donot_replay *rep)
{
krb5_error_code ret;
- struct dfl_data *t;
- krb5_timestamp now;
+ int fd;
- ret = krb5_timeofday(context, &now);
+ ret = open_file(context, &fd);
if (ret)
return ret;
- k5_mutex_lock(&id->lock);
-
- switch(rc_store(context, id, rep, now, FALSE)) {
- case CMP_MALLOC:
- k5_mutex_unlock(&id->lock);
- return KRB5_RC_MALLOC;
- case CMP_REPLAY:
- k5_mutex_unlock(&id->lock);
- return KRB5KRB_AP_ERR_REPEAT;
- case 0: break;
- default: /* wtf? */ ;
- }
- t = (struct dfl_data *)id->data;
-#ifndef NOIOSTUFF
- ret = krb5_rc_io_store(context, t, rep);
- if (ret) {
- k5_mutex_unlock(&id->lock);
- return ret;
- }
-#endif
- /* Shall we automatically expunge? */
- if (t->nummisses > t->numhits + EXCESSREPS)
- {
- ret = krb5_rc_dfl_expunge_locked(context, id);
- k5_mutex_unlock(&id->lock);
- return ret;
- }
-#ifndef NOIOSTUFF
- else
- {
- if (krb5_rc_io_sync(context, &t->d)) {
- k5_mutex_unlock(&id->lock);
- return KRB5_RC_IO;
- }
- }
-#endif
- k5_mutex_unlock(&id->lock);
- return 0;
+ ret = k5_rcfile2_store(context, fd, rep);
+ close(fd);
+ return ret;
}
-static krb5_error_code
-krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
+static krb5_error_code KRB5_CALLCONV
+dfl_expunge(krb5_context context, krb5_rcache rc)
{
- struct dfl_data *t = (struct dfl_data *)id->data;
-#ifdef NOIOSTUFF
- unsigned int i;
- struct authlist **q;
- struct authlist **qt;
- struct authlist *r;
- struct authlist *rt;
- krb5_timestamp now;
-
- if (krb5_timestamp(context, &now))
- now = 0;
-
- for (q = &t->a; *q; q = qt) {
- qt = &(*q)->na;
- if (alive(now, &(*q)->rep, t->lifespan) == CMP_EXPIRED) {
- free((*q)->rep.client);
- free((*q)->rep.server);
- if ((*q)->rep.msghash)
- free((*q)->rep.msghash);
- free(*q);
- *q = *qt; /* why doesn't this feel right? */
- }
- }
- for (i = 0; i < t->hsize; i++)
- t->h[i] = (struct authlist *) 0;
- for (r = t->a; r; r = r->na) {
- i = hash(&r->rep, t->hsize);
- rt = t->h[i];
- t->h[i] = r;
- r->nh = rt;
- }
return 0;
-#else
- struct authlist *q;
- char *name;
- krb5_error_code retval = 0;
- krb5_rcache tmp;
- krb5_deltat lifespan = t->lifespan; /* save original lifespan */
-
- if (! t->recovering) {
- name = t->name;
- t->name = 0; /* Clear name so it isn't freed */
- (void) krb5_rc_dfl_close_no_free(context, id);
- retval = krb5_rc_dfl_resolve(context, id, name);
- free(name);
- if (retval)
- return retval;
- retval = krb5_rc_dfl_recover_locked(context, id);
- if (retval)
- return retval;
- t = (struct dfl_data *)id->data; /* point to recovered cache */
- }
-
- retval = krb5_rc_resolve_type(context, &tmp, "dfl");
- if (retval)
- return retval;
- retval = krb5_rc_resolve(context, tmp, 0);
- if (retval)
- goto cleanup;
- retval = krb5_rc_initialize(context, tmp, lifespan);
- if (retval)
- goto cleanup;
- for (q = t->a; q; q = q->na) {
- if (krb5_rc_io_store(context, (struct dfl_data *)tmp->data, &q->rep)) {
- retval = KRB5_RC_IO;
- goto cleanup;
- }
- }
- /* NOTE: We set retval in case we have an error */
- retval = KRB5_RC_IO;
- if (krb5_rc_io_sync(context, &((struct dfl_data *)tmp->data)->d))
- goto cleanup;
- if (krb5_rc_io_sync(context, &t->d))
- goto cleanup;
- if (krb5_rc_io_move(context, &t->d, &((struct dfl_data *)tmp->data)->d))
- goto cleanup;
- retval = 0;
-cleanup:
- (void) krb5_rc_dfl_close(context, tmp);
- return retval;
-#endif
}
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_expunge(krb5_context context, krb5_rcache id)
-{
- krb5_error_code ret;
-
- k5_mutex_lock(&id->lock);
- ret = krb5_rc_dfl_expunge_locked(context, id);
- k5_mutex_unlock(&id->lock);
- return ret;
-}
+const krb5_rc_ops krb5_rc_dfl_ops =
+{
+ 0,
+ "dfl",
+ dfl_init,
+ dfl_recover,
+ dfl_recover_or_init,
+ dfl_destroy,
+ dfl_close,
+ dfl_store,
+ dfl_expunge,
+ dfl_get_span,
+ dfl_get_name,
+ dfl_resolve
+};
diff --git a/src/lib/krb5/rcache/rc_dfl.h b/src/lib/krb5/rcache/rc_dfl.h
deleted file mode 100644
index ad036a2..0000000
--- a/src/lib/krb5/rcache/rc_dfl.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/rcache/rc_dfl.h */
-/*
- * This file of the Kerberos V5 software is derived from public-domain code
- * contributed by Daniel J. Bernstein, <brnstnd at acf10.nyu.edu>.
- *
- */
-
-/*
- * Declarations for the default replay cache implementation.
- */
-
-#ifndef KRB5_RC_DFL_H
-#define KRB5_RC_DFL_H
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_init(krb5_context, krb5_rcache, krb5_deltat);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_recover(krb5_context, krb5_rcache);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_recover_or_init(krb5_context, krb5_rcache, krb5_deltat);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_destroy(krb5_context, krb5_rcache);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_close(krb5_context, krb5_rcache);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_store(krb5_context, krb5_rcache, krb5_donot_replay *);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_expunge(krb5_context, krb5_rcache);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_get_span(krb5_context, krb5_rcache, krb5_deltat *);
-
-char * KRB5_CALLCONV
-krb5_rc_dfl_get_name(krb5_context, krb5_rcache);
-
-krb5_error_code KRB5_CALLCONV
-krb5_rc_dfl_resolve(krb5_context, krb5_rcache, char *);
-
-krb5_error_code krb5_rc_dfl_close_no_free(krb5_context, krb5_rcache);
-void krb5_rc_free_entry(krb5_context, krb5_donot_replay **);
-#endif
diff --git a/src/lib/krb5/rcache/rc_io.c b/src/lib/krb5/rcache/rc_io.c
deleted file mode 100644
index 1800460..0000000
--- a/src/lib/krb5/rcache/rc_io.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/rcache/rc_io.c */
-/*
- * This file of the Kerberos V5 software is derived from public-domain code
- * contributed by Daniel J. Bernstein, <brnstnd at acf10.nyu.edu>.
- *
- */
-
-/*
- * I/O functions for the replay cache default implementation.
- */
-
-#if defined(_WIN32)
-# define PATH_SEPARATOR "\\"
-#else
-# define PATH_SEPARATOR "/"
-#endif
-
-#define KRB5_RC_VNO 0x0501 /* krb5, rcache v 1 */
-
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include "k5-int.h"
-#include <stdio.h> /* for P_tmpdir */
-#include "rc_base.h"
-#include "rc_dfl.h"
-#include "rc_io.h"
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#if !defined(_WINSOCKAPI_)
-#include <netinet/in.h>
-#endif
-#else
-#error find some way to use net-byte-order file version numbers.
-#endif
-
-#define UNIQUE getpid() /* hopefully unique number */
-
-#define GETDIR (dir = getdir(), dirlen = strlen(dir) + sizeof(PATH_SEPARATOR) - 1)
-
-static char *
-getdir(void)
-{
- char *dir;
-
- if (!(dir = secure_getenv("KRB5RCACHEDIR"))) {
-#if defined(_WIN32)
- if (!(dir = getenv("TEMP")))
- if (!(dir = getenv("TMP")))
- dir = "C:";
-#else
- if (!(dir = secure_getenv("TMPDIR"))) {
-#ifdef RCTMPDIR
- dir = RCTMPDIR;
-#else
- dir = "/tmp";
-#endif
- }
-#endif
- }
- return dir;
-}
-
-/*
- * Called from krb5_rc_io_creat(); calls mkstemp() and does some
- * sanity checking on the file modes in case some broken mkstemp()
- * implementation creates the file with overly permissive modes. To
- * avoid race conditions, do not fchmod() a file for which mkstemp set
- * incorrect modes.
- */
-static krb5_error_code
-krb5_rc_io_mkstemp(krb5_context context, krb5_rc_iostuff *d, char *dir)
-{
- krb5_error_code retval = 0;
-#if HAVE_SYS_STAT_H
- struct stat stbuf;
-
- memset(&stbuf, 0, sizeof(stbuf));
-#endif
- if (asprintf(&d->fn, "%s%skrb5_RCXXXXXX",
- dir, PATH_SEPARATOR) < 0) {
- d->fn = NULL;
- return KRB5_RC_IO_MALLOC;
- }
- d->fd = mkstemp(d->fn);
- if (d->fd == -1) {
- /*
- * This return value is deliberate because d->fd == -1 causes
- * caller to go into errno interpretation code.
- */
- return 0;
- }
-#if HAVE_SYS_STAT_H
- /*
- * Be paranoid and check that mkstemp made the file accessible
- * only to the user.
- */
- retval = fstat(d->fd, &stbuf);
- if (retval) {
- k5_setmsg(context, retval,
- _("Cannot fstat replay cache file %s: %s"),
- d->fn, strerror(errno));
- return KRB5_RC_IO_UNKNOWN;
- }
- if (stbuf.st_mode & 077) {
- k5_setmsg(context, retval,
- _("Insecure mkstemp() file mode for replay cache file %s; "
- "try running this program with umask 077"), d->fn);
- return KRB5_RC_IO_UNKNOWN;
- }
-#endif
- return 0;
-}
-
-static krb5_error_code
-rc_map_errno (krb5_context context, int e, const char *fn,
- const char *operation)
-{
- switch (e) {
- case EFBIG:
-#ifdef EDQUOT
- case EDQUOT:
-#endif
- case ENOSPC:
- return KRB5_RC_IO_SPACE;
-
- case EIO:
- return KRB5_RC_IO_IO;
-
- case EPERM:
- case EACCES:
- case EROFS:
- case EEXIST:
- k5_setmsg(context, KRB5_RC_IO_PERM,
- _("Cannot %s replay cache file %s: %s"),
- operation, fn, strerror(e));
- return KRB5_RC_IO_PERM;
-
- default:
- k5_setmsg(context, KRB5_RC_IO_UNKNOWN, _("Cannot %s replay cache: %s"),
- operation, strerror(e));
- return KRB5_RC_IO_UNKNOWN;
- }
-}
-
-
-krb5_error_code
-krb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
-{
- krb5_int16 rc_vno = htons(KRB5_RC_VNO);
- krb5_error_code retval = 0;
- int flags, do_not_unlink = 0;
- char *dir;
- size_t dirlen;
-
- GETDIR;
- if (fn && *fn) {
- if (asprintf(&d->fn, "%s%s%s", dir, PATH_SEPARATOR, *fn) < 0)
- return KRB5_RC_IO_MALLOC;
- d->fd = -1;
- do {
- if (unlink(d->fn) == -1 && errno != ENOENT)
- break;
- flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY;
- d->fd = THREEPARAMOPEN(d->fn, flags, 0600);
- } while (d->fd == -1 && errno == EEXIST);
- } else {
- retval = krb5_rc_io_mkstemp(context, d, dir);
- if (retval)
- goto cleanup;
- if (d->fd != -1 && fn) {
- *fn = strdup(d->fn + dirlen);
- if (*fn == NULL) {
- free(d->fn);
- return KRB5_RC_IO_MALLOC;
- }
- }
- }
- if (d->fd == -1) {
- retval = rc_map_errno(context, errno, d->fn, "create");
- if (retval == KRB5_RC_IO_PERM)
- do_not_unlink = 1;
- goto cleanup;
- }
- set_cloexec_fd(d->fd);
- retval = krb5_rc_io_write(context, d, (krb5_pointer)&rc_vno,
- sizeof(rc_vno));
- if (retval)
- goto cleanup;
-
- retval = krb5_rc_io_sync(context, d);
-
-cleanup:
- if (retval) {
- if (d->fn) {
- if (!do_not_unlink)
- (void) unlink(d->fn);
- free(d->fn);
- d->fn = NULL;
- }
- if (d->fd != -1) {
- (void) close(d->fd);
- }
- }
- return retval;
-}
-
-static krb5_error_code
-krb5_rc_io_open_internal(krb5_context context, krb5_rc_iostuff *d, char *fn,
- char* full_pathname)
-{
- krb5_int16 rc_vno;
- krb5_error_code retval = 0;
- int do_not_unlink = 1;
-#ifndef NO_USERID
- struct stat sb1, sb2;
-#endif
- char *dir;
-
- dir = getdir();
- if (full_pathname) {
- if (!(d->fn = strdup(full_pathname)))
- return KRB5_RC_IO_MALLOC;
- } else {
- if (asprintf(&d->fn, "%s%s%s", dir, PATH_SEPARATOR, fn) < 0)
- return KRB5_RC_IO_MALLOC;
- }
-
-#ifdef NO_USERID
- d->fd = THREEPARAMOPEN(d->fn, O_RDWR | O_BINARY, 0600);
- if (d->fd == -1) {
- retval = rc_map_errno(context, errno, d->fn, "open");
- goto cleanup;
- }
-#else
- d->fd = -1;
- retval = lstat(d->fn, &sb1);
- if (retval != 0) {
- retval = rc_map_errno(context, errno, d->fn, "lstat");
- goto cleanup;
- }
- d->fd = THREEPARAMOPEN(d->fn, O_RDWR | O_BINARY, 0600);
- if (d->fd < 0) {
- retval = rc_map_errno(context, errno, d->fn, "open");
- goto cleanup;
- }
- retval = fstat(d->fd, &sb2);
- if (retval < 0) {
- retval = rc_map_errno(context, errno, d->fn, "fstat");
- goto cleanup;
- }
- /* check if someone was playing with symlinks */
- if ((sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino)
- || (sb1.st_mode & S_IFMT) != S_IFREG)
- {
- retval = KRB5_RC_IO_PERM;
- k5_setmsg(context, retval, "rcache not a file %s", d->fn);
- goto cleanup;
- }
- /* check that non other can read/write/execute the file */
- if (sb1.st_mode & 077) {
- k5_setmsg(context, retval,
- _("Insecure file mode for replay cache file %s"), d->fn);
- return KRB5_RC_IO_UNKNOWN;
- }
- /* owned by me */
- if (sb1.st_uid != geteuid()) {
- retval = KRB5_RC_IO_PERM;
- k5_setmsg(context, retval, _("rcache not owned by %d"),
- (int)geteuid());
- goto cleanup;
- }
-#endif
- set_cloexec_fd(d->fd);
-
- do_not_unlink = 0;
- retval = krb5_rc_io_read(context, d, (krb5_pointer) &rc_vno,
- sizeof(rc_vno));
- if (retval)
- goto cleanup;
-
- if (ntohs(rc_vno) != KRB5_RC_VNO)
- retval = KRB5_RCACHE_BADVNO;
-
-cleanup:
- if (retval) {
- if (!do_not_unlink)
- (void) unlink(d->fn);
- free(d->fn);
- d->fn = NULL;
- if (d->fd >= 0)
- (void) close(d->fd);
- }
- return retval;
-}
-
-krb5_error_code
-krb5_rc_io_open(krb5_context context, krb5_rc_iostuff *d, char *fn)
-{
- return krb5_rc_io_open_internal(context, d, fn, NULL);
-}
-
-krb5_error_code
-krb5_rc_io_move(krb5_context context, krb5_rc_iostuff *new1,
- krb5_rc_iostuff *old)
-{
-#if defined(_WIN32) || defined(__CYGWIN__)
- char *new_fn = NULL;
- char *old_fn = NULL;
- off_t offset = 0;
- krb5_error_code retval = 0;
- /*
- * Initial work around provided by Tom Sanfilippo to work around
- * poor Windows emulation of POSIX functions. Rename and dup has
- * different semantics!
- *
- * Additional fixes and explanation provided by dalmeida at mit.edu:
- *
- * First, we save the offset of "old". Then, we close and remove
- * the "new" file so we can do the rename. We also close "old" to
- * make sure the rename succeeds (though that might not be
- * necessary on some systems).
- *
- * Next, we do the rename. If all goes well, we seek the "new"
- * file to the position "old" was at.
- *
- * --- WARNING!!! ---
- *
- * Since "old" is now gone, we mourn its disappearance, but we
- * cannot emulate that Unix behavior... THIS BEHAVIOR IS
- * DIFFERENT FROM UNIX. However, it is ok because this function
- * gets called such that "old" gets closed right afterwards.
- */
- offset = lseek(old->fd, 0, SEEK_CUR);
-
- new_fn = new1->fn;
- new1->fn = NULL;
- close(new1->fd);
- new1->fd = -1;
-
- unlink(new_fn);
-
- old_fn = old->fn;
- old->fn = NULL;
- close(old->fd);
- old->fd = -1;
-
- if (rename(old_fn, new_fn) == -1) { /* MUST be atomic! */
- retval = KRB5_RC_IO_UNKNOWN;
- goto cleanup;
- }
-
- retval = krb5_rc_io_open_internal(context, new1, 0, new_fn);
- if (retval)
- goto cleanup;
-
- if (lseek(new1->fd, offset, SEEK_SET) == -1) {
- retval = KRB5_RC_IO_UNKNOWN;
- goto cleanup;
- }
-
-cleanup:
- free(new_fn);
- free(old_fn);
- return retval;
-#else
- char *fn = NULL;
- if (rename(old->fn, new1->fn) == -1) /* MUST be atomic! */
- return KRB5_RC_IO_UNKNOWN;
- fn = new1->fn;
- new1->fn = NULL; /* avoid clobbering */
- (void) krb5_rc_io_close(context, new1);
- new1->fn = fn;
- new1->fd = dup(old->fd);
- set_cloexec_fd(new1->fd);
- return 0;
-#endif
-}
-
-krb5_error_code
-krb5_rc_io_write(krb5_context context, krb5_rc_iostuff *d, krb5_pointer buf,
- unsigned int num)
-{
- if (write(d->fd, (char *) buf, num) == -1)
- switch(errno)
- {
-#ifdef EDQUOT
- case EDQUOT:
-#endif
- case EFBIG:
- case ENOSPC:
- k5_setmsg(context, KRB5_RC_IO_SPACE,
- _("Can't write to replay cache: %s"), strerror(errno));
- return KRB5_RC_IO_SPACE;
- case EIO:
- k5_setmsg(context, KRB5_RC_IO_IO,
- _("Can't write to replay cache: %s"), strerror(errno));
- return KRB5_RC_IO_IO;
- case EBADF:
- default:
- k5_setmsg(context, KRB5_RC_IO_UNKNOWN,
- _("Can't write to replay cache: %s"), strerror(errno));
- return KRB5_RC_IO_UNKNOWN;
- }
- return 0;
-}
-
-krb5_error_code
-krb5_rc_io_sync(krb5_context context, krb5_rc_iostuff *d)
-{
-#if defined(_WIN32)
-#ifndef fsync
-#define fsync _commit
-#endif
-#endif
- if (fsync(d->fd) == -1) {
- switch(errno)
- {
- case EBADF: return KRB5_RC_IO_UNKNOWN;
- case EIO: return KRB5_RC_IO_IO;
- default:
- k5_setmsg(context, KRB5_RC_IO_UNKNOWN,
- _("Cannot sync replay cache file: %s"), strerror(errno));
- return KRB5_RC_IO_UNKNOWN;
- }
- }
- return 0;
-}
-
-krb5_error_code
-krb5_rc_io_read(krb5_context context, krb5_rc_iostuff *d, krb5_pointer buf,
- unsigned int num)
-{
- int count;
- if ((count = read(d->fd, (char *) buf, num)) == -1)
- switch(errno)
- {
- case EIO: return KRB5_RC_IO_IO;
- case EBADF:
- default:
- k5_setmsg(context, KRB5_RC_IO_UNKNOWN,
- _("Can't read from replay cache: %s"), strerror(errno));
- return KRB5_RC_IO_UNKNOWN;
- }
- if (count < 0 || (unsigned int)count != num)
- return KRB5_RC_IO_EOF;
- return 0;
-}
-
-krb5_error_code
-krb5_rc_io_close(krb5_context context, krb5_rc_iostuff *d)
-{
- if (d->fn != NULL) {
- free(d->fn);
- d->fn = NULL;
- }
- if (d->fd != -1) {
- if (close(d->fd) == -1) /* can't happen */
- return KRB5_RC_IO_UNKNOWN;
- d->fd = -1;
- }
- return 0;
-}
-
-krb5_error_code
-krb5_rc_io_destroy(krb5_context context, krb5_rc_iostuff *d)
-{
- if (unlink(d->fn) == -1)
- switch(errno)
- {
- case EIO:
- k5_setmsg(context, KRB5_RC_IO_IO,
- _("Can't destroy replay cache: %s"), strerror(errno));
- return KRB5_RC_IO_IO;
- case EPERM:
- case EBUSY:
- case EROFS:
- k5_setmsg(context, KRB5_RC_IO_PERM,
- _("Can't destroy replay cache: %s"), strerror(errno));
- return KRB5_RC_IO_PERM;
- case EBADF:
- default:
- k5_setmsg(context, KRB5_RC_IO_UNKNOWN,
- _("Can't destroy replay cache: %s"), strerror(errno));
- return KRB5_RC_IO_UNKNOWN;
- }
- return 0;
-}
-
-krb5_error_code
-krb5_rc_io_mark(krb5_context context, krb5_rc_iostuff *d)
-{
- d->mark = lseek(d->fd, (off_t) 0, SEEK_CUR); /* can't fail */
- return 0;
-}
-
-krb5_error_code
-krb5_rc_io_unmark(krb5_context context, krb5_rc_iostuff *d)
-{
- (void) lseek(d->fd, d->mark, SEEK_SET); /* if it fails, tough luck */
- return 0;
-}
-
-long
-krb5_rc_io_size(krb5_context context, krb5_rc_iostuff *d)
-{
- struct stat statb;
-
- if (fstat(d->fd, &statb) == 0)
- return statb.st_size;
- else
- return 0;
-}
diff --git a/src/lib/krb5/rcache/rc_io.h b/src/lib/krb5/rcache/rc_io.h
deleted file mode 100644
index f5ab239..0000000
--- a/src/lib/krb5/rcache/rc_io.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/rcache/rc_io.h */
-/*
- * This file of the Kerberos V5 software is derived from public-domain code
- * contributed by Daniel J. Bernstein, <brnstnd at acf10.nyu.edu>.
- *
- */
-
-/*
- * Declarations for the I/O sub-package of the replay cache
- */
-
-#ifndef KRB5_RC_IO_H
-#define KRB5_RC_IO_H
-
-typedef struct krb5_rc_iostuff {
- int fd;
-#ifdef MSDOS_FILESYSTEM
- long mark;
-#else
- off_t mark; /* on newer systems, should be pos_t */
-#endif
- char *fn;
-} krb5_rc_iostuff;
-
-/* first argument is always iostuff for result file */
-
-krb5_error_code
-krb5_rc_io_creat(krb5_context, krb5_rc_iostuff *, char **);
-
-krb5_error_code
-krb5_rc_io_open(krb5_context, krb5_rc_iostuff *, char *);
-
-krb5_error_code
-krb5_rc_io_move(krb5_context, krb5_rc_iostuff *, krb5_rc_iostuff *);
-
-krb5_error_code
-krb5_rc_io_write(krb5_context, krb5_rc_iostuff *, krb5_pointer, unsigned int);
-
-krb5_error_code
-krb5_rc_io_read(krb5_context, krb5_rc_iostuff *, krb5_pointer, unsigned int);
-
-krb5_error_code
-krb5_rc_io_close(krb5_context, krb5_rc_iostuff *);
-
-krb5_error_code
-krb5_rc_io_destroy(krb5_context, krb5_rc_iostuff *);
-
-krb5_error_code
-krb5_rc_io_mark(krb5_context, krb5_rc_iostuff *);
-
-krb5_error_code
-krb5_rc_io_unmark(krb5_context, krb5_rc_iostuff *);
-
-krb5_error_code
-krb5_rc_io_sync(krb5_context, krb5_rc_iostuff *);
-
-long
-krb5_rc_io_size(krb5_context, krb5_rc_iostuff *);
-#endif
diff --git a/src/lib/krb5/rcache/rcdef.c b/src/lib/krb5/rcache/rcdef.c
deleted file mode 100644
index 01d166b..0000000
--- a/src/lib/krb5/rcache/rcdef.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/rcache/rcdef.c - Default replay cache operations vector */
-/*
- * Copyright 1990 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "k5-int.h"
-#include "rc-int.h"
-#include "rc_dfl.h"
-
-const krb5_rc_ops krb5_rc_dfl_ops =
-{
- 0,
- "dfl",
- krb5_rc_dfl_init,
- krb5_rc_dfl_recover,
- krb5_rc_dfl_recover_or_init,
- krb5_rc_dfl_destroy,
- krb5_rc_dfl_close,
- krb5_rc_dfl_store,
- krb5_rc_dfl_expunge,
- krb5_rc_dfl_get_span,
- krb5_rc_dfl_get_name,
- krb5_rc_dfl_resolve
-};
More information about the cvs-krb5
mailing list