Skip to content

Commit 8d60795

Browse files
committed
Add support for linux kernel lucid ctx buffer format
1 parent 9c6e612 commit 8d60795

File tree

1 file changed

+130
-11
lines changed

1 file changed

+130
-11
lines changed

proxy/src/gp_export.c

Lines changed: 130 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
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

178179
enum 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+
207303
uint32_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

Comments
 (0)