summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2013-11-18 17:14:07 -0500
committerNalin Dahyabhai <nalin@dahyabhai.net>2013-11-18 17:14:07 -0500
commit81715b17761d8df43312d3bbe5283ebb6285b256 (patch)
tree58021369903534406349fd660a123731826ae070
parentdee7ae00a438215e311e3a0c9a351e6fc08e3809 (diff)
downloadkrb5-81715b17761d8df43312d3bbe5283ebb6285b256.tar.gz
krb5-81715b17761d8df43312d3bbe5283ebb6285b256.tar.xz
krb5-81715b17761d8df43312d3bbe5283ebb6285b256.zip
Pull in keyring offset storage from RT#7768
- pull in fix to store KDC time offsets in keyring credential caches (RT#7768, #1030607)
-rw-r--r--krb5-master-keyring-offsets.patch311
-rw-r--r--krb5.spec8
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@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@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@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@redhat.com> - 1.11.4-1
- update to 1.11.4
- drop patch for RT#7650, obsoleted