[krb5] Pull in keyring offset storage from RT#7768

Nalin Dahyabhai nalin at fedoraproject.org
Tue Nov 19 02:29:52 UTC 2013


commit 81715b17761d8df43312d3bbe5283ebb6285b256
Author: Nalin Dahyabhai <nalin at dahyabhai.net>
Date:   Mon Nov 18 17:14:07 2013 -0500

    Pull in keyring offset storage from RT#7768
    
    - pull in fix to store KDC time offsets in keyring credential caches
      (RT#7768, #1030607)

 krb5-master-keyring-offsets.patch |  311 +++++++++++++++++++++++++++++++++++++
 krb5.spec                         |    8 +-
 2 files changed, 318 insertions(+), 1 deletions(-)
---
diff --git a/krb5-master-keyring-offsets.patch b/krb5-master-keyring-offsets.patch
new file mode 100644
index 0000000..b54e84b
--- /dev/null
+++ b/krb5-master-keyring-offsets.patch
@@ -0,0 +1,311 @@
+commit fb4817a32d0c369049e0868468dd2eb75487630d
+Author: Simo Sorce <simo at redhat.com>
+Date:   Thu Nov 14 17:23:59 2013 -0500
+
+    Add support to store time offsets in cc_keyring
+    
+    The code follows the same model used for the memory ccache type.  Time
+    offsets are stored in each credential cache in a special key just like
+    the principal name.  Legacy session caches do not store timestamps as
+    legacy code would fail when iterating over the new offset key.
+    
+    [ghudson at mit.edu: minor formatting changes; note legacy session
+    exception in commit message]
+    
+    ticket: 7768 (new)
+    target_version: 1.12
+    tags: pullup
+
+diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
+index a07a0dc..2192fa5 100644
+--- a/src/lib/krb5/ccache/cc_keyring.c
++++ b/src/lib/krb5/ccache/cc_keyring.c
+@@ -189,6 +189,11 @@ debug_print(char *fmt, ...)
+ #define KRCC_PERSISTENT_KEYRING_NAME "_krb"
+ 
+ /*
++ * Name of the key holding time offsets for the individual cache
++ */
++#define KRCC_TIME_OFFSETS "__krb5_time_offsets__"
++
++/*
+  * Keyring name prefix and length of random name part
+  */
+ #define KRCC_NAME_PREFIX "krb_ccache_"
+@@ -217,6 +222,7 @@ typedef struct _krb5_krcc_cursor
+     int     numkeys;
+     int     currkey;
+     key_serial_t princ_id;
++    key_serial_t offsets_id;
+     key_serial_t *keys;
+ } *krb5_krcc_cursor;
+ 
+@@ -340,6 +346,12 @@ static krb5_error_code krb5_krcc_save_principal
+ 
+ static krb5_error_code krb5_krcc_retrieve_principal
+ (krb5_context context, krb5_ccache id, krb5_principal * princ);
++static krb5_error_code krb5_krcc_save_time_offsets
++(krb5_context context, krb5_ccache id, krb5_int32 time_offset,
++ krb5_int32 usec_offset);
++static krb5_error_code krb5_krcc_get_time_offsets
++(krb5_context context, krb5_ccache id, krb5_int32 *time_offset,
++ krb5_int32 *usec_offset);
+ 
+ /* Routines to parse a key from a keyring into a cred structure */
+ static krb5_error_code krb5_krcc_parse
+@@ -410,6 +422,12 @@ krb5_krcc_parse_index(krb5_context context, krb5_int32 *version,
+ static krb5_error_code
+ krb5_krcc_unparse_index(krb5_context context, krb5_int32 version,
+                         const char *primary, void **datapp, int *lenptr);
++static krb5_error_code
++krb5_krcc_parse_offsets(krb5_context context, krb5_int32 *time_offset,
++                        krb5_int32 *usec_offset, void *payload, int psize);
++static krb5_error_code
++krb5_krcc_unparse_offsets(krb5_context context, krb5_int32 time_offset,
++                          krb5_int32 usec_offset, void **datapp, int *lenptr);
+ 
+ /* Note the following is a stub function for Linux */
+ extern krb5_error_code krb5_change_cache(void);
+@@ -835,6 +853,7 @@ krb5_krcc_initialize(krb5_context context, krb5_ccache id,
+                      krb5_principal princ)
+ {
+     krb5_krcc_data *data = (krb5_krcc_data *)id->data;
++    krb5_os_context os_ctx = &context->os_context;
+     krb5_error_code kret;
+     const char *cache_name, *p;
+ 
+@@ -863,6 +882,15 @@ krb5_krcc_initialize(krb5_context context, krb5_ccache id,
+         (void)keyctl_link(data->cache_id, KEY_SPEC_SESSION_KEYRING);
+ 
+     kret = krb5_krcc_save_principal(context, id, princ);
++
++    /* Save time offset if it is valid and this is not a legacy cache.  Legacy
++     * applications would fail to parse the new key in the cache keyring. */
++    if (!is_legacy_cache_name(data->name) &&
++        (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) {
++        kret = krb5_krcc_save_time_offsets(context, id, os_ctx->time_offset,
++                                           os_ctx->usec_offset);
++    }
++
+     if (kret == KRB5_OK)
+         krb5_change_cache();
+ 
+@@ -1039,6 +1067,7 @@ make_cache(key_serial_t collection_id, key_serial_t cache_id,
+ static krb5_error_code KRB5_CALLCONV
+ krb5_krcc_resolve(krb5_context context, krb5_ccache *id, const char *residual)
+ {
++    krb5_os_context os_ctx = &context->os_context;
+     krb5_error_code ret;
+     key_serial_t collection_id, cache_id;
+     char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL;
+@@ -1067,6 +1096,19 @@ krb5_krcc_resolve(krb5_context context, krb5_ccache *id, const char *residual)
+ 
+     ret = make_cache(collection_id, cache_id, anchor_name, collection_name,
+                      subsidiary_name, id);
++    if (ret)
++        goto cleanup;
++
++    /* Lookup time offsets if necessary. */
++    if ((context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) &&
++        !(os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) {
++        if (krb5_krcc_get_time_offsets(context, *id,
++                                       &os_ctx->time_offset,
++                                       &os_ctx->usec_offset) == 0) {
++            os_ctx->os_flags &= ~KRB5_OS_TOFFSET_TIME;
++            os_ctx->os_flags |= KRB5_OS_TOFFSET_VALID;
++        }
++    }
+ 
+ cleanup:
+     free(anchor_name);
+@@ -1122,6 +1164,8 @@ krb5_krcc_start_seq_get(krb5_context context, krb5_ccache id,
+     }
+ 
+     krcursor->princ_id = d->princ_id;
++    krcursor->offsets_id = keyctl_search(d->cache_id, KRCC_KEY_TYPE_USER,
++                                         KRCC_TIME_OFFSETS, 0);
+     krcursor->numkeys = size / sizeof(key_serial_t);
+     krcursor->keys = keys;
+ 
+@@ -1174,8 +1218,10 @@ krb5_krcc_next_cred(krb5_context context, krb5_ccache id,
+     if (krcursor->currkey >= krcursor->numkeys)
+         return KRB5_CC_END;
+ 
+-    /* If we're pointing at the entry with the principal, skip it */
+-    if (krcursor->keys[krcursor->currkey] == krcursor->princ_id) {
++    /* If we're pointing at the entry with the principal, or at the key
++     * with the time offsets, skip it. */
++    while (krcursor->keys[krcursor->currkey] == krcursor->princ_id ||
++           krcursor->keys[krcursor->currkey] == krcursor->offsets_id) {
+         krcursor->currkey++;
+         /* Check if we have now reached the end */
+         if (krcursor->currkey >= krcursor->numkeys)
+@@ -1621,6 +1667,84 @@ errout:
+     return kret;
+ }
+ 
++static  krb5_error_code
++krb5_krcc_save_time_offsets(krb5_context context, krb5_ccache id,
++                            krb5_int32 time_offset, krb5_int32 usec_offset)
++{
++    krb5_krcc_data *d = (krb5_krcc_data *)id->data;
++    krb5_error_code kret;
++    key_serial_t newkey;
++    void *payload = NULL;
++    int psize;
++
++    k5_cc_mutex_assert_locked(context, &d->lock);
++
++    /* Prepare the payload. */
++    kret = krb5_krcc_unparse_offsets(context, time_offset, usec_offset,
++                                     &payload, &psize);
++    CHECK_N_GO(kret, errout);
++
++    /* Add new key into keyring. */
++    newkey = add_key(KRCC_KEY_TYPE_USER, KRCC_TIME_OFFSETS, payload, psize,
++                     d->cache_id);
++    if (newkey == -1) {
++        kret = errno;
++        DEBUG_PRINT(("Error adding time offsets key: %s\n", strerror(kret)));
++    } else {
++        kret = KRB5_OK;
++        krb5_krcc_update_change_time(d);
++    }
++
++errout:
++    free(payload);
++    return kret;
++}
++
++static krb5_error_code
++krb5_krcc_get_time_offsets(krb5_context context, krb5_ccache id,
++                           krb5_int32 *time_offset, krb5_int32 *usec_offset)
++{
++    krb5_krcc_data *d = (krb5_krcc_data *)id->data;
++    krb5_error_code kret;
++    key_serial_t key;
++    krb5_int32 t, u;
++    void *payload = NULL;
++    int psize;
++
++    k5_cc_mutex_lock(context, &d->lock);
++
++    if (!d->cache_id) {
++        kret = KRB5_FCC_NOFILE;
++        goto errout;
++    }
++
++    key = keyctl_search(d->cache_id, KRCC_KEY_TYPE_USER, KRCC_TIME_OFFSETS, 0);
++    if (key == -1) {
++        kret = ENOENT;
++        goto errout;
++    }
++
++    psize = keyctl_read_alloc(key, &payload);
++    if (psize == -1) {
++        DEBUG_PRINT(("Reading time offsets key %d: %s\n",
++                     key, strerror(errno)));
++        kret = KRB5_CC_IO;
++        goto errout;
++    }
++
++    kret = krb5_krcc_parse_offsets(context, &t, &u, payload, psize);
++    if (kret)
++        goto errout;
++
++    *time_offset = t;
++    *usec_offset = u;
++
++errout:
++    free(payload);
++    k5_cc_mutex_unlock(context, &d->lock);
++    return kret;
++}
++
+ struct krcc_ptcursor_data {
+     key_serial_t collection_id;
+     char *anchor_name;
+@@ -2656,6 +2780,83 @@ errout:
+     return kret;
+ }
+ 
++static krb5_error_code
++krb5_krcc_parse_offsets(krb5_context context, krb5_int32 *time_offset,
++                        krb5_int32 *usec_offset, void *payload, int psize)
++{
++    krb5_error_code kret;
++    krb5_krcc_bc bc;
++
++    bc.bpp = payload;
++    bc.endp = bc.bpp + psize;
++
++    kret = krb5_krcc_parse_int32(context, time_offset, &bc);
++    CHECK_OUT(kret);
++
++    kret = krb5_krcc_parse_int32(context, usec_offset, &bc);
++    CHECK_OUT(kret);
++
++    return KRB5_OK;
++}
++
++static krb5_error_code
++krb5_krcc_unparse_offsets_internal(krb5_context context,
++                                   krb5_int32 time_offset,
++                                   krb5_int32 usec_offset,
++                                   krb5_krcc_bc *bc)
++{
++    krb5_error_code kret;
++
++    kret = krb5_krcc_unparse_int32(context, time_offset, bc);
++    CHECK_OUT(kret);
++
++    kret = krb5_krcc_unparse_int32(context, usec_offset, bc);
++    CHECK_OUT(kret);
++
++    return KRB5_OK;
++}
++
++static krb5_error_code
++krb5_krcc_unparse_offsets(krb5_context context, krb5_int32 time_offset,
++                          krb5_int32 usec_offset, void **datapp, int *lenptr)
++{
++    krb5_error_code kret;
++    krb5_krcc_bc bc;
++    char *buf;
++
++    if (!datapp || !lenptr)
++        return EINVAL;
++
++    *datapp = NULL;
++    *lenptr = 0;
++
++    /* Do a dry run first to calculate the size. */
++    bc.bpp = bc.endp = NULL;
++    bc.size = 0;
++    kret = krb5_krcc_unparse_offsets_internal(context, time_offset,
++                                              usec_offset, &bc);
++    CHECK_OUT(kret);
++
++    buf = malloc(bc.size);
++    if (buf == NULL)
++        return ENOMEM;
++
++    bc.bpp = buf;
++    bc.endp = buf + bc.size;
++    kret = krb5_krcc_unparse_offsets_internal(context, time_offset,
++                                              usec_offset, &bc);
++    CHECK(kret);
++
++    /* Success! */
++    *datapp = buf;
++    *lenptr = bc.bpp - buf;
++    kret = KRB5_OK;
++
++errout:
++    if (kret)
++        free(buf);
++    return kret;
++}
+ /*
+  * Utility routine: called by krb5_krcc_* functions to keep
+  * result of krb5_krcc_last_change_time up to date.
diff --git a/krb5.spec b/krb5.spec
index 693d4a7..6dadefa 100644
--- a/krb5.spec
+++ b/krb5.spec
@@ -41,7 +41,7 @@
 Summary: The Kerberos network authentication system
 Name: krb5
 Version: 1.11.4
-Release: 1%{?dist}
+Release: 2%{?dist}
 # Maybe we should explode from the now-available-to-everybody tarball instead?
 # http://web.mit.edu/kerberos/dist/krb5/1.11/krb5-1.11.4-signed.tar
 Source0: krb5-%{version}.tar.gz
@@ -106,6 +106,7 @@ Patch134: krb5-1.11-kpasswdtest.patch
 Patch135: krb5-1.11-check_transited.patch
 Patch136: krb5-1.11.3-prompter1.patch
 Patch137: krb5-1.11.3-prompter2.patch
+Patch138: krb5-master-keyring-offsets.patch
 
 # Patches for otp plugin backport
 Patch201: krb5-1.11.2-keycheck.patch
@@ -351,6 +352,7 @@ ln -s NOTICE LICENSE
 %patch135 -p1 -b .check_transited
 %patch136 -p1 -b .prompter1
 %patch137 -p1 -b .prompter2
+%patch138 -p1 -b .keyring-offsets
 
 %patch201 -p1 -b .keycheck
 %patch202 -p1 -b .otp
@@ -1002,6 +1004,10 @@ exit 0
 %{_sbindir}/uuserver
 
 %changelog
+* Mon Nov 18 2013 Nalin Dahyabhai <nalin at redhat.com> - 1.11.4-2
+- pull in fix to store KDC time offsets in keyring credential caches (RT#7768,
+  #1030607)
+
 * Tue Nov 12 2013 Nalin Dahyabhai <nalin at redhat.com> - 1.11.4-1
 - update to 1.11.4
   - drop patch for RT#7650, obsoleted


More information about the scm-commits mailing list