krb5 commit: Add KRB5RCACHENAME and default_rcache_name

Greg Hudson ghudson at mit.edu
Fri May 31 15:45:14 EDT 2019


https://github.com/krb5/krb5/commit/0e68760cb8dce4ea25fd73d6eab95bce103b6443
commit 0e68760cb8dce4ea25fd73d6eab95bce103b6443
Author: Greg Hudson <ghudson at mit.edu>
Date:   Fri May 17 13:45:08 2019 -0400

    Add KRB5RCACHENAME and default_rcache_name
    
    In krb5_get_server_rcache(), stop constructing a residual value based
    on piece and the euid, and instead resolve default replay cache
    (previously an unused operation, as krb5_rc_default() was not part of
    the API and was never used).
    
    To determine the default replay cache name, try the KRB5RCACHENAME
    environment variable first, and then try KRB5RCACHETYPE for
    compatibility.  If neither of those environment variables are set, try
    the default_rcache_name profile relation in [libdefaults] before
    falling back to "dfl:".
    
    ticket: 8786

 doc/admin/conf_files/krb5_conf.rst |    5 ++
 doc/basic/rcache_def.rst           |   29 ++++------
 doc/user/user_config/kerberos.rst  |   17 +++++--
 src/include/k5-int.h               |    1 +
 src/include/krb5/krb5.hin          |   11 ++--
 src/lib/krb5/krb/srv_rcache.c      |   58 ++-------------------
 src/lib/krb5/rcache/rc_base.c      |   98 +++++++++++++++++++++++-------------
 src/man/kerberos.man               |   21 ++++++--
 src/man/krb5.conf.man              |    5 ++
 9 files changed, 126 insertions(+), 119 deletions(-)

diff --git a/doc/admin/conf_files/krb5_conf.rst b/doc/admin/conf_files/krb5_conf.rst
index 89f0243..e4de1a0 100644
--- a/doc/admin/conf_files/krb5_conf.rst
+++ b/doc/admin/conf_files/krb5_conf.rst
@@ -148,6 +148,11 @@ The libdefaults section may contain any of the following relations:
     application servers such as sshd.  The default is |keytab|.  This
     relation is subject to parameter expansion (see below).
 
+**default_rcache_name**
+    This relation specifies the name of the default replay cache.
+    The default is ``dfl:``.  This relation is subject to parameter
+    expansion (see below).  New in release 1.18.
+
 **default_realm**
     Identifies the default Kerberos realm for the client.  Set its
     value to your Kerberos realm.  If this value is not set, then a
diff --git a/doc/basic/rcache_def.rst b/doc/basic/rcache_def.rst
index 5e550fc..de3b215 100644
--- a/doc/basic/rcache_def.rst
+++ b/doc/basic/rcache_def.rst
@@ -74,9 +74,6 @@ are in lowercase.  The following types are defined:
    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 location of the replay cache file is determined
 as follows:
 
@@ -96,21 +93,19 @@ directory, unless overridden by the **KRB5RCACHEDIR** environment
 variable.  The filename on Windows is ``krb5.rcache2``, and the file
 is opened normally.
 
-Performance issues
-------------------
+Default replay cache name
+-------------------------
+
+The default replay cache name is determined by the following, in
+descending order of priority:
 
-Several known minor performance issues that may occur when replay
-cache is enabled on the Kerberos system include: delays due to writing
-the authenticator data to disk slowing down response time for very
-heavily loaded servers, and delays during the rewrite that may be
-unacceptable to high-performance services.
+#. The **KRB5RCACHENAME** environment variable (new in release 1.18).
 
-For use cases where replays are adequately defended against for all
-protocols using a given service principal name, or where performance
-or other considerations outweigh the risk of replays, the special
-replay cache type "none" can be specified::
+#. The **KRB5RCACHETYPE** environment variable.  If this variable is
+   set, the residual value is empty.
 
-    KRB5RCACHETYPE=none
+#. The **default_rcache_name** profile variable in :ref:`libdefaults`
+   (new in release 1.18).
 
-It doesn't record any information about authenticators, and reports
-that any authenticator seen is not a replay.
+#. If none of the above are set, the default replay cache name is
+   ``dfl:``.
diff --git a/doc/user/user_config/kerberos.rst b/doc/user/user_config/kerberos.rst
index 56412f0..bcb79d9 100644
--- a/doc/user/user_config/kerberos.rst
+++ b/doc/user/user_config/kerberos.rst
@@ -108,13 +108,22 @@ programs.  These include:
     Distribution Center daemon and associated programs.  The default
     is |kdcdir|\ ``/kdc.conf``.
 
+**KRB5RCACHENAME**
+    (New in release 1.18) Specifies the location of the default replay
+    cache, in the form *type*:*residual*.  The ``file2`` type with a
+    pathname residual specifies a replay cache file in the version-2
+    format in the specified location.  The ``none`` type (residual is
+    ignored) disables the replay cache.  The ``dfl`` type (residual is
+    ignored) indicates the default, which uses a file2 replay cache in
+    a temporary directory.  The default is ``dfl:``.
+
 **KRB5RCACHETYPE**
-    Specifies the default type of replay cache to use for servers.
-    Valid types include ``dfl`` for the normal file type and ``none``
-    for no replay cache.  The default is ``dfl``.
+    Specifies the type of the default replay cache, if
+    **KRB5RCACHENAME** is unspecified.  No residual can be specified,
+    so ``none`` and ``dfl`` are the only useful types.
 
 **KRB5RCACHEDIR**
-    Specifies the default directory for replay caches used by servers.
+    Specifies the directory used by the ``dfl`` replay cache type.
     The default is the value of the **TMPDIR** environment variable,
     or ``/var/tmp`` if **TMPDIR** is not set.
 
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 30e4501..a2faa9d 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -196,6 +196,7 @@ typedef unsigned char   u_char;
 #define KRB5_CONF_DEFAULT_KEYTAB_NAME          "default_keytab_name"
 #define KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION "default_principal_expiration"
 #define KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS      "default_principal_flags"
+#define KRB5_CONF_DEFAULT_RCACHE_NAME          "default_rcache_name"
 #define KRB5_CONF_DEFAULT_REALM                "default_realm"
 #define KRB5_CONF_DEFAULT_TGS_ENCTYPES         "default_tgs_enctypes"
 #define KRB5_CONF_DEFAULT_TKT_ENCTYPES         "default_tkt_enctypes"
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 8bdca2f..d65cf8f 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -3944,13 +3944,14 @@ krb5_copy_checksum(krb5_context context, const krb5_checksum *ckfrom,
  * Generate a replay cache object for server use and open it.
  *
  * @param [in]  context         Library context
- * @param [in]  piece           Unique identifier for replay cache
+ * @param [in]  piece           Unused (replay cache identifier)
  * @param [out] rcptr           Handle to an open rcache
  *
- * This function generates a replay cache name based on @a piece and opens a
- * handle to it.  Typically @a piece is the first component of the service
- * principal name.  Use krb5_rc_close() to close @a rcptr when it is no longer
- * needed.
+ * This function creates a handle to the default replay cache.  Use
+ * krb5_rc_close() to close @a rcptr when it is no longer needed.
+ *
+ * @version Prior to release 1.18, this function creates a handle to a
+ * different replay cache for each unique value of @a piece.
  *
  * @retval 0 Success; otherwise - Kerberos error codes
  */
diff --git a/src/lib/krb5/krb/srv_rcache.c b/src/lib/krb5/krb/srv_rcache.c
index 692c853..0929145 100644
--- a/src/lib/krb5/krb/srv_rcache.c
+++ b/src/lib/krb5/krb/srv_rcache.c
@@ -28,60 +28,14 @@
 #include <ctype.h>
 #include <stdio.h>
 
-/* Macro for valid RC name characters*/
-#define isvalidrcname(x) ((!ispunct(x))&&isgraph(x))
 krb5_error_code KRB5_CALLCONV
 krb5_get_server_rcache(krb5_context context, const krb5_data *piece,
                        krb5_rcache *rcptr)
 {
-    krb5_rcache rcache = 0;
-    char *cachetype;
-    krb5_error_code retval;
-    unsigned int i;
-    struct k5buf buf = EMPTY_K5BUF;
-#ifdef HAVE_GETEUID
-    unsigned long uid = geteuid();
-#endif
-
-    if (piece == NULL)
-        return ENOMEM;
-
-    cachetype = krb5_rc_default_type(context);
-
-    k5_buf_init_dynamic(&buf);
-    k5_buf_add(&buf, cachetype);
-    k5_buf_add(&buf, ":");
-    for (i = 0; i < piece->length; i++) {
-        if (piece->data[i] == '-')
-            k5_buf_add(&buf, "--");
-        else if (!isvalidrcname((int) piece->data[i]))
-            k5_buf_add_fmt(&buf, "-%03o", piece->data[i]);
-        else
-            k5_buf_add_len(&buf, &piece->data[i], 1);
-    }
-#ifdef HAVE_GETEUID
-    k5_buf_add_fmt(&buf, "_%lu", uid);
-#endif
-
-    if (k5_buf_status(&buf) != 0)
-        return ENOMEM;
-
-    retval = krb5_rc_resolve_full(context, &rcache, buf.data);
-    if (retval)
-        goto cleanup;
-
-    retval = krb5_rc_recover_or_initialize(context, rcache,
-                                           context->clockskew);
-    if (retval)
-        goto cleanup;
-
-    *rcptr = rcache;
-    rcache = 0;
-    retval = 0;
-
-cleanup:
-    if (rcache)
-        krb5_rc_close(context, rcache);
-    k5_buf_free(&buf);
-    return retval;
+    /*
+     * This function used to compose a name based on the first component of the
+     * server principal, but now ignores the piece argument and resolves the
+     * default replay cache.
+     */
+    return krb5_rc_default(context, rcptr);
 }
diff --git a/src/lib/krb5/rcache/rc_base.c b/src/lib/krb5/rcache/rc_base.c
index c5f1d23..6693759 100644
--- a/src/lib/krb5/rcache/rc_base.c
+++ b/src/lib/krb5/rcache/rc_base.c
@@ -13,6 +13,7 @@
 #include "rc_base.h"
 #include "rc-int.h"
 #include "k5-thread.h"
+#include "../os/os-proto.h"
 
 struct krb5_rc_typelist {
     const krb5_rc_ops *ops;
@@ -124,25 +125,65 @@ krb5_rc_default_name(krb5_context context)
         return (char *) 0;
 }
 
+static krb5_error_code
+resolve_type_and_residual(krb5_context context, const char *type,
+                          char *residual, krb5_rcache *rc_out)
+{
+    krb5_error_code ret;
+    krb5_rcache rc;
+
+    *rc_out = NULL;
+
+    ret = krb5_rc_resolve_type(context, &rc, type);
+    if (ret)
+        return ret;
+
+    ret = krb5_rc_resolve(context, rc, residual);
+    if (ret) {
+        k5_mutex_destroy(&rc->lock);
+        free(rc);
+        return ret;
+    }
+
+    rc->magic = KV5M_RCACHE;
+    *rc_out = rc;
+    return 0;
+}
+
 krb5_error_code
 krb5_rc_default(krb5_context context, krb5_rcache *idptr)
 {
-    krb5_error_code retval;
-    krb5_rcache id;
+    krb5_error_code ret;
+    const char *val;
+    char *profstr, *rcname;
 
     *idptr = NULL;
-    retval = krb5_rc_resolve_type(context, &id, krb5_rc_default_type(context));
-    if (retval)
-        return retval;
-    retval = krb5_rc_resolve(context, id, krb5_rc_default_name(context));
-    if (retval) {
-        k5_mutex_destroy(&id->lock);
-        free(id);
-        return retval;
+
+    /* If KRB5RCACHENAME is set in the environment, resolve it. */
+    val = secure_getenv("KRB5RCACHENAME");
+    if (val != NULL)
+        return krb5_rc_resolve_full(context, idptr, val);
+
+    /* If KRB5RCACHETYPE is set in the environment, resolve it with an empty
+     * residual (primarily to support KRB5RCACHETYPE=none). */
+    val = secure_getenv("KRB5RCACHETYPE");
+    if (val != NULL)
+        return resolve_type_and_residual(context, val, "", idptr);
+
+    /* If [libdefaults] default_rcache_name is set, expand path tokens in the
+     * value and resolve it. */
+    if (profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS,
+                           KRB5_CONF_DEFAULT_RCACHE_NAME, NULL, NULL,
+                           &profstr) == 0 && profstr != NULL) {
+        ret = k5_expand_path_tokens(context, profstr, &rcname);
+        profile_release_string(profstr);
+        ret = krb5_rc_resolve_full(context, idptr, rcname);
+        free(rcname);
+        return ret;
     }
-    id->magic = KV5M_RCACHE;
-    *idptr = id;
-    return retval;
+
+    /* Resolve the default type with no residual. */
+    return resolve_type_and_residual(context, "dfl", "", idptr);
 }
 
 
@@ -150,33 +191,20 @@ krb5_error_code
 krb5_rc_resolve_full(krb5_context context, krb5_rcache *idptr,
                      const char *string_name)
 {
-    char *type;
-    char *residual;
-    krb5_error_code retval;
-    unsigned int diff;
-    krb5_rcache id;
+    krb5_error_code ret;
+    char *type, *sep;
 
     *idptr = NULL;
 
-    if (!(residual = strchr(string_name,':')))
+    sep = strchr(string_name, ':');
+    if (sep == NULL)
         return KRB5_RC_PARSE;
 
-    diff = residual - string_name;
-    if (!(type = malloc(diff + 1)))
-        return KRB5_RC_MALLOC;
-    (void) strncpy(type, string_name, diff);
-    type[residual - string_name] = '\0';
+    type = k5memdup0(string_name, sep - string_name, &ret);
+    if (type == NULL)
+        return ret;
 
-    retval = krb5_rc_resolve_type(context, &id,type);
+    ret = resolve_type_and_residual(context, type, sep + 1, idptr);
     free(type);
-    if (retval)
-        return retval;
-    if ((retval = krb5_rc_resolve(context, id,residual + 1))) {
-        k5_mutex_destroy(&id->lock);
-        free(id);
-        return retval;
-    }
-    id->magic = KV5M_RCACHE;
-    *idptr = id;
-    return retval;
+    return ret;
 }
diff --git a/src/man/kerberos.man b/src/man/kerberos.man
index 026f460..a109538 100644
--- a/src/man/kerberos.man
+++ b/src/man/kerberos.man
@@ -1,6 +1,6 @@
 .\" Man page generated from reStructuredText.
 .
-.TH "KERBEROS" "7" " " "1.17" "MIT Kerberos"
+.TH "KERBEROS" "7" " " "1.18" "MIT Kerberos"
 .SH NAME
 kerberos \- Overview of using Kerberos
 .
@@ -141,13 +141,22 @@ contains additional configuration directives for the Key
 Distribution Center daemon and associated programs.  The default
 is \fB at LOCALSTATEDIR@\fP\fB/krb5kdc\fP\fB/kdc.conf\fP\&.
 .TP
+\fBKRB5RCACHENAME\fP
+(New in release 1.18) Specifies the location of the default replay
+cache, in the form \fItype\fP:\fIresidual\fP\&.  The \fBfile2\fP type with a
+pathname residual specifies a replay cache file in the version\-2
+format in the specified location.  The \fBnone\fP type (residual is
+ignored) disables the replay cache.  The \fBdfl\fP type (residual is
+ignored) indicates the default, which uses a file2 replay cache in
+a temporary directory.  The default is \fBdfl:\fP\&.
+.TP
 \fBKRB5RCACHETYPE\fP
-Specifies the default type of replay cache to use for servers.
-Valid types include \fBdfl\fP for the normal file type and \fBnone\fP
-for no replay cache.  The default is \fBdfl\fP\&.
+Specifies the type of the default replay cache, if
+\fBKRB5RCACHENAME\fP is unspecified.  No residual can be specified,
+so \fBnone\fP and \fBdfl\fP are the only useful types.
 .TP
 \fBKRB5RCACHEDIR\fP
-Specifies the default directory for replay caches used by servers.
+Specifies the directory used by the \fBdfl\fP replay cache type.
 The default is the value of the \fBTMPDIR\fP environment variable,
 or \fB/var/tmp\fP if \fBTMPDIR\fP is not set.
 .TP
@@ -197,6 +206,6 @@ Institute of Technology
 .SH AUTHOR
 MIT
 .SH COPYRIGHT
-1985-2018, MIT
+1985-2019, MIT
 .\" Generated by docutils manpage writer.
 .
diff --git a/src/man/krb5.conf.man b/src/man/krb5.conf.man
index d6ff91c..e0bee9c 100644
--- a/src/man/krb5.conf.man
+++ b/src/man/krb5.conf.man
@@ -242,6 +242,11 @@ This relation specifies the default keytab name to be used by
 application servers such as sshd.  The default is \fB at KTNAME@\fP\&.  This
 relation is subject to parameter expansion (see below).
 .TP
+\fBdefault_rcache_name\fP
+This relation specifies the name of the default replay cache.
+The default is \fBdfl:\fP\&.  This relation is subject to parameter
+expansion (see below).  New in release 1.18.
+.TP
 \fBdefault_realm\fP
 Identifies the default Kerberos realm for the client.  Set its
 value to your Kerberos realm.  If this value is not set, then a


More information about the cvs-krb5 mailing list