diff --git a/SOURCES/gssproxy-0.3.0-continuations.patch b/SOURCES/gssproxy-0.3.0-continuations.patch new file mode 100644 index 0000000..967d329 --- /dev/null +++ b/SOURCES/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/SOURCES/gssproxy-0.3.0-flags_handling.patch b/SOURCES/gssproxy-0.3.0-flags_handling.patch new file mode 100644 index 0000000..0beeb79 --- /dev/null +++ b/SOURCES/gssproxy-0.3.0-flags_handling.patch @@ -0,0 +1,451 @@ +From 591fad86aba3520a76eaf75aa0fd5e585fac94a5 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 13 Nov 2013 19:54:27 -0500 +Subject: [PATCH 1/5] Autoinitialize creds on init_sec_context +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the remote client tries to initialize the context without first +acquiring credentials, try to acquire appropriate credentials if +the service allows it. + +Reviewed-by: Günther Deschner +--- + proxy/src/gp_rpc_init_sec_context.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c +index 2781238..76ffaab 100644 +--- a/proxy/src/gp_rpc_init_sec_context.c ++++ b/proxy/src/gp_rpc_init_sec_context.c +@@ -24,6 +24,7 @@ + */ + + #include "gp_rpc_process.h" ++#include + + int gp_init_sec_context(struct gp_call_ctx *gpcall, + union gp_rpc_arg *arg, +@@ -74,13 +75,7 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, + if (ret_maj) { + goto done; + } +- } else { +- /* FIXME: get ccache from gpsvc ? */ +- ret_maj = GSS_S_CRED_UNAVAIL; +- ret_min = 0; +- goto done; + } +- + ret_maj = gp_conv_gssx_to_name(&ret_min, isca->target_name, &target_name); + if (ret_maj) { + goto done; +@@ -107,6 +102,23 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, + gp_conv_gssx_to_buffer(isca->input_token, &ibuf); + } + ++ if (!isca->cred_handle) { ++ if (gss_oid_equal(mech_type, gss_mech_krb5)) { ++ ret_maj = gp_add_krb5_creds(&ret_min, gpcall, ++ NULL, NULL, ++ GSS_C_INITIATE, ++ time_req, 0, &ich, ++ NULL, NULL, NULL); ++ } else { ++ ret_maj = GSS_S_NO_CRED; ++ ret_min = 0; ++ } ++ ++ if (ret_maj) { ++ goto done; ++ } ++ } ++ + ret_maj = gss_init_sec_context(&ret_min, + ich, + &ctx, +@@ -170,5 +182,6 @@ done: + &iscr->status); + gss_release_name(&ret_min, &target_name); + gss_release_oid(&ret_min, &mech_type); ++ gss_release_cred(&ret_min, &ich); + return ret; + } +-- +1.8.3.1 + + +From 32b1d5aa0497c4e3677b4575cc7e299590df5618 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 13 Nov 2013 20:03:53 -0500 +Subject: [PATCH 2/5] Try impersonation even when a name is not provided +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In some cases a name may not be provided, still try to perform +impersonation if the service is configured that way. + +Reviewed-by: Günther Deschner +--- + proxy/src/gp_creds.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index e02a667..5337390 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -289,6 +289,11 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall, + } + *requested_name = name; + } ++ } else { ++ /* No name provided */ ++ if (svc->euid != target_uid) { ++ user_requested = true; ++ } + } + + /* impersonation case (only for initiation) */ +-- +1.8.3.1 + + +From 6a096c0a0a37d2fa9e0b03edce05929a7d98f390 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Sat, 16 Nov 2013 17:01:24 -0500 +Subject: [PATCH 3/5] config: Add code to source flag filters +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +2 New configuration options are made available: +- filter_flags +- enforce_flags + +Any GSS Flags listed in the filter_flags option is forcibly filtered +out before a gss_init_sec_context() call is invoked. +Any GSS Flags listed in the enforce_flags option is forcibly added +to the list of flags requested by a gss_init_sec_context() call is +invoked. + +Flags can be either literals or numeric and must be preceded by the +sign + (to add to the list) or - (to remove from the list). + +Resolves: https://fedorahosted.org/gss-proxy/ticket/109 + +Reviewed-by: Günther Deschner +--- + proxy/src/gp_config.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++ + proxy/src/gp_proxy.h | 2 ++ + 2 files changed, 90 insertions(+) + +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index 8da291b..e21e70d 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -32,6 +32,27 @@ + #include "gp_config.h" + #include "gp_selinux.h" + ++#include ++ ++struct gp_flag_def { ++ const char *name; ++ uint32_t value; ++}; ++ ++struct gp_flag_def flag_names[] = { ++ { "DELEGATE", GSS_C_DELEG_FLAG }, ++ { "MUTUAL_AUTH", GSS_C_MUTUAL_FLAG }, ++ { "REPLAY_DETECT", GSS_C_REPLAY_FLAG }, ++ { "SEQUENCE", GSS_C_SEQUENCE_FLAG }, ++ { "CONFIDENTIALITY", GSS_C_CONF_FLAG }, ++ { "INTEGRITIY", GSS_C_INTEG_FLAG }, ++ { "ANONYMOUS", GSS_C_ANON_FLAG }, ++ { NULL, 0 } ++}; ++ ++#define DEFAULT_FILTERED_FLAGS GSS_C_DELEG_FLAG ++#define DEFAULT_ENFORCED_FLAGS 0 ++ + static void free_str_array(const char ***a, int *count) + { + const char **array; +@@ -117,6 +138,60 @@ static int get_krb5_mech_cfg(struct gp_service *svc, + return ret; + } + ++static int parse_flags(const char *value, uint32_t *storage) ++{ ++ char *handle; ++ char *token; ++ char *str; ++ bool add; ++ unsigned long int conv; ++ uint32_t flagval; ++ int i; ++ ++ str = strdup(value); ++ if (!str) { ++ return ENOMEM; ++ } ++ ++ token = strtok_r(str, ", ", &handle); ++ for (token = strtok_r(str, ", ", &handle); ++ token != NULL; ++ token = strtok_r(NULL, ", ", &handle)) { ++ switch (token[0]) { ++ case '+': ++ add = true; ++ break; ++ case '-': ++ add = false; ++ break; ++ default: ++ GPERROR("Ignoring flag [%s], missing +/- qualifier.\n", token); ++ continue; ++ } ++ token++; ++ for (i = 0; flag_names[i].name != NULL; i++) { ++ if (strcasecmp(token, flag_names[i].name) == 0) { ++ flagval = flag_names[i].value; ++ break; ++ } ++ } ++ if (flag_names[i].name == NULL) { ++ conv = strtoul(token, &handle, 0); ++ if (conv == 0 || conv == ULONG_MAX || *handle != '\0') { ++ GPERROR("Ignoring flag [%s], unrecognized value.\n", token); ++ continue; ++ } ++ flagval = conv; ++ } ++ GPDEBUG("%s Flag %s (%u).\n", add?"Add":"Remove", token, flagval); ++ if (add) *storage |= flagval; ++ else *storage &= ~flagval; ++ } ++ safefree(str); ++ ++ return 0; ++} ++ + static int setup_service_creds_handle(struct gp_service *svc) + { + uint32_t ret_maj, ret_min; +@@ -297,6 +372,19 @@ static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) + goto done; + } + } ++ ++ cfg->svcs[n]->filter_flags = DEFAULT_FILTERED_FLAGS; ++ ret = gp_config_get_string(ctx, secname, "filter_flags", &value); ++ if (ret == 0) { ++ parse_flags(value, &cfg->svcs[n]->filter_flags); ++ } ++ ++ cfg->svcs[n]->enforce_flags = DEFAULT_ENFORCED_FLAGS; ++ ret = gp_config_get_string(ctx, secname, "enforce_flags", &value); ++ if (ret == 0) { ++ ret = parse_flags(value, &cfg->svcs[n]->enforce_flags); ++ if (ret) goto done; ++ } + } + safefree(secname); + } +diff --git a/proxy/src/gp_proxy.h b/proxy/src/gp_proxy.h +index 8390f5d..b6c64ae 100644 +--- a/proxy/src/gp_proxy.h ++++ b/proxy/src/gp_proxy.h +@@ -57,6 +57,8 @@ struct gp_service { + char *socket; + SELINUX_CTX selinux_ctx; + gss_cred_usage_t cred_usage; ++ uint32_t filter_flags; ++ uint32_t enforce_flags; + + uint32_t mechs; + struct gp_cred_krb5 krb5; +-- +1.8.3.1 + + +From 3df6ac81f4a6d8cf6ff514e7d7f2cbe58840c393 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Sat, 16 Nov 2013 17:09:45 -0500 +Subject: [PATCH 4/5] server: Implement flag filtering enforcement +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://fedorahosted.org/gss-proxy/ticket/109 + +Reviewed-by: Günther Deschner +--- + proxy/src/gp_creds.c | 6 ++++++ + proxy/src/gp_rpc_creds.h | 3 +++ + proxy/src/gp_rpc_init_sec_context.c | 2 ++ + 3 files changed, 11 insertions(+) + +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index 5337390..60c4e12 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -548,3 +548,9 @@ done: + + return ret_maj; + } ++ ++void gp_filter_flags(struct gp_call_ctx *gpcall, uint32_t *flags) ++{ ++ *flags |= gpcall->service->enforce_flags; ++ *flags &= ~gpcall->service->filter_flags; ++} +diff --git a/proxy/src/gp_rpc_creds.h b/proxy/src/gp_rpc_creds.h +index 6389ebe..4c8febb 100644 +--- a/proxy/src/gp_rpc_creds.h ++++ b/proxy/src/gp_rpc_creds.h +@@ -46,4 +46,7 @@ uint32_t gp_add_krb5_creds(uint32_t *min, + gss_OID_set *actual_mechs, + uint32_t *initiator_time_rec, + uint32_t *acceptor_time_rec); ++ ++void gp_filter_flags(struct gp_call_ctx *gpcall, uint32_t *flags); ++ + #endif /* _GP_RPC_CREDS_H_ */ +diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c +index 76ffaab..5e5d6f1 100644 +--- a/proxy/src/gp_rpc_init_sec_context.c ++++ b/proxy/src/gp_rpc_init_sec_context.c +@@ -119,6 +119,8 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, + } + } + ++ gp_filter_flags(gpcall, &req_flags); ++ + ret_maj = gss_init_sec_context(&ret_min, + ich, + &ctx, +-- +1.8.3.1 + + +From c8386418a754211da5ddf5469a0f1c0fddf21240 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Sat, 16 Nov 2013 17:27:52 -0500 +Subject: [PATCH 5/5] man: Describe new flag filtering/enforcing options +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://fedorahosted.org/gss-proxy/ticket/109 + +Reviewed-by: Günther Deschner +--- + proxy/man/gssproxy.conf.5.xml | 58 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + +diff --git a/proxy/man/gssproxy.conf.5.xml b/proxy/man/gssproxy.conf.5.xml +index b0012b5..b4d5add 100644 +--- a/proxy/man/gssproxy.conf.5.xml ++++ b/proxy/man/gssproxy.conf.5.xml +@@ -162,6 +162,64 @@ + + + ++ enforce_flags (string) ++ ++ ++ A list of GSS Request Flags that are added ++ unconditionally to every context initialization ++ call. ++ Flags can only be added to the list or removed ++ from the list by prepending a +/- sign to the ++ flag name or value. ++ ++ ++ Recognized flag names: DELEGATE, MUTUAL_AUTH, ++ REPLAY_DETECT, SEQUENCE, CONFIDENTIALITY, ++ INTEGRITY, ANONYMOUS ++ ++ Examples: ++ ++ enforce_flags = +REPLAY_DETECT ++ enforce_flags = -0x0001 ++ ++ ++ Default: enforce_flags = ++ ++ ++ ++ ++ filter_flags (string) ++ ++ ++ A list of GSS Request Flags that are filtered ++ unconditionally from every context initialization ++ call. ++ Flags can only be added to the list or removed ++ from the list by prepending a +/- sign to the ++ flag name or value. ++ ++ ++ NOTE: Because often gssproxy is used to withold ++ access to credentials the Delegate Flag is filtered ++ by default. To allow a service to delegate ++ credentials use the first example below. ++ ++ ++ Recognized flag names: DELEGATE, MUTUAL_AUTH, ++ REPLAY_DETECT, SEQUENCE, CONFIDENTIALITY, ++ INTEGRITY, ANONYMOUS ++ ++ Examples: ++ ++ filter_flags = -DELEGATE ++ filter_flags = -0x0001 +ANONYMOUS ++ ++ ++ Default: filter_flags = +DELEGATE ++ ++ ++ ++ + impersonate (boolean) + + Use impersonation (s4u2self + s4u2proxy) to obtain credentials +-- +1.8.3.1 + +From 8b147c9196d9068d0fc5e5a8919b84e8cbb97ef4 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Fri, 6 Dec 2013 17:51:14 -0500 +Subject: [PATCH] Fix config token parsing. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://fedorahosted.org/gss-proxy/ticket/112 + +Signed-off-by: Simo Sorce +Reviewed-by: Günther Deschner +--- + proxy/src/gp_config.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index 2fc4a6f..ee96975 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -153,7 +153,6 @@ static int parse_flags(const char *value, uint32_t *storage) + return ENOMEM; + } + +- token = strtok_r(str, ", ", &handle); + for (token = strtok_r(str, ", ", &handle); + token != NULL; + token = strtok_r(NULL, ", ", &handle)) { +-- +1.8.3.1 + diff --git a/SOURCES/gssproxy-0.3.0-gss_init_sec_context.patch b/SOURCES/gssproxy-0.3.0-gss_init_sec_context.patch new file mode 100644 index 0000000..117a071 --- /dev/null +++ b/SOURCES/gssproxy-0.3.0-gss_init_sec_context.patch @@ -0,0 +1,36 @@ +From cc538c36ca32850e0b3280b7d8524d23345eed9e Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 13 Nov 2013 17:57:06 -0500 +Subject: [PATCH 1/3] Preserve requested flags and lifetime +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +These arguments have been accidentally forgotten causing failures for +applications that specify non default flags and non indefinite lifetime. + +https://fedorahosted.org/gss-proxy/ticket/106 + +Reviewed-by: Günther Deschner +--- + proxy/src/client/gpm_init_sec_context.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/proxy/src/client/gpm_init_sec_context.c b/proxy/src/client/gpm_init_sec_context.c +index 12df858..b6ce34f 100644 +--- a/proxy/src/client/gpm_init_sec_context.c ++++ b/proxy/src/client/gpm_init_sec_context.c +@@ -70,6 +70,9 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status, + goto done; + } + ++ arg->req_flags = req_flags; ++ arg->time_req = time_req; ++ + if (input_cb) { + ret = gp_conv_cb_to_gssx_alloc(input_cb, &arg->input_cb); + if (ret) { +-- +1.8.3.1 + + diff --git a/SOURCES/gssproxy-0.3.0-gss_inquire_cred_by_mech.patch b/SOURCES/gssproxy-0.3.0-gss_inquire_cred_by_mech.patch new file mode 100644 index 0000000..0543417 --- /dev/null +++ b/SOURCES/gssproxy-0.3.0-gss_inquire_cred_by_mech.patch @@ -0,0 +1,186 @@ +From 122b35f7adf37bc81f6d53bb5f9e058b68334cbb Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 13 Nov 2013 18:12:44 -0500 +Subject: [PATCH 2/3] Add way to return regular oid from special +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In some cases we need to pass on the corresponding real oid, after we +are given a special oid. +Add helper functions to do that. + +https://fedorahosted.org/gss-proxy/ticket/107 + +Reviewed-by: Günther Deschner +--- + proxy/src/mechglue/gss_plugin.c | 55 +++++++++++++++++++++++++++++++---------- + proxy/src/mechglue/gss_plugin.h | 1 + + 2 files changed, 43 insertions(+), 13 deletions(-) + +diff --git a/proxy/src/mechglue/gss_plugin.c b/proxy/src/mechglue/gss_plugin.c +index 0e62990..5b40df9 100644 +--- a/proxy/src/mechglue/gss_plugin.c ++++ b/proxy/src/mechglue/gss_plugin.c +@@ -176,7 +176,8 @@ static bool gpp_special_equal(const gss_OID s, const gss_OID n) + } + + struct gpp_special_oid_list { +- gss_OID_desc oid; ++ gss_OID_desc regular_oid; ++ gss_OID_desc special_oid; + struct gpp_special_oid_list *next; + sig_atomic_t next_is_set; + }; +@@ -250,19 +251,25 @@ static const gss_OID gpp_new_special_mech(const gss_OID n) + if (!item) { + return GSS_C_NO_OID; + } +- item->oid.length = base->length + n->length; +- item->oid.elements = malloc(item->oid.length); +- if (!item->oid.elements) { ++ item->regular_oid.length = n->length; ++ item->regular_oid.elements = malloc(n->length); ++ item->special_oid.length = base->length + n->length; ++ item->special_oid.elements = malloc(item->special_oid.length); ++ if (!item->regular_oid.elements || ++ !item->special_oid.elements) { ++ free(item->regular_oid.elements); ++ free(item->special_oid.elements); + free(item); + return GSS_C_NO_OID; + } + +- memcpy(item->oid.elements, base->elements, base->length); +- memcpy(item->oid.elements + base->length, n->elements, n->length); ++ memcpy(item->regular_oid.elements, n->elements, n->length); ++ memcpy(item->special_oid.elements, base->elements, base->length); ++ memcpy(item->special_oid.elements + base->length, n->elements, n->length); + + gpp_add_special_oids(item); + +- return (const gss_OID)&item->oid; ++ return (const gss_OID)&item->special_oid; + } + + const gss_OID gpp_special_mech(const gss_OID mech_type) +@@ -278,14 +285,14 @@ const gss_OID gpp_special_mech(const gss_OID mech_type) + if (mech_type == GSS_C_NO_OID) { + /* return the first special one if none specified */ + if (item) { +- return (const gss_OID)&item->oid; ++ return (const gss_OID)&item->special_oid; + } + return GSS_C_NO_OID; + } + + while (item) { +- if (gpp_special_equal(&item->oid, mech_type)) { +- return (const gss_OID)&item->oid; ++ if (gpp_special_equal(&item->special_oid, mech_type)) { ++ return (const gss_OID)&item->special_oid; + } + item = gpp_next_special_oids(item); + } +@@ -294,6 +301,26 @@ const gss_OID gpp_special_mech(const gss_OID mech_type) + return gpp_new_special_mech(mech_type); + } + ++const gss_OID gpp_unspecial_mech(const gss_OID mech_type) ++{ ++ struct gpp_special_oid_list *item = NULL; ++ ++ if (!gpp_is_special_oid(mech_type)) { ++ return mech_type; ++ } ++ ++ item = gpp_get_special_oids(); ++ while (item) { ++ if (gss_oid_equal(&item->special_oid, mech_type)) { ++ return (const gss_OID)&item->regular_oid; ++ } ++ item = gpp_next_special_oids(item); ++ } ++ ++ /* none matched */ ++ return mech_type; ++} ++ + gss_OID_set gpp_special_available_mechs(const gss_OID_set mechs) + { + gss_OID_set amechs = GSS_C_NO_OID_SET; +@@ -318,8 +345,9 @@ gss_OID_set gpp_special_available_mechs(const gss_OID_set mechs) + } + break; + } +- if (gpp_special_equal(&item->oid, &mechs->elements[i])) { +- maj = gss_add_oid_set_member(&min, &item->oid, &amechs); ++ if (gpp_special_equal(&item->special_oid, &mechs->elements[i])) { ++ maj = gss_add_oid_set_member(&min, &item->special_oid, ++ &amechs); + if (maj != GSS_S_COMPLETE) { + goto done; + } +@@ -362,7 +390,8 @@ OM_uint32 gssi_internal_release_oid(OM_uint32 *minor_status, gss_OID *oid) + item = gpp_get_special_oids(); + + while (item) { +- if (&item->oid == *oid) { ++ if ((&item->regular_oid == *oid) || ++ (&item->special_oid == *oid)) { + *oid = GSS_C_NO_OID; + return GSS_S_COMPLETE; + } +diff --git a/proxy/src/mechglue/gss_plugin.h b/proxy/src/mechglue/gss_plugin.h +index 26e04c5..739ec26 100644 +--- a/proxy/src/mechglue/gss_plugin.h ++++ b/proxy/src/mechglue/gss_plugin.h +@@ -78,6 +78,7 @@ gss_OID_set gss_mech_interposer(gss_OID mech_type); + enum gpp_behavior gpp_get_behavior(void); + bool gpp_is_special_oid(const gss_OID mech_type); + const gss_OID gpp_special_mech(const gss_OID mech_type); ++const gss_OID gpp_unspecial_mech(const gss_OID mech_type); + gss_OID_set gpp_special_available_mechs(const gss_OID_set mechs); + uint32_t gpp_map_error(uint32_t err); + uint32_t gpp_unmap_error(uint32_t err); +-- +1.8.3.1 + + +From b8901d1d20a5d0ef1a3118bfe5816e04c09e6cf5 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 13 Nov 2013 18:13:44 -0500 +Subject: [PATCH 3/3] Fix calling gpm_inquire_cred_by_mech +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We need to pass the real mechanism oid here, not the spcial oid. +special oids are used exclusively by the interposer and gssapi +machinery that calls the interposer, they must never be propagated +to clients or servers. + +https://fedorahosted.org/gss-proxy/ticket/107 + +Reviewed-by: Günther Deschner +--- + proxy/src/mechglue/gpp_creds.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c +index aaaf577..dff9c44 100644 +--- a/proxy/src/mechglue/gpp_creds.c ++++ b/proxy/src/mechglue/gpp_creds.c +@@ -213,7 +213,8 @@ OM_uint32 gssi_inquire_cred_by_mech(OM_uint32 *minor_status, + initiator_lifetime, acceptor_lifetime, + cred_usage); + } else if (cred->remote) { +- maj = gpm_inquire_cred_by_mech(&min, cred->remote, mech_type, ++ maj = gpm_inquire_cred_by_mech(&min, cred->remote, ++ gpp_unspecial_mech(mech_type), + gpname ? &gpname->remote : NULL, + initiator_lifetime, acceptor_lifetime, + cred_usage); +-- +1.8.3.1 + diff --git a/SOURCES/gssproxy-0.3.1-deadlock_fix.patch b/SOURCES/gssproxy-0.3.1-deadlock_fix.patch new file mode 100644 index 0000000..c6e7661 --- /dev/null +++ b/SOURCES/gssproxy-0.3.1-deadlock_fix.patch @@ -0,0 +1,36 @@ +From f39b471f34b381784a1bd1906bf8335ac2c7ef5e Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Tue, 11 Mar 2014 18:16:32 -0400 +Subject: [PATCH] Properly cleanup mutex on failure. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If the call to create socket fails we leave a dangling lock and the client +enters into a deadlock on the next call. + +Fixes: https://fedorahosted.org/gss-proxy/ticket/121 + +Signed-off-by: Simo Sorce +Reviewed-by: Günther Deschner +--- + proxy/src/client/gpm_common.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 74296da..4651194 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -153,6 +153,9 @@ static int gpm_grab_sock(struct gpm_ctx *gpmctx) + ret = gpm_open_socket(gpmctx); + } + ++ if (ret) { ++ pthread_mutex_unlock(&gpmctx->lock); ++ } + return ret; + } + +-- +1.8.5.3 + diff --git a/SOURCES/gssproxy-0.3.1-nfsd_startup.patch b/SOURCES/gssproxy-0.3.1-nfsd_startup.patch new file mode 100644 index 0000000..ebd4530 --- /dev/null +++ b/SOURCES/gssproxy-0.3.1-nfsd_startup.patch @@ -0,0 +1,240 @@ +From 58a39677c961c72b052eae0b9d94b992254d6e10 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Fri, 3 Jan 2014 16:45:35 -0500 +Subject: [PATCH 1/2] Add utility functions to read()/write() safely +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Automatically handle short reads due to singals interrupting the process. + +Signed-off-by: Simo Sorce +Reviewed-by: Günther Deschner +--- + proxy/src/gp_common.h | 2 ++ + proxy/src/gp_util.c | 39 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 41 insertions(+) + +diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h +index f2b8c3e..3a1b7be 100644 +--- a/proxy/src/gp_common.h ++++ b/proxy/src/gp_common.h +@@ -69,6 +69,8 @@ bool gp_same(const char *a, const char *b); + bool gp_boolean_is_true(const char *s); + char *gp_getenv(const char *name); + ++ssize_t gp_safe_read(int fd, void *buf, size_t count); ++ssize_t gp_safe_write(int fd, const void *buf, size_t count); + /* NOTE: read the note in gp_util.c before using gp_strerror() */ + char *gp_strerror(int errnum); + +diff --git a/proxy/src/gp_util.c b/proxy/src/gp_util.c +index 4fbac4e..34f3024 100644 +--- a/proxy/src/gp_util.c ++++ b/proxy/src/gp_util.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + bool gp_same(const char *a, const char *b) + { +@@ -125,3 +126,41 @@ char *gp_strerror(int errnum) + errno = saved_errno; + return buf; + } ++ ++ssize_t gp_safe_read(int fd, void *buf, size_t count) ++{ ++ char *b = (char *)buf; ++ ssize_t len = 0; ++ ssize_t ret; ++ ++ do { ++ ret = read(fd, &b[len], count - len); ++ if (ret == -1) { ++ if (errno == EINTR) continue; ++ return ret; ++ } ++ if (ret == 0) break; /* EOF */ ++ len += ret; ++ } while (count > len); ++ ++ return len; ++} ++ ++ssize_t gp_safe_write(int fd, const void *buf, size_t count) ++{ ++ const char *b = (const char *)buf; ++ ssize_t len = 0; ++ ssize_t ret; ++ ++ do { ++ ret = write(fd, &b[len], count - len); ++ if (ret == -1) { ++ if (errno == EINTR) continue; ++ return ret; ++ } ++ if (ret == 0) break; /* EOF */ ++ len += ret; ++ } while (count > len); ++ ++ return len; ++} +-- +1.8.4.2 + + +From bd8ffcf67be8fdbe14bc49a65a8eafe904119d88 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Fri, 3 Jan 2014 12:10:36 -0500 +Subject: [PATCH 2/2] Block parent process until child is initialized. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This way the init system will not proceed starting dependencies until gssproxy +is actually ready to serve requests. +In particular this is used to make sure the nfsd proc file has been touched +before the nfsd server is started. + +Resolves: https://fedorahosted.org/gss-proxy/ticket/114 + +Signed-off-by: Simo Sorce +Reviewed-by: Günther Deschner +--- + proxy/src/gp_init.c | 42 +++++++++++++++++++++++++++++++++++++++--- + proxy/src/gp_proxy.h | 3 ++- + proxy/src/gssproxy.c | 11 +++++++++-- + 3 files changed, 50 insertions(+), 6 deletions(-) + +diff --git a/proxy/src/gp_init.c b/proxy/src/gp_init.c +index 830ae16..6207a78 100644 +--- a/proxy/src/gp_init.c ++++ b/proxy/src/gp_init.c +@@ -37,12 +37,22 @@ + #include + #include "gp_proxy.h" + +-void init_server(bool daemonize) ++void init_server(bool daemonize, int *wait_fd) + { + pid_t pid, sid; + int ret; + ++ *wait_fd = -1; ++ + if (daemonize) { ++ int pipefd[2]; ++ char buf[1]; ++ ++ /* create parent-child pipe */ ++ ret = pipe(pipefd); ++ if (ret == -1) { ++ exit(EXIT_FAILURE); ++ } + + pid = fork(); + if (pid == -1) { +@@ -50,10 +60,22 @@ void init_server(bool daemonize) + exit(EXIT_FAILURE); + } + if (pid != 0) { +- /* ok kill the parent */ +- exit(EXIT_SUCCESS); ++ /* wait for child to signal it is ready */ ++ close(pipefd[1]); ++ ret = gp_safe_read(pipefd[0], buf, 1); ++ if (ret == 1) { ++ /* child signaled all ok */ ++ exit(EXIT_SUCCESS); ++ } else { ++ /* lost child, something went wrong */ ++ exit(EXIT_FAILURE); ++ } + } + ++ /* child */ ++ close(pipefd[0]); ++ *wait_fd = pipefd[1]; ++ + sid = setsid(); + if (sid == -1) { + /* setsid error ? abort */ +@@ -78,6 +100,20 @@ void init_server(bool daemonize) + gp_logging_init(); + } + ++void init_done(int wait_fd) ++{ ++ char buf = 0; ++ int ret; ++ ++ if (wait_fd != -1) { ++ ret = gp_safe_write(wait_fd, &buf, 1); ++ if (ret != 1) { ++ exit(EXIT_FAILURE); ++ } ++ close(wait_fd); ++ } ++} ++ + void fini_server(void) + { + closelog(); +diff --git a/proxy/src/gp_proxy.h b/proxy/src/gp_proxy.h +index 733fec5..79bebb8 100644 +--- a/proxy/src/gp_proxy.h ++++ b/proxy/src/gp_proxy.h +@@ -106,7 +106,8 @@ struct gp_creds_handle *gp_service_get_creds_handle(struct gp_service *svc); + void free_config(struct gp_config **config); + + /* from gp_init.c */ +-void init_server(bool daemonize); ++void init_server(bool daemonize, int *wait_fd); ++void init_done(int wait_fd); + void fini_server(void); + verto_ctx *init_event_loop(void); + void init_proc_nfsd(struct gp_config *cfg); +diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c +index 1bf0a0b..80430d6 100644 +--- a/proxy/src/gssproxy.c ++++ b/proxy/src/gssproxy.c +@@ -42,6 +42,7 @@ int main(int argc, const char *argv[]) + int vflags; + struct gssproxy_ctx *gpctx; + struct gp_sock_ctx *sock_ctx; ++ int wait_fd; + int ret; + int i; + +@@ -97,7 +98,7 @@ int main(int argc, const char *argv[]) + exit(EXIT_FAILURE); + } + +- init_server(gpctx->config->daemonize); ++ init_server(gpctx->config->daemonize, &wait_fd); + + write_pid(); + +@@ -139,9 +140,15 @@ int main(int argc, const char *argv[]) + } + } + +- /* special call to tell the Linux kernel gss-proxy is available */ ++ /* We need to tell nfsd that GSS-Proxy is available before it starts, ++ * as nfsd needs to know GSS-Proxy is in use before the first time it ++ * needs to call accept_sec_context. */ + init_proc_nfsd(gpctx->config); + ++ /* Now it is safe to tell the init system that we're done starting up, ++ * so it can continue with dependencies and start nfsd */ ++ init_done(wait_fd); ++ + ret = gp_workers_init(gpctx); + if (ret) { + exit(EXIT_FAILURE); +-- +1.8.4.2 + diff --git a/SOURCES/gssproxy-0.3.1-secure_getenv.patch b/SOURCES/gssproxy-0.3.1-secure_getenv.patch new file mode 100644 index 0000000..fd540c4 --- /dev/null +++ b/SOURCES/gssproxy-0.3.1-secure_getenv.patch @@ -0,0 +1,249 @@ +From 1d78d1af3da7eeb15aa1f054b740f31a12f48f31 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Sat, 16 Nov 2013 17:08:06 -0500 +Subject: [PATCH 1/3] config: Do not modify const strings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Take a copy here, the option string is const and strtok_r() is not a safe +function as it may change the string it manipulates. + +Reviewed-by: Günther Deschner +--- + proxy/src/gp_config.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index e21e70d..63f264e 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -209,6 +209,7 @@ static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) + int num_sec; + char *secname = NULL; + const char *value; ++ char *vcopy; + char *token; + char *handle; + int valnum; +@@ -318,7 +319,12 @@ static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) + goto done; + } + +- token = strtok_r(no_const(value), ", ", &handle); ++ vcopy = strdup(value); ++ if (!vcopy) { ++ ret = ENOMEM; ++ goto done; ++ } ++ token = strtok_r(vcopy, ", ", &handle); + do { + + ret = strcmp(value, "krb5"); +@@ -329,6 +335,7 @@ static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) + } else { + GPERROR("Failed to read krb5 config for %s.\n", + secname); ++ safefree(vcopy); + return ret; + } + } else { +@@ -338,6 +345,7 @@ static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx) + + token = strtok_r(NULL, ", ", &handle); + } while (token != NULL); ++ safefree(vcopy); + + if (cfg->svcs[n]->mechs == 0) { + GPDEBUG("No mechs found for [%s], ignoring.\n", secname); +-- +1.8.3.1 + + +From a272091dfd568cb96738cc96ea01bbf7f24ee62c Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Sat, 16 Nov 2013 18:54:28 -0500 +Subject: [PATCH 2/3] creds: Allow admins to define only client creds +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When a service is configured with cred_usage = initiate it is +ok to allow only client credentials to be defined. + +Reviewed-by: Günther Deschner +--- + proxy/src/gp_creds.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index 60c4e12..1ac1fac 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -376,7 +376,12 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall, + * if any. */ + if (use_service_keytab) { + if (k_num == -1) { +- ret = EINVAL; ++ if (ck_num == -1) { ++ ret = EINVAL; ++ } else { ++ /* allow a service to define only the client keytab */ ++ ret = 0; ++ } + goto done; + } + if (ck_num == -1) { +-- +1.8.3.1 + + +From 23f4ee4359d10f66e1938ce6b1d92d3cc77865ff Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 20 Nov 2013 11:58:22 -0500 +Subject: [PATCH 3/3] Use secure_getenv in client and mechglue module +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +proxymehc.so may be used in setuid binaries so follow best security +practices and use secure_getenv() if available. +Fallback to poorman emulation when secure_getenv() is not available. + +Resolves: https://fedorahosted.org/gss-proxy/ticket/110 + +Reviewed-by: Günther Deschner +--- + proxy/Makefile.am | 7 ++++--- + proxy/configure.ac | 2 ++ + proxy/src/client/gpm_common.c | 2 +- + proxy/src/gp_common.h | 1 + + proxy/src/gp_util.c | 20 ++++++++++++++++++++ + proxy/src/mechglue/gss_plugin.c | 4 ++-- + 6 files changed, 30 insertions(+), 6 deletions(-) + +diff --git a/proxy/Makefile.am b/proxy/Makefile.am +index 065be6e..c946421 100644 +--- a/proxy/Makefile.am ++++ b/proxy/Makefile.am +@@ -102,7 +102,9 @@ GP_RPCCLI_OBJ = \ + src/client/gpm_wrap.c \ + src/client/gpm_unwrap.c \ + src/client/gpm_wrap_size_limit.c \ +- src/client/gpm_common.c ++ src/client/gpm_common.c \ ++ src/gp_util.c ++ + GP_MECHGLUE_OBJ = \ + src/mechglue/gpp_accept_sec_context.c \ + src/mechglue/gpp_acquire_cred.c \ +@@ -114,8 +116,7 @@ GP_MECHGLUE_OBJ = \ + src/mechglue/gpp_indicate_mechs.c \ + src/mechglue/gpp_priv_integ.c \ + src/mechglue/gpp_misc.c \ +- src/mechglue/gss_plugin.c \ +- src/gp_util.c ++ src/mechglue/gss_plugin.c + + dist_noinst_HEADERS = \ + rpcgen/gp_rpc.h \ +diff --git a/proxy/configure.ac b/proxy/configure.ac +index b75a1ef..a0cc4ef 100644 +--- a/proxy/configure.ac ++++ b/proxy/configure.ac +@@ -149,6 +149,8 @@ AC_CHECK_LIB(gssrpc, gssrpc_xdrmem_create,, + [$GSSAPI_LIBS $GSSRPC_LIBS]) + AC_SUBST([GSSRPC_LIBS]) + ++AC_CHECK_FUNCS([__secure_getenv secure_getenv]) ++ + WITH_INITSCRIPT + if test x$initscript = xsystemd; then + WITH_SYSTEMD_UNIT_DIR +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index df1f5a1..74296da 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -68,7 +68,7 @@ static int get_pipe_name(struct gpm_ctx *gpmctx, char *name) + const char *socket; + int ret; + +- socket = getenv("GSSPROXY_SOCKET"); ++ socket = gp_getenv("GSSPROXY_SOCKET"); + if (!socket) { + socket = GP_SOCKET_NAME; + } +diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h +index 9e4ae81..b5c525f 100644 +--- a/proxy/src/gp_common.h ++++ b/proxy/src/gp_common.h +@@ -67,6 +67,7 @@ + + bool gp_same(const char *a, const char *b); + bool gp_boolean_is_true(const char *s); ++char *gp_getenv(const char *name); + + #include "rpcgen/gss_proxy.h" + +diff --git a/proxy/src/gp_util.c b/proxy/src/gp_util.c +index 8400da1..a6c870f 100644 +--- a/proxy/src/gp_util.c ++++ b/proxy/src/gp_util.c +@@ -23,8 +23,10 @@ + DEALINGS IN THE SOFTWARE. + */ + ++#include "config.h" + #include + #include ++#include + + bool gp_same(const char *a, const char *b) + { +@@ -46,3 +48,21 @@ bool gp_boolean_is_true(const char *s) + + return false; + } ++ ++char *gp_getenv(const char *name) ++{ ++#if HAVE_SECURE_GETENV ++ return secure_getenv(name); ++#elif HAVE___SECURE_GETENV ++ return __secure_getenv(name); ++#else ++#include ++#include ++#warning secure_getenv not available, falling back to poorman emulation ++ if ((getuid() == geteuid()) && ++ (getgid() == getegid())) { ++ return getenv(name); ++ } ++ return NULL; ++#endif ++} +diff --git a/proxy/src/mechglue/gss_plugin.c b/proxy/src/mechglue/gss_plugin.c +index 5b40df9..372ab2e 100644 +--- a/proxy/src/mechglue/gss_plugin.c ++++ b/proxy/src/mechglue/gss_plugin.c +@@ -64,7 +64,7 @@ enum gpp_behavior gpp_get_behavior(void) + char *envval; + + if (behavior == GPP_UNINITIALIZED) { +- envval = getenv("GSSPROXY_BEHAVIOR"); ++ envval = gp_getenv("GSSPROXY_BEHAVIOR"); + if (envval) { + if (strcmp(envval, "LOCAL_ONLY") == 0) { + behavior = GPP_LOCAL_ONLY; +@@ -102,7 +102,7 @@ gss_OID_set gss_mech_interposer(gss_OID mech_type) + + /* avoid looping in the gssproxy daemon by avoiding to interpose + * any mechanism */ +- envval = getenv("GSS_USE_PROXY"); ++ envval = gp_getenv("GSS_USE_PROXY"); + if (!envval) { + return NULL; + } +-- +1.8.3.1 + diff --git a/SOURCES/gssproxy-0.3.1-strerror_r.patch b/SOURCES/gssproxy-0.3.1-strerror_r.patch new file mode 100644 index 0000000..7b82051 --- /dev/null +++ b/SOURCES/gssproxy-0.3.1-strerror_r.patch @@ -0,0 +1,307 @@ +From 27ae6c5b8b37a8086800cd1a4edbb01a7fddfad6 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Thu, 21 Nov 2013 11:59:40 -0500 +Subject: [PATCH 1/2] Add Thread-safe implementation of strerror() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Unfortunately strerror() is not thread safe so we have to juggle with +strerror_r() which is a can of worms as 2 incompatible implementations +are available depending on what is defined at compile time. + +Try to do something sane. + +https://fedorahosted.org/gss-proxy/ticket/111 + +Reviewed-by: Günther Deschner +--- + proxy/src/gp_common.h | 3 +++ + proxy/src/gp_util.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 62 insertions(+) + +diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h +index b5c525f..f2b8c3e 100644 +--- a/proxy/src/gp_common.h ++++ b/proxy/src/gp_common.h +@@ -69,6 +69,9 @@ bool gp_same(const char *a, const char *b); + bool gp_boolean_is_true(const char *s); + char *gp_getenv(const char *name); + ++/* NOTE: read the note in gp_util.c before using gp_strerror() */ ++char *gp_strerror(int errnum); ++ + #include "rpcgen/gss_proxy.h" + + union gp_rpc_arg { +diff --git a/proxy/src/gp_util.c b/proxy/src/gp_util.c +index a6c870f..4fbac4e 100644 +--- a/proxy/src/gp_util.c ++++ b/proxy/src/gp_util.c +@@ -27,6 +27,8 @@ + #include + #include + #include ++#include ++#include + + bool gp_same(const char *a, const char *b) + { +@@ -66,3 +68,60 @@ char *gp_getenv(const char *name) + return NULL; + #endif + } ++ ++/* NOTE: because strerror_r() is such a mess with glibc, we need to do some ++ * magic checking to find out what function prototype is being used of the ++ * two incompatible ones, and pray it doesn't change in the future. ++ * On top of that to avoid impacting the current code too much we've got to use ++ * thread-local storage to hold a buffer. ++ * gp_strerror() is basically a thread-safe version of strerror() that can ++ * never fail. ++ */ ++const char gp_internal_err[] = "Internal strerror_r() error."; ++#define MAX_GP_STRERROR 1024 ++char *gp_strerror(int errnum) ++{ ++ static __thread char buf[MAX_GP_STRERROR]; ++ int saved_errno = errno; ++ ++#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) ++ /* XSI version */ ++ int ret; ++ ++ ret = strerror_r(errnum, buf, MAX_GP_STRERROR); ++ if (ret == -1) ret = errno; ++ switch (ret) { ++ case 0: ++ break; ++ case EINVAL: ++ ret = snprintf(buf, MAX_GP_STRERROR, ++ "Unknown error code: %d", errnum); ++ if (ret > 0) break; ++ /* fallthrough */ ++ default: ++ ret = snprintf(buf, MAX_GP_STRERROR, ++ "Internal error describing error code: %d", errnum); ++ if (ret > 0) break; ++ memset(buf, 0, MAX_GP_STRERROR); ++ strncpy(buf, gp_internal_err, MAX_GP_STRERROR); ++ buf[MAX_GP_STRERROR -1] = '\0'; ++ } ++#else ++ /* GNU-specific version */ ++ char *ret; ++ ++ ret = strerror_r(errnum, buf, MAX_GP_STRERROR); ++ if (ret == NULL) { ++ memset(buf, 0, MAX_GP_STRERROR); ++ strncpy(buf, gp_internal_err, MAX_GP_STRERROR); ++ buf[MAX_GP_STRERROR -1] = '\0'; ++ } else if (ret != buf) { ++ memset(buf, 0, MAX_GP_STRERROR); ++ strncpy(buf, ret, MAX_GP_STRERROR); ++ buf[MAX_GP_STRERROR -1] = '\0'; ++ } ++#endif ++ ++ errno = saved_errno; ++ return buf; ++} +-- +1.8.3.1 + + +From db8099da53167ca4ebf3b9f5ef0c702ddfe8b366 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Thu, 21 Nov 2013 12:14:36 -0500 +Subject: [PATCH 2/2] Use gp_strerror() everywhere instead of strerror() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://fedorahosted.org/gss-proxy/ticket/111 + +Reviewed-by: Günther Deschner +--- + proxy/src/client/gpm_init_sec_context.c | 4 ++-- + proxy/src/gp_config.c | 2 +- + proxy/src/gp_config_dinglibs.c | 4 ++-- + proxy/src/gp_init.c | 10 +++++----- + proxy/src/gp_socket.c | 14 +++++++------- + 5 files changed, 17 insertions(+), 17 deletions(-) + +diff --git a/proxy/src/client/gpm_init_sec_context.c b/proxy/src/client/gpm_init_sec_context.c +index f6dfe53..bd88055 100644 +--- a/proxy/src/client/gpm_init_sec_context.c ++++ b/proxy/src/client/gpm_init_sec_context.c +@@ -90,7 +90,7 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status, + /* execute proxy request */ + ret = gpm_make_call(GSSX_INIT_SEC_CONTEXT, &uarg, &ures); + if (ret) { +- gpm_save_internal_status(ret, strerror(ret)); ++ gpm_save_internal_status(ret, gp_strerror(ret)); + goto done; + } + +@@ -114,7 +114,7 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status, + if (res->output_token) { + ret = gp_conv_gssx_to_buffer_alloc(res->output_token, &outbuf); + if (ret) { +- gpm_save_internal_status(ret, strerror(ret)); ++ gpm_save_internal_status(ret, gp_strerror(ret)); + goto done; + } + } +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index 63f264e..2fc4a6f 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -464,7 +464,7 @@ int load_config(struct gp_config *cfg) + + done: + if (ret != 0) { +- GPERROR("Error reading configuration %d: %s", ret, strerror(ret)); ++ GPERROR("Error reading configuration %d: %s", ret, gp_strerror(ret)); + } + gp_config_close(ctx); + safefree(ctx); +diff --git a/proxy/src/gp_config_dinglibs.c b/proxy/src/gp_config_dinglibs.c +index 8716b91..515b951 100644 +--- a/proxy/src/gp_config_dinglibs.c ++++ b/proxy/src/gp_config_dinglibs.c +@@ -238,7 +238,7 @@ int gp_dinglibs_init(const char *config_file, + &file_ctx); + if (ret) { + GPDEBUG("Failed to open config file: %d (%s)\n", +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + ini_config_destroy(ini_config); + return ret; + } +@@ -255,7 +255,7 @@ int gp_dinglibs_init(const char *config_file, + char **errors = NULL; + /* we had a parsing failure */ + GPDEBUG("Failed to parse config file: %d (%s)\n", +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + if (ini_config_error_count(ini_config)) { + ini_config_get_errors(ini_config, &errors); + if (errors) { +diff --git a/proxy/src/gp_init.c b/proxy/src/gp_init.c +index 92c0a47..7e29c59 100644 +--- a/proxy/src/gp_init.c ++++ b/proxy/src/gp_init.c +@@ -158,7 +158,7 @@ void init_proc_nfsd(struct gp_config *cfg) + ret = errno; + GPDEBUG("Failed to open %s: %d (%s)\n", + LINUX_PROC_USE_GSS_PROXY_FILE, +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + return; + } + +@@ -167,7 +167,7 @@ void init_proc_nfsd(struct gp_config *cfg) + ret = errno; + GPDEBUG("Failed to write to %s: %d (%s)\n", + LINUX_PROC_USE_GSS_PROXY_FILE, +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + } + + ret = close(fd); +@@ -175,7 +175,7 @@ void init_proc_nfsd(struct gp_config *cfg) + ret = errno; + GPDEBUG("Failed to close %s: %d (%s)\n", + LINUX_PROC_USE_GSS_PROXY_FILE, +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + } + } + +@@ -191,7 +191,7 @@ void write_pid(void) + if (!f) { + ret = errno; + GPDEBUG("Failed to open %s: %d (%s)\n", +- GP_PID_FILE, ret, strerror(ret)); ++ GP_PID_FILE, ret, gp_strerror(ret)); + return; + } + +@@ -204,6 +204,6 @@ void write_pid(void) + if (ret != 0) { + ret = errno; + GPDEBUG("Failed to close %s: %d (%s)\n", +- GP_PID_FILE, ret, strerror(ret)); ++ GP_PID_FILE, ret, gp_strerror(ret)); + } + } +diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c +index b1851a2..3e8afc5 100644 +--- a/proxy/src/gp_socket.c ++++ b/proxy/src/gp_socket.c +@@ -184,7 +184,7 @@ struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx, + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + ret = errno; +- GPDEBUG("Failed to init socket! (%d: %s)\n", ret, strerror(ret)); ++ GPDEBUG("Failed to init socket! (%d: %s)\n", ret, gp_strerror(ret)); + goto done; + } + +@@ -192,14 +192,14 @@ struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx, + if (ret == -1) { + ret = errno; + GPDEBUG("Failed to bind socket %s! (%d: %s)\n", addr.sun_path, +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + goto done; + } + + ret = listen(fd, 10); + if (ret == -1) { + ret = errno; +- GPDEBUG("Failed to listen! (%d: %s)\n", ret, strerror(ret)); ++ GPDEBUG("Failed to listen! (%d: %s)\n", ret, gp_strerror(ret)); + goto done; + } + +@@ -218,7 +218,7 @@ struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx, + done: + if (ret) { + GPERROR("Failed to create Unix Socket! (%d:%s)", +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + if (fd != -1) { + close(fd); + fd = -1; +@@ -245,7 +245,7 @@ static int get_peercred(int fd, struct gp_conn *conn) + if (ret == -1) { + ret = errno; + GPDEBUG("Failed to get SO_PEERCRED options! (%d:%s)\n", +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + return ret; + } + if (len != sizeof(struct ucred)) { +@@ -262,7 +262,7 @@ static int get_peercred(int fd, struct gp_conn *conn) + } else { + ret = errno; + GPDEBUG("Failed to get peer's SELinux context (%d:%s)\n", +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + /* consider thisnot fatal, selinux may be disabled */ + } + +@@ -579,7 +579,7 @@ void accept_sock_conn(verto_ctx *vctx, verto_ev *ev) + done: + if (ret) { + GPERROR("Error connecting client: (%d:%s)", +- ret, strerror(ret)); ++ ret, gp_strerror(ret)); + gp_conn_free(conn); + } + } +-- +1.8.3.1 + diff --git a/SPECS/gssproxy.spec b/SPECS/gssproxy.spec index 9faf139..db12cb9 100644 --- a/SPECS/gssproxy.spec +++ b/SPECS/gssproxy.spec @@ -1,6 +1,6 @@ Name: gssproxy Version: 0.3.0 -Release: 0%{?dist} +Release: 9%{?dist} Summary: GSSAPI Proxy Group: System Environment/Libraries @@ -8,6 +8,14 @@ License: MIT URL: http://fedorahosted.org/gss-proxy 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 +Patch3: gssproxy-0.3.0-flags_handling.patch +Patch4: gssproxy-0.3.1-secure_getenv.patch +Patch5: gssproxy-0.3.1-strerror_r.patch +Patch6: gssproxy-0.3.1-nfsd_startup.patch +Patch7: gssproxy-0.3.1-deadlock_fix.patch %global servicename gssproxy %global pubconfpath %{_sysconfdir}/gssproxy @@ -52,6 +60,15 @@ A proxy for GSSAPI credential handling %prep %setup -q +%patch0 -p2 -b .gss_init_sec_context +%patch1 -p2 -b .gss_inquire_cred_by_mech +%patch2 -p2 -b .continuations +%patch3 -p2 -b .flags_handling +%patch4 -p2 -b .secure_getenv +%patch5 -p2 -b .strerror_r +%patch6 -p2 -b .nfsd_startup +%patch7 -p2 -b .deadlock_fix + %build autoreconf -f -i %configure \ @@ -103,6 +120,48 @@ rm -rf %{buildroot} %systemd_postun_with_restart gssproxy.service %changelog +* Wed Mar 12 2014 Guenther Deschner 0.3.0-9 +- Fix potential mutex deadlock +- resolves: #1075268 + +* Fri Jan 24 2014 Daniel Mach - 0.3.0-8 +- Mass rebuild 2014-01-24 + +* Thu Jan 16 2014 Guenther Deschner 0.3.0-7 +- Fix nfsd startup +- resolves: https://fedorahosted.org/gss-proxy/ticket/114 +- resolves: #1053710 + +* Fri Dec 27 2013 Daniel Mach - 0.3.0-6 +- Mass rebuild 2013-12-27 + +* Tue Dec 17 2013 Guenther Deschner 0.3.0-5 +- Fix flags handling. +- resolves: https://fedorahosted.org/gss-proxy/ticket/112 +- related: #1031710 + +* Wed Nov 27 2013 Guenther Deschner 0.3.0-4 +- Use secure_getenv +- resolves: https://fedorahosted.org/gss-proxy/ticket/110 +- resolves: #1032684 +- Use strerror_r instead of strerror +- resolves: https://fedorahosted.org/gss-proxy/ticket/111 +- resolves: #1033350 + +* Tue Nov 19 2013 Guenther Deschner 0.3.0-3 +- Fix flags handling in gss_init_sec_context() +- resolves: https://fedorahosted.org/gss-proxy/ticket/106 +- resolves: #1031713 +- Fix OID handling in gss_inquire_cred_by_mech() +- resolves: https://fedorahosted.org/gss-proxy/ticket/107 +- resolves: #1031712 +- Fix continuation processing for not yet fully established contexts. +- resolves: https://fedorahosted.org/gss-proxy/ticket/108 +- resolves: #1031711 +- Add flags filtering and flags enforcing. +- resolves: https://fedorahosted.org/gss-proxy/ticket/109 +- resolves: #1031710 + * Wed Oct 23 2013 Guenther Deschner 0.3.0-0 - New upstream release 0.3.0: * Add support for impersonation (depends on s4u2self/s4u2proxy on the KDC)