Update: Kerberos Ticket Forwarding Patch/Update [3.2]

Derrick Schommer dschommer at F5.com
Fri Aug 1 19:27:03 GMT 2008


Okay, I was going to ask about the structure, and if it was "cool" to use "magic numbers" in order to get the size right. 

Derrick

-----Original Message-----
From: Love Hörnquist Åstrand [mailto:lha at kth.se] 
Sent: Friday, August 01, 2008 15:25
To: Derrick Schommer
Cc: samba-technical at lists.samba.org
Subject: Re: Update: Kerberos Ticket Forwarding Patch/Update [3.2]

First, you should really just use gssapi interface for this.

See 3 comments inline

 > +struct gssChecksum {
 > +
 > +  uint32_t   lgth;                       /* Number of bytes in the  
'Bnd' field (always 16) */
 > +  uint8_t    bnd[GSSAPI_BNDLENGTH];      /* 16-byte Bnd field. */
 > +  uint32_t   flags;                      /* Context-establishment  
flags. */
 > +  uint16_t   dlgOpt;                     /* Delegation options */
 > +  uint16_t   dlgth;                      /* Length of Deleg field  
buffer. */
 > +  uint8_t    deleg[];                    /* Deleg field buffer  
( one or more bytes of GSS-API data) */

foo[] is still a gcc-ism.

the whole structure should go, see Jeremy mail about padding. You know  
the size, its 4+ GSSAPI_BNDLENGTH + 4 + 2 + 2 + deleg fieldbuffer  
length, no need to do sizeof.

 > +
 >  /**************************************************************
 >   Wrappers around kerberos string functions that convert from
 >   utf8 -> unix charset and vica versa.
 > @@ -691,7 +707,38 @@
 >  		*expire_time = (time_t)credsp->times.endtime;
 >  	}
 >
 > -	in_data.length = 0;
 > +	/* Fetch a forwarded TGT from the KDC so that we can hand off a  
2nd ticket
 > +	 as part of the kerberos exchange. */
 > +	if( credsp->ticket_flags & TKT_FLG_OK_AS_DELEGATE ) {
 > +
 > +	  DEBUG( 3, ("ads_krb5_mk_req: server marked as OK to delegate  
to, building forwardable TGT\n")  );
 > +
 > +	  if( *auth_context == NULL ) {
 > +	    /* Allocate if it has not yet been allocated. */
 > +	    krb5_auth_con_init( context, auth_context );
 > +	  }
 > +
 > +	  krb5_auth_con_setuseruserkey( context, *auth_context, &credsp- 
 >keyblock );
 > +
 > +	  /* Must use a subkey for forwarded tickets. */
 > +	  krb5_auth_con_setflags( context, *auth_context,  
KRB5_AUTH_CONTEXT_USE_SUBKEY);
 > +	
 > +	  retval = ads_krb5_get_fwd_ticket( context,
 > +									    auth_context,
 > +									    credsp,
 > +									    ccache,
 > +									    &in_data );
 > +	  if( 0 == retval ) {
 > +	    /* We need to do this in order to allow our GSS-API: */
 > +	    krb5_auth_con_set_req_cksumtype( context, *auth_context,  
GSSAPI_CHECKSUM );
 > +	  } else {
 > +	    DEBUG( 1, ("ads_krb5_get_fwd_ticket failed (%s)\n",  
error_message( retval ) ) );
 > +	  }
 > +
 > +	} else {
 > +		in_data.length = 0;
 > +	}
 > +
 >  	retval = krb5_mk_req_extended(context, auth_context,  
ap_req_options,
 >  				      &in_data, credsp, outbuf);
 >  	if (retval) {
 > @@ -699,6 +746,11 @@
 >  			 error_message(retval)));
 >  	}
 >  	
 > +	if( in_data.data ) {
 > +	  free( in_data.data );
 > +	  in_data.length = 0;
 > +	}
 > +
 >  	krb5_free_creds(context, credsp);
 >
 >  cleanup_creds:
 > @@ -1704,6 +1756,149 @@
 >   	return ret;
 >  }
 >
 > +
 > +
 > +/**************************************************************
 > +Routine: ads_krb5_get_fwd_ticket
 > + Description:
 > +    When a service ticket is flagged as trusted
 > +    for delegation we should provide a forwardable
 > +    ticket so that the remote host can act on our
 > +    behalf.  This is done by taking the 2nd forwardable
 > +    TGT and storing it in the GSS-API authenticator
 > +    "checksum".  This routine will populate
 > +    the krb5_data authenticator with this TGT.
 > + Parameters:
 > +    krb5_context context: The kerberos context for this  
authentication.
 > +    krb5_auth_context:    The authentication context.
 > +    krb5_creds *credsp:   The ticket credentials (AS-REP).
 > +    krb5_ccache ccache:   The credentials cache.
 > +    krb5_data &authenticator: The checksum field that will store  
the TGT, and
 > +     authenticator.data must be freed by the caller.
 > +
 > + Returns:
 > +    krb5_error_code: 0 if no errors, otherwise set.
 > +**************************************************************/
 > +krb5_error_code ads_krb5_get_fwd_ticket( krb5_context         
context,
 > +					 krb5_auth_context * auth_context,
 > +					 krb5_creds *        credsp,
 > +					 krb5_ccache         ccache,
 > +					 krb5_data *         authenticator )
 > +{
 > +
 > +	krb5_data       fwdData    = { 0 };   /* Forwarded TGT will be  
stored within this blob of data */
 > +	krb5_error_code retval     = 0;       /* Assume success until  
proven otherwise. */
 > +
 > +	retval = krb5_fwd_tgt_creds( 	context,                    /* Krb5  
context [in] */
 > +			       					*auth_context,              /* Authentication  
context [in] */
 > +			       					KRB5_TGS_NAME,              /* Ticket service name  
("krbtgt") [in] */
 > +			       					credsp->client,             /* Client principal for  
the tgt [in] */
 > +			       					credsp->server,             /* Server principal for  
the tgt [in] */
 > +			       					ccache,                     /* Credential cache to  
use for storage [in] */
 > +			       					1,                          /* Turn on for  
"Forwardable ticket" [in] */
 > +			       					&fwdData );                 /* Resulting response  
[out] */
 > +
 > +	if( 0 == retval ) {
 > +
 > +    	krb5_creds **inputCreds;
 > +
 > +    	/* Read the forward data response and extract a credentials  
block. */
 > +    	retval = krb5_rd_cred( context, *auth_context, &fwdData,  
&inputCreds, NULL );
 > +
 > +    	/* Remove that input data, we never needed it anyway. */
 > +    	if( fwdData.length > 0 ) {
 > +      		krb5_free_data_contents( context, &fwdData );
 > +    	}
 > +
 > +    	if( 0 == retval ) {
 > +
 > +	    	krb5_data * pKrbCred  = NULL;
 > +
 > +			/* The mk_1cred will be a single credential ticket that will  
contain all the
 > +		     informatin needed to hand to a remote host so they can work  
on behalf of
 > +		     us (power of attorney I believe its called).  The mk_1cred  
will build
 > +		     what is known as a KRB_CRED structure, or an ASN.1  
APPLICATION 22 message:
 > +	         RFC-1510 page 63:
 > +		        KRB-CRED         ::= [APPLICATION 22]   SEQUENCE {
 > +      		 	pvno[0]                INTEGER,
 > +      		 	msg-type[1]            INTEGER, -- KRB_CRED
 > +      		 	tickets[2]             SEQUENCE OF Ticket,
 > +      		 	enc-part[3]            EncryptedData
 > +      		    }
 > +
 > +      		That will be represented here: */
 > +
 > +      		retval = krb5_mk_1cred( 	context,
 > +			 	  					   	*auth_context,
 > +						     		    *inputCreds,    /* INPUT (this is what we're  
using as a source) */
 > +								      	&pKrbCred,      /* OUTPUT (our resulting KRB_CRED  
structure) */
 > +										NULL );
 > +
 > +			if( 0 == retval ) {
 > +
 > +				/* We're going to allocate a gssChecksum structure with a little
 > +					extra data the length of the kerberos credentials length
 > +					(APPLICATION 22) so that we can pack it on the end of the  
structure. */
 > +
 > +				char * pChksum 	= malloc( sizeof( struct gssChecksum ) +  
pKrbCred->length );
 > +				char * p 		= pChksum;
 > +
 > +				SIVAL( p, 0, GSSAPI_BNDLENGTH );
 > +				p += 4;
 > +
 > +				/* Zero out the bindings fields */
 > +				memset( p, 0x0, GSSAPI_BNDLENGTH );
 > +				p += GSSAPI_BNDLENGTH;
 > +
 > +				SIVAL( p, 0, GSS_C_DELEG_FLAG );

All gss-api flags should be sent.

 > +				p += 4;
 > +				SSVAL( p, 0, 1 );
 > +				p += 2;
 > +				SSVAL( p, 0, pKrbCred->length );
 > +				p += 2;
 > +
 > +				/* Migrate the kerberos KRB_CRED data to the checksum  
delegation */
 > +				memcpy( p, pKrbCred->data, pKrbCred->length );
 > +				p += pKrbCred->length;
 > +
 > +				/* We need to do this in order to allow our GSS-API  */
 > +				krb5_auth_con_set_req_cksumtype( context, *auth_context,  
GSSAPI_CHECKSUM );
 > +	
 > +				/* We now have a service ticket, now turn it into an AP-REQ. */
 > +				authenticator->length = ntohs( pKrbCred->length +  
sizeof( struct gssChecksum ) );
 > +				
 > +				/* Caller should call free() when they're done with this. */
 > +				authenticator->data   = (char *) pChksum;
 > +
 > +				if( pKrbCred->length > 0 ) {
 > +	  				krb5_free_data( context, pKrbCred );
 > +				}
 > +
 > +			} else {
 > +				DEBUG(1,("ads_krb5_get_fwd_ticket: krb5_mk_1cred failed (%s)\n",
 > +		 					error_message(retval)));
 > +      		}
 > +
 > +		    /* This free's the triple pointer mess. */
 > +     		krb5_free_tgt_creds( context, inputCreds );
 > +
 > +		} else {
 > +			DEBUG(1,("ads_krb5_get_fwd_ticket: krb5_rd_cred failed (%s)\n",
 > +	       					error_message(retval)));
 > +		}
 > +
 > +	} else {
 > +    		DEBUG(1,("ads_krb5_get_fwd_ticket: krb5_fwd_tgt_creds failed  
(%s)\n",
 > +	     			error_message(retval)));
 > +	}
 > +
 > +	return retval;
 > +
 > +}
 > +
 > +
 > +
 > +
 >  #else /* HAVE_KRB5 */
 >   /* this saves a few linking headaches */
 >   int cli_krb5_get_ticket(const char *principal, time_t time_offset,
 > @@ -1715,3 +1910,5 @@
 >  }
 >
 >  #endif
 > +
 > +

1 aug 2008 kl. 19.59 skrev Derrick Schommer:

> Okay, I've updated the patch to include LE conversions using the  
> macros'
> supplied in byteorder.h, I've also taken out the structure copies and
> replaced it with the byte-stream design seen in other areas of the  
> samba
> protocol builds. I've tested to make sure it didn't break with the
> updates, and it all seems good.
>
>
>
> When we've got all the issues and code reviews nailed down I'll send  
> on
> the 3.0 patch. I won't waste time sending extra emails until we're  
> good
> to go.
>
>
>
> Thanks!
>
>
>
> Derrick Schommer |  Corporate Systems Engineer
>
> F5 Networks
>
>  P 978.513.2900
>
> F 978.513.2990
>
> www.f5.com <http://www.f5.com>
>
>  D 978.513.2960
>
> M 603.765.0012
>
>
>
>
>
> <image001.gif><samba-3.2.patch>



More information about the samba-technical mailing list