SPNEGO-delegated credentials

pk kranenburg at few.eur.nl
Tue May 22 14:48:58 EDT 2007


Consider the following scenario:

	- a GSSAPI server using the MIT krb5 1.6 gssapi implementation.

	- some GSSAPI client initiating a connection to that server
	  using SPNEGO with krb5 as the preferred mechanism and also
	  allowing its credentials to be forwarded.

	- the server accepting the client preferred machanism and credentials
	  and completing the security context. The server stores the
	  negotiated machanism and the delegated client credentials as
	  provied by the final call to accept_sec_context().

	- the server decides to initiate a GSSAPI conection with a third
	  service on behalf of the client, using the krb5 mechanism and
	  the delegated client credentials in its calls to init_sec_context()
	  for this connection.


Observe the failure of establishing a security context between server and
third-party on behalf of the client using the delegated credentials.

This is because the (gss encapsulated) delegated client credentials as
produced by accept_sec_context() is associated with the SPNEGO mechanism
(and not the negotiated krb5 mechanism) and goes unrecognised as a
suitable credential when used in init_sec_context() with the krb5
mechanism.  However, the krb5 credentials that would be needed are
still there, albeit embedded one level deeper within the spnego tagged
credentials.

It is seems reasonable that the spnego mechanism -- being a "pseudo"
mechanism -- should try to recover these embedded credentials for
use with direct application of the negotiated mechanism.

The following patch does that by adding a function to the per-mech
glue data to extract embedded credentials and use this in the
gssint_get_mechanism_cred() glue routine, allowing init_sec_contect()
access to the correct mechanism-specific credentials.


--
Paul Kranenburg
Erasmus University, FEW


----------------
----------------
diff -r -c /tmp/krb5-1.6.orig/src/lib/gssapi/mechglue/g_glue.c ./lib/gssapi/mechglue/g_glue.c
*** /tmp/krb5-1.6.orig/src/lib/gssapi/mechglue/g_glue.c	Tue Aug  8 01:33:39 2006
--- ./lib/gssapi/mechglue/g_glue.c	Fri May 18 15:31:27 2007
***************
*** 529,541 ****
      gss_OID		mech_type;
  {
      int		i;
      
      if (union_cred == GSS_C_NO_CREDENTIAL)
  	return GSS_C_NO_CREDENTIAL;
!     
      for (i=0; i < union_cred->count; i++) {
  	if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
  	    return union_cred->cred_array[i];
      }
      return GSS_C_NO_CREDENTIAL;
  }
--- 529,553 ----
      gss_OID		mech_type;
  {
      int		i;
+     gss_mechanism mech;
      
      if (union_cred == GSS_C_NO_CREDENTIAL)
  	return GSS_C_NO_CREDENTIAL;
! 
      for (i=0; i < union_cred->count; i++) {
  	if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
  	    return union_cred->cred_array[i];
+ 
+ 	/*
+ 	 * Check for embedded credentials if this credential element's
+ 	 * associated mechanism supports it (currently only SPNEGO does).
+ 	 */
+ 	mech = gssint_get_mechanism (&union_cred->mechs_array[i]);
+ 	if (mech && mech->extract_cred != NULL) {
+ 		gss_cred_id_t cred;
+ 		cred = mech->extract_cred(union_cred->cred_array[i], mech_type);
+ 		if (cred) return cred;
+ 	}
      }
      return GSS_C_NO_CREDENTIAL;
  }
diff -r -c /tmp/krb5-1.6.orig/src/lib/gssapi/mechglue/mglueP.h ./lib/gssapi/mechglue/mglueP.h
*** /tmp/krb5-1.6.orig/src/lib/gssapi/mechglue/mglueP.h	Tue Aug  8 01:33:39 2006
--- ./lib/gssapi/mechglue/mglueP.h	Tue May  8 11:15:26 2007
***************
*** 370,375 ****
--- 370,376 ----
  		gss_OID_set *,		/* elements_stored */
  		gss_cred_usage_t *	/* cred_usage_stored */
  	/* */);
+ 	gss_cred_id_t (*extract_cred)(gss_cred_id_t, gss_OID);
  } *gss_mechanism;
  
  /*
diff -r -c /tmp/krb5-1.6.orig/src/lib/gssapi/spnego/spnego_mech.c ./lib/gssapi/spnego/spnego_mech.c
*** /tmp/krb5-1.6.orig/src/lib/gssapi/spnego/spnego_mech.c	Fri Jun 30 00:12:19 2006
--- ./lib/gssapi/spnego/spnego_mech.c	Fri May 18 15:35:22 2007
***************
*** 151,156 ****
--- 151,158 ----
  get_negTokenResp(OM_uint32 *, unsigned char *, unsigned int,
  		 OM_uint32 *, gss_OID *, gss_buffer_t *, gss_buffer_t *);
  
+ static gss_cred_id_t spnego_extract_cred(gss_cred_id_t, gss_OID);
+ 
  /*
   * The Mech OID for SPNEGO:
   * { iso(1) org(3) dod(6) internet(1) security(5)
***************
*** 189,196 ****
--- 191,209 ----
  	spnego_gss_wrap_size_limit,	/* gss_wrap_size_limit */
  	NULL,				/* gss_export_name */
  	NULL,				/* gss_store_cred */
+ 	spnego_extract_cred,
  };
  
+ /*
+  * spnego credentials may contain crendentials associated with
+  * the actual negotiated mechanism. This routine is called by
+  * mech glue to extract those embedded crendentials.
+  */
+ gss_cred_id_t spnego_extract_cred(gss_cred_id_t cred, gss_OID mech_type)
+ {
+ 	return gssint_get_mechanism_cred((gss_union_cred_t)cred, mech_type);
+ }
+ 
  static gss_mechanism spnego_mech_configs[] = {
  	&spnego_mechanism, NULL
  };



More information about the krbdev mailing list