3030#include "gp_conv.h"
3131#include "gp_export.h"
3232#include "gp_debug.h"
33+ #include <gssapi/gssapi_krb5.h>
3334
3435/* FIXME: F I X M E
3536 *
@@ -172,7 +173,7 @@ int gp_find_cred(gssx_cred *cred, gss_cred_id_t *out)
172173
173174/* Exported Contexts */
174175
175- #define EXP_CTX_TYPE_OPTION "exported_contex_type "
176+ #define EXP_CTX_TYPE_OPTION "exported_context_type "
176177#define LINUX_LUCID_V1 "linux_lucid_v1"
177178
178179enum exp_ctx_types {
@@ -204,6 +205,101 @@ int gp_get_exported_context_type(struct gssx_call_ctx *ctx)
204205 return EXP_CTX_DEFAULT ;
205206}
206207
208+ #define KRB5_CTX_FLAG_INITIATOR 0x00000001
209+ #define KRB5_CTX_FLAG_CFX 0x00000002
210+ #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
211+
212+ /* we use what svcgssd calls a "krb5_rfc4121_buffer"
213+ * Format: uint32_t flags
214+ * int32_t endtime
215+ * uint64_t seq_send
216+ * uint32_t enctype
217+ * u8[] raw key
218+ */
219+
220+ static uint32_t gp_format_linux_lucid_v1 (uint32_t * min ,
221+ gss_krb5_lucid_context_v1_t * lucid ,
222+ gssx_buffer * out )
223+ {
224+ uint8_t * buffer ;
225+ uint8_t * p ;
226+ size_t length ;
227+ uint32_t flags ;
228+ uint32_t enctype ;
229+ uint32_t keysize ;
230+ void * keydata ;
231+ uint32_t maj ;
232+
233+ if (lucid -> version != 1 ||
234+ (lucid -> protocol != 0 && lucid -> protocol != 1 )) {
235+ * min = ENOTSUP ;
236+ return GSS_S_FAILURE ;
237+ }
238+
239+ flags = 0 ;
240+ if (lucid -> initiate ) {
241+ flags |= KRB5_CTX_FLAG_INITIATOR ;
242+ }
243+ if (lucid -> protocol == 1 ) {
244+ flags |= KRB5_CTX_FLAG_CFX ;
245+ }
246+ if (lucid -> protocol == 1 && lucid -> cfx_kd .have_acceptor_subkey == 1 ) {
247+ flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY ;
248+ }
249+
250+ if (lucid -> protocol == 0 ) {
251+ enctype = lucid -> rfc1964_kd .ctx_key .type ;
252+ keysize = lucid -> rfc1964_kd .ctx_key .length ;
253+ keydata = lucid -> rfc1964_kd .ctx_key .data ;
254+ } else {
255+ if (lucid -> cfx_kd .have_acceptor_subkey == 1 ) {
256+ enctype = lucid -> cfx_kd .acceptor_subkey .type ;
257+ keysize = lucid -> cfx_kd .acceptor_subkey .length ;
258+ keydata = lucid -> cfx_kd .acceptor_subkey .data ;
259+ } else {
260+ enctype = lucid -> cfx_kd .ctx_key .type ;
261+ keysize = lucid -> cfx_kd .ctx_key .length ;
262+ keydata = lucid -> cfx_kd .ctx_key .data ;
263+ }
264+ }
265+
266+ length = sizeof (flags )
267+ + sizeof (lucid -> endtime )
268+ + sizeof (lucid -> send_seq )
269+ + sizeof (enctype )
270+ + keysize ;
271+
272+ buffer = calloc (1 , length );
273+ if (!buffer ) {
274+ * min = ENOMEM ;
275+ maj = GSS_S_FAILURE ;
276+ goto done ;
277+ }
278+ p = buffer ;
279+
280+ memcpy (p , & flags , sizeof (flags ));
281+ p += sizeof (flags );
282+ memcpy (p , & lucid -> endtime , sizeof (lucid -> endtime ));
283+ p += sizeof (lucid -> endtime );
284+ memcpy (p , & lucid -> send_seq , sizeof (lucid -> send_seq ));
285+ p += sizeof (lucid -> send_seq );
286+ memcpy (p , & enctype , sizeof (enctype ));
287+ p += sizeof (enctype );
288+ memcpy (p , keydata , keysize );
289+
290+ out -> octet_string_val = (void * )buffer ;
291+ out -> octet_string_len = length ;
292+ maj = GSS_S_COMPLETE ;
293+ * min = 0 ;
294+
295+ done :
296+ if (maj ) {
297+ free (buffer );
298+ }
299+ return maj ;
300+ }
301+
302+
207303uint32_t gp_export_ctx_id_to_gssx (uint32_t * min , int type ,
208304 gss_ctx_id_t * in , gssx_ctx * out )
209305{
@@ -212,14 +308,15 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
212308 gss_name_t src_name = GSS_C_NO_NAME ;
213309 gss_name_t targ_name = GSS_C_NO_NAME ;
214310 gss_buffer_desc export_buffer = GSS_C_EMPTY_BUFFER ;
311+ gss_krb5_lucid_context_v1_t * lucid = NULL ;
215312 uint32_t lifetime_rec ;
216313 gss_OID mech_type ;
217314 uint32_t ctx_flags ;
218315 int is_locally_initiated ;
219316 int is_open ;
220317 int ret ;
221318
222- /* TODO: For mechs that need multiple roundtrips to complete */
319+ /* TODO: For mechs that need multiple roundtrips to complete */
223320 /* out->state; */
224321
225322 /* we do not need the client to release anything until we handle state */
@@ -263,16 +360,35 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
263360
264361 /* note: once converted the original context token is not usable anymore,
265362 * so this must be the last call to use it */
266- ret_maj = gss_export_sec_context (& ret_min , in , & export_buffer );
267- if (ret_maj ) {
268- ret_maj = GSS_S_FAILURE ;
269- ret_min = ENOMEM ;
270- goto done ;
271- }
272- ret = gp_conv_buffer_to_gssx (& export_buffer , & out -> exported_context_token );
273- if (ret ) {
363+ switch (type ) {
364+ case EXP_CTX_DEFAULT :
365+ ret_maj = gss_export_sec_context (& ret_min , in , & export_buffer );
366+ if (ret_maj ) {
367+ goto done ;
368+ }
369+ ret = gp_conv_buffer_to_gssx (& export_buffer ,
370+ & out -> exported_context_token );
371+ if (ret ) {
372+ ret_maj = GSS_S_FAILURE ;
373+ ret_min = ret ;
374+ goto done ;
375+ }
376+ break ;
377+ case EXP_CTX_LINUX_LUCID_V1 :
378+ ret_maj = gss_krb5_export_lucid_sec_context (& ret_min , in , 1 ,
379+ (void * * )& lucid );
380+ if (ret_maj ) {
381+ goto done ;
382+ }
383+ ret_maj = gp_format_linux_lucid_v1 (& ret_min , lucid ,
384+ & out -> exported_context_token );
385+ if (ret_maj ) {
386+ goto done ;
387+ }
388+ break ;
389+ default :
274390 ret_maj = GSS_S_FAILURE ;
275- ret_min = ret ;
391+ ret_min = EINVAL ;
276392 goto done ;
277393 }
278394
@@ -284,6 +400,9 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
284400 gss_release_name (& ret_min , & src_name );
285401 gss_release_name (& ret_min , & targ_name );
286402 gss_release_buffer (& ret_min , & export_buffer );
403+ if (lucid ) {
404+ gss_krb5_free_lucid_sec_context (& ret_min , lucid );
405+ }
287406 if (ret_maj ) {
288407 xdr_free ((xdrproc_t )xdr_gssx_OID , (char * )& out -> mech );
289408 xdr_free ((xdrproc_t )xdr_gssx_name , (char * )& out -> src_name );
0 commit comments