diff options
| author | Nalin Dahyabhai <nalin@dahyabhai.net> | 2013-11-18 17:46:04 -0500 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin@dahyabhai.net> | 2013-11-18 17:46:04 -0500 |
| commit | cf42e92cc6d7dfacb04b5d2378f59262c5bb3b2e (patch) | |
| tree | e3f83578c81d57cd7d99079b9d61c89bf1cdb692 | |
| parent | afbeb7e967df2de809f8d86c3bcba7269f778530 (diff) | |
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 | 4 |
2 files changed, 315 insertions, 0 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. @@ -111,6 +111,7 @@ Patch138: krb5-1.11.3-gss-ccache-import.patch Patch139: krb5-CVE-2013-1418.patch Patch140: krb5-CVE-2013-1417.patch Patch141: krb5-1.11.3-client-loop.patch +Patch142: krb5-master-keyring-offsets.patch # Patches for otp plugin backport Patch201: krb5-1.11.2-keycheck.patch @@ -361,6 +362,7 @@ ln -s NOTICE LICENSE %patch139 -p1 -b .CVE-2013-1418 %patch140 -p1 -b .CVE-2013-1417 %patch141 -p1 -b .client-loop +%patch142 -p1 -b .keyring-offsets %patch201 -p1 -b .keycheck %patch202 -p1 -b .otp @@ -1015,6 +1017,8 @@ exit 0 * Mon Nov 18 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-33 - backport fix to not spin on a short read when reading the length of a response over TCP (RT#7508, #1029674) +- pull in fix to store KDC time offsets in keyring credential caches (RT#7768, + #1030607) * Fri Nov 15 2013 Nalin Dahyabhai <nalin@redhat.com> - 1.11.3-32 - incorporate fix for a KDC NULL pointer dereference while handling referrals |
