This is an automated email from the git hooks/post-receive script.
rharwood pushed a change to branch master in repository gssproxy.
from e45dcdd Release version 0.6.0 new 1508917 Missing keytab should not be fatal
The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference.
Summary of changes: proxy/src/gp_export.c | 182 ++++++++++++++++++++++++++----------------------- proxy/tests/testlib.py | 17 ++++- 2 files changed, 114 insertions(+), 85 deletions(-)
This is an automated email from the git hooks/post-receive script.
rharwood pushed a commit to branch master in repository gssproxy.
commit 15089179c31df036042ab6317fd0ea373ea059ce Author: Simo Sorce simo@redhat.com Date: Fri Jan 20 15:55:53 2017 -0500
Missing keytab should not be fatal
In 1e6b5a4c004c520c5865c04c6bd3d40373d174c2 we've been a littl bit too zealous and made lack of a keytab a fatal condition when a keytab was specified explicitly in config files. However we distribute a config file that explictly mentions the default keytab.
In general lack of a keytab is not really an impediment and gssproxy will work properly until restarted (at which point saved cfredentials will become unreadable as the encryption key is lost). But even if access to crdential is lost in most cases this is a recoverable situation.
So relax the constraint and fallback to a random key in all cases.
Signed-off-by: Simo Sorce simo@redhat.com [rharwood@redhat.com Style fixup] Reviewed-by: Robbie Harwood rharwood@redhat.com Merged: https://pagure.io/gssproxy/pull-request/45 --- proxy/src/gp_export.c | 182 ++++++++++++++++++++++++++----------------------- proxy/tests/testlib.py | 17 ++++- 2 files changed, 114 insertions(+), 85 deletions(-)
diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c index c83303a..5f25f56 100644 --- a/proxy/src/gp_export.c +++ b/proxy/src/gp_export.c @@ -39,6 +39,101 @@ void gp_free_creds_handle(struct gp_creds_handle **in) return; }
+uint32_t gp_init_creds_with_keytab(uint32_t *min, const char *svc_name, + const char *keytab, + struct gp_creds_handle *handle) +{ + char ktname[MAX_KEYTAB_NAME_LEN + 1] = {0}; + krb5_keytab ktid = NULL; + krb5_kt_cursor cursor; + krb5_keytab_entry entry; + krb5_enctype *permitted; + uint32_t ret_maj = 0; + uint32_t ret_min = 0; + int ret; + + if (keytab) { + strncpy(ktname, keytab, MAX_KEYTAB_NAME_LEN); + ret = krb5_kt_resolve(handle->context, keytab, &ktid); + } + /* if the keytab is not specified or fails to resolve try default */ + if (!keytab || ret != 0) { + ret = krb5_kt_default_name(handle->context, ktname, + MAX_KEYTAB_NAME_LEN); + if (ret) { + strncpy(ktname, "[default]", MAX_KEYTAB_NAME_LEN); + } + ret = krb5_kt_default(handle->context, &ktid); + } + if (ret == 0) { + ret = krb5_kt_have_content(handle->context, ktid); + } + if (ret) { + GPDEBUG("Keytab %s has no content (%d)\n", ktname, ret); + ret_min = ret; + ret_maj = GSS_S_CRED_UNAVAIL; + goto done; + } + + ret = krb5_get_permitted_enctypes(handle->context, &permitted); + if (ret) { + GPDEBUG("Failed to source permitted enctypes (%d)\n", ret); + ret_min = ret; + ret_maj = GSS_S_FAILURE; + goto done; + } + + ret = krb5_kt_start_seq_get(handle->context, ktid, &cursor); + if (ret) { + GPDEBUG("krb5_kt_start_seq_get() failed (%d)\n", ret); + ret_min = ret; + ret_maj = GSS_S_FAILURE; + goto done; + } + do { + ret = krb5_kt_next_entry(handle->context, ktid, &entry, &cursor); + if (ret == 0) { + for (unsigned i = 0; permitted[i] != 0; i++) { + if (permitted[i] == entry.key.enctype) { + /* should we derive a key instead ? */ + ret = krb5_copy_keyblock(handle->context, &entry.key, + &handle->key); + if (ret == 0) { + GPDEBUG("Service: %s, Keytab: %s, Enctype: %d\n", + svc_name, ktname, entry.key.enctype); + ret = KRB5_KT_END; + } else { + GPDEBUG("krb5_copy_keyblock failed (%d)\n", ret); + } + break; + } + } + (void)krb5_free_keytab_entry_contents(handle->context, &entry); + } + } while (ret == 0); + (void)krb5_kt_end_seq_get(handle->context, ktid, &cursor); + if ((ret == KRB5_KT_END) && (handle->key == NULL)) { + ret = KRB5_WRONG_ETYPE; + ret_maj = GSS_S_CRED_UNAVAIL; + goto done; + } + if (ret != KRB5_KT_END) { + ret_min = ret; + ret_maj = GSS_S_CRED_UNAVAIL; + goto done; + } + + ret_min = 0; + ret_maj = GSS_S_COMPLETE; + +done: + if (ktid) { + (void)krb5_kt_close(handle->context, ktid); + } + *min = ret_min; + return ret_maj; +} + uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name, const char *keytab, struct gp_creds_handle **out) @@ -46,8 +141,6 @@ uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name, struct gp_creds_handle *handle; uint32_t ret_maj = 0; uint32_t ret_min = 0; - krb5_keytab ktid = NULL; - char ktname[MAX_KEYTAB_NAME_LEN + 1] = {0}; int ret;
handle = calloc(1, sizeof(struct gp_creds_handle)); @@ -67,85 +160,9 @@ uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name,
/* Try to use a keytab, and fall back to a random runtime secret if all * else fails */ - if (keytab) { - ret = krb5_kt_resolve(handle->context, keytab, &ktid); - if (ret == 0) { - ret = krb5_kt_have_content(handle->context, ktid); - } - /* if a keytab is specified then it must be usable */ - if (ret) { - ret_min = ret; - ret_maj = GSS_S_CRED_UNAVAIL; - goto done; - } - strncpy(ktname, keytab, MAX_KEYTAB_NAME_LEN); - } else { - ret = krb5_kt_default(handle->context, &ktid); - /* if the default keyab does not exist or is empty it is not fatal */ - if (ret) { - ktid = NULL; - } else { - ret = krb5_kt_have_content(handle->context, ktid); - if (ret) { - (void)krb5_kt_close(handle->context, ktid); - ktid = NULL; - } else { - ret = krb5_kt_default_name(handle->context, ktname, - MAX_KEYTAB_NAME_LEN); - if (ret) strncpy(ktname, "[default]", MAX_KEYTAB_NAME_LEN); - } - } - } - - if (ktid) { - krb5_kt_cursor cursor; - krb5_keytab_entry entry; - krb5_enctype *permitted; - - ret = krb5_get_permitted_enctypes(handle->context, &permitted); - if (ret) { - ret_min = ret; - ret_maj = GSS_S_FAILURE; - goto done; - } - - ret = krb5_kt_start_seq_get(handle->context, ktid, &cursor); - if (ret) { - ret_min = ret; - ret_maj = GSS_S_FAILURE; - goto done; - } - do { - ret = krb5_kt_next_entry(handle->context, ktid, &entry, &cursor); - if (ret == 0) { - for (unsigned i = 0; permitted[i] != 0; i++) { - if (permitted[i] == entry.key.enctype) { - /* should we derive a key instead ? */ - ret = krb5_copy_keyblock(handle->context, &entry.key, - &handle->key); - if (ret == 0) { - GPDEBUG("Service: %s, Enckey: %s, Enctype: %d\n", - svc_name, ktname, entry.key.enctype); - ret = KRB5_KT_END; - } - break; - } - } - (void)krb5_free_keytab_entry_contents(handle->context, &entry); - } - } while (ret == 0); - (void)krb5_kt_end_seq_get(handle->context, ktid, &cursor); - if ((ret == KRB5_KT_END) && (handle->key == NULL)) { - ret = KRB5_WRONG_ETYPE; - ret_maj = GSS_S_CRED_UNAVAIL; - goto done; - } - if (ret != KRB5_KT_END) { - ret_min = ret; - ret_maj = GSS_S_CRED_UNAVAIL; - goto done; - } - } else { + ret_maj = gp_init_creds_with_keytab(&ret_min, svc_name, keytab, handle); + if (ret_maj != GSS_S_COMPLETE) { + /* fallback */ ret = krb5_init_keyblock(handle->context, GP_CREDS_HANDLE_KEY_ENCTYPE, 0, &handle->key); @@ -167,9 +184,6 @@ uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name, ret_min = 0;
done: - if (handle->context && ktid) { - (void)krb5_kt_close(handle->context, ktid); - } *min = ret_min; if (ret_maj) { gp_free_creds_handle(&handle); diff --git a/proxy/tests/testlib.py b/proxy/tests/testlib.py index 0a0af2e..858e9a9 100755 --- a/proxy/tests/testlib.py +++ b/proxy/tests/testlib.py @@ -538,6 +538,11 @@ GSSPROXY_CONF_TEMPLATE = ''' cred_store = client_keytab:${GSSPROXY_CLIENT_KEYTAB} trusted = yes euid = ${UIDNUMBER} + +[service/badkeytab] + mechs = krb5 + cred_store = keytab:/intentionally/missing/keytab + euid = 123 '''
# Contains a garbage service entry @@ -553,7 +558,17 @@ GSSPROXY_CONF_MINIMAL_TEMPLATE = ''' euid = nobody '''
-GSSPROXY_CONF_SOCKET_TEMPLATE = GSSPROXY_CONF_TEMPLATE + ''' +GSSPROXY_CONF_SOCKET_TEMPLATE = ''' +[gssproxy] + debug_level = 3 + +[service/test] + mechs = krb5 + cred_store = keytab:${GSSPROXY_KEYTAB} + cred_store = ccache:FILE:${GSSPROXY_CLIENT_CCACHE} + cred_store = client_keytab:${GSSPROXY_CLIENT_KEYTAB} + trusted = yes + euid = ${UIDNUMBER} socket = ${SECOND_SOCKET} '''
gss-proxy@lists.fedorahosted.org