diff --git a/gssproxy-0.3.0-continuations.patch b/gssproxy-0.3.0-continuations.patch new file mode 100644 index 0000000..967d329 --- /dev/null +++ b/gssproxy-0.3.0-continuations.patch @@ -0,0 +1,331 @@ +From 556ea844a5783f9876ee748e1c686bb268f54e8a Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Fri, 15 Nov 2013 10:33:52 -0500 +Subject: [PATCH] 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(-) + +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; +-- +1.8.3.1 + diff --git a/gssproxy.spec b/gssproxy.spec index 3a5ea9e..6227600 100644 --- a/gssproxy.spec +++ b/gssproxy.spec @@ -10,6 +10,7 @@ Source0: http://fedorahosted.org/released/gss-proxy/%{name}-%{version}.tar.gz BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) Patch0: gssproxy-0.3.0-gss_init_sec_context.patch Patch1: gssproxy-0.3.0-gss_inquire_cred_by_mech.patch +Patch2: gssproxy-0.3.0-continuations.patch %global servicename gssproxy %global pubconfpath %{_sysconfdir}/gssproxy @@ -56,6 +57,7 @@ A proxy for GSSAPI credential handling %patch0 -p2 -b .gss_init_sec_context %patch1 -p2 -b .gss_inquire_cred_by_mech +%patch2 -p2 -b .continuations %build autoreconf -f -i @@ -113,6 +115,8 @@ rm -rf %{buildroot} - resolves: https://fedorahosted.org/gss-proxy/ticket/106 - Fix OID handling in gss_inquire_cred_by_mech() - resolves: https://fedorahosted.org/gss-proxy/ticket/107 +- Fix continuation processing for not yet fully established contexts. +- resolves: https://fedorahosted.org/gss-proxy/ticket/108 * Wed Oct 23 2013 Guenther Deschner 0.3.0-0 - New upstream release 0.3.0: