diff options
Diffstat (limited to 'sys/kgssapi/gss_init_sec_context.c')
-rw-r--r-- | sys/kgssapi/gss_init_sec_context.c | 145 |
1 files changed, 144 insertions, 1 deletions
diff --git a/sys/kgssapi/gss_init_sec_context.c b/sys/kgssapi/gss_init_sec_context.c index fa0d3fb2ae19..a0f48fda8b29 100644 --- a/sys/kgssapi/gss_init_sec_context.c +++ b/sys/kgssapi/gss_init_sec_context.c @@ -42,6 +42,11 @@ #include "gssd.h" #include "kgss_if.h" +/* + * This function should only be called when the gssd + * daemon running on the system is an old one that + * does not use gss_krb5_export_lucid_sec_context(). + */ OM_uint32 gss_init_sec_context(OM_uint32 * minor_status, const gss_cred_id_t initiator_cred_handle, @@ -133,7 +138,145 @@ gss_init_sec_context(OM_uint32 * minor_status, * etc.) to the kernel implementation. */ if (res.major_status == GSS_S_COMPLETE) - res.major_status = kgss_transfer_context(ctx); + res.major_status = kgss_transfer_context(ctx, NULL); + + return (res.major_status); +} + +OM_uint32 +gss_supports_lucid(uint32_t *minor_status, uint32_t *vers) +{ + struct supports_lucid_res res; + enum clnt_stat stat; + CLIENT *cl; + + *minor_status = 0; + + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + + bzero(&res, sizeof(res)); + stat = gssd_supports_lucid_1(NULL, &res, cl); + CLNT_RELEASE(cl); + if (stat != RPC_SUCCESS) { + *minor_status = stat; + return (GSS_S_FAILURE); + } + + if (vers) + *vers = res.vers; + + return (res.major_status); +} + +/* + * This function should be called when the gssd daemon is + * one that uses gss_krb5_export_lucid_sec_context(). + * There is a lot of code common with + * gss_init_sec_context(). However, the structures used + * are not the same and future changes may be needed for + * this one. As such, I have not factored out the common + * code. + * gss_supports_lucid() may be used to check to see if the + * gssd daemon uses gss_krb5_export_lucid_sec_context(). + */ +OM_uint32 +gss_init_sec_context_lucid_v1(OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID input_mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + struct init_sec_context_lucid_v1_res res; + struct init_sec_context_lucid_v1_args args; + enum clnt_stat stat; + gss_ctx_id_t ctx = *context_handle; + CLIENT *cl; + + *minor_status = 0; + + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + + args.uid = curthread->td_ucred->cr_uid; + if (initiator_cred_handle) + args.cred = initiator_cred_handle->handle; + else + args.cred = 0; + if (ctx) + args.ctx = ctx->handle; + else + args.ctx = 0; + args.name = target_name->handle; + args.mech_type = input_mech_type; + args.req_flags = req_flags; + args.time_req = time_req; + args.input_chan_bindings = input_chan_bindings; + if (input_token) + args.input_token = *input_token; + else { + args.input_token.length = 0; + args.input_token.value = NULL; + } + + bzero(&res, sizeof(res)); + stat = gssd_init_sec_context_lucid_v1_1(&args, &res, cl); + CLNT_RELEASE(cl); + if (stat != RPC_SUCCESS) { + *minor_status = stat; + return (GSS_S_FAILURE); + } + + if (res.major_status != GSS_S_COMPLETE + && res.major_status != GSS_S_CONTINUE_NEEDED) { + *minor_status = res.minor_status; + xdr_free((xdrproc_t) xdr_init_sec_context_lucid_v1_res, &res); + return (res.major_status); + } + + *minor_status = res.minor_status; + + if (!ctx) { + ctx = kgss_create_context(res.actual_mech_type); + if (!ctx) { + xdr_free((xdrproc_t) xdr_init_sec_context_lucid_v1_res, &res); + *minor_status = 0; + return (GSS_S_BAD_MECH); + } + } + *context_handle = ctx; + ctx->handle = res.ctx; + if (actual_mech_type) + *actual_mech_type = KGSS_MECH_TYPE(ctx); + kgss_copy_buffer(&res.output_token, output_token); + if (ret_flags) + *ret_flags = res.ret_flags; + if (time_rec) + *time_rec = res.time_rec; + + /* + * If the context establishment is complete, export it from + * userland and hand the result (which includes key material + * etc.) to the kernel implementation. + */ + if (res.major_status == GSS_S_COMPLETE) { + res.major_status = kgss_transfer_context(ctx, &res.lucid); + if (res.major_status != GSS_S_COMPLETE) + printf("gss_init_sec_context_lucid_v1: " + "transfer failed\n"); + } + + xdr_free((xdrproc_t) xdr_init_sec_context_lucid_v1_res, &res); return (res.major_status); } |