Expired Krb5 TGT prevents GSSAPI from calling SPNEGO plugins
Adam Bernstein
abernstein at vmware.com
Tue Mar 1 14:00:02 EST 2016
_*BACKGROUND*_*:*
VMware vcenter product initial configuration uses a GSSAPI plugin
implementing the Secure Remote Password (SRP) protocol. This is a
"bootstrap" authentication protocol, used to store initial
authentication identities in our LDAP directory, and other operations
requiring security. During configuration, DCE/RPC secured by GSSAPI/SRP
is used. Once configured, DCE/RPC secured by GSSAPI/KRB5 is used. We are
using MIT Kerberos version 1.14.
_*ISSUE:*_
During development, we discovered an expired Kerberos credentials cache
causes GSSAPI krb5_gss_inquire_cred() to fail with the error
GSS_S_CREDENTIALS_EXPIRED. This prevents SPNEGO from attempting
authentication with plugin mechanisms configured in /etc/gss/mech.
To reproduce this problem, the current user must have a Kerberos
credentials cache containing an expired krbtgt. For example, see the
below expired credentials cache:
# /opt/likewise/bin/klist
Ticket cache: FILE:/tmp/krb5cc_0
Default principal: sles11-test2.testlab15.com at VSPHERE.LOCAL
Valid starting Expires Service principal
02/24/2016 16:28:36 02/24/2016 16:34:34 krbtgt/VSPHERE.LOCAL at VSPHERE.LOCAL
GSSAPI authentication with SRP is not possible for the user
"sles11-test2.testlab15.com at VSPHERE.LOCAL" when this expired ticket
exists. After deleting this expired cache, SPNEGO authentication
proceeds to SRP.
_*PROPOSED SOLUTION:*_
Attached is a patch for gssapi/mechglue/g_inq_cred.c : gss_inq_cred()
which fixes this issue.
The strategy used in this patch is rather than returning the error
GSS_S_CREDENTIALS_EXPIRED, skip adding the Kerberos mech OID to the
"mechs" OID set.
When krb5_gss_inquire_cred() returns GSS_S_CREDENTIALS_EXPIRED,
mech_offset is set to 1. The assumption made here is the Kerberos mech
OID always exists and is always first in the union_cred->mechs array.
When GSS_S_CREDENTIALS_EXPIRED is returned, the Kerberos OID is not
added to the mechs OID set.
Should "mechanisms" be NULL, the original behavior of returning an empty
OID set is preserved, unless krb5_gss_inquire_cred() failed with
GSS_S_CREDENTIALS_EXPIRED, then that error is returned.
Note: The patch does properly preserve tab/space indentation. Depending
on your email reader, this may not appear to be true.
Please consider accepting the following patch for inclusion in the next
release of MIT Kerberos.
Thanks,
Adam
====
Adam Bernstein
Staff Engineer, VMware
abernstein at vmware.com
500 108th Ave NE, Bellevue WA, 98004
-------------- next part --------------
==== //public/vmware-likewise-open-6-1/likewise-stable/likewise-v6.1/likewise-open/krb5/src/lib/gssapi/mechglue/g_inq_cred.c#3 - /mnt/hgfs/abernstein/workspaces/panda/vmware-likewise-open-6-1/likewise-stable/likewise-v6.1/likewise-open/krb5/src/lib/gssapi/mechglue/g_inq_cred.c ====
***************
*** 51,56 ****
--- 51,58 ----
{
OM_uint32 status, temp_minor_status;
+ OM_uint32 status2 = 0;
+ OM_uint32 mech_offset = 0;
gss_union_cred_t union_cred;
gss_mechanism mech;
gss_cred_id_t mech_cred;
***************
*** 100,110 ****
status = mech->gss_inquire_cred(minor_status, mech_cred,
name ? &mech_name : NULL,
lifetime, cred_usage, NULL);
! if (status != GSS_S_COMPLETE) {
map_error(minor_status, mech);
return(status);
}
if (name) {
/* Convert mech_name into a union_name equivalent. */
status = gssint_convert_name_to_union_name(&temp_minor_status,
--- 102,117 ----
status = mech->gss_inquire_cred(minor_status, mech_cred,
name ? &mech_name : NULL,
lifetime, cred_usage, NULL);
! if (status != GSS_S_COMPLETE && status != GSS_S_CREDENTIALS_EXPIRED) {
map_error(minor_status, mech);
return(status);
}
+ status2 = status;
+ if (status2 == GSS_S_CREDENTIALS_EXPIRED) {
+ mech_offset = 1;
+ }
+
if (name) {
/* Convert mech_name into a union_name equivalent. */
status = gssint_convert_name_to_union_name(&temp_minor_status,
***************
*** 122,134 ****
*/
if(mechanisms != NULL) {
! if (union_cred) {
status = gssint_make_public_oid_set(minor_status,
! union_cred->mechs_array,
! union_cred->count, &mechs);
if (GSS_ERROR(status))
goto error;
} else {
status = gss_create_empty_oid_set(minor_status, &mechs);
if (GSS_ERROR(status))
goto error;
--- 129,145 ----
*/
if(mechanisms != NULL) {
! if (union_cred && (union_cred->count - mech_offset) > 0) {
status = gssint_make_public_oid_set(minor_status,
! &union_cred->mechs_array[mech_offset],
! union_cred->count - mech_offset, &mechs);
if (GSS_ERROR(status))
goto error;
} else {
+ if (status2 == GSS_S_CREDENTIALS_EXPIRED) {
+ status = GSS_S_CREDENTIALS_EXPIRED;
+ goto error;
+ }
status = gss_create_empty_oid_set(minor_status, &mechs);
if (GSS_ERROR(status))
goto error;
More information about the krbdev
mailing list