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