30
30
#include "gp_conv.h"
31
31
#include "gp_export.h"
32
32
#include "gp_debug.h"
33
+ #include <gssapi/gssapi_krb5.h>
33
34
34
35
/* FIXME: F I X M E
35
36
*
@@ -172,7 +173,7 @@ int gp_find_cred(gssx_cred *cred, gss_cred_id_t *out)
172
173
173
174
/* Exported Contexts */
174
175
175
- #define EXP_CTX_TYPE_OPTION "exported_contex_type "
176
+ #define EXP_CTX_TYPE_OPTION "exported_context_type "
176
177
#define LINUX_LUCID_V1 "linux_lucid_v1"
177
178
178
179
enum exp_ctx_types {
@@ -204,6 +205,101 @@ int gp_get_exported_context_type(struct gssx_call_ctx *ctx)
204
205
return EXP_CTX_DEFAULT ;
205
206
}
206
207
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
+
207
303
uint32_t gp_export_ctx_id_to_gssx (uint32_t * min , int type ,
208
304
gss_ctx_id_t * in , gssx_ctx * out )
209
305
{
@@ -212,14 +308,15 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
212
308
gss_name_t src_name = GSS_C_NO_NAME ;
213
309
gss_name_t targ_name = GSS_C_NO_NAME ;
214
310
gss_buffer_desc export_buffer = GSS_C_EMPTY_BUFFER ;
311
+ gss_krb5_lucid_context_v1_t * lucid = NULL ;
215
312
uint32_t lifetime_rec ;
216
313
gss_OID mech_type ;
217
314
uint32_t ctx_flags ;
218
315
int is_locally_initiated ;
219
316
int is_open ;
220
317
int ret ;
221
318
222
- /* TODO: For mechs that need multiple roundtrips to complete */
319
+ /* TODO: For mechs that need multiple roundtrips to complete */
223
320
/* out->state; */
224
321
225
322
/* 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,
263
360
264
361
/* note: once converted the original context token is not usable anymore,
265
362
* 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 :
274
390
ret_maj = GSS_S_FAILURE ;
275
- ret_min = ret ;
391
+ ret_min = EINVAL ;
276
392
goto done ;
277
393
}
278
394
@@ -284,6 +400,9 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
284
400
gss_release_name (& ret_min , & src_name );
285
401
gss_release_name (& ret_min , & targ_name );
286
402
gss_release_buffer (& ret_min , & export_buffer );
403
+ if (lucid ) {
404
+ gss_krb5_free_lucid_sec_context (& ret_min , lucid );
405
+ }
287
406
if (ret_maj ) {
288
407
xdr_free ((xdrproc_t )xdr_gssx_OID , (char * )& out -> mech );
289
408
xdr_free ((xdrproc_t )xdr_gssx_name , (char * )& out -> src_name );
0 commit comments