From 556ea844a5783f9876ee748e1c686bb268f54e8a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 15 Nov 2013 10:33:52 -0500 Subject: Fix continuations in context establishment calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly support continuations, including returning the rigth error code and exporting partial contexts. Fixes multistep authentications in particular for the initialization case which always uses continuations. Resolves: https://fedorahosted.org/gss-proxy/ticket/108 Reviewed-by: Günther Deschner --- proxy/src/client/gpm_init_sec_context.c | 21 ++++++++++----------- proxy/src/gp_export.c | 33 +++++++++++++++++++++++++++++---- proxy/src/gp_export.h | 3 ++- proxy/src/gp_rpc_accept_sec_context.c | 20 +++++++++++++++++--- proxy/src/gp_rpc_get_mic.c | 2 +- proxy/src/gp_rpc_init_sec_context.c | 16 +++++++++++++++- proxy/src/gp_rpc_unwrap.c | 2 +- proxy/src/gp_rpc_verify_mic.c | 2 +- proxy/src/gp_rpc_wrap.c | 2 +- 9 files changed, 77 insertions(+), 24 deletions(-) (limited to 'proxy/src') diff --git a/proxy/src/client/gpm_init_sec_context.c b/proxy/src/client/gpm_init_sec_context.c index b6ce34f..f6dfe53 100644 --- a/proxy/src/client/gpm_init_sec_context.c +++ b/proxy/src/client/gpm_init_sec_context.c @@ -104,13 +104,6 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status, } } - if (res->status.major_status) { - gpm_save_status(&res->status); - ret_maj = res->status.major_status; - ret_min = res->status.minor_status; - goto done; - } - if (res->context_handle) { ctx = res->context_handle; /* we are stealing the delegated creds on success, so we do not want @@ -118,12 +111,18 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status, res->context_handle = NULL; } - ret = gp_conv_gssx_to_buffer_alloc(res->output_token, &outbuf); - if (ret) { - gpm_save_internal_status(ret, strerror(ret)); - goto done; + if (res->output_token) { + ret = gp_conv_gssx_to_buffer_alloc(res->output_token, &outbuf); + if (ret) { + gpm_save_internal_status(ret, strerror(ret)); + goto done; + } } + ret_maj = res->status.major_status; + ret_min = res->status.minor_status; + gpm_save_status(&res->status); + done: if (ret != 0) { ret_min = ret; diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c index 51dd686..3cd5148 100644 --- a/proxy/src/gp_export.c +++ b/proxy/src/gp_export.c @@ -390,6 +390,7 @@ done: #define LINUX_LUCID_V1 "linux_lucid_v1" enum exp_ctx_types { + EXP_CTX_PARTIAL = -1, /* cannot be specified by client */ EXP_CTX_DEFAULT = 0, EXP_CTX_LINUX_LUCID_V1 = 1, }; @@ -418,6 +419,11 @@ int gp_get_exported_context_type(struct gssx_call_ctx *ctx) return EXP_CTX_DEFAULT; } +int gp_get_continue_needed_type(void) +{ + return EXP_CTX_PARTIAL; +} + #define KRB5_CTX_FLAG_INITIATOR 0x00000001 #define KRB5_CTX_FLAG_CFX 0x00000002 #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 @@ -513,7 +519,7 @@ done: } -uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, +uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, gss_OID mech, gss_ctx_id_t *in, gssx_ctx *out) { uint32_t ret_maj; @@ -529,9 +535,6 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, int is_open; int ret; -/* TODO: For mechs that need multiple roundtrips to complete */ - /* out->state; */ - /* we do not need the client to release anything until we handle state */ out->needs_release = false; @@ -539,6 +542,11 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, &lifetime_rec, &mech_type, &ctx_flags, &is_locally_initiated, &is_open); if (ret_maj) { + if (type == EXP_CTX_PARTIAL) { + /* This may happen on partially established context, + * so just go on and put in what we can */ + goto export; + } goto done; } @@ -571,9 +579,26 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, out->open = true; } +export: /* note: once converted the original context token is not usable anymore, * so this must be the last call to use it */ switch (type) { + case EXP_CTX_PARTIAL: + /* this happens only when a init_sec_context call returns a partially + * initialized context so we return only what we have, not much */ + ret = gp_conv_oid_to_gssx(mech, &out->mech); + if (ret) { + ret_maj = GSS_S_FAILURE; + ret_min = ret; + goto done; + } + + out->locally_initiated = true; + out->open = false; + + /* out->state; */ + + /* fall through */ case EXP_CTX_DEFAULT: ret_maj = gss_export_sec_context(&ret_min, in, &export_buffer); if (ret_maj) { diff --git a/proxy/src/gp_export.h b/proxy/src/gp_export.h index 58c0040..03e5d18 100644 --- a/proxy/src/gp_export.h +++ b/proxy/src/gp_export.h @@ -37,7 +37,8 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, gssx_cred *cred, gss_cred_id_t *out); int gp_get_exported_context_type(struct gssx_call_ctx *ctx); -uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, +int gp_get_continue_needed_type(void); +uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, gss_OID mech, gss_ctx_id_t *in, gssx_ctx *out); uint32_t gp_import_gssx_to_ctx_id(uint32_t *min, int type, gssx_ctx *in, gss_ctx_id_t *out); diff --git a/proxy/src/gp_rpc_accept_sec_context.c b/proxy/src/gp_rpc_accept_sec_context.c index 40370aa..efbf07a 100644 --- a/proxy/src/gp_rpc_accept_sec_context.c +++ b/proxy/src/gp_rpc_accept_sec_context.c @@ -46,6 +46,8 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall, gss_cred_id_t *pdch = NULL; int exp_ctx_type; int exp_creds_type; + uint32_t acpt_maj; + uint32_t acpt_min; int ret; asca = &arg->accept_sec_context; @@ -109,17 +111,25 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall, &ret_flags, NULL, pdch); - if (ret_maj) { + if (ret_maj != GSS_S_COMPLETE && + ret_maj != GSS_S_CONTINUE_NEEDED) { goto done; + } else { + acpt_maj = ret_maj; + acpt_min = ret_min; + } + if (acpt_maj == GSS_S_CONTINUE_NEEDED) { + exp_ctx_type = gp_get_continue_needed_type(); } + ascr->context_handle = calloc(1, sizeof(gssx_ctx)); if (!ascr->context_handle) { ret_maj = GSS_S_FAILURE; ret_min = ENOMEM; goto done; } - ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, + ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, oid, &ctx, ascr->context_handle); if (ret_maj) { goto done; @@ -138,7 +148,7 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall, goto done; } - if ((ret_flags & GSS_C_DELEG_FLAG) && asca->ret_deleg_cred) { + if ((ret_flags & GSS_C_DELEG_FLAG) && asca->ret_deleg_cred && dch) { ascr->delegated_cred_handle = calloc(1, sizeof(gssx_cred)); if (!ascr->delegated_cred_handle) { ret_maj = GSS_S_FAILURE; @@ -159,6 +169,10 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall, &ascr->options.options_val); done: + if (ret_maj == GSS_S_COMPLETE) { + ret_maj = acpt_maj; + ret_min = acpt_min; + } ret = gp_conv_status_to_gssx(&asca->call_ctx, ret_maj, ret_min, oid, &ascr->status); diff --git a/proxy/src/gp_rpc_get_mic.c b/proxy/src/gp_rpc_get_mic.c index ca60fe4..2db7d3f 100644 --- a/proxy/src/gp_rpc_get_mic.c +++ b/proxy/src/gp_rpc_get_mic.c @@ -73,7 +73,7 @@ int gp_get_mic(struct gp_call_ctx *gpcall, goto done; } - ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, + ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID, &context_handle, gmr->context_handle); if (ret_maj) { diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c index 944389c..2781238 100644 --- a/proxy/src/gp_rpc_init_sec_context.c +++ b/proxy/src/gp_rpc_init_sec_context.c @@ -45,6 +45,8 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, gss_buffer_desc obuf = GSS_C_EMPTY_BUFFER; uint32_t ret_maj; uint32_t ret_min; + uint32_t init_maj; + uint32_t init_min; int exp_ctx_type; int ret; @@ -121,6 +123,12 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, if (ret_maj != GSS_S_COMPLETE && ret_maj != GSS_S_CONTINUE_NEEDED) { goto done; + } else { + init_maj = ret_maj; + init_min = ret_min; + } + if (init_maj == GSS_S_CONTINUE_NEEDED) { + exp_ctx_type = gp_get_continue_needed_type(); } iscr->context_handle = calloc(1, sizeof(gssx_ctx)); @@ -129,7 +137,7 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, ret_min = ENOMEM; goto done; } - ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, + ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, mech_type, &ctx, iscr->context_handle); if (ret_maj) { goto done; @@ -150,7 +158,13 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, } } + ret_maj = GSS_S_COMPLETE; + done: + if (ret_maj == GSS_S_COMPLETE) { + ret_maj = init_maj; + ret_min = init_min; + } ret = gp_conv_status_to_gssx(&isca->call_ctx, ret_maj, ret_min, mech_type, &iscr->status); diff --git a/proxy/src/gp_rpc_unwrap.c b/proxy/src/gp_rpc_unwrap.c index a20b8ea..faffa82 100644 --- a/proxy/src/gp_rpc_unwrap.c +++ b/proxy/src/gp_rpc_unwrap.c @@ -85,7 +85,7 @@ int gp_unwrap(struct gp_call_ctx *gpcall, goto done; } - ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, + ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID, &context_handle, uwr->context_handle); if (ret_maj) { diff --git a/proxy/src/gp_rpc_verify_mic.c b/proxy/src/gp_rpc_verify_mic.c index 68369a0..a2d3f7e 100644 --- a/proxy/src/gp_rpc_verify_mic.c +++ b/proxy/src/gp_rpc_verify_mic.c @@ -76,7 +76,7 @@ int gp_verify_mic(struct gp_call_ctx *gpcall, goto done; } - ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, + ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID, &context_handle, vmr->context_handle); if (ret_maj) { diff --git a/proxy/src/gp_rpc_wrap.c b/proxy/src/gp_rpc_wrap.c index d17c292..c2da7ba 100644 --- a/proxy/src/gp_rpc_wrap.c +++ b/proxy/src/gp_rpc_wrap.c @@ -85,7 +85,7 @@ int gp_wrap(struct gp_call_ctx *gpcall, goto done; } - ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, + ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID, &context_handle, wr->context_handle); if (ret_maj) { goto done; -- cgit