diff options
author | Nalin Dahyabhai <nalin@dahyabhai.net> | 2013-11-18 17:14:07 -0500 |
---|---|---|
committer | Nalin Dahyabhai <nalin@dahyabhai.net> | 2013-11-18 17:14:07 -0500 |
commit | 81715b17761d8df43312d3bbe5283ebb6285b256 (patch) | |
tree | 58021369903534406349fd660a123731826ae070 | |
parent | dee7ae00a438215e311e3a0c9a351e6fc08e3809 (diff) | |
download | krb5-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.patch | 311 | ||||
-rw-r--r-- | 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@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. @@ -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 |