From 472fdff9d2bd274a49293098fa01b6968617ca57 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Oct 30 2019 15:20:02 +0000 Subject: import gssproxy-0.7.0-28.el7 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b195da3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/gssproxy-0.7.0.tar.gz diff --git a/.gssproxy.metadata b/.gssproxy.metadata new file mode 100644 index 0000000..b056804 --- /dev/null +++ b/.gssproxy.metadata @@ -0,0 +1 @@ +6fe2fc0e6754b279af6d2a5b9443de5f20d62e5a SOURCES/gssproxy-0.7.0.tar.gz diff --git a/SOURCES/Add-Client-ID-to-debug-messages.patch b/SOURCES/Add-Client-ID-to-debug-messages.patch new file mode 100644 index 0000000..a8394a5 --- /dev/null +++ b/SOURCES/Add-Client-ID-to-debug-messages.patch @@ -0,0 +1,148 @@ +From 20ddb6f200f61332ff43aca7ad9421303d0a3138 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Thu, 25 May 2017 15:22:37 -0400 +Subject: [PATCH] Add Client ID to debug messages + +This allows to sort out which debug message belongs to which client when +multiple clients are preforming operations at the same time. + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood + +Resolves: #189 +Merges: #191 +(cherry picked from commit 2f158fe4d39c11589d214d3d602c6d10411052dc) +--- + proxy/src/gp_debug.c | 28 +++++++++++++++++++++++++++- + proxy/src/gp_debug.h | 1 + + proxy/src/gp_proxy.h | 1 + + proxy/src/gp_socket.c | 5 +++++ + proxy/src/gp_workers.c | 6 ++++++ + proxy/src/gssproxy.c | 4 ++++ + 6 files changed, 44 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/gp_debug.c b/proxy/src/gp_debug.c +index 3029574..4a141fc 100644 +--- a/proxy/src/gp_debug.c ++++ b/proxy/src/gp_debug.c +@@ -64,6 +64,32 @@ const char *gp_debug_timestamp(void) + return buffer; + } + ++/* thread local connection/client id */ ++static __thread int cid; ++ ++void gp_debug_set_conn_id(int id) ++{ ++ cid = id; ++} ++ ++static const char*gp_debug_conn_id(void) ++{ ++ static __thread char buffer[18]; ++ static __thread int last_cid = 0; ++ ++ if (cid == 0) { ++ buffer[0] = '\0'; ++ return buffer; ++ } ++ ++ if (last_cid == cid) return buffer; ++ ++ (void)snprintf(buffer, 17, "[CID %d]", cid); ++ buffer[17] = '\0'; ++ last_cid = cid; ++ return buffer; ++} ++ + void gp_debug_printf(const char *format, ...) + { + va_list varargs; +@@ -76,7 +102,7 @@ void gp_debug_time_printf(const char *format, ...) + { + va_list varargs; + +- fprintf(stderr, "%s", gp_debug_timestamp()); ++ fprintf(stderr, "%s%s", gp_debug_conn_id(), gp_debug_timestamp()); + + va_start(varargs, format); + vfprintf(stderr, format, varargs); +diff --git a/proxy/src/gp_debug.h b/proxy/src/gp_debug.h +index d3420b0..1c2f8a3 100644 +--- a/proxy/src/gp_debug.h ++++ b/proxy/src/gp_debug.h +@@ -14,6 +14,7 @@ int gp_debug_args(int level); + void gp_debug_toggle(int); + void gp_debug_printf(const char *format, ...); + void gp_debug_time_printf(const char *format, ...); ++void gp_debug_set_conn_id(int id); + + #define GPDEBUG(...) do { \ + if (gp_debug) { \ +diff --git a/proxy/src/gp_proxy.h b/proxy/src/gp_proxy.h +index 971a7b6..55ab83c 100644 +--- a/proxy/src/gp_proxy.h ++++ b/proxy/src/gp_proxy.h +@@ -113,6 +113,7 @@ void gp_socket_send_data(verto_ctx *vctx, struct gp_conn *conn, + struct gp_creds *gp_conn_get_creds(struct gp_conn *conn); + uid_t gp_conn_get_uid(struct gp_conn *conn); + const char *gp_conn_get_socket(struct gp_conn *conn); ++int gp_conn_get_cid(struct gp_conn *conn); + bool gp_selinux_ctx_equal(SELINUX_CTX ctx1, SELINUX_CTX ctx2); + bool gp_conn_check_selinux(struct gp_conn *conn, SELINUX_CTX ctx); + +diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c +index 29b6a44..5064e51 100644 +--- a/proxy/src/gp_socket.c ++++ b/proxy/src/gp_socket.c +@@ -103,6 +103,11 @@ const char *gp_conn_get_socket(struct gp_conn *conn) + return conn->sock_ctx->socket; + } + ++int gp_conn_get_cid(struct gp_conn *conn) ++{ ++ return conn->us.sd; ++} ++ + void gp_conn_free(struct gp_conn *conn) + { + if (!conn) return; +diff --git a/proxy/src/gp_workers.c b/proxy/src/gp_workers.c +index c089b54..d37e57c 100644 +--- a/proxy/src/gp_workers.c ++++ b/proxy/src/gp_workers.c +@@ -357,6 +357,9 @@ static void *gp_worker_main(void *pvt) + + while (!t->pool->shutdown) { + ++ /* initialize debug client id to 0 until work is scheduled */ ++ gp_debug_set_conn_id(0); ++ + /* ======> COND_MUTEX */ + pthread_mutex_lock(&t->cond_mutex); + while (t->query == NULL) { +@@ -374,6 +377,9 @@ static void *gp_worker_main(void *pvt) + /* <====== COND_MUTEX */ + pthread_mutex_unlock(&t->cond_mutex); + ++ /* set client id before hndling requests */ ++ gp_debug_set_conn_id(gp_conn_get_cid(q->conn)); ++ + /* handle the client request */ + gp_handle_query(t->pool, q); + +diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c +index 5c5937d..94a6a61 100644 +--- a/proxy/src/gssproxy.c ++++ b/proxy/src/gssproxy.c +@@ -159,6 +159,10 @@ int main(int argc, const char *argv[]) + int wait_fd; + int ret = -1; + ++ /* initialize debug client id to 0 in the main thread */ ++ /* we do this early, before any code starts using debug statements */ ++ gp_debug_set_conn_id(0); ++ + struct poptOption long_options[] = { + POPT_AUTOHELP + {"daemon", 'D', POPT_ARG_NONE, &opt_daemon, 0, \ diff --git a/SOURCES/Add-a-safety-timeout-to-epoll.patch b/SOURCES/Add-a-safety-timeout-to-epoll.patch new file mode 100644 index 0000000..af46776 --- /dev/null +++ b/SOURCES/Add-a-safety-timeout-to-epoll.patch @@ -0,0 +1,48 @@ +From dcc5ec2c848f57c600ef127f1ed3640154a67cbe Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 6 Mar 2019 10:36:11 -0500 +Subject: [PATCH] Add a safety timeout to epoll + +Add a safety timeout just in case something goes wrong with the use of +timerfd. This way the process should't be stuck forever. + +Signed-off-by: Simo Sorce +[rharwood@redhat.com: remove outdated comment] +Reviewed-by: Robbie Harwood +Merges: #241 +(cherry picked from commit d55be9fa2455fe52b6eb904ad427f22141ab3f26) +(cherry picked from commit a494f23b6d8d43fe1a824cd69c3dd93a18fc75a1) +--- + proxy/src/client/gpm_common.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 554c91c..462d88b 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -14,6 +14,7 @@ + #define FRAGMENT_BIT (1 << 31) + + #define RESPONSE_TIMEOUT 15 ++#define SAFETY_TIMEOUT RESPONSE_TIMEOUT * 10 * 1000 + #define MAX_TIMEOUT_RETRY 3 + + struct gpm_ctx { +@@ -287,7 +288,7 @@ static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) + } + + do { +- epoll_ret = epoll_wait(gpmctx->epollfd, events, 2, -1); ++ epoll_ret = epoll_wait(gpmctx->epollfd, events, 2, SAFETY_TIMEOUT); + } while (epoll_ret < 0 && errno == EINTR); + + if (epoll_ret < 0) { +@@ -295,8 +296,6 @@ static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) + ret = errno; + gpm_epoll_close(gpmctx); + } else if (epoll_ret == 0) { +- /* Shouldn't happen as timeout == -1; treat it like a timeout +- * occurred. */ + ret = ETIMEDOUT; + gpm_epoll_close(gpmctx); + } else if (epoll_ret == 1 && events[0].data.fd == gpmctx->timerfd) { diff --git a/SOURCES/Allow-connection-to-self-when-impersonator-set.patch b/SOURCES/Allow-connection-to-self-when-impersonator-set.patch new file mode 100644 index 0000000..995ed4a --- /dev/null +++ b/SOURCES/Allow-connection-to-self-when-impersonator-set.patch @@ -0,0 +1,236 @@ +From 0e04be2c1398dac40c50910a59157eed0ad5a7e4 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Tue, 14 Mar 2017 10:43:17 -0400 +Subject: [PATCH] Allow connection to self when impersonator set + +If the target of a context establishment is the impersonator itself, +then allow it. This kind of context establishment is used by tools like +mod_auth_gssapi to be able to inspect the ticket just obtained via +impersonation and it is basically a noop as the acceptor and the +impersonator are the same entitiy. + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #172 +(cherry picked from commit eada55e831d12b42d3be3a555ff4e133bed7f594) +--- + proxy/src/gp_creds.c | 57 +++++++++++++++++++++++++---- + proxy/src/gp_rpc_creds.h | 3 +- + proxy/src/gp_rpc_init_sec_context.c | 2 +- + proxy/tests/t_impersonate.py | 35 +++++++++++++----- + 4 files changed, 78 insertions(+), 19 deletions(-) + +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index 95a1c48..7d89b06 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -883,7 +883,8 @@ static uint32_t get_impersonator_name(uint32_t *min, gss_cred_id_t cred, + } + } else if (ret_maj == GSS_S_UNAVAILABLE) { + /* Not supported by krb5 library yet, fallback to raw krb5 calls */ +- /* TODO: Remove once we set a required dependency on MIT 1.15+ */ ++ /* TODO: Remove once we set a minimum required dependency on a ++ * release that supports this call */ + ret_maj = get_impersonator_fallback(&ret_min, cred, impersonator); + if (ret_maj == GSS_S_FAILURE) { + if (ret_min == KRB5_CC_NOTFOUND) { +@@ -899,9 +900,47 @@ done: + return ret_maj; + } + ++static uint32_t check_impersonator_name(uint32_t *min, ++ gss_name_t target_name, ++ const char *impersonator) ++{ ++ gss_name_t canon_name = NULL; ++ gss_buffer_desc buf; ++ uint32_t ret_maj = 0; ++ uint32_t ret_min = 0; ++ uint32_t discard; ++ bool match; ++ ++ ret_maj = gss_canonicalize_name(&discard, target_name, &gp_mech_krb5, ++ &canon_name); ++ if (ret_maj != GSS_S_COMPLETE) { ++ *min = ret_min; ++ return ret_maj; ++ } ++ ++ ret_maj = gss_display_name(&discard, canon_name, &buf, NULL); ++ gss_release_name(&discard, &canon_name); ++ if (ret_maj != GSS_S_COMPLETE) { ++ *min = ret_min; ++ return ret_maj; ++ } ++ ++ match = (strncmp(impersonator, buf.value, buf.length) == 0) && ++ (strlen(impersonator) == buf.length); ++ gss_release_buffer(&discard, &buf); ++ ++ *min = 0; ++ if (match) { ++ return GSS_S_COMPLETE; ++ } else { ++ return GSS_S_UNAUTHORIZED; ++ } ++} ++ + uint32_t gp_cred_allowed(uint32_t *min, + struct gp_call_ctx *gpcall, +- gss_cred_id_t cred) ++ gss_cred_id_t cred, ++ gss_name_t target_name) + { + char *impersonator = NULL; + uint32_t ret_maj = 0; +@@ -924,11 +963,11 @@ uint32_t gp_cred_allowed(uint32_t *min, + if (ret_maj) goto done; + + /* if we find an impersonator entry we bail as that is not authorized, +- * if it were then gpcall->service->allow_const_deleg would have caused +- * the ealier check to return GSS_S_COMPLETE already */ ++ * *unless* the target is the impersonator itself! If the operation ++ * were authorized then gpcall->service->allow_const_deleg would have ++ * caused the ealier check to return GSS_S_COMPLETE already */ + if (impersonator != NULL) { +- ret_min = 0; +- ret_maj = GSS_S_UNAUTHORIZED; ++ ret_maj = check_impersonator_name(&ret_min, target_name, impersonator); + } + + done: +@@ -937,7 +976,11 @@ done: + GPDEBUGN(2, "Unauthorized impersonator credentials detected\n"); + break; + case GSS_S_COMPLETE: +- GPDEBUGN(2, "No impersonator credentials detected\n"); ++ if (impersonator) { ++ GPDEBUGN(2, "Credentials allowed for 'self'\n"); ++ } else { ++ GPDEBUGN(2, "No impersonator credentials detected\n"); ++ } + break; + default: + GPDEBUG("Failure while checking credentials\n"); +diff --git a/proxy/src/gp_rpc_creds.h b/proxy/src/gp_rpc_creds.h +index 54fe482..c116e53 100644 +--- a/proxy/src/gp_rpc_creds.h ++++ b/proxy/src/gp_rpc_creds.h +@@ -34,7 +34,8 @@ uint32_t gp_add_krb5_creds(uint32_t *min, + + uint32_t gp_cred_allowed(uint32_t *min, + struct gp_call_ctx *gpcall, +- gss_cred_id_t cred); ++ gss_cred_id_t cred, ++ gss_name_t target_name); + + void gp_filter_flags(struct gp_call_ctx *gpcall, uint32_t *flags); + +diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c +index 767a3ff..413e2ec 100644 +--- a/proxy/src/gp_rpc_init_sec_context.c ++++ b/proxy/src/gp_rpc_init_sec_context.c +@@ -108,7 +108,7 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, + } + } + +- ret_maj = gp_cred_allowed(&ret_min, gpcall, ich); ++ ret_maj = gp_cred_allowed(&ret_min, gpcall, ich, target_name); + if (ret_maj) { + goto done; + } +diff --git a/proxy/tests/t_impersonate.py b/proxy/tests/t_impersonate.py +index 3e25962..29f9a41 100755 +--- a/proxy/tests/t_impersonate.py ++++ b/proxy/tests/t_impersonate.py +@@ -34,19 +34,20 @@ IMPERSONATE_CONF_TEMPLATE = ''' + + ''' + +-def run_cmd(testdir, env, conf, name, socket, cmd, expected_failure): ++def run_cmd(testdir, env, conf, name, socket, cmd, keytab, expected_failure): + + logfile = conf['logfile'] + testenv = env.copy() + testenv.update({'KRB5CCNAME': os.path.join(testdir, 't' + conf['prefix'] + + '_impersonate.ccache'), +- 'KRB5_KTNAME': os.path.join(testdir, PROXY_KTNAME), ++ 'KRB5_KTNAME': os.path.join(testdir, keytab), + 'KRB5_TRACE': os.path.join(testdir, 't' + conf['prefix'] + + '_impersonate.trace'), + 'GSS_USE_PROXY': 'yes', + 'GSSPROXY_SOCKET': socket, + 'GSSPROXY_BEHAVIOR': 'REMOTE_FIRST'}) + ++ print("\nTesting: [%s]" % (name,), file=logfile) + print("[COMMAND]\n%s\n[ENVIRONMENT]\n%s\n" % (cmd, testenv), file=logfile) + logfile.flush() + +@@ -74,45 +75,59 @@ def run(testdir, env, conf): + rets = [] + + # Test all permitted ++ msg = "Impersonate" + socket = os.path.join(testdir, 'impersonate.socket') + cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, + path_prefix + 'impersonate.cache'] +- r = run_cmd(testdir, env, conf, "Impersonate", socket, cmd, False) ++ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, False) + rets.append(r) + +- #Test fail ++ #Test self fail ++ msg = "Impersonate fail self" + socket = os.path.join(testdir, 'impersonate-proxyonly.socket') + cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, + path_prefix + 'impersonate.cache'] +- r = run_cmd(testdir, env, conf, "Impersonate fail self", socket, cmd, True) ++ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, True) + rets.append(r) + +- #Test fail ++ #Test proxy fail ++ msg = "Impersonate fail proxy" + socket = os.path.join(testdir, 'impersonate-selfonly.socket') + cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, + path_prefix + 'impersonate.cache'] +- r = run_cmd(testdir, env, conf, "Impersonate fail proxy", socket, cmd, True) ++ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, True) + rets.append(r) + + #Test s4u2self half succeed ++ msg = "s4u2self delegation" + socket = os.path.join(testdir, 'impersonate-selfonly.socket') + cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, + path_prefix + 'impersonate.cache', 's4u2self'] +- r = run_cmd(testdir, env, conf, "s4u2self delegation", socket, cmd, False) ++ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, False) ++ rets.append(r) ++ ++ #Test proxy to self succeed ++ msg = "Impersonate to self" ++ socket = os.path.join(testdir, 'impersonate-selfonly.socket') ++ cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, HOST_GSS, ++ path_prefix + 'impersonate.cache', 's4u2proxy'] ++ r = run_cmd(testdir, env, conf, msg, socket, cmd, SVC_KTNAME, False) + rets.append(r) + + #Test s4u2proxy half fail ++ msg = "s4u2proxy fail" + socket = os.path.join(testdir, 'impersonate-selfonly.socket') + cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, + path_prefix + 'impersonate.cache', 's4u2proxy'] +- r = run_cmd(testdir, env, conf, "s4u2proxy fail", socket, cmd, True) ++ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, True) + rets.append(r) + + #Test s4u2proxy half succeed ++ msg = "s4u2proxy" + socket = os.path.join(testdir, 'impersonate-proxyonly.socket') + cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, + path_prefix + 'impersonate.cache', 's4u2proxy'] +- r = run_cmd(testdir, env, conf, "s4u2proxy", socket, cmd, False) ++ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, False) + rets.append(r) + + # Reset back gssproxy conf diff --git a/SOURCES/Always-choose-highest-requested-debug-level.patch b/SOURCES/Always-choose-highest-requested-debug-level.patch new file mode 100644 index 0000000..0517c64 --- /dev/null +++ b/SOURCES/Always-choose-highest-requested-debug-level.patch @@ -0,0 +1,107 @@ +From 08fab6898a9937fbc39de6222cd33167707cd763 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 11 Apr 2018 16:15:00 -0400 +Subject: [PATCH] Always choose highest requested debug level + +Allowing the CLI to lower the debug level specified in a config file +is dubious, and previously broken since we don't distinguish "default +value" from "explicitly requested value of 0" in popt. This resulted +in "Debug Enabled (level: 0)" even when the log level was not actually +0, which is confusing for users. + +Remove the gp_debug_args() function since it is no longer used. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #229 +(cherry picked from commit 5a714768aec776dc875237dd729c85389932a688) +--- + proxy/src/gp_debug.c | 34 ++++++++-------------------------- + proxy/src/gp_debug.h | 3 +-- + proxy/src/gssproxy.c | 2 +- + 3 files changed, 10 insertions(+), 29 deletions(-) + +diff --git a/proxy/src/gp_debug.c b/proxy/src/gp_debug.c +index 4a141fc..a0f51f0 100644 +--- a/proxy/src/gp_debug.c ++++ b/proxy/src/gp_debug.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */ ++/* Copyright (C) 2011,2018 the GSS-PROXY contributors, see COPYING for license */ + + #include "config.h" + #include +@@ -7,35 +7,17 @@ + #include "gp_log.h" + + /* global debug switch */ +-int gp_debug; +- +-int gp_debug_args(int level) { +- static int args_level = 0; +- +- if (level != 0) { +- args_level = level; +- } +- return args_level; +-} ++int gp_debug = 0; + + void gp_debug_toggle(int level) + { +- static bool krb5_trace_set = false; ++ if (level <= gp_debug) ++ return; + +- /* Command line and environment options override config file */ +- gp_debug = gp_debug_args(0); +- if (gp_debug == 0) { +- gp_debug = level; +- } +- if (level >= 3) { +- if (!getenv("KRB5_TRACE")) { +- setenv("KRB5_TRACE", "/dev/stderr", 1); +- krb5_trace_set = true; +- } +- } else if (krb5_trace_set) { +- unsetenv("KRB5_TRACE"); +- krb5_trace_set = false; +- } ++ if (level >= 3 && !getenv("KRB5_TRACE")) ++ setenv("KRB5_TRACE", "/dev/stderr", 1); ++ ++ gp_debug = level; + GPDEBUG("Debug Enabled (level: %d)\n", level); + } + +diff --git a/proxy/src/gp_debug.h b/proxy/src/gp_debug.h +index 1c2f8a3..4932bfd 100644 +--- a/proxy/src/gp_debug.h ++++ b/proxy/src/gp_debug.h +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */ ++/* Copyright (C) 2011,2018 the GSS-PROXY contributors, see COPYING for license */ + + #ifndef _GP_DEBUG_H_ + #define _GP_DEBUG_H_ +@@ -10,7 +10,6 @@ + + extern int gp_debug; + +-int gp_debug_args(int level); + void gp_debug_toggle(int); + void gp_debug_printf(const char *format, ...); + void gp_debug_time_printf(const char *format, ...); +diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c +index 5fc4f8d..3b6a16e 100644 +--- a/proxy/src/gssproxy.c ++++ b/proxy/src/gssproxy.c +@@ -209,7 +209,7 @@ int main(int argc, const char *argv[]) + + if (opt_debug || opt_debug_level > 0) { + if (opt_debug_level == 0) opt_debug_level = 1; +- gp_debug_args(opt_debug_level); ++ gp_debug_toggle(opt_debug_level); + } + + if (opt_daemon && opt_interactive) { diff --git a/SOURCES/Always-initialize-out-cred-in-gp_import_gssx_cred.patch b/SOURCES/Always-initialize-out-cred-in-gp_import_gssx_cred.patch new file mode 100644 index 0000000..bbec739 --- /dev/null +++ b/SOURCES/Always-initialize-out-cred-in-gp_import_gssx_cred.patch @@ -0,0 +1,34 @@ +From ad753abb87a561ae72db09f210390343d0084431 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Mon, 15 Apr 2019 19:54:17 -0400 +Subject: [PATCH] Always initialize out cred in gp_import_gssx_cred() + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #244 +(cherry picked from commit 5697dfd94345c945f93070c40b9d4480f3d3d7ea) +--- + proxy/src/gp_export.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index 5e8e160..403e339 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -449,6 +449,8 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + uint32_t ret_min = 0; + int ret; + ++ *out = GSS_C_NO_CREDENTIAL; ++ + handle = gp_service_get_creds_handle(gpcall->service); + if (!handle) { + ret_maj = GSS_S_FAILURE; +@@ -470,7 +472,6 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + if (ret) { + /* Allow for re-issuance of the keytab. */ + GPDEBUG("Stored ccache failed to decrypt; treating as empty\n"); +- *out = GSS_C_NO_CREDENTIAL; + goto done; + } + diff --git a/SOURCES/Always-use-the-encype-we-selected.patch b/SOURCES/Always-use-the-encype-we-selected.patch new file mode 100644 index 0000000..ccc1d69 --- /dev/null +++ b/SOURCES/Always-use-the-encype-we-selected.patch @@ -0,0 +1,43 @@ +From d8166808a98fd1c3772de5d75e27656ed2ab124d Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Tue, 27 Feb 2018 11:59:25 -0500 +Subject: [PATCH] Always use the encype we selected + +The enctype is selected from the keytab or from the fallback code. +Either way make sure to use the enctype stored in the key block. + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #226 +(cherry picked from commit d73c96d658059ce64ecd41ff2924071d86f2b54f) +--- + proxy/src/gp_export.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index c9f5fd4..5e8e160 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -168,11 +168,10 @@ uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name, + GP_CREDS_HANDLE_KEY_ENCTYPE, 0, + &handle->key); + if (ret == 0) { +- ret = krb5_c_make_random_key(handle->context, +- GP_CREDS_HANDLE_KEY_ENCTYPE, ++ ret = krb5_c_make_random_key(handle->context, handle->key->enctype, + handle->key); + GPDEBUG("Service: %s, Enckey: [ephemeral], Enctype: %d\n", +- svc_name, GP_CREDS_HANDLE_KEY_ENCTYPE); ++ svc_name, handle->key->enctype); + } + if (ret) { + ret_min = ret; +@@ -254,7 +253,7 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key, + + memset(&enc_handle, '\0', sizeof(krb5_enc_data)); + +- enc_handle.enctype = GP_CREDS_HANDLE_KEY_ENCTYPE; ++ enc_handle.enctype = key->enctype; + enc_handle.ciphertext.data = in->octet_string_val; + enc_handle.ciphertext.length = in->octet_string_len; + diff --git a/SOURCES/Appease-gcc-7-s-fallthrough-detection.patch b/SOURCES/Appease-gcc-7-s-fallthrough-detection.patch new file mode 100644 index 0000000..024c200 --- /dev/null +++ b/SOURCES/Appease-gcc-7-s-fallthrough-detection.patch @@ -0,0 +1,27 @@ +From f62ece3a9655c6507f40e03a36e28ecbba16f744 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 19 May 2017 12:18:03 -0400 +Subject: [PATCH] Appease gcc-7's fallthrough detection + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #188 +(cherry picked from commit fdb56f8a0b6a5fd6a2072a525e228596c264883e) +--- + proxy/src/gp_export.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index 3a927c9..f44da50 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -888,7 +888,8 @@ static uint32_t gp_export_creds_linux(uint32_t *min, gss_name_t name, + if (res != NULL) { + break; + } +- /* fall through as ret == NULL is equivalent to ENOENT */ ++ /* ret == NULL is equivalent to ENOENT */ ++ /* fall through */ + case ENOENT: + case ESRCH: + free(pwbuf); diff --git a/SOURCES/Avoid-uninitialized-free-when-allocating-buffers.patch b/SOURCES/Avoid-uninitialized-free-when-allocating-buffers.patch new file mode 100644 index 0000000..27ddb7d --- /dev/null +++ b/SOURCES/Avoid-uninitialized-free-when-allocating-buffers.patch @@ -0,0 +1,43 @@ +From e660bc0594b6ddca143b460bb7edbbfba69f84ed Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 1 May 2019 11:27:13 -0400 +Subject: [PATCH] Avoid uninitialized free when allocating buffers + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Resolves: #248 +(cherry picked from commit eafa3c9272c95646400123f8e4d6fb50cf36d36c) +(cherry picked from commit e19466d172e0fd6d86b98b1423e9d99e0be30313) +[rharwood@redhat.com: fuzz around padded] +(cherry picked from commit abcc6cc90c6da5ea4fce65dd60e46b76767be557) +[rharwood@redhat.com: more padded fuzz] +--- + proxy/src/gp_export.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index dbfddeb..a5681c0 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -300,6 +300,7 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + &data_in, + &enc_handle); + if (ret) { ++ free(enc_handle.ciphertext.data); + ret = EINVAL; + goto done; + } +@@ -308,12 +309,12 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + enc_handle.ciphertext.data, + out); + if (ret) { ++ free(enc_handle.ciphertext.data); + goto done; + } + + done: + free(padded); +- free(enc_handle.ciphertext.data); + return ret; + } + diff --git a/SOURCES/Change-impersonator-check-code.patch b/SOURCES/Change-impersonator-check-code.patch new file mode 100644 index 0000000..4cc5de9 --- /dev/null +++ b/SOURCES/Change-impersonator-check-code.patch @@ -0,0 +1,215 @@ +From 37d1667ad0cc91f46a493281e62775cc8bbe3b5b Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Tue, 14 Mar 2017 10:20:08 -0400 +Subject: [PATCH] Change impersonator check code + +In MIT 1.15 we now have a native way to check for an impersonator, +implement the use of that function but still keep the fallback for +earlier krb5 versions that do not support this method for now. + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #172 +(cherry picked from commit 73b50c0b2799f0aed53337a6516b8e1a27279ebf) +--- + proxy/configure.ac | 3 + + proxy/src/gp_creds.c | 145 ++++++++++++++++++++++++++++++++----------- + 2 files changed, 111 insertions(+), 37 deletions(-) + +diff --git a/proxy/configure.ac b/proxy/configure.ac +index 63c0edf..c52dbb6 100644 +--- a/proxy/configure.ac ++++ b/proxy/configure.ac +@@ -131,6 +131,9 @@ AC_CHECK_LIB(gssapi_krb5, gss_export_cred,, + [AC_MSG_ERROR([GSSAPI library does not support gss_export_cred])], + [$GSSAPI_LIBS]) + ++AC_CHECK_DECLS([GSS_KRB5_GET_CRED_IMPERSONATOR], [], [], ++ [[#include ]]) ++ + AC_SUBST([KRB5_CFLAGS]) + AC_SUBST([KRB5_LIBS]) + AC_SUBST([GSSAPI_CFLAGS]) +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index 171a724..95a1c48 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -773,9 +773,9 @@ void gp_filter_flags(struct gp_call_ctx *gpcall, uint32_t *flags) + *flags &= ~gpcall->service->filter_flags; + } + +-uint32_t gp_cred_allowed(uint32_t *min, +- struct gp_call_ctx *gpcall, +- gss_cred_id_t cred) ++ ++static uint32_t get_impersonator_fallback(uint32_t *min, gss_cred_id_t cred, ++ char **impersonator) + { + uint32_t ret_maj = 0; + uint32_t ret_min = 0; +@@ -785,22 +785,6 @@ uint32_t gp_cred_allowed(uint32_t *min, + krb5_data config; + int err; + +- if (cred == GSS_C_NO_CREDENTIAL) { +- return GSS_S_CRED_UNAVAIL; +- } +- +- if (gpcall->service->trusted || +- gpcall->service->impersonate || +- gpcall->service->allow_const_deleg) { +- +- GPDEBUGN(2, "Credentials allowed by configuration\n"); +- *min = 0; +- return GSS_S_COMPLETE; +- } +- +- /* FIXME: krb5 specific code, should get an oid registerd to query the +- * cred with gss_inquire_cred_by_oid() or similar instead */ +- + err = krb5_init_context(&context); + if (err) { + ret_min = err; +@@ -835,21 +819,116 @@ uint32_t gp_cred_allowed(uint32_t *min, + goto done; + } + +- /* if we find an impersonator entry we bail as that is not authorized, +- * if it were then gpcall->service->allow_const_deleg would have caused +- * the ealier check to return GSS_S_COMPLETE already */ + err = krb5_cc_get_config(context, ccache, NULL, "proxy_impersonator", + &config); +- if (!err) { ++ if (err == 0) { ++ *impersonator = strndup(config.data, config.length); ++ if (!*impersonator) { ++ ret_min = ENOMEM; ++ ret_maj = GSS_S_FAILURE; ++ } else { ++ ret_min = 0; ++ ret_maj = GSS_S_COMPLETE; ++ } + krb5_free_data_contents(context, &config); +- ret_min = 0; +- ret_maj = GSS_S_UNAUTHORIZED; +- } else if (err != KRB5_CC_NOTFOUND) { ++ } else { + ret_min = err; + ret_maj = GSS_S_FAILURE; +- } else { ++ } ++ ++done: ++ if (context) { ++ if (ccache) { ++ krb5_cc_destroy(context, ccache); ++ } ++ krb5_free_context(context); ++ } ++ free(memcache); ++ ++ *min = ret_min; ++ return ret_maj; ++} ++ ++#if !HAVE_DECL_GSS_KRB5_GET_CRED_IMPERSONATOR ++gss_OID_desc impersonator_oid = { ++ 11, discard_const("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0e") ++}; ++const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR = &impersonator_oid; ++#endif ++ ++static uint32_t get_impersonator_name(uint32_t *min, gss_cred_id_t cred, ++ char **impersonator) ++{ ++ gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; ++ uint32_t ret_maj = 0; ++ uint32_t ret_min = 0; ++ uint32_t discard; ++ ++ *impersonator = NULL; ++ ++ ret_maj = gss_inquire_cred_by_oid(&ret_min, cred, ++ GSS_KRB5_GET_CRED_IMPERSONATOR, ++ &bufset); ++ if (ret_maj == GSS_S_COMPLETE) { ++ if (bufset->count == 0) { ++ ret_min = ENOENT; ++ ret_maj = GSS_S_COMPLETE; ++ goto done; ++ } ++ *impersonator = strndup(bufset->elements[0].value, ++ bufset->elements[0].length); ++ if (!*impersonator) { ++ ret_min = ENOMEM; ++ ret_maj = GSS_S_FAILURE; ++ } ++ } else if (ret_maj == GSS_S_UNAVAILABLE) { ++ /* Not supported by krb5 library yet, fallback to raw krb5 calls */ ++ /* TODO: Remove once we set a required dependency on MIT 1.15+ */ ++ ret_maj = get_impersonator_fallback(&ret_min, cred, impersonator); ++ if (ret_maj == GSS_S_FAILURE) { ++ if (ret_min == KRB5_CC_NOTFOUND) { ++ ret_min = ENOENT; ++ ret_maj = GSS_S_COMPLETE; ++ } ++ } ++ } ++ ++done: ++ (void)gss_release_buffer_set(&discard, &bufset); ++ *min = ret_min; ++ return ret_maj; ++} ++ ++uint32_t gp_cred_allowed(uint32_t *min, ++ struct gp_call_ctx *gpcall, ++ gss_cred_id_t cred) ++{ ++ char *impersonator = NULL; ++ uint32_t ret_maj = 0; ++ uint32_t ret_min = 0; ++ ++ if (cred == GSS_C_NO_CREDENTIAL) { ++ return GSS_S_CRED_UNAVAIL; ++ } ++ ++ if (gpcall->service->trusted || ++ gpcall->service->impersonate || ++ gpcall->service->allow_const_deleg) { ++ ++ GPDEBUGN(2, "Credentials allowed by configuration\n"); ++ *min = 0; ++ return GSS_S_COMPLETE; ++ } ++ ++ ret_maj = get_impersonator_name(&ret_min, cred, &impersonator); ++ if (ret_maj) goto done; ++ ++ /* if we find an impersonator entry we bail as that is not authorized, ++ * if it were then gpcall->service->allow_const_deleg would have caused ++ * the ealier check to return GSS_S_COMPLETE already */ ++ if (impersonator != NULL) { + ret_min = 0; +- ret_maj = GSS_S_COMPLETE; ++ ret_maj = GSS_S_UNAUTHORIZED; + } + + done: +@@ -864,15 +943,7 @@ done: + GPDEBUG("Failure while checking credentials\n"); + break; + } +- if (context) { +- /* NOTE: destroy only if we created a MEMORY ccache */ +- if (ccache) { +- if (memcache) krb5_cc_destroy(context, ccache); +- else krb5_cc_close(context, ccache); +- } +- krb5_free_context(context); +- } +- free(memcache); ++ free(impersonator); + *min = ret_min; + return ret_maj; + } diff --git a/SOURCES/Change-the-way-we-handle-encrypted-buffers.patch b/SOURCES/Change-the-way-we-handle-encrypted-buffers.patch new file mode 100644 index 0000000..aad7c21 --- /dev/null +++ b/SOURCES/Change-the-way-we-handle-encrypted-buffers.patch @@ -0,0 +1,193 @@ +From 1311e03610fc4bdc0dbcba8803802e3cff5c232b Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 17 Apr 2019 18:00:59 -0400 +Subject: [PATCH] Change the way we handle encrypted buffers + +The previous change has backwards incompatible behavior that may also +lead to buffer overruns. + +Because we have no easy way to indicate a format change and to maintain +backwards compatibility for the ciphers that were working (those that +added padding were hopelessly borken anyway) introduce code to simply +add padding that we can recognize and remove when we read back the token. + +On ciphers that do not add padding this is basically a no op and the +tokens will be identical to the ones we previously emitted. + +On ciphers that add padding we pad the plaintext so that we hit a block +boundary and cause no extra padding to be added by krb5_c_encrypt +itself. On decryption we check if padding bytes are appended to the +buffer and remove them. + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #246 +(cherry picked from commit 839be8aa7e54e93819e8291b570e4c7cfe7e98f1) +--- + proxy/src/gp_export.c | 110 +++++++++++++++++++++++++++++++++--------- + 1 file changed, 86 insertions(+), 24 deletions(-) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index aa0a8ec..dbfddeb 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -193,9 +193,15 @@ done: + return ret_maj; + } + +-/* We need to include a length in our payloads because krb5_c_decrypt() will +- * pad the contents for some enctypes, and gss_import_cred() doesn't like +- * having extra bytes on tokens. */ ++#define ENC_MIN_PAD_LEN 8 ++ ++/* We need to pad our payloads because krb5_c_decrypt() may pad the ++ * contents for some enctypes, and gss_import_cred() doesn't like ++ * having extra bytes on tokens. ++ * Explicit padding and depadding is used in order to maintain backwards ++ * compatibility over upgrades (and downgrades), it would have been ++ * better if we simply had a better formatting of the returned blob ++ * so we could simply change a "blob version" number */ + static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + size_t len, void *buf, octet_string *out) + { +@@ -203,8 +209,9 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + krb5_data data_in; + krb5_enc_data enc_handle; + size_t cipherlen; +- char *packed = NULL; +- uint32_t netlen; ++ size_t padcheck; ++ uint8_t pad = 0; ++ char *padded = NULL; + + if (len > (uint32_t)(-1)) { + /* Needs to fit in 4 bytes of payload, so... */ +@@ -212,28 +219,72 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + goto done; + } + +- packed = malloc(len); +- if (!packed) { +- ret = errno; ++ ret = krb5_c_encrypt_length(context, ++ key->enctype, ++ len, &cipherlen); ++ if (ret) { + goto done; + } + +- netlen = htonl(len); +- memcpy(packed, (uint8_t *)&netlen, 4); +- memcpy(packed + 4, buf, len); +- +- data_in.length = len + 4; +- data_in.data = packed; +- +- memset(&enc_handle, '\0', sizeof(krb5_enc_data)); +- ++ /* try again with len + 1 to see if padding is required */ + ret = krb5_c_encrypt_length(context, + key->enctype, +- data_in.length, +- &cipherlen); ++ len + 1, &padcheck); + if (ret) { + goto done; + } ++ if (padcheck == cipherlen) { ++ int i; ++ /* padding required */ ++ pad = ENC_MIN_PAD_LEN; ++ /* always add enough padding that it makes it extremely unlikley ++ * legitimate plaintext will be incorrectly depadded in the ++ * decrypt function */ ++ ret = krb5_c_encrypt_length(context, ++ key->enctype, ++ len + pad, &cipherlen); ++ if (ret) { ++ goto done; ++ } ++ /* we support only block sizes up to 16 bytes as this is the largest ++ * supported block size in krb ciphers for now */ ++ for (i = 0; i < 15; i++) { ++ /* find the point at which padcheck increases, that's when we ++ * cross a blocksize boundary internally and we can calculate ++ * the padding that will be used */ ++ ret = krb5_c_encrypt_length(context, ++ key->enctype, ++ len + pad + i + 1, &padcheck); ++ if (ret) { ++ goto done; ++ } ++ if (padcheck > cipherlen) { ++ pad += i; ++ break; ++ } ++ } ++ if (i > 15) { ++ ret = EINVAL; ++ goto done; ++ } ++ } ++ ++ if (pad != 0) { ++ padded = malloc(len + pad); ++ if (!padded) { ++ ret = errno; ++ goto done; ++ } ++ ++ memcpy(padded, buf, len); ++ memset(padded + len, pad, pad); ++ ++ data_in.length = len + pad; ++ data_in.data = padded; ++ } else { ++ data_in.length = len; ++ data_in.data = buf; ++ } + + enc_handle.ciphertext.length = cipherlen; + enc_handle.ciphertext.data = malloc(enc_handle.ciphertext.length); +@@ -261,7 +312,7 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + } + + done: +- free(packed); ++ free(padded); + free(enc_handle.ciphertext.data); + return ret; + } +@@ -273,7 +324,8 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key, + int ret; + krb5_data data_out; + krb5_enc_data enc_handle; +- uint32_t netlen; ++ uint8_t pad; ++ int i, j; + + memset(&enc_handle, '\0', sizeof(krb5_enc_data)); + +@@ -295,9 +347,19 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key, + } + + /* And handle the padding. */ +- memcpy(&netlen, buf, 4); +- *len = ntohl(netlen); +- memmove(buf, buf + 4, *len); ++ i = data_out.length - 1; ++ pad = data_out.data[i]; ++ if (pad >= ENC_MIN_PAD_LEN && pad < i) { ++ j = pad; ++ while (j > 0) { ++ j--; ++ if (pad != data_out.data[i - j]) break; ++ } ++ if (j == 0) { ++ data_out.length -= pad; ++ } ++ } ++ *len = data_out.length; + + return 0; + } diff --git a/SOURCES/Clarify-debug-and-debug_level-in-man-pages.patch b/SOURCES/Clarify-debug-and-debug_level-in-man-pages.patch new file mode 100644 index 0000000..242ebe5 --- /dev/null +++ b/SOURCES/Clarify-debug-and-debug_level-in-man-pages.patch @@ -0,0 +1,74 @@ +From 384a1cff4855ad612ca71d3831a0c2c19a355c49 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 11 Apr 2018 16:01:21 -0400 +Subject: [PATCH] Clarify debug and debug_level in man pages + +In particular, add debug_level to gssproxy(5) since it was previously +accepted but not documented. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #229 +(cherry picked from commit e0e96e46be03102903533a9816b4deefe1adfaf8) +--- + proxy/man/gssproxy.8.xml | 24 +++++++++++++++++++++++- + proxy/man/gssproxy.conf.5.xml | 5 ++++- + 2 files changed, 27 insertions(+), 2 deletions(-) + +diff --git a/proxy/man/gssproxy.8.xml b/proxy/man/gssproxy.8.xml +index 1df4b0d..21f7e6a 100644 +--- a/proxy/man/gssproxy.8.xml ++++ b/proxy/man/gssproxy.8.xml +@@ -118,13 +118,35 @@ + + + ++ + + + , + + + +- Turn on debugging. ++ Turn on debugging. This option is identical to ++ --debug-level=1. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Turn on debugging at the specified level. 0 ++ corresponds to no logging, while 1 turns on basic ++ debug logging. Level 2 increases verbosity, including ++ more detailed credential verification. ++ ++ ++ At level 3 and above, KRB5_TRACE output is logged. If ++ KRB5_TRACE was already set in the execution ++ environment, trace output is sent to its value ++ instead. + + + +diff --git a/proxy/man/gssproxy.conf.5.xml b/proxy/man/gssproxy.conf.5.xml +index ad9d96f..abb6745 100644 +--- a/proxy/man/gssproxy.conf.5.xml ++++ b/proxy/man/gssproxy.conf.5.xml +@@ -191,7 +191,10 @@ + + debug (boolean) + +- Enable debugging to syslog. ++ ++ Enable debugging to syslog. Setting to true is ++ identical to setting debug_level to 1. ++ + Default: debug = false + + diff --git a/SOURCES/Close-epoll-fd-within-the-lock.patch b/SOURCES/Close-epoll-fd-within-the-lock.patch new file mode 100644 index 0000000..d92e914 --- /dev/null +++ b/SOURCES/Close-epoll-fd-within-the-lock.patch @@ -0,0 +1,165 @@ +From 69e1baa7d7f271d294e619148b4a2bae10230b5e Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Wed, 6 Mar 2019 10:31:13 -0500 +Subject: [PATCH] Close epoll fd within the lock + +A race condition may happen where we close the epoll socket, after +another thread grabbed the lock and is using epoll itself. +On some kernels this may cause epoll to not fire any event leaving the +thread stuck forever. + +Signed-off-by: Simo Sorce +[rharwood@redhat.com: cleanup commit message, adjusted function ordering] +Reviewed-by: Robbie Harwood +Merges: #241 +(cherry picked from commit 0ccfd32f8ef16caf65698c5319dfa251d43433af) + +Squashed with: + +Reorder functions + +Keep related functions closer together like before + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Resolves: #242 +(cherry picked from commit 6accc0afead574e11447447c949f2abcb1a34826) +(cherry picked from commit c33de0c213d570f370fd954869c2ad99901b2cf3) +[rharwood@redhat.com: I learned an important lesson upstream] +--- + proxy/src/client/gpm_common.c | 100 ++++++++++++++++++---------------- + 1 file changed, 54 insertions(+), 46 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index b482efb..554c91c 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -139,44 +139,8 @@ static void gpm_close_socket(struct gpm_ctx *gpmctx) + gpmctx->fd = -1; + } + +-static int gpm_grab_sock(struct gpm_ctx *gpmctx) ++static void gpm_timer_close(struct gpm_ctx *gpmctx) + { +- int ret; +- pid_t p; +- uid_t u; +- gid_t g; +- +- ret = pthread_mutex_lock(&gpmctx->lock); +- if (ret) { +- return ret; +- } +- +- /* Detect fork / setresuid and friends */ +- p = getpid(); +- u = geteuid(); +- g = getegid(); +- +- if (gpmctx->fd != -1 && +- (p != gpmctx->pid || u != gpmctx->uid || g != gpmctx->gid)) { +- gpm_close_socket(gpmctx); +- } +- +- if (gpmctx->fd == -1) { +- ret = gpm_open_socket(gpmctx); +- } +- +- if (ret) { +- pthread_mutex_unlock(&gpmctx->lock); +- } +- return ret; +-} +- +-static int gpm_release_sock(struct gpm_ctx *gpmctx) +-{ +- return pthread_mutex_unlock(&gpmctx->lock); +-} +- +-static void gpm_timer_close(struct gpm_ctx *gpmctx) { + if (gpmctx->timerfd < 0) { + return; + } +@@ -248,7 +212,59 @@ static int gpm_epoll_setup(struct gpm_ctx *gpmctx) { + return ret; + } + +-static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) { ++static int gpm_release_sock(struct gpm_ctx *gpmctx) ++{ ++ gpm_epoll_close(gpmctx); ++ gpm_timer_close(gpmctx); ++ return pthread_mutex_unlock(&gpmctx->lock); ++} ++ ++static int gpm_grab_sock(struct gpm_ctx *gpmctx) ++{ ++ int ret; ++ pid_t p; ++ uid_t u; ++ gid_t g; ++ ++ ret = pthread_mutex_lock(&gpmctx->lock); ++ if (ret) { ++ return ret; ++ } ++ ++ /* Detect fork / setresuid and friends */ ++ p = getpid(); ++ u = geteuid(); ++ g = getegid(); ++ ++ if (gpmctx->fd != -1 && ++ (p != gpmctx->pid || u != gpmctx->uid || g != gpmctx->gid)) { ++ gpm_close_socket(gpmctx); ++ } ++ ++ if (gpmctx->fd == -1) { ++ ret = gpm_open_socket(gpmctx); ++ if (ret) { ++ goto done; ++ } ++ } ++ ++ /* setup timer */ ++ ret = gpm_timer_setup(gpmctx, RESPONSE_TIMEOUT); ++ if (ret) { ++ goto done; ++ } ++ /* create epoll fd as well */ ++ ret = gpm_epoll_setup(gpmctx); ++ ++done: ++ if (ret) { ++ gpm_release_sock(gpmctx); ++ } ++ return ret; ++} ++ ++static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) ++{ + int ret; + int epoll_ret; + struct epoll_event ev; +@@ -526,11 +542,6 @@ static int gpm_send_recv_loop(struct gpm_ctx *gpmctx, char *send_buffer, + int ret; + int retry_count; + +- /* setup timer */ +- ret = gpm_timer_setup(gpmctx, RESPONSE_TIMEOUT); +- if (ret) +- return ret; +- + for (retry_count = 0; retry_count < MAX_TIMEOUT_RETRY; retry_count++) { + /* send to proxy */ + ret = gpm_send_buffer(gpmctx, send_buffer, send_length); +@@ -757,9 +768,6 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) + } + + done: +- gpm_timer_close(gpmctx); +- gpm_epoll_close(gpmctx); +- + if (sockgrab) { + gpm_release_sock(gpmctx); + } diff --git a/SOURCES/Conditionally-reload-kernel-interface-on-SIGHUP.patch b/SOURCES/Conditionally-reload-kernel-interface-on-SIGHUP.patch new file mode 100644 index 0000000..42286f6 --- /dev/null +++ b/SOURCES/Conditionally-reload-kernel-interface-on-SIGHUP.patch @@ -0,0 +1,59 @@ +From 8a5ba5feb98ecc3c57ee865604799fc4e4a90c61 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Mon, 26 Jun 2017 17:04:16 -0400 +Subject: [PATCH] Conditionally reload kernel interface on SIGHUP + +Signed-off-by: Alexander Scheel +[rharwood@redhat.com: Simplified logic, rewrote commit message] +Reviewed-by: Robbie Harwood +Resolves: #193 +Merges: #201 +(cherry picked from commit 938af94b8f33c227dcdd6a53ed42de418578d29d) +--- + proxy/src/gp_init.c | 4 +++- + proxy/src/gssproxy.c | 3 +++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/proxy/src/gp_init.c b/proxy/src/gp_init.c +index e69934d..6a2b047 100644 +--- a/proxy/src/gp_init.c ++++ b/proxy/src/gp_init.c +@@ -145,6 +145,7 @@ void init_proc_nfsd(struct gp_config *cfg) + char buf[] = "1"; + bool enabled = false; + int fd, ret; ++ static int poked = 0; + + /* check first if any service enabled kernel support */ + for (int i = 0; i < cfg->num_svcs; i++) { +@@ -154,7 +155,7 @@ void init_proc_nfsd(struct gp_config *cfg) + } + } + +- if (!enabled) { ++ if (!enabled || poked) { + return; + } + +@@ -173,6 +174,7 @@ void init_proc_nfsd(struct gp_config *cfg) + LINUX_PROC_USE_GSS_PROXY_FILE, ret, gp_strerror(ret)); + } + ++ poked = 1; + close(fd); + if (ret != 0) { + goto fail; +diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c +index 94a6a61..5fc4f8d 100644 +--- a/proxy/src/gssproxy.c ++++ b/proxy/src/gssproxy.c +@@ -140,6 +140,9 @@ static void hup_handler(verto_ctx *vctx, verto_ev *ev UNUSED) + exit(ret); + } + ++ /* conditionally reload kernel interface */ ++ init_proc_nfsd(gpctx->config); ++ + free_config(&old_config); + + GPDEBUG("New config loaded successfully.\n"); diff --git a/SOURCES/Do-not-call-gpm_grab_sock-twice.patch b/SOURCES/Do-not-call-gpm_grab_sock-twice.patch new file mode 100644 index 0000000..5a5852c --- /dev/null +++ b/SOURCES/Do-not-call-gpm_grab_sock-twice.patch @@ -0,0 +1,59 @@ +From 32578afb817f20446d888326814b52a8f3d6c0fe Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Thu, 26 Oct 2017 16:59:18 -0400 +Subject: [PATCH] Do not call gpm_grab_sock() twice + +In the gpm_get_ctx() call, we unnecessarily call gpm_grab_sock() which +would cause the lock to be held by one thread and never released. We +already call gpm_grab_sock() as the first thing after gpm_get_ctx() in +gpm_make_call(), plus gpm_make_call() properly releases the socket +once done. + +This corrects the deadlock fix in +461a5fa9f91a2753ebeef6323a64239c35e2f250, which incorrectly released +the lock we wanted to grab. This caused the socket to not be locked +to our thread. Another thread could come along and change the global +ctx while we were still using the socket from another thread, causing +concurrency issues as only one request can be in flight on any given +socket at the same time. + +In special cases where the "thread" uid/gid changes (like in +rpc.gssd), we end up closing the socket while we are still waiting for +an answer from the server, causing additional issues and confusion. + +[rharwood@redhat.com: squashed 2 commits; minor edits accordingly] +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #218 +(cherry picked from commit 8590c5dbc6fa07d0c366df23b982a4b6b9ffc259) +--- + proxy/src/client/gpm_common.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 69f4741..2133618 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -152,7 +152,9 @@ static int gpm_grab_sock(struct gpm_ctx *gpmctx) + ret = gpm_open_socket(gpmctx); + } + +- pthread_mutex_unlock(&gpmctx->lock); ++ if (ret) { ++ pthread_mutex_unlock(&gpmctx->lock); ++ } + return ret; + } + +@@ -304,11 +306,6 @@ static struct gpm_ctx *gpm_get_ctx(void) + + pthread_once(&gpm_init_once_control, gpm_init_once); + +- ret = gpm_grab_sock(&gpm_global_ctx); +- if (ret) { +- return NULL; +- } +- + return &gpm_global_ctx; + } + diff --git a/SOURCES/Don-t-leak-mech_type-when-CONTINUE_NEEDED-from-init_.patch b/SOURCES/Don-t-leak-mech_type-when-CONTINUE_NEEDED-from-init_.patch new file mode 100644 index 0000000..bcad8ca --- /dev/null +++ b/SOURCES/Don-t-leak-mech_type-when-CONTINUE_NEEDED-from-init_.patch @@ -0,0 +1,27 @@ +From dd1699810efe933858badce463bece239d19e886 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Tue, 8 Aug 2017 11:36:56 -0400 +Subject: [PATCH] Don't leak mech_type when CONTINUE_NEEDED from + init_sec_context + +Signed-off-by: Alexander Scheel +Reviewed-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #207 +(cherry picked from commit ca26c0f58ac961a16b06c3fb93b985d574116b2c) +--- + proxy/src/gp_export.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index 0c39045..c9f5fd4 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -687,6 +687,7 @@ export: + 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 */ ++ xdr_free((xdrproc_t)xdr_gssx_OID, (char *)&out->mech); + ret = gp_conv_oid_to_gssx(mech, &out->mech); + if (ret) { + ret_maj = GSS_S_FAILURE; diff --git a/SOURCES/Emit-debug-on-queue-errors.patch b/SOURCES/Emit-debug-on-queue-errors.patch new file mode 100644 index 0000000..99e7690 --- /dev/null +++ b/SOURCES/Emit-debug-on-queue-errors.patch @@ -0,0 +1,26 @@ +From f1f89ef85b65b95f568d46fea85c7e7834e3a101 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Thu, 26 Oct 2017 11:47:54 -0400 +Subject: [PATCH] Emit debug on queue errors + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #218 +(cherry picked from commit af666affbd4735ba437e3d89d9e22984a556ed16) +--- + proxy/src/gp_workers.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/proxy/src/gp_workers.c b/proxy/src/gp_workers.c +index 2a33c21..18f38f6 100644 +--- a/proxy/src/gp_workers.c ++++ b/proxy/src/gp_workers.c +@@ -314,6 +314,8 @@ static void gp_handle_reply(verto_ctx *vctx, verto_ev *ev) + case GP_QUERY_IN: + /* ?! fallback and kill client conn */ + case GP_QUERY_ERR: ++ GPDEBUGN(3, "[status] Handling query error, terminating CID %d.\n", ++ gp_conn_get_cid(q->conn)); + gp_conn_free(q->conn); + gp_query_free(q, true); + break; diff --git a/SOURCES/Fix-double-free-of-popt-context-when-querying-versio.patch b/SOURCES/Fix-double-free-of-popt-context-when-querying-versio.patch new file mode 100644 index 0000000..5837abd --- /dev/null +++ b/SOURCES/Fix-double-free-of-popt-context-when-querying-versio.patch @@ -0,0 +1,28 @@ +From 3203f956cd77c43b6432b01d2d82950e9dac3580 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 24 Aug 2017 15:13:52 -0400 +Subject: [PATCH] Fix double free of popt context when querying version + +This is a non-exploitable, cosmetic issue which causes a segfault (in +some cases) rather than a clean exit of the program. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #209 +(cherry picked from commit 6ef4eb72bef742ed1ebb2824df5a600819e19666) +--- + proxy/src/gssproxy.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c +index 3b6a16e..3221615 100644 +--- a/proxy/src/gssproxy.c ++++ b/proxy/src/gssproxy.c +@@ -202,7 +202,6 @@ int main(int argc, const char *argv[]) + + if (opt_version) { + puts(VERSION""DISTRO_VERSION""PRERELEASE_VERSION); +- poptFreeContext(pc); + ret = 0; + goto cleanup; + } diff --git a/SOURCES/Fix-error-checking-on-get_impersonator_fallback.patch b/SOURCES/Fix-error-checking-on-get_impersonator_fallback.patch new file mode 100644 index 0000000..7e17ad5 --- /dev/null +++ b/SOURCES/Fix-error-checking-on-get_impersonator_fallback.patch @@ -0,0 +1,28 @@ +From f21071fb3662824698b61d384b1144657a508043 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Mar 2017 14:57:57 -0400 +Subject: [PATCH] Fix error checking on get_impersonator_fallback() + +Separate commit to ease backporting. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #173 +(cherry picked from commit 25e31ebccde7f0d98480b6a99962fef61dd251b4) +--- + proxy/src/gp_creds.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index e05ad01..fdc6bdf 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -885,7 +885,7 @@ static uint32_t get_impersonator_name(uint32_t *min, gss_cred_id_t cred, + * release that supports this call */ + ret_maj = get_impersonator_fallback(&ret_min, cred, impersonator); + if (ret_maj == GSS_S_FAILURE) { +- if (ret_min == KRB5_CC_NOTFOUND) { ++ if (ret_min == (uint32_t)KRB5_CC_NOTFOUND) { + ret_min = ENOENT; + ret_maj = GSS_S_COMPLETE; + } diff --git a/SOURCES/Fix-error-handling-in-gp_config_from_dir.patch b/SOURCES/Fix-error-handling-in-gp_config_from_dir.patch new file mode 100644 index 0000000..a3c43ae --- /dev/null +++ b/SOURCES/Fix-error-handling-in-gp_config_from_dir.patch @@ -0,0 +1,50 @@ +From 8603c619ca9bc923534d83ee432ddd756f285d4c Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 12 Jul 2017 09:26:52 -0400 +Subject: [PATCH] Fix error handling in gp_config_from_dir + +Signed-off-by: Alexander Scheel +[rharwood@redhat.com: c99, refactor some existing code] +Reviewed-by: Robbie Harwood +Merges: #204 +(cherry picked from commit eb880e93ed4a48c67ac27b4d5194f0f7786da83e) +--- + proxy/src/gp_config.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index 8fd60a3..07f7c8d 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -798,17 +798,21 @@ static int gp_config_from_dir(const char *config_dir, + &error_list, + NULL); + if (ret) { +- if (error_list) { +- uint32_t i; +- uint32_t len = ref_array_getlen(error_list, &i); +- for (i = 0; i < len; i++) { +- GPDEBUG("Error when reading config directory: %s\n", +- (const char *) ref_array_get(error_list, i, NULL)); +- } +- ref_array_destroy(error_list); +- } else { +- GPDEBUG("Error when reading config directory number: %d\n", ret); ++ uint32_t len; ++ ++ if (!error_list) { ++ GPAUDIT("Error when reading config directory number: %d\n", ret); ++ return ret; + } ++ ++ len = ref_array_len(error_list); ++ for (uint32_t i = 0; i < len; i++) { ++ /* libini has an unfixable bug where error strings are (char **) */ ++ GPAUDIT("Error when reading config directory: %s\n", ++ *(char **)ref_array_get(error_list, i, NULL)); ++ } ++ ++ ref_array_destroy(error_list); + return ret; + } + diff --git a/SOURCES/Fix-error-handling-in-gpm_send_buffer-gpm_recv_buffe.patch b/SOURCES/Fix-error-handling-in-gpm_send_buffer-gpm_recv_buffe.patch new file mode 100644 index 0000000..3dad153 --- /dev/null +++ b/SOURCES/Fix-error-handling-in-gpm_send_buffer-gpm_recv_buffe.patch @@ -0,0 +1,61 @@ +From 027596a3df85d11948f4fb3a28d27d6523645589 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Thu, 14 Sep 2017 11:24:39 -0500 +Subject: [PATCH] Fix error handling in gpm_send_buffer/gpm_recv_buffer + +Signed-off-by: Alexander Scheel +Reviewed-by: Robbie Harwood +Merges: #213 +[rharwood@redhat.com: commit message formatting, copyright update] +(cherry picked from commit f2530fc280dd84e6abc0f5475e261aa0d2ee2a21) +--- + proxy/src/client/gpm_common.c | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index b14e846..0d314fa 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */ ++/* Copyright (C) 2011,2017 the GSS-PROXY contributors, see COPYING for license */ + + #include "gssapi_gpm.h" + #include +@@ -415,10 +415,7 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx, + ret = 0; + + done: +- if (ret) { +- /* on errors we can only close the fd and return */ +- gpm_close_socket(gpmctx); +- } ++ /* we only need to return as gpm_retry_socket closes the socket */ + return ret; + } + +@@ -488,9 +485,10 @@ static int gpm_recv_buffer(struct gpm_ctx *gpmctx, + + done: + if (ret) { +- /* on errors we can only close the fd and return */ +- gpm_close_socket(gpmctx); +- gpm_epoll_close(gpmctx); ++ /* on errors, free the buffer to prevent calling ++ * xdr_destroy(&xdr_reply_ctx); */ ++ free(*buffer); ++ *buffer = NULL; + } + return ret; + } +@@ -560,10 +558,6 @@ static int gpm_send_recv_loop(struct gpm_ctx *gpmctx, char *send_buffer, + /* Close and reopen socket before trying again */ + ret = gpm_retry_socket(gpmctx); + +- /* Free buffer and set it to NULL to prevent free(xdr_reply_ctx) */ +- free(*recv_buffer); +- *recv_buffer = NULL; +- + if (ret != 0) + return ret; + ret = ETIMEDOUT; diff --git a/SOURCES/Fix-handling-of-non-EPOLLIN-EPOLLOUT-events.patch b/SOURCES/Fix-handling-of-non-EPOLLIN-EPOLLOUT-events.patch new file mode 100644 index 0000000..6f1aea5 --- /dev/null +++ b/SOURCES/Fix-handling-of-non-EPOLLIN-EPOLLOUT-events.patch @@ -0,0 +1,79 @@ +From a2a5789d6410e12469ea0f81c9a31ce70bac9ede Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Thu, 14 Sep 2017 11:16:42 -0500 +Subject: [PATCH] Fix handling of non-EPOLLIN/EPOLLOUT events + +Signed-off-by: Alexander Scheel +Reviewed-by: Robbie Harwood +Merges: #213 +(cherry picked from commit b8f5b2f75612a11753cf742ee0477b98df8e6b02) +--- + proxy/src/client/gpm_common.c | 49 +++++++++++++++++++++++++---------- + 1 file changed, 35 insertions(+), 14 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 7d1158e..b14e846 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -283,26 +283,47 @@ static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) { + gpm_epoll_close(gpmctx); + } else if (epoll_ret == 1 && events[0].data.fd == gpmctx->timerfd) { + /* Got an event which is only our timer */ +- ret = read(gpmctx->timerfd, &timer_read, sizeof(uint64_t)); +- if (ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { +- /* In the case when reading from the timer failed, don't hide the +- * timer error behind ETIMEDOUT such that it isn't retried */ +- ret = errno; ++ if ((events[0].events & EPOLLIN) == 0) { ++ /* We got an event which was not EPOLLIN; assume this is an error, ++ * and exit with EBADF: epoll_wait said timerfd had an event, ++ * but that event is not an EPOLIN event. */ ++ ret = EBADF; + } else { +- /* If ret == 0, then we definitely timed out. Else, if ret == -1 +- * and errno == EAGAIN or errno == EWOULDBLOCK, we're in a weird +- * edge case where epoll thinks the timer can be read, but it +- * is blocking more; treat it like a TIMEOUT and retry, as +- * nothing around us would handle EAGAIN from timer and retry +- * it. */ +- ret = ETIMEDOUT; ++ ret = read(gpmctx->timerfd, &timer_read, sizeof(uint64_t)); ++ if (ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { ++ /* In the case when reading from the timer failed, don't hide the ++ * timer error behind ETIMEDOUT such that it isn't retried */ ++ ret = errno; ++ } else { ++ /* If ret == 0, then we definitely timed out. Else, if ret == -1 ++ * and errno == EAGAIN or errno == EWOULDBLOCK, we're in a weird ++ * edge case where epoll thinks the timer can be read, but it ++ * is blocking more; treat it like a TIMEOUT and retry, as ++ * nothing around us would handle EAGAIN from timer and retry ++ * it. */ ++ ret = ETIMEDOUT; ++ } + } + gpm_epoll_close(gpmctx); + } else { + /* If ret == 2, then we ignore the timerfd; that way if the next + * operation cannot be performed immediately, we timeout and retry. +- * If ret == 1 and data.fd == gpmctx->fd, return 0. */ +- ret = 0; ++ * Always check the returned event of the socket fd. */ ++ int fd_index = 0; ++ if (epoll_ret == 2 && events[fd_index].data.fd != gpmctx->fd) { ++ fd_index = 1; ++ } ++ ++ if ((events[fd_index].events & event_flags) == 0) { ++ /* We cannot call EPOLLIN/EPOLLOUT at this time; assume that this ++ * is a fatal error; return with EBADFD to distinguish from ++ * EBADF in timer_fd case. */ ++ ret = EBADFD; ++ gpm_epoll_close(gpmctx); ++ } else { ++ /* We definintely got a EPOLLIN/EPOLLOUT event; return success. */ ++ ret = 0; ++ } + } + + epoll_ret = epoll_ctl(gpmctx->epollfd, EPOLL_CTL_DEL, gpmctx->fd, NULL); diff --git a/SOURCES/Fix-memory-leak.patch b/SOURCES/Fix-memory-leak.patch new file mode 100644 index 0000000..540c1ef --- /dev/null +++ b/SOURCES/Fix-memory-leak.patch @@ -0,0 +1,25 @@ +From abcd9ae04b1c3f9f0ebb72bd48737b08d5d7fe65 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Thu, 25 May 2017 21:35:37 -0400 +Subject: [PATCH] Fix memory leak + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Related-to: #176 +(cherry picked from commit 69a73d85eb3e70fdc7501794d5fd11a73a1d20fa) +--- + proxy/src/gp_export.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index f44da50..4e081df 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -381,6 +381,7 @@ uint32_t gp_export_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + + done: + *min = ret_min; ++ gss_release_buffer(&ret_min, &token); + gss_release_name(&ret_min, &name); + gss_release_oid_set(&ret_min, &mechanisms); + return ret_maj; diff --git a/SOURCES/Fix-mismatched-sign-comparisons.patch b/SOURCES/Fix-mismatched-sign-comparisons.patch new file mode 100644 index 0000000..8d27612 --- /dev/null +++ b/SOURCES/Fix-mismatched-sign-comparisons.patch @@ -0,0 +1,741 @@ +From a68b8b418bfc42c628fee605cc52dca92ab410c9 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Mar 2017 14:52:08 -0400 +Subject: [PATCH] Fix mismatched sign comparisons + +We are c99, so also migrate to `for`-loop initializers where possible for +clarity. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #173 +(cherry picked from commit 377e92c7ead312c530b233a1e023493ecde033d6) +--- + proxy/src/client/gpm_acquire_cred.c | 11 ++----- + proxy/src/client/gpm_common.c | 4 +-- + proxy/src/client/gpm_import_and_canon_name.c | 7 ++--- + proxy/src/client/gpm_indicate_mechs.c | 33 +++++++++----------- + proxy/src/gp_common.h | 3 +- + proxy/src/gp_config.c | 9 ++---- + proxy/src/gp_conv.c | 6 ++-- + proxy/src/gp_creds.c | 3 +- + proxy/src/gp_export.c | 9 ++---- + proxy/src/gp_rpc_acquire_cred.c | 5 ++- + proxy/src/gp_rpc_debug.c | 26 +++++++-------- + proxy/src/gp_rpc_indicate_mechs.c | 15 +++------ + proxy/src/gp_socket.c | 4 +-- + proxy/src/gp_util.c | 4 +-- + proxy/tests/t_utils.c | 4 +-- + 15 files changed, 58 insertions(+), 85 deletions(-) + +diff --git a/proxy/src/client/gpm_acquire_cred.c b/proxy/src/client/gpm_acquire_cred.c +index 632973d..8e30e1d 100644 +--- a/proxy/src/client/gpm_acquire_cred.c ++++ b/proxy/src/client/gpm_acquire_cred.c +@@ -6,8 +6,6 @@ static int gpmint_cred_to_actual_mechs(gssx_cred *c, gss_OID_set *a) + { + gssx_cred_element *e; + gss_OID_set m = GSS_C_NO_OID_SET; +- int i; +- + + if (c->elements.elements_len) { + +@@ -22,7 +20,7 @@ static int gpmint_cred_to_actual_mechs(gssx_cred *c, gss_OID_set *a) + return ENOMEM; + } + +- for (i = 0; i < c->elements.elements_len; i++) { ++ for (unsigned i = 0; i < c->elements.elements_len; i++) { + e = &c->elements.elements_val[i]; + + m->elements[i].elements = gp_memdup(e->mech.octet_string_val, +@@ -280,7 +278,6 @@ OM_uint32 gpm_inquire_cred(OM_uint32 *minor_status, + uint32_t ret_maj = GSS_S_COMPLETE; + uint32_t life; + int cu; +- int i; + + if (!cred) { + *minor_status = 0; +@@ -308,8 +305,7 @@ OM_uint32 gpm_inquire_cred(OM_uint32 *minor_status, + life = GSS_C_INDEFINITE; + cu = -1; + +- for (i = 0; i < cred->elements.elements_len; i++) { +- ++ for (unsigned i = 0; i < cred->elements.elements_len; i++) { + e = &cred->elements.elements_val[i]; + + switch (e->cred_usage) { +@@ -402,7 +398,7 @@ OM_uint32 gpm_inquire_cred_by_mech(OM_uint32 *minor_status, + gss_OID_desc tmp_oid; + uint32_t ret_min = 0; + uint32_t ret_maj = GSS_S_COMPLETE; +- int i; ++ unsigned i; + + if (!cred) { + *minor_status = 0; +@@ -414,7 +410,6 @@ OM_uint32 gpm_inquire_cred_by_mech(OM_uint32 *minor_status, + } + + for (i = 0; i < cred->elements.elements_len; i++) { +- + e = &cred->elements.elements_val[i]; + gp_conv_gssx_to_oid(&e->mech, &tmp_oid); + if (!gss_oid_equal(&tmp_oid, mech_type)) { +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 030765a..8c96986 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -166,7 +166,7 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx, + char *buffer, uint32_t length) + { + uint32_t size; +- size_t wn; ++ ssize_t wn; + size_t pos; + bool retry; + int ret; +@@ -232,7 +232,7 @@ static int gpm_recv_buffer(struct gpm_ctx *gpmctx, + char *buffer, uint32_t *length) + { + uint32_t size; +- size_t rn; ++ ssize_t rn; + size_t pos; + int ret; + +diff --git a/proxy/src/client/gpm_import_and_canon_name.c b/proxy/src/client/gpm_import_and_canon_name.c +index 83d0736..70149a3 100644 +--- a/proxy/src/client/gpm_import_and_canon_name.c ++++ b/proxy/src/client/gpm_import_and_canon_name.c +@@ -275,7 +275,6 @@ OM_uint32 gpm_inquire_name(OM_uint32 *minor_status, + { + gss_buffer_set_t xattrs = GSS_C_NO_BUFFER_SET; + int ret; +- int i; + + *minor_status = 0; + +@@ -306,13 +305,13 @@ OM_uint32 gpm_inquire_name(OM_uint32 *minor_status, + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } +- for (i = 0; i < xattrs->count; i++) { ++ for (unsigned i = 0; i < xattrs->count; i++) { + ret = gp_copy_gssx_to_buffer( + &name->name_attributes.name_attributes_val[i].attr, + &xattrs->elements[i]); + if (ret) { +- for (--i; i >= 0; i--) { +- free(xattrs->elements[i].value); ++ for (; i > 0; i--) { ++ free(xattrs->elements[i-1].value); + } + free(xattrs->elements); + free(xattrs); +diff --git a/proxy/src/client/gpm_indicate_mechs.c b/proxy/src/client/gpm_indicate_mechs.c +index d4df923..b019a96 100644 +--- a/proxy/src/client/gpm_indicate_mechs.c ++++ b/proxy/src/client/gpm_indicate_mechs.c +@@ -51,7 +51,6 @@ static uint32_t gpm_copy_gss_OID_set(uint32_t *minor_status, + gss_OID_set n; + uint32_t ret_maj; + uint32_t ret_min; +- int i; + + ret_maj = gss_create_empty_oid_set(&ret_min, &n); + if (ret_maj) { +@@ -59,7 +58,7 @@ static uint32_t gpm_copy_gss_OID_set(uint32_t *minor_status, + return ret_maj; + } + +- for (i = 0; i < oldset->count; i++) { ++ for (size_t i = 0; i < oldset->count; i++) { + ret_maj = gss_add_oid_set_member(&ret_min, &oldset->elements[i], &n); + if (ret_maj) { + *minor_status = ret_min; +@@ -124,7 +123,6 @@ static void gpmint_indicate_mechs(void) + uint32_t ret_min; + uint32_t ret_maj = 0; + int ret = 0; +- int i; + + memset(arg, 0, sizeof(gssx_arg_indicate_mechs)); + memset(res, 0, sizeof(gssx_res_indicate_mechs)); +@@ -158,7 +156,7 @@ static void gpmint_indicate_mechs(void) + goto done; + } + +- for (i = 0; i < res->mechs.mechs_len; i++) { ++ for (unsigned i = 0; i < res->mechs.mechs_len; i++) { + mi = &res->mechs.mechs_val[i]; + gi = &global_mechs.info[i]; + +@@ -222,7 +220,7 @@ static void gpmint_indicate_mechs(void) + goto done; + } + +- for (i = 0; i < res->mech_attr_descs.mech_attr_descs_len; i++) { ++ for (unsigned i = 0; i < res->mech_attr_descs.mech_attr_descs_len; i++) { + ma = &res->mech_attr_descs.mech_attr_descs_val[i]; + ga = &global_mechs.desc[i]; + +@@ -249,7 +247,7 @@ static void gpmint_indicate_mechs(void) + + done: + if (ret || ret_maj) { +- for (i = 0; i < global_mechs.desc_len; i++) { ++ for (unsigned i = 0; i < global_mechs.desc_len; i++) { + ga = &global_mechs.desc[i]; + gss_release_oid(&discard, &ga->attr); + gss_release_buffer(&discard, ga->name); +@@ -258,7 +256,7 @@ done: + } + free(global_mechs.desc); + global_mechs.desc = NULL; +- for (i = 0; i < global_mechs.info_len; i++) { ++ for (unsigned i = 0; i < global_mechs.info_len; i++) { + gi = &global_mechs.info[i]; + gss_release_oid(&discard, &gi->mech); + gss_release_oid_set(&discard, &gi->name_types); +@@ -335,7 +333,6 @@ OM_uint32 gpm_inquire_names_for_mech(OM_uint32 *minor_status, + { + uint32_t ret_min; + uint32_t ret_maj; +- int i; + + if (!minor_status) { + return GSS_S_CALL_INACCESSIBLE_WRITE; +@@ -351,7 +348,7 @@ OM_uint32 gpm_inquire_names_for_mech(OM_uint32 *minor_status, + return GSS_S_FAILURE; + } + +- for (i = 0; i < global_mechs.info_len; i++) { ++ for (unsigned i = 0; i < global_mechs.info_len; i++) { + if (!gpm_equal_oids(global_mechs.info[i].mech, mech_type)) { + continue; + } +@@ -375,7 +372,6 @@ OM_uint32 gpm_inquire_mechs_for_name(OM_uint32 *minor_status, + uint32_t discard; + gss_OID name_type = GSS_C_NO_OID; + int present; +- int i; + + if (!minor_status) { + return GSS_S_CALL_INACCESSIBLE_WRITE; +@@ -402,7 +398,7 @@ OM_uint32 gpm_inquire_mechs_for_name(OM_uint32 *minor_status, + goto done; + } + +- for (i = 0; i < global_mechs.info_len; i++) { ++ for (unsigned i = 0; i < global_mechs.info_len; i++) { + ret_maj = gss_test_oid_set_member(&ret_min, name_type, + global_mechs.info[i].name_types, + &present); +@@ -439,7 +435,6 @@ OM_uint32 gpm_inquire_attrs_for_mech(OM_uint32 *minor_status, + uint32_t ret_min; + uint32_t ret_maj; + uint32_t discard; +- int i; + + if (!minor_status) { + return GSS_S_CALL_INACCESSIBLE_WRITE; +@@ -451,7 +446,7 @@ OM_uint32 gpm_inquire_attrs_for_mech(OM_uint32 *minor_status, + return GSS_S_FAILURE; + } + +- for (i = 0; i < global_mechs.info_len; i++) { ++ for (unsigned i = 0; i < global_mechs.info_len; i++) { + if (!gpm_equal_oids(global_mechs.info[i].mech, mech)) { + continue; + } +@@ -495,7 +490,6 @@ OM_uint32 gpm_inquire_saslname_for_mech(OM_uint32 *minor_status, + uint32_t ret_min; + uint32_t ret_maj; + uint32_t discard; +- int i; + + if (!minor_status) { + return GSS_S_CALL_INACCESSIBLE_WRITE; +@@ -511,7 +505,7 @@ OM_uint32 gpm_inquire_saslname_for_mech(OM_uint32 *minor_status, + return GSS_S_FAILURE; + } + +- for (i = 0; i < global_mechs.info_len; i++) { ++ for (unsigned i = 0; i < global_mechs.info_len; i++) { + if (!gpm_equal_oids(global_mechs.info[i].mech, desired_mech)) { + continue; + } +@@ -554,7 +548,6 @@ OM_uint32 gpm_display_mech_attr(OM_uint32 *minor_status, + uint32_t ret_min; + uint32_t ret_maj; + uint32_t discard; +- int i; + + if (!minor_status) { + return GSS_S_CALL_INACCESSIBLE_WRITE; +@@ -570,7 +563,7 @@ OM_uint32 gpm_display_mech_attr(OM_uint32 *minor_status, + return GSS_S_FAILURE; + } + +- for (i = 0; i < global_mechs.desc_len; i++) { ++ for (unsigned i = 0; i < global_mechs.desc_len; i++) { + if (!gpm_equal_oids(global_mechs.desc[i].attr, mech_attr)) { + continue; + } +@@ -614,7 +607,6 @@ OM_uint32 gpm_indicate_mechs_by_attrs(OM_uint32 *minor_status, + uint32_t ret_maj; + uint32_t discard; + int present; +- int i, j; + + if (!minor_status) { + return GSS_S_CALL_INACCESSIBLE_WRITE; +@@ -636,8 +628,9 @@ OM_uint32 gpm_indicate_mechs_by_attrs(OM_uint32 *minor_status, + return ret_maj; + } + +- for (i = 0; i < global_mechs.info_len; i++) { ++ for (unsigned i = 0; i < global_mechs.info_len; i++) { + if (desired_mech_attrs != GSS_C_NO_OID_SET) { ++ unsigned j; + for (j = 0; j < desired_mech_attrs->count; j++) { + ret_maj = gss_test_oid_set_member(&ret_min, + &desired_mech_attrs->elements[j], +@@ -657,6 +650,7 @@ OM_uint32 gpm_indicate_mechs_by_attrs(OM_uint32 *minor_status, + } + } + if (except_mech_attrs != GSS_C_NO_OID_SET) { ++ unsigned j; + for (j = 0; j < except_mech_attrs->count; j++) { + ret_maj = gss_test_oid_set_member(&ret_min, + &except_mech_attrs->elements[j], +@@ -676,6 +670,7 @@ OM_uint32 gpm_indicate_mechs_by_attrs(OM_uint32 *minor_status, + } + } + if (critical_mech_attrs != GSS_C_NO_OID_SET) { ++ unsigned j; + for (j = 0; j < critical_mech_attrs->count; j++) { + ret_maj = gss_test_oid_set_member(&ret_min, + &critical_mech_attrs->elements[j], +diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h +index edc23b4..4f76e58 100644 +--- a/proxy/src/gp_common.h ++++ b/proxy/src/gp_common.h +@@ -104,9 +104,8 @@ union gp_rpc_res { + #define gp_options_find(res, opts, name, len) \ + do { \ + struct gssx_option *_v; \ +- int _o; \ + res = NULL; \ +- for (_o = 0; _o < opts.options_len; _o++) { \ ++ for (unsigned _o = 0; _o < opts.options_len; _o++) { \ + _v = &opts.options_val[_o]; \ + if (gp_option_name_match(_v, name, len)) { \ + res = _v; \ +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index 5c1ca02..a671333 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -57,11 +57,9 @@ static void free_str_array(const char ***a, int *count) + + void free_cred_store_elements(gss_key_value_set_desc *cs) + { +- int i; +- + if (!cs->elements) return; + +- for (i = 0; i < cs->count; i++) { ++ for (unsigned i = 0; i < cs->count; i++) { + safefree(cs->elements[i].key); + safefree(cs->elements[i].value); + } +@@ -146,7 +144,7 @@ static int get_krb5_mech_cfg(struct gp_service *svc, + &count, &strings); + if (ret == 0) { + const char *p; +- size_t len; ++ ssize_t len; + char *key; + + svc->krb5.store.elements = +@@ -698,7 +696,6 @@ struct gp_creds_handle *gp_service_get_creds_handle(struct gp_service *svc) + void free_config(struct gp_config **cfg) + { + struct gp_config *config = *cfg; +- uint32_t i; + + if (!config) { + return; +@@ -709,7 +706,7 @@ void free_config(struct gp_config **cfg) + free(config->socket_name); + free(config->proxy_user); + +- for (i=0; i < config->num_svcs; i++) { ++ for (int i = 0; i < config->num_svcs; i++) { + gp_service_free(config->svcs[i]); + safefree(config->svcs[i]); + } +diff --git a/proxy/src/gp_conv.c b/proxy/src/gp_conv.c +index 71d6d9d..b874b06 100644 +--- a/proxy/src/gp_conv.c ++++ b/proxy/src/gp_conv.c +@@ -599,7 +599,6 @@ done: + int gp_conv_gssx_to_oid_set(gssx_OID_set *in, gss_OID_set *out) + { + gss_OID_set o; +- int i; + + if (in->gssx_OID_set_len == 0) { + *out = GSS_C_NO_OID_SET; +@@ -618,7 +617,7 @@ int gp_conv_gssx_to_oid_set(gssx_OID_set *in, gss_OID_set *out) + return ENOMEM; + } + +- for (i = 0; i < o->count; i++) { ++ for (size_t i = 0; i < o->count; i++) { + o->elements[i].elements = + gp_memdup(in->gssx_OID_set_val[i].octet_string_val, + in->gssx_OID_set_val[i].octet_string_len); +@@ -641,7 +640,6 @@ int gp_conv_gssx_to_oid_set(gssx_OID_set *in, gss_OID_set *out) + int gp_conv_oid_set_to_gssx(gss_OID_set in, gssx_OID_set *out) + { + int ret; +- int i; + + if (in->count == 0) { + return 0; +@@ -653,7 +651,7 @@ int gp_conv_oid_set_to_gssx(gss_OID_set in, gssx_OID_set *out) + return ENOMEM; + } + +- for (i = 0; i < in->count; i++) { ++ for (size_t i = 0; i < in->count; i++) { + ret = gp_conv_octet_string(in->elements[i].length, + in->elements[i].elements, + &out->gssx_OID_set_val[i]); +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index 6570b06..e05ad01 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -312,7 +312,6 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall, + int k_num = -1; + int ck_num = -1; + int cc_num = -1; +- int d; + + memset(cs, 0, sizeof(gss_key_value_set_desc)); + +@@ -419,7 +418,7 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall, + ret = ENOMEM; + goto done; + } +- for (d = 0; d < svc->krb5.store.count; d++) { ++ for (unsigned d = 0; d < svc->krb5.store.count; d++) { + if (strcmp(svc->krb5.store.elements[d].key, "client_keytab") == 0) { + ck_num = cs->count; + } else if (strcmp(svc->krb5.store.elements[d].key, "keytab") == 0) { +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index 12b8d5f..3a927c9 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -288,7 +288,6 @@ uint32_t gp_export_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + uint32_t acceptor_lifetime = 0; + struct gssx_cred_element *el; + int ret; +- int i, j; + struct gp_creds_handle *handle = NULL; + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + +@@ -314,8 +313,7 @@ uint32_t gp_export_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + } + out->elements.elements_len = mechanisms->count; + +- for (i = 0, j = 0; i < mechanisms->count; i++, j++) { +- ++ for (unsigned i = 0, j = 0; i < mechanisms->count; i++, j++) { + el = &out->elements.elements_val[j]; + + ret_maj = gss_inquire_cred_by_mech(&ret_min, *in, +@@ -399,11 +397,10 @@ static void gp_set_cred_options(gssx_cred *cred, gss_cred_id_t gss_cred) + krb5_enctype *ktypes; + bool no_ci_flags = false; + uint32_t maj, min; +- int i, j; + +- for (i = 0; i < cred->elements.elements_len; i++) { ++ for (unsigned i = 0; i < cred->elements.elements_len; i++) { + ce = &cred->elements.elements_val[i]; +- for (j = 0; j < ce->options.options_len; j++) { ++ for (unsigned j = 0; j < ce->options.options_len; j++) { + op = &ce->options.options_val[j]; + if ((op->option.octet_string_len == + sizeof(KRB5_SET_ALLOWED_ENCTYPE)) && +diff --git a/proxy/src/gp_rpc_acquire_cred.c b/proxy/src/gp_rpc_acquire_cred.c +index e9c7d56..fcb4fbe 100644 +--- a/proxy/src/gp_rpc_acquire_cred.c ++++ b/proxy/src/gp_rpc_acquire_cred.c +@@ -20,7 +20,6 @@ int gp_acquire_cred(struct gp_call_ctx *gpcall, + gss_cred_id_t *add_out_cred = NULL; + int acquire_type = ACQ_NORMAL; + int ret; +- int i; + + aca = &arg->acquire_cred; + acr = &res->acquire_cred; +@@ -63,7 +62,7 @@ int gp_acquire_cred(struct gp_call_ctx *gpcall, + goto done; + } + +- for (i = 0; i < desired_mechs->count; i++) { ++ for (unsigned i = 0; i < desired_mechs->count; i++) { + desired_mech = &desired_mechs->elements[i]; + + if (!gp_creds_allowed_mech(gpcall, desired_mech)) { +@@ -93,7 +92,7 @@ int gp_acquire_cred(struct gp_call_ctx *gpcall, + + cred_usage = gp_conv_gssx_to_cred_usage(aca->cred_usage); + +- for (i = 0; i < use_mechs->count; i++) { ++ for (unsigned i = 0; i < use_mechs->count; i++) { + desired_mech = &use_mechs->elements[i]; + /* this should really be folded into an extended + * gss_add_cred in gssapi that can accept a set of URIs +diff --git a/proxy/src/gp_rpc_debug.c b/proxy/src/gp_rpc_debug.c +index 2e2c050..a814448 100644 +--- a/proxy/src/gp_rpc_debug.c ++++ b/proxy/src/gp_rpc_debug.c +@@ -19,7 +19,7 @@ void gpdbg_octet_string(octet_string *x) + } + fprintf(stderr, "... ] "); + } else { +- for (int i = 0; i < x->octet_string_len; i++) { ++ for (unsigned i = 0; i < x->octet_string_len; i++) { + fprintf(stderr, "%x", x->octet_string_val[i]); + } + fprintf(stderr, " ] "); +@@ -55,7 +55,7 @@ void gpdbg_gssx_OID(gssx_OID *x) + void gpdbg_gssx_OID_set(gssx_OID_set *x) + { + gp_debug_printf("{ "); +- for (int i = 0; i < x->gssx_OID_set_len; i++) { ++ for (unsigned i = 0; i < x->gssx_OID_set_len; i++) { + gpdbg_gssx_OID(&x->gssx_OID_set_val[i]); + } + gp_debug_printf("} "); +@@ -90,7 +90,7 @@ void gpdbg_gssx_option(gssx_option *x) + #define gpdbg_extensions(x) do { \ + if ((x)->extensions.extensions_len > 0) { \ + gp_debug_printf("[ "); \ +- for (int i = 0; i < (x)->extensions.extensions_len; i++) { \ ++ for (unsigned i = 0; i < (x)->extensions.extensions_len; i++) { \ + gpdbg_gssx_option(&(x)->extensions.extensions_val[i]); \ + } \ + gp_debug_printf("] "); \ +@@ -100,7 +100,7 @@ void gpdbg_gssx_option(gssx_option *x) + #define gpdbg_options(x) do { \ + if ((x)->options.options_len > 0) { \ + gp_debug_printf("[ "); \ +- for (int i = 0; i < (x)->options.options_len; i++) { \ ++ for (unsigned i = 0; i < (x)->options.options_len; i++) { \ + gpdbg_gssx_option(&(x)->options.options_val[i]); \ + } \ + gp_debug_printf("] "); \ +@@ -168,7 +168,7 @@ void gpdbg_gssx_call_ctx(gssx_call_ctx *x) + #define gpdbg_name_attributes(X) do { \ + gp_debug_printf("[ "); \ + if (x->name_attributes.name_attributes_len > 0) { \ +- for (int i = 0; i < x->name_attributes.name_attributes_len; i++) { \ ++ for (unsigned i = 0; i < x->name_attributes.name_attributes_len; i++) { \ + gpdbg_gssx_name_attr( \ + &x->name_attributes.name_attributes_val[i]); \ + } \ +@@ -209,7 +209,7 @@ void gpdbg_gssx_cred(gssx_cred *x) + gp_debug_printf("{ "); + gpdbg_gssx_name(&x->desired_name); + gp_debug_printf("[ "); +- for (int i = 0; i < x->elements.elements_len; i++) { ++ for (unsigned i = 0; i < x->elements.elements_len; i++) { + gpdbg_gssx_cred_element(&x->elements.elements_val[i]); + } + gp_debug_printf("] "); +@@ -289,17 +289,17 @@ void gpdbg_gssx_res_indicate_mechs(gssx_res_indicate_mechs *x) + gp_debug_printf(" GSSX_RES_INDICATE_MECHS( status: "); + gpdbg_gssx_status(&x->status); + gp_debug_printf("mechs: [ "); +- for (int i = 0; i < x->mechs.mechs_len; i++) { ++ for (unsigned i = 0; i < x->mechs.mechs_len; i++) { + gpdbg_gssx_mech_info(&x->mechs.mechs_val[i]); + } + gp_debug_printf("] "); + gp_debug_printf("mech_attr_descs: [ "); +- for (int i = 0; i < x->mech_attr_descs.mech_attr_descs_len; i++) { ++ for (unsigned i = 0; i < x->mech_attr_descs.mech_attr_descs_len; i++) { + gpdbg_gssx_mech_attr(&x->mech_attr_descs.mech_attr_descs_val[i]); + } + gp_debug_printf("] "); + gp_debug_printf("supported_extensions: [ "); +- for (int i = 0; ++ for (unsigned i = 0; + i < x->supported_extensions.supported_extensions_len; i++) { + gpdbg_gssx_buffer( + &x->supported_extensions.supported_extensions_val[i]); +@@ -602,7 +602,7 @@ void gpdbg_gssx_arg_wrap(gssx_arg_wrap *x) + gp_debug_printf("conf_req: "); + gp_debug_printf("%d ", (int)x->conf_req); + gp_debug_printf("message_buffer: [ "); +- for (int i = 0; i < x->message_buffer.message_buffer_len; i++) { ++ for (unsigned i = 0; i < x->message_buffer.message_buffer_len; i++) { + gpdbg_octet_string(&x->message_buffer.message_buffer_val[i]); + } + gp_debug_printf("] "); +@@ -618,7 +618,7 @@ void gpdbg_gssx_res_wrap(gssx_res_wrap *x) + gp_debug_printf("context_handle: "); + GPRPCDEBUG(gssx_ctx, x->context_handle); + gp_debug_printf("token_buffer: [ "); +- for (int i = 0; i < x->token_buffer.token_buffer_len; i++) { ++ for (unsigned i = 0; i < x->token_buffer.token_buffer_len; i++) { + gpdbg_octet_string(&x->token_buffer.token_buffer_val[i]); + } + gp_debug_printf("] "); +@@ -640,7 +640,7 @@ void gpdbg_gssx_arg_unwrap(gssx_arg_unwrap *x) + gp_debug_printf("context_handle: "); + gpdbg_gssx_ctx(&x->context_handle); + gp_debug_printf("token_buffer: [ "); +- for (int i = 0; i < x->token_buffer.token_buffer_len; i++) { ++ for (unsigned i = 0; i < x->token_buffer.token_buffer_len; i++) { + gpdbg_octet_string(&x->token_buffer.token_buffer_val[i]); + } + gp_debug_printf("] "); +@@ -656,7 +656,7 @@ void gpdbg_gssx_res_unwrap(gssx_res_unwrap *x) + gp_debug_printf("context_handle: "); + GPRPCDEBUG(gssx_ctx, x->context_handle); + gp_debug_printf("message_buffer: [ "); +- for (int i = 0; i < x->message_buffer.message_buffer_len; i++) { ++ for (unsigned i = 0; i < x->message_buffer.message_buffer_len; i++) { + gpdbg_octet_string(&x->message_buffer.message_buffer_val[i]); + } + gp_debug_printf("] "); +diff --git a/proxy/src/gp_rpc_indicate_mechs.c b/proxy/src/gp_rpc_indicate_mechs.c +index 8abbc7f..6ae6756 100644 +--- a/proxy/src/gp_rpc_indicate_mechs.c ++++ b/proxy/src/gp_rpc_indicate_mechs.c +@@ -25,8 +25,7 @@ int gp_indicate_mechs(struct gp_call_ctx *gpcall UNUSED, + uint32_t ret_maj; + uint32_t ret_min; + int present; +- int h, i, j; +- int ret; ++ int ret; + + ima = &arg->indicate_mechs; + imr = &res->indicate_mechs; +@@ -53,8 +52,7 @@ int gp_indicate_mechs(struct gp_call_ctx *gpcall UNUSED, + } + imr->mechs.mechs_len = mech_set->count; + +- for (i = 0, h = 0; i < mech_set->count; i++, h++) { +- ++ for (unsigned i = 0, h = 0; i < mech_set->count; i++, h++) { + mi = &imr->mechs.mechs_val[h]; + + ret = gp_conv_oid_to_gssx(&mech_set->elements[i], &mi->mech); +@@ -104,8 +102,7 @@ int gp_indicate_mechs(struct gp_call_ctx *gpcall UNUSED, + ret_min = ret; + goto done; + } +- for (j = 0; j < mech_attrs->count; j++) { +- ++ for (unsigned j = 0; j < mech_attrs->count; j++) { + ret_maj = gss_test_oid_set_member(&ret_min, + &mech_attrs->elements[j], + attr_set, +@@ -136,8 +133,7 @@ int gp_indicate_mechs(struct gp_call_ctx *gpcall UNUSED, + goto done; + } + +- for (j = 0; j < known_mech_attrs->count; j++) { +- ++ for (unsigned j = 0; j < known_mech_attrs->count; j++) { + ret_maj = gss_test_oid_set_member(&ret_min, + &known_mech_attrs->elements[j], + attr_set, +@@ -205,8 +201,7 @@ int gp_indicate_mechs(struct gp_call_ctx *gpcall UNUSED, + } + imr->mech_attr_descs.mech_attr_descs_len = attr_set->count; + +- for (i = 0; i < attr_set->count; i++) { +- ++ for (unsigned i = 0; i < attr_set->count; i++) { + ma = &imr->mech_attr_descs.mech_attr_descs_val[i]; + + ret = gp_conv_oid_to_gssx(&attr_set->elements[i], &ma->attr); +diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c +index 829ff21..17ecf7c 100644 +--- a/proxy/src/gp_socket.c ++++ b/proxy/src/gp_socket.c +@@ -303,7 +303,7 @@ static void gp_socket_read(verto_ctx *vctx, verto_ev *ev) + struct gp_buffer *rbuf; + uint32_t size; + bool header = false; +- size_t rn; ++ ssize_t rn; + int ret; + int fd; + +@@ -487,7 +487,7 @@ static void gp_socket_write(verto_ctx *vctx, verto_ev *ev) + return; + } + if (vecs == 2) { +- if (wn < sizeof(size)) { ++ if (wn < (ssize_t) sizeof(size)) { + /* don't bother trying to handle sockets that can't + * buffer even 4 bytes */ + gp_conn_free(wbuf->conn); +diff --git a/proxy/src/gp_util.c b/proxy/src/gp_util.c +index ca83eb3..f158b84 100644 +--- a/proxy/src/gp_util.c ++++ b/proxy/src/gp_util.c +@@ -109,7 +109,7 @@ char *gp_strerror(int errnum) + ssize_t gp_safe_read(int fd, void *buf, size_t count) + { + char *b = (char *)buf; +- ssize_t len = 0; ++ size_t len = 0; + ssize_t ret; + + do { +@@ -128,7 +128,7 @@ 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) + { + const char *b = (const char *)buf; +- ssize_t len = 0; ++ size_t len = 0; + ssize_t ret; + + do { +diff --git a/proxy/tests/t_utils.c b/proxy/tests/t_utils.c +index 6af9a16..36f7bd1 100644 +--- a/proxy/tests/t_utils.c ++++ b/proxy/tests/t_utils.c +@@ -8,7 +8,7 @@ + int t_send_buffer(int fd, char *buf, uint32_t len) + { + uint32_t size; +- size_t wn; ++ ssize_t wn; + size_t pos; + + size = htonl(len); +@@ -36,7 +36,7 @@ int t_send_buffer(int fd, char *buf, uint32_t len) + int t_recv_buffer(int fd, char *buf, uint32_t *len) + { + uint32_t size; +- size_t rn; ++ ssize_t rn; + size_t pos; + + rn = read(fd, &size, sizeof(uint32_t)); diff --git a/SOURCES/Fix-most-memory-leaks.patch b/SOURCES/Fix-most-memory-leaks.patch new file mode 100644 index 0000000..f4a83d3 --- /dev/null +++ b/SOURCES/Fix-most-memory-leaks.patch @@ -0,0 +1,250 @@ +From 9f9ab1e13c72b7c1fd06b6ba085ba2853bb9c3ca Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Thu, 29 Jun 2017 10:59:46 -0400 +Subject: [PATCH] Fix most memory leaks + +Signed-off-by: Alexander Scheel +[rharwood@redhat.com: commit message, whitespace] +Reviewed-by: Robbie Harwood +Merges: #203 +Related: #176 +(cherry picked from commit 470cf4d745d57f0597124a35b2faf86ba1107bb5) +[rharwood@redhat.com: backport around missing program support] +--- + proxy/src/gp_config.c | 1 + + proxy/src/gp_creds.c | 2 ++ + proxy/src/gp_export.c | 3 ++- + proxy/src/gp_rpc_acquire_cred.c | 17 ++++++++----- + proxy/src/gssproxy.c | 42 +++++++++++++++++++++++--------- + proxy/src/mechglue/gpp_context.c | 2 ++ + proxy/tests/t_acquire.c | 3 +++ + 7 files changed, 51 insertions(+), 19 deletions(-) + +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index a671333..b4ab90c 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -75,6 +75,7 @@ static void gp_service_free(struct gp_service *svc) + free_cred_store_elements(&svc->krb5.store); + gp_free_creds_handle(&svc->krb5.creds_handle); + } ++ free(svc->socket); + SELINUX_context_free(svc->selinux_ctx); + memset(svc, 0, sizeof(struct gp_service)); + } +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index fdc6bdf..2cb4ce7 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -1049,6 +1049,8 @@ uint32_t gp_count_tickets(uint32_t *min, gss_cred_id_t cred, uint32_t *ccsum) + goto done; + } + ++ krb5_free_cred_contents(context, &creds); ++ + /* TODO: Should we do a real checksum over all creds->ticket data and + * flags in future ? */ + (*ccsum)++; +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index 4e081df..ab08bb7 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -47,7 +47,7 @@ uint32_t gp_init_creds_with_keytab(uint32_t *min, const char *svc_name, + krb5_keytab ktid = NULL; + krb5_kt_cursor cursor; + krb5_keytab_entry entry; +- krb5_enctype *permitted; ++ krb5_enctype *permitted = NULL; + uint32_t ret_maj = 0; + uint32_t ret_min = 0; + int ret; +@@ -127,6 +127,7 @@ uint32_t gp_init_creds_with_keytab(uint32_t *min, const char *svc_name, + ret_maj = GSS_S_COMPLETE; + + done: ++ krb5_free_enctypes(handle->context, permitted); + if (ktid) { + (void)krb5_kt_close(handle->context, ktid); + } +diff --git a/proxy/src/gp_rpc_acquire_cred.c b/proxy/src/gp_rpc_acquire_cred.c +index fcb4fbe..7ddb427 100644 +--- a/proxy/src/gp_rpc_acquire_cred.c ++++ b/proxy/src/gp_rpc_acquire_cred.c +@@ -130,17 +130,18 @@ int gp_acquire_cred(struct gp_call_ctx *gpcall, + } + } + +- acr->output_cred_handle = calloc(1, sizeof(gssx_cred)); +- if (!acr->output_cred_handle) { +- ret_maj = GSS_S_FAILURE; +- ret_min = ENOMEM; +- goto done; +- } + + if (out_cred == in_cred) { + acr->output_cred_handle = aca->input_cred_handle; + aca->input_cred_handle = NULL; + } else { ++ acr->output_cred_handle = calloc(1, sizeof(gssx_cred)); ++ if (!acr->output_cred_handle) { ++ ret_maj = GSS_S_FAILURE; ++ ret_min = ENOMEM; ++ goto done; ++ } ++ + ret_maj = gp_export_gssx_cred(&ret_min, gpcall, + &out_cred, acr->output_cred_handle); + if (ret_maj) { +@@ -154,6 +155,10 @@ done: + + GPRPCDEBUG(gssx_res_acquire_cred, acr); + ++ if (add_out_cred != &in_cred && add_out_cred != &out_cred) ++ gss_release_cred(&ret_min, add_out_cred); ++ if (in_cred != out_cred) ++ gss_release_cred(&ret_min, &in_cred); + gss_release_cred(&ret_min, &out_cred); + gss_release_oid_set(&ret_min, &use_mechs); + gss_release_oid_set(&ret_min, &desired_mechs); +diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c +index a020218..5c5937d 100644 +--- a/proxy/src/gssproxy.c ++++ b/proxy/src/gssproxy.c +@@ -157,7 +157,7 @@ int main(int argc, const char *argv[]) + verto_ctx *vctx; + verto_ev *ev; + int wait_fd; +- int ret; ++ int ret = -1; + + struct poptOption long_options[] = { + POPT_AUTOHELP +@@ -187,13 +187,17 @@ int main(int argc, const char *argv[]) + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); +- return 1; ++ ++ ret = 1; ++ goto cleanup; + } + } + + if (opt_version) { + puts(VERSION""DISTRO_VERSION""PRERELEASE_VERSION); +- return 0; ++ poptFreeContext(pc); ++ ret = 0; ++ goto cleanup; + } + + if (opt_debug || opt_debug_level > 0) { +@@ -204,7 +208,8 @@ int main(int argc, const char *argv[]) + if (opt_daemon && opt_interactive) { + fprintf(stderr, "Option -i|--interactive is not allowed together with -D|--daemon\n"); + poptPrintUsage(pc, stderr, 0); +- return 1; ++ ret = 0; ++ goto cleanup; + } + + if (opt_interactive) { +@@ -218,7 +223,8 @@ int main(int argc, const char *argv[]) + opt_config_socket, + opt_daemon); + if (!gpctx->config) { +- exit(EXIT_FAILURE); ++ ret = EXIT_FAILURE; ++ goto cleanup; + } + + init_server(gpctx->config->daemonize, &wait_fd); +@@ -229,7 +235,8 @@ int main(int argc, const char *argv[]) + if (!vctx) { + fprintf(stderr, "Failed to initialize event loop. " + "Is there at least one libverto backend installed?\n"); +- return 1; ++ ret = 1; ++ goto cleanup; + } + gpctx->vctx = vctx; + +@@ -237,12 +244,13 @@ int main(int argc, const char *argv[]) + ev = verto_add_signal(vctx, VERTO_EV_FLAG_PERSIST, hup_handler, SIGHUP); + if (!ev) { + fprintf(stderr, "Failed to register SIGHUP handler with verto!\n"); +- return 1; ++ ret = 1; ++ goto cleanup; + } + + ret = init_sockets(vctx, NULL); + if (ret != 0) { +- return ret; ++ goto cleanup; + } + + /* We need to tell nfsd that GSS-Proxy is available before it starts, +@@ -256,12 +264,14 @@ int main(int argc, const char *argv[]) + + ret = drop_privs(gpctx->config); + if (ret) { +- exit(EXIT_FAILURE); ++ ret = EXIT_FAILURE; ++ goto cleanup; + } + + ret = gp_workers_init(gpctx); + if (ret) { +- exit(EXIT_FAILURE); ++ ret = EXIT_FAILURE; ++ goto cleanup; + } + + verto_run(vctx); +@@ -271,9 +281,17 @@ int main(int argc, const char *argv[]) + + fini_server(); + +- poptFreeContext(pc); + + free_config(&gpctx->config); ++ free(gpctx); + +- return 0; ++ ret = 0; ++ ++cleanup: ++ poptFreeContext(pc); ++ free(opt_config_file); ++ free(opt_config_dir); ++ free(opt_config_socket); ++ ++ return ret; + } +diff --git a/proxy/src/mechglue/gpp_context.c b/proxy/src/mechglue/gpp_context.c +index 2f41e4f..69e69e0 100644 +--- a/proxy/src/mechglue/gpp_context.c ++++ b/proxy/src/mechglue/gpp_context.c +@@ -362,6 +362,8 @@ OM_uint32 gssi_delete_sec_context(OM_uint32 *minor_status, + } + } + ++ free(ctx); ++ + return rmaj; + } + +diff --git a/proxy/tests/t_acquire.c b/proxy/tests/t_acquire.c +index 2bb7706..5334565 100644 +--- a/proxy/tests/t_acquire.c ++++ b/proxy/tests/t_acquire.c +@@ -132,5 +132,8 @@ done: + gss_release_buffer(&ret_min, &in_token); + gss_release_buffer(&ret_min, &out_token); + gss_release_cred(&ret_min, &cred_handle); ++ gss_release_name(&ret_min, &target_name); ++ gss_delete_sec_context(&ret_min, &init_ctx, GSS_C_NO_BUFFER); ++ gss_delete_sec_context(&ret_min, &accept_ctx, GSS_C_NO_BUFFER); + return ret; + } diff --git a/SOURCES/Fix-potential-free-of-non-heap-address.patch b/SOURCES/Fix-potential-free-of-non-heap-address.patch new file mode 100644 index 0000000..699307b --- /dev/null +++ b/SOURCES/Fix-potential-free-of-non-heap-address.patch @@ -0,0 +1,28 @@ +From e087470af1a51b58fbac434ff2e30bc3f2a1f9ac Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Mon, 11 Sep 2017 10:52:03 -0400 +Subject: [PATCH] Fix potential free of non-heap address + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #211 +(cherry picked from commit 068f4174001c3ea4ae7913fb37210fec84abf1df) +--- + proxy/src/client/gpm_common.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index dba23a6..c65c69d 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -553,8 +553,8 @@ static int gpm_send_recv_loop(struct gpm_ctx *gpmctx, char *send_buffer, + ret = gpm_retry_socket(gpmctx); + + /* Free buffer and set it to NULL to prevent free(xdr_reply_ctx) */ +- free(recv_buffer); +- recv_buffer = NULL; ++ free(*recv_buffer); ++ *recv_buffer = NULL; + + if (ret != 0) + return ret; diff --git a/SOURCES/Fix-segfault-when-no-config-files-are-present.patch b/SOURCES/Fix-segfault-when-no-config-files-are-present.patch new file mode 100644 index 0000000..f41fbea --- /dev/null +++ b/SOURCES/Fix-segfault-when-no-config-files-are-present.patch @@ -0,0 +1,39 @@ +From 76954aa028a897021a9bdcb0a1b5249e2652f7b6 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 16 May 2017 14:16:23 -0400 +Subject: [PATCH] Fix segfault when no config files are present + +Resolves: rhbz#1451255 +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #185 +(cherry picked from commit df434333de34a13440857b511a4c60fbc6a71a5c) +--- + proxy/src/gp_config.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index b4ab90c..8fd60a3 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -844,16 +844,17 @@ int gp_config_init(const char *config_file, const char *config_dir, + + if (config_file) { + ret = gp_config_from_file(config_file, ini_config, collision_flags); +- if (ret == ENOENT) { +- GPDEBUG("Expected config file %s but did not find it.\n", ++ if (ret) { ++ GPDEBUG("Error when trying to read config file %s.\n", + config_file); +- } else if (ret) { + return ret; + } + } + if (config_dir) { + ret = gp_config_from_dir(config_dir, &ini_config, collision_flags); + if (ret) { ++ GPDEBUG("Error when trying to read config directory %s.\n", ++ config_dir); + return ret; + } + } diff --git a/SOURCES/Fix-silent-crash-with-duplicate-config-sections.patch b/SOURCES/Fix-silent-crash-with-duplicate-config-sections.patch new file mode 100644 index 0000000..5496f74 --- /dev/null +++ b/SOURCES/Fix-silent-crash-with-duplicate-config-sections.patch @@ -0,0 +1,220 @@ +From caec174b203206185b6075c0e822c6f45070dd87 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 9 Aug 2017 15:00:26 -0400 +Subject: [PATCH] Fix silent crash with duplicate config sections + +Signed-off-by: Alexander Scheel +Reviewed-by: Simo Sorce +Resolves: #194 +Merges: #202 +(cherry picked from commit c0d85387fc38f9554d601ec2ddb111031a694387) +--- + proxy/configure.ac | 125 ++++++++++++++++++++++++++++++++++++++++++ + proxy/src/gp_config.c | 27 ++++----- + 2 files changed, 137 insertions(+), 15 deletions(-) + +diff --git a/proxy/configure.ac b/proxy/configure.ac +index c52dbb6..9e01f7d 100644 +--- a/proxy/configure.ac ++++ b/proxy/configure.ac +@@ -107,6 +107,131 @@ fi + AC_SUBST(INI_LIBS) + AC_SUBST(INI_CFLAGS) + ++AC_CHECK_LIB(ref_array, ref_array_destroy, [], ++ [AC_MSG_WARN([ref_array library must support ref_array_destroy])], ++ [$INI_CONFIG_LIBS]) ++ ++AC_RUN_IFELSE([AC_LANG_SOURCE([[ ++/* See: https://pagure.io/SSSD/ding-libs/pull-request/3172 */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int write_to_file(char *path, char *text) ++{ ++ FILE *f = fopen(path, "w"); ++ int bytes = 0; ++ if (f == NULL) ++ return 1; ++ ++ bytes = fprintf(f, "%s", text); ++ if (bytes != strlen(text)) ++ return 1; ++ ++ return fclose(f); ++} ++ ++int main(void) ++{ ++ char base_path[PATH_MAX]; ++ char augment_path[PATH_MAX]; ++ ++ char config_base[] = ++ "[section]\n" ++ "key1 = first\n" ++ "key2 = exists\n"; ++ ++ char config_augment[] = ++ "[section]\n" ++ "key1 = augment\n" ++ "key3 = exists\n"; ++ ++ char *builddir; ++ ++ struct ini_cfgobj *in_cfg, *result_cfg; ++ struct ini_cfgfile *file_ctx; ++ ++ uint32_t merge_flags = INI_MS_DETECT | INI_MS_PRESERVE; ++ ++ int ret; ++ ++ builddir = getenv("builddir"); ++ if (builddir == NULL) { ++ builddir = strdup("."); ++ } ++ ++ snprintf(base_path, PATH_MAX, "%s/tmp_augment_base.conf", builddir); ++ snprintf(augment_path, PATH_MAX, "%s/tmp_augment_augment.conf", builddir); ++ ++ ret = write_to_file(base_path, config_base); ++ if (ret != 0) { ++ ret = 1; ++ goto cleanup; ++ } ++ ++ ret = write_to_file(augment_path, config_augment); ++ if (ret != 0) { ++ goto cleanup; ++ } ++ ++ /* Match only augment.conf */ ++ const char *m_patterns[] = { "^tmp_augment_augment.conf$", NULL }; ++ ++ /* Match all sections */ ++ const char *m_sections[] = { ".*", NULL }; ++ ++ /* Create config collection */ ++ ret = ini_config_create(&in_cfg); ++ if (ret != EOK) ++ goto cleanup; ++ ++ /* Open base.conf */ ++ ret = ini_config_file_open(base_path, 0, &file_ctx); ++ if (ret != EOK) ++ goto cleanup; ++ ++ /* Seed in_cfg with base.conf */ ++ ret = ini_config_parse(file_ctx, 1, 0, 0, in_cfg); ++ if (ret != EOK) ++ goto cleanup; ++ ++ /* Update base.conf with augment.conf */ ++ ret = ini_config_augment(in_cfg, ++ builddir, ++ m_patterns, ++ m_sections, ++ NULL, ++ INI_STOP_ON_NONE, ++ 0, ++ INI_PARSE_NOSPACE|INI_PARSE_NOTAB, ++ merge_flags, ++ &result_cfg, ++ NULL, ++ NULL); ++ /* We always expect EEXIST due to DETECT being set. */ ++ if (ret != EEXIST) ++ goto cleanup; ++ ++ ret = 0; ++ ++cleanup: ++ remove(base_path); ++ remove(augment_path); ++ ++ /* Per autoconf guidelines */ ++ if (ret != 0) ++ ret = 1; ++ ++ return ret; ++} ++]])] ++,, [AC_MSG_ERROR(["ini_config library must support extended INI_MS_DETECT. See: https://pagure.io/SSSD/ding-libs/pull-request/3172"])]) ++ + AX_PTHREAD(,[AC_MSG_ERROR([Could not find Pthreads support])]) + + LIBS="$PTHREAD_LIBS $LIBS" +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index 07f7c8d..cd057a0 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -728,7 +728,7 @@ static int gp_config_from_file(const char *config_file, + 0, /* metadata_flags, FIXME */ + &file_ctx); + if (ret) { +- GPDEBUG("Failed to open config file: %d (%s)\n", ++ GPERROR("Failed to open config file: %d (%s)\n", + ret, gp_strerror(ret)); + ini_config_destroy(ini_config); + return ret; +@@ -742,7 +742,7 @@ static int gp_config_from_file(const char *config_file, + if (ret) { + char **errors = NULL; + /* we had a parsing failure */ +- GPDEBUG("Failed to parse config file: %d (%s)\n", ++ GPERROR("Failed to parse config file: %d (%s)\n", + ret, gp_strerror(ret)); + if (ini_config_error_count(ini_config)) { + ini_config_get_errors(ini_config, &errors); +@@ -791,26 +791,25 @@ static int gp_config_from_dir(const char *config_dir, + INI_STOP_ON_ANY, /* error_level */ + collision_flags, + INI_PARSE_NOWRAP, +- /* do not allow colliding sections with the same +- * name in different files */ +- INI_MS_ERROR, ++ /* allow sections with the same name in ++ * different files, but log warnings */ ++ INI_MS_DETECT | INI_MS_PRESERVE, + &result_cfg, + &error_list, + NULL); +- if (ret) { ++ if (error_list) { + uint32_t len; +- +- if (!error_list) { +- GPAUDIT("Error when reading config directory number: %d\n", ret); +- return ret; +- } +- + len = ref_array_len(error_list); + for (uint32_t i = 0; i < len; i++) { + /* libini has an unfixable bug where error strings are (char **) */ + GPAUDIT("Error when reading config directory: %s\n", + *(char **)ref_array_get(error_list, i, NULL)); + } ++ ref_array_destroy(error_list); ++ } ++ ++ if (ret && ret != EEXIST) { ++ GPERROR("Error when reading config directory number: %d\n", ret); + + ref_array_destroy(error_list); + return ret; +@@ -821,9 +820,7 @@ static int gp_config_from_dir(const char *config_dir, + ini_config_destroy(*ini_config); + *ini_config = result_cfg; + } +- if (error_list) { +- ref_array_destroy(error_list); +- } ++ + return 0; + } + diff --git a/SOURCES/Fix-unused-variables.patch b/SOURCES/Fix-unused-variables.patch new file mode 100644 index 0000000..069b942 --- /dev/null +++ b/SOURCES/Fix-unused-variables.patch @@ -0,0 +1,503 @@ +From a3c9d87924455448cf3bcb20d34f1bd4e6b915d8 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Mar 2017 13:52:36 -0400 +Subject: [PATCH] Fix unused variables + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #173 +(cherry picked from commit e72d1fa53df8af55b47639ed01f9f0bafa7a2ca8) +--- + proxy/src/client/gpm_common.c | 1 + + proxy/src/client/gpm_display_status.c | 2 +- + proxy/src/client/gpm_release_handle.c | 2 +- + proxy/src/gp_common.h | 1 + + proxy/src/gp_config.c | 8 ++------ + proxy/src/gp_conv.c | 4 ++-- + proxy/src/gp_conv.h | 3 +-- + proxy/src/gp_creds.c | 7 +++---- + proxy/src/gp_init.c | 2 +- + proxy/src/gp_rpc_accept_sec_context.c | 3 +-- + proxy/src/gp_rpc_acquire_cred.c | 3 +-- + proxy/src/gp_rpc_get_mic.c | 4 ++-- + proxy/src/gp_rpc_import_and_canon_name.c | 5 ++--- + proxy/src/gp_rpc_indicate_mechs.c | 5 ++--- + proxy/src/gp_rpc_init_sec_context.c | 3 +-- + proxy/src/gp_rpc_process.c | 21 ++++----------------- + proxy/src/gp_rpc_process.h | 6 ++++++ + proxy/src/gp_rpc_release_handle.c | 5 ++--- + proxy/src/gp_rpc_unwrap.c | 5 ++--- + proxy/src/gp_rpc_verify_mic.c | 5 ++--- + proxy/src/gp_rpc_wrap.c | 4 ++-- + proxy/src/gp_rpc_wrap_size_limit.c | 5 ++--- + proxy/src/gp_socket.c | 2 +- + proxy/src/gssproxy.c | 2 +- + 24 files changed, 44 insertions(+), 64 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 0a54dbc..030765a 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -320,6 +320,7 @@ static void gpm_release_ctx(struct gpm_ctx *gpmctx) + OM_uint32 gpm_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer) + { ++ *minor_status = 0; + if (buffer != GSS_C_NO_BUFFER) { + if (buffer->value) { + free(buffer->value); +diff --git a/proxy/src/client/gpm_display_status.c b/proxy/src/client/gpm_display_status.c +index 1f8d755..bbb546f 100644 +--- a/proxy/src/client/gpm_display_status.c ++++ b/proxy/src/client/gpm_display_status.c +@@ -43,7 +43,7 @@ void gpm_save_internal_status(uint32_t err, char *err_str) + OM_uint32 gpm_display_status(OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, +- const gss_OID mech_type, ++ const gss_OID mech_type UNUSED, + OM_uint32 *message_context, + gss_buffer_t status_string) + { +diff --git a/proxy/src/client/gpm_release_handle.c b/proxy/src/client/gpm_release_handle.c +index 7a6aaed..8f49ee9 100644 +--- a/proxy/src/client/gpm_release_handle.c ++++ b/proxy/src/client/gpm_release_handle.c +@@ -58,7 +58,7 @@ done: + + OM_uint32 gpm_delete_sec_context(OM_uint32 *minor_status, + gssx_ctx **context_handle, +- gss_buffer_t output_token) ++ gss_buffer_t output_token UNUSED) + { + union gp_rpc_arg uarg; + union gp_rpc_res ures; +diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h +index 36fd843..edc23b4 100644 +--- a/proxy/src/gp_common.h ++++ b/proxy/src/gp_common.h +@@ -8,6 +8,7 @@ + #include "gp_log.h" + + #define no_const(ptr) ((void *)((uintptr_t)(ptr))) ++#define UNUSED __attribute__((unused)) + + /* add element to list head */ + #define LIST_ADD(list, elem) do { \ +diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c +index 1b833fd..5c1ca02 100644 +--- a/proxy/src/gp_config.c ++++ b/proxy/src/gp_config.c +@@ -720,7 +720,6 @@ void free_config(struct gp_config **cfg) + } + + static int gp_config_from_file(const char *config_file, +- struct gp_ini_context *ctx, + struct ini_cfgobj *ini_config, + const uint32_t collision_flags) + { +@@ -764,7 +763,6 @@ static int gp_config_from_file(const char *config_file, + } + + static int gp_config_from_dir(const char *config_dir, +- struct gp_ini_context *ctx, + struct ini_cfgobj **ini_config, + const uint32_t collision_flags) + { +@@ -847,8 +845,7 @@ int gp_config_init(const char *config_file, const char *config_dir, + } + + if (config_file) { +- ret = gp_config_from_file(config_file, ctx, ini_config, +- collision_flags); ++ ret = gp_config_from_file(config_file, ini_config, collision_flags); + if (ret == ENOENT) { + GPDEBUG("Expected config file %s but did not find it.\n", + config_file); +@@ -857,8 +854,7 @@ int gp_config_init(const char *config_file, const char *config_dir, + } + } + if (config_dir) { +- ret = gp_config_from_dir(config_dir, ctx, &ini_config, +- collision_flags); ++ ret = gp_config_from_dir(config_dir, &ini_config, collision_flags); + if (ret) { + return ret; + } +diff --git a/proxy/src/gp_conv.c b/proxy/src/gp_conv.c +index 6aa66a8..71d6d9d 100644 +--- a/proxy/src/gp_conv.c ++++ b/proxy/src/gp_conv.c +@@ -6,6 +6,7 @@ + #include + #include + #include "gp_conv.h" ++#include "src/gp_common.h" + + void *gp_memdup(void *in, size_t len) + { +@@ -488,8 +489,7 @@ done: + return ret_maj; + } + +-int gp_conv_status_to_gssx(struct gssx_call_ctx *call_ctx, +- uint32_t ret_maj, uint32_t ret_min, ++int gp_conv_status_to_gssx(uint32_t ret_maj, uint32_t ret_min, + gss_OID mech, struct gssx_status *status) + { + int ret; +diff --git a/proxy/src/gp_conv.h b/proxy/src/gp_conv.h +index e247dbd..699b301 100644 +--- a/proxy/src/gp_conv.h ++++ b/proxy/src/gp_conv.h +@@ -39,8 +39,7 @@ uint32_t gp_conv_name_to_gssx_alloc(uint32_t *min, + gss_name_t in, gssx_name **out); + uint32_t gp_conv_gssx_to_name(uint32_t *min, gssx_name *in, gss_name_t *out); + +-int gp_conv_status_to_gssx(struct gssx_call_ctx *call_ctx, +- uint32_t ret_maj, uint32_t ret_min, ++int gp_conv_status_to_gssx(uint32_t ret_maj, uint32_t ret_min, + gss_OID mech, struct gssx_status *status); + + int gp_copy_utf8string(utf8string *in, utf8string *out); +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index 7d89b06..6570b06 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -252,7 +252,6 @@ done: + + static int ensure_segregated_ccache(struct gp_call_ctx *gpcall, + int cc_num, +- struct gp_service *svc, + gss_key_value_set_desc *cs) + { + int ret; +@@ -482,7 +481,7 @@ static int gp_get_cred_environment(struct gp_call_ctx *gpcall, + } + } + +- ret = ensure_segregated_ccache(gpcall, cc_num, svc, cs); ++ ret = ensure_segregated_ccache(gpcall, cc_num, cs); + if (ret != 0) { + goto done; + } +@@ -587,8 +586,8 @@ uint32_t gp_add_krb5_creds(uint32_t *min, + gss_cred_id_t in_cred, + gssx_name *desired_name, + gss_cred_usage_t cred_usage, +- uint32_t initiator_time_req, +- uint32_t acceptor_time_req, ++ uint32_t initiator_time_req UNUSED, ++ uint32_t acceptor_time_req UNUSED, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + uint32_t *initiator_time_rec, +diff --git a/proxy/src/gp_init.c b/proxy/src/gp_init.c +index d367f92..e69934d 100644 +--- a/proxy/src/gp_init.c ++++ b/proxy/src/gp_init.c +@@ -96,7 +96,7 @@ void fini_server(void) + closelog(); + } + +-static void break_loop(verto_ctx *vctx, verto_ev *ev) ++static void break_loop(verto_ctx *vctx, verto_ev *ev UNUSED) + { + GPDEBUG("Exiting after receiving a signal\n"); + verto_break(vctx); +diff --git a/proxy/src/gp_rpc_accept_sec_context.c b/proxy/src/gp_rpc_accept_sec_context.c +index 22a4cf7..ae4de55 100644 +--- a/proxy/src/gp_rpc_accept_sec_context.c ++++ b/proxy/src/gp_rpc_accept_sec_context.c +@@ -152,8 +152,7 @@ done: + ret_maj = acpt_maj; + ret_min = acpt_min; + } +- ret = gp_conv_status_to_gssx(&asca->call_ctx, +- ret_maj, ret_min, oid, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, oid, + &ascr->status); + GPRPCDEBUG(gssx_res_accept_sec_context, ascr); + +diff --git a/proxy/src/gp_rpc_acquire_cred.c b/proxy/src/gp_rpc_acquire_cred.c +index 9a55937..e9c7d56 100644 +--- a/proxy/src/gp_rpc_acquire_cred.c ++++ b/proxy/src/gp_rpc_acquire_cred.c +@@ -150,8 +150,7 @@ int gp_acquire_cred(struct gp_call_ctx *gpcall, + } + + done: +- ret = gp_conv_status_to_gssx(&aca->call_ctx, +- ret_maj, ret_min, desired_mech, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, desired_mech, + &acr->status); + + GPRPCDEBUG(gssx_res_acquire_cred, acr); +diff --git a/proxy/src/gp_rpc_get_mic.c b/proxy/src/gp_rpc_get_mic.c +index 1d9a1fe..dfba77e 100644 +--- a/proxy/src/gp_rpc_get_mic.c ++++ b/proxy/src/gp_rpc_get_mic.c +@@ -3,7 +3,7 @@ + #include "gp_rpc_process.h" + #include + +-int gp_get_mic(struct gp_call_ctx *gpcall, ++int gp_get_mic(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -79,7 +79,7 @@ int gp_get_mic(struct gp_call_ctx *gpcall, + ret_min = 0; + + done: +- ret = gp_conv_status_to_gssx(&gma->call_ctx, ret_maj, ret_min, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, + GSS_C_NO_OID, &gmr->status); + GPRPCDEBUG(gssx_res_get_mic, gmr); + gss_release_buffer(&ret_min, &message_token); +diff --git a/proxy/src/gp_rpc_import_and_canon_name.c b/proxy/src/gp_rpc_import_and_canon_name.c +index 3d67f40..e7b8e63 100644 +--- a/proxy/src/gp_rpc_import_and_canon_name.c ++++ b/proxy/src/gp_rpc_import_and_canon_name.c +@@ -8,7 +8,7 @@ + * I am not kidding, if you hav not read it, go back and do it now, or do not + * touch this function */ + +-int gp_import_and_canon_name(struct gp_call_ctx *gpcall, ++int gp_import_and_canon_name(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -64,8 +64,7 @@ int gp_import_and_canon_name(struct gp_call_ctx *gpcall, + /* TODO: icna->name_attributes */ + + done: +- ret = gp_conv_status_to_gssx(&icna->call_ctx, +- ret_maj, ret_min, mech, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, mech, + &icnr->status); + GPRPCDEBUG(gssx_res_import_and_canon_name, icnr); + +diff --git a/proxy/src/gp_rpc_indicate_mechs.c b/proxy/src/gp_rpc_indicate_mechs.c +index c24b926..8abbc7f 100644 +--- a/proxy/src/gp_rpc_indicate_mechs.c ++++ b/proxy/src/gp_rpc_indicate_mechs.c +@@ -3,7 +3,7 @@ + #include "gp_rpc_process.h" + #include "gp_debug.h" + +-int gp_indicate_mechs(struct gp_call_ctx *gpcall, ++int gp_indicate_mechs(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -251,8 +251,7 @@ int gp_indicate_mechs(struct gp_call_ctx *gpcall, + } + + done: +- ret = gp_conv_status_to_gssx(&ima->call_ctx, +- ret_maj, ret_min, GSS_C_NO_OID, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, GSS_C_NO_OID, + &imr->status); + GPRPCDEBUG(gssx_res_indicate_mechs, imr); + +diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c +index 413e2ec..e4af495 100644 +--- a/proxy/src/gp_rpc_init_sec_context.c ++++ b/proxy/src/gp_rpc_init_sec_context.c +@@ -187,8 +187,7 @@ done: + ret_maj = init_maj; + ret_min = init_min; + } +- ret = gp_conv_status_to_gssx(&isca->call_ctx, +- ret_maj, ret_min, mech_type, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, mech_type, + &iscr->status); + + GPRPCDEBUG(gssx_res_init_sec_context, iscr); +diff --git a/proxy/src/gp_rpc_process.c b/proxy/src/gp_rpc_process.c +index d1a0232..0ea17f0 100644 +--- a/proxy/src/gp_rpc_process.c ++++ b/proxy/src/gp_rpc_process.c +@@ -396,20 +396,7 @@ int gp_rpc_process_call(struct gp_call_ctx *gpcall, + return ret; + } + +-int gp_get_call_context(gp_exec_std_args) +-{ +- return 0; +-} +-int gp_export_cred(gp_exec_std_args) +-{ +- return 0; +-} +-int gp_import_cred(gp_exec_std_args) +-{ +- return 0; +-} +- +-int gp_store_cred(gp_exec_std_args) +-{ +- return 0; +-} ++GP_EXEC_UNUSED_FUNC(gp_get_call_context); ++GP_EXEC_UNUSED_FUNC(gp_export_cred); ++GP_EXEC_UNUSED_FUNC(gp_import_cred); ++GP_EXEC_UNUSED_FUNC(gp_store_cred); +diff --git a/proxy/src/gp_rpc_process.h b/proxy/src/gp_rpc_process.h +index eb02c95..da27795 100644 +--- a/proxy/src/gp_rpc_process.h ++++ b/proxy/src/gp_rpc_process.h +@@ -24,6 +24,12 @@ struct gp_service; + union gp_rpc_arg *arg, \ + union gp_rpc_res *res + ++#define GP_EXEC_UNUSED_FUNC(name) \ ++ int name(struct gp_call_ctx *gpcall UNUSED, \ ++ union gp_rpc_arg *arg UNUSED, \ ++ union gp_rpc_res *res UNUSED) \ ++ { return 0; } ++ + int gp_indicate_mechs(gp_exec_std_args); + int gp_get_call_context(gp_exec_std_args); + int gp_import_and_canon_name(gp_exec_std_args); +diff --git a/proxy/src/gp_rpc_release_handle.c b/proxy/src/gp_rpc_release_handle.c +index 4ffdfb9..c8ba8f2 100644 +--- a/proxy/src/gp_rpc_release_handle.c ++++ b/proxy/src/gp_rpc_release_handle.c +@@ -2,7 +2,7 @@ + + #include "gp_rpc_process.h" + +-int gp_release_handle(struct gp_call_ctx *gpcall, ++int gp_release_handle(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -35,8 +35,7 @@ int gp_release_handle(struct gp_call_ctx *gpcall, + break; + } + +- ret = gp_conv_status_to_gssx(&rha->call_ctx, +- ret_maj, ret_min, GSS_C_NO_OID, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, GSS_C_NO_OID, + &rhr->status); + GPRPCDEBUG(gssx_res_release_handle, rhr); + +diff --git a/proxy/src/gp_rpc_unwrap.c b/proxy/src/gp_rpc_unwrap.c +index bc052cb..fad8cfe 100644 +--- a/proxy/src/gp_rpc_unwrap.c ++++ b/proxy/src/gp_rpc_unwrap.c +@@ -3,7 +3,7 @@ + #include "gp_rpc_process.h" + #include + +-int gp_unwrap(struct gp_call_ctx *gpcall, ++int gp_unwrap(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -106,8 +106,7 @@ int gp_unwrap(struct gp_call_ctx *gpcall, + ret_min = 0; + + done: +- ret = gp_conv_status_to_gssx(&uwa->call_ctx, +- ret_maj, ret_min, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, + GSS_C_NO_OID, + &uwr->status); + GPRPCDEBUG(gssx_res_unwrap, uwr); +diff --git a/proxy/src/gp_rpc_verify_mic.c b/proxy/src/gp_rpc_verify_mic.c +index d2920d2..6da6dac 100644 +--- a/proxy/src/gp_rpc_verify_mic.c ++++ b/proxy/src/gp_rpc_verify_mic.c +@@ -3,7 +3,7 @@ + #include "gp_rpc_process.h" + #include + +-int gp_verify_mic(struct gp_call_ctx *gpcall, ++int gp_verify_mic(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -74,8 +74,7 @@ int gp_verify_mic(struct gp_call_ctx *gpcall, + ret_min = 0; + + done: +- ret = gp_conv_status_to_gssx(&vma->call_ctx, +- ret_maj, ret_min, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, + GSS_C_NO_OID, + &vmr->status); + GPRPCDEBUG(gssx_res_verify_mic, vmr); +diff --git a/proxy/src/gp_rpc_wrap.c b/proxy/src/gp_rpc_wrap.c +index d5c950e..ae20bdb 100644 +--- a/proxy/src/gp_rpc_wrap.c ++++ b/proxy/src/gp_rpc_wrap.c +@@ -3,7 +3,7 @@ + #include "gp_rpc_process.h" + #include + +-int gp_wrap(struct gp_call_ctx *gpcall, ++int gp_wrap(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -105,7 +105,7 @@ int gp_wrap(struct gp_call_ctx *gpcall, + ret_min = 0; + + done: +- ret = gp_conv_status_to_gssx(&wa->call_ctx, ret_maj, ret_min, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, + GSS_C_NO_OID, &wr->status); + GPRPCDEBUG(gssx_res_wrap, wr); + gss_release_buffer(&ret_min, &output_message_buffer); +diff --git a/proxy/src/gp_rpc_wrap_size_limit.c b/proxy/src/gp_rpc_wrap_size_limit.c +index 355113c..cab6826 100644 +--- a/proxy/src/gp_rpc_wrap_size_limit.c ++++ b/proxy/src/gp_rpc_wrap_size_limit.c +@@ -3,7 +3,7 @@ + #include "gp_rpc_process.h" + #include + +-int gp_wrap_size_limit(struct gp_call_ctx *gpcall, ++int gp_wrap_size_limit(struct gp_call_ctx *gpcall UNUSED, + union gp_rpc_arg *arg, + union gp_rpc_res *res) + { +@@ -51,8 +51,7 @@ int gp_wrap_size_limit(struct gp_call_ctx *gpcall, + ret_min = 0; + + done: +- ret = gp_conv_status_to_gssx(&wsla->call_ctx, +- ret_maj, ret_min, ++ ret = gp_conv_status_to_gssx(ret_maj, ret_min, + GSS_C_NO_OID, + &wslr->status); + GPRPCDEBUG(gssx_res_wrap_size_limit, wslr); +diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c +index 62d7dbc..829ff21 100644 +--- a/proxy/src/gp_socket.c ++++ b/proxy/src/gp_socket.c +@@ -146,7 +146,7 @@ static int set_fd_flags(int fd, int flags) + return 0; + } + +-void free_unix_socket(verto_ctx *ctx, verto_ev *ev) ++void free_unix_socket(verto_ctx *ctx UNUSED, verto_ev *ev) + { + struct gp_sock_ctx *sock_ctx = NULL; + sock_ctx = verto_get_private(ev); +diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c +index 561188e..a020218 100644 +--- a/proxy/src/gssproxy.c ++++ b/proxy/src/gssproxy.c +@@ -119,7 +119,7 @@ static int init_sockets(verto_ctx *vctx, struct gp_config *old_config) + return 0; + } + +-static void hup_handler(verto_ctx *vctx, verto_ev *ev) ++static void hup_handler(verto_ctx *vctx, verto_ev *ev UNUSED) + { + int ret; + struct gp_config *new_config, *old_config; diff --git a/SOURCES/Handle-gss_import_cred-failure-when-importing-gssx-c.patch b/SOURCES/Handle-gss_import_cred-failure-when-importing-gssx-c.patch new file mode 100644 index 0000000..eabce35 --- /dev/null +++ b/SOURCES/Handle-gss_import_cred-failure-when-importing-gssx-c.patch @@ -0,0 +1,31 @@ +From 5c6f2fc4f63b2812b0305a3f0de9904c5ebd38ef Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Mon, 15 Apr 2019 19:56:50 -0400 +Subject: [PATCH] Handle gss_import_cred() failure when importing gssx creds + +Otherwise, we might attempt to set options on a non-existent handle, +leading to a segfault. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #244 +(cherry picked from commit 84cf88f6c6cfeb8e3fd2c26ed0fe9fe5bf3810d2) +--- + proxy/src/gp_export.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index 403e339..7ad8037 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -476,6 +476,10 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + } + + ret_maj = gss_import_cred(&ret_min, &token, out); ++ if (ret_maj) { ++ GPDEBUG("gss_import_cred failed when importing gssx cred\n"); ++ goto done; ++ } + + /* check if there is any client option we need to set on credentials */ + gp_set_cred_options(cred, *out); diff --git a/SOURCES/Handle-outdated-encrypted-ccaches.patch b/SOURCES/Handle-outdated-encrypted-ccaches.patch new file mode 100644 index 0000000..c9c35d9 --- /dev/null +++ b/SOURCES/Handle-outdated-encrypted-ccaches.patch @@ -0,0 +1,121 @@ +From 24d776205605f3c113fdc2cb356d4c28b8033676 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 15 Sep 2017 18:07:28 -0400 +Subject: [PATCH] Handle outdated encrypted ccaches + +When the encrypting keytab changes, all credentials that it was used +to encrypt must be re-created. Otherwise, we log obtuse messages and +fail to do what the user wants. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #214 +(cherry picked from commit 657d3c8339309dd8e2bfa4ee10f005e0f0c055e8) +--- + proxy/src/gp_export.c | 11 ++++++----- + proxy/src/gp_rpc_accept_sec_context.c | 28 +++++++++++++++++++++++++++ + proxy/src/gp_rpc_init_sec_context.c | 2 +- + 3 files changed, 35 insertions(+), 6 deletions(-) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index ab08bb7..0c39045 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -268,7 +268,7 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key, + &enc_handle, + &data_out); + if (ret) { +- return EINVAL; ++ return ret; + } + + *len = data_out.length; +@@ -446,8 +446,8 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + { + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + struct gp_creds_handle *handle = NULL; +- uint32_t ret_maj; +- uint32_t ret_min; ++ uint32_t ret_maj = GSS_S_COMPLETE; ++ uint32_t ret_min = 0; + int ret; + + handle = gp_service_get_creds_handle(gpcall->service); +@@ -469,8 +469,9 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall, + &cred->cred_handle_reference, + &token.length, token.value); + if (ret) { +- ret_maj = GSS_S_FAILURE; +- ret_min = ENOENT; ++ /* Allow for re-issuance of the keytab. */ ++ GPDEBUG("Stored ccache failed to decrypt; treating as empty\n"); ++ *out = GSS_C_NO_CREDENTIAL; + goto done; + } + +diff --git a/proxy/src/gp_rpc_accept_sec_context.c b/proxy/src/gp_rpc_accept_sec_context.c +index ae4de55..2cdc94b 100644 +--- a/proxy/src/gp_rpc_accept_sec_context.c ++++ b/proxy/src/gp_rpc_accept_sec_context.c +@@ -25,6 +25,13 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall, + int exp_creds_type; + uint32_t acpt_maj; + uint32_t acpt_min; ++ struct gp_cred_check_handle gcch = { ++ .ctx = gpcall, ++ .options.options_len = arg->accept_sec_context.options.options_len, ++ .options.options_val = arg->accept_sec_context.options.options_val, ++ }; ++ uint32_t gccn_before = 0; ++ uint32_t gccn_after = 0; + int ret; + + asca = &arg->accept_sec_context; +@@ -52,6 +59,8 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall, + if (ret_maj) { + goto done; + } ++ ++ gccn_before = gp_check_sync_creds(&gcch, ach); + } + + if (ach == GSS_C_NO_CREDENTIAL) { +@@ -146,6 +155,25 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall, + src_name, oid, + &ascr->options.options_len, + &ascr->options.options_val); ++ if (ret_maj) { ++ goto done; ++ } ++ ++ gccn_after = gp_check_sync_creds(&gcch, ach); ++ ++ if (gccn_before != gccn_after) { ++ /* export creds back to client for sync up */ ++ ret_maj = gp_export_sync_creds(&ret_min, gpcall, &ach, ++ &ascr->options.options_val, ++ &ascr->options.options_len); ++ if (ret_maj) { ++ /* not fatal, log and continue */ ++ GPDEBUG("Failed to export sync creds (%d: %d)", ++ (int)ret_maj, (int)ret_min); ++ } ++ } ++ ++ ret_maj = GSS_S_COMPLETE; + + done: + if (ret_maj == GSS_S_COMPLETE) { +diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c +index e4af495..f362dbc 100644 +--- a/proxy/src/gp_rpc_init_sec_context.c ++++ b/proxy/src/gp_rpc_init_sec_context.c +@@ -91,7 +91,7 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, + gp_conv_gssx_to_buffer(isca->input_token, &ibuf); + } + +- if (!isca->cred_handle) { ++ if (!ich) { + if (gss_oid_equal(mech_type, gss_mech_krb5)) { + ret_maj = gp_add_krb5_creds(&ret_min, gpcall, + ACQ_NORMAL, NULL, NULL, diff --git a/SOURCES/Include-header-for-writev.patch b/SOURCES/Include-header-for-writev.patch new file mode 100644 index 0000000..1b6c36e --- /dev/null +++ b/SOURCES/Include-header-for-writev.patch @@ -0,0 +1,49 @@ +From 26b5ff6b802b6a24b23ea774b0305f6f2031d4da Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 17 May 2017 12:21:37 -0400 +Subject: [PATCH] Include header for writev() + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #186 +(cherry picked from commit c8c5e8d2b2154d1006633634478a24bfa0b04b4d) +--- + proxy/src/gp_socket.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c +index 17ecf7c..29b6a44 100644 +--- a/proxy/src/gp_socket.c ++++ b/proxy/src/gp_socket.c +@@ -1,19 +1,22 @@ + /* Copyright (C) 2011,2015 the GSS-PROXY contributors, see COPYING for license */ + + #include "config.h" +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include ++ + #include "gp_proxy.h" + #include "gp_creds.h" + #include "gp_selinux.h" + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ + #define FRAGMENT_BIT (1 << 31) + + struct unix_sock_conn { diff --git a/SOURCES/Include-length-when-using-krb5_c_decrypt.patch b/SOURCES/Include-length-when-using-krb5_c_decrypt.patch new file mode 100644 index 0000000..9780736 --- /dev/null +++ b/SOURCES/Include-length-when-using-krb5_c_decrypt.patch @@ -0,0 +1,98 @@ +From d535ea0d4b3cfa8e1cc26a060ec2ed818f2b69ac Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 16 Apr 2019 16:08:32 -0400 +Subject: [PATCH] Include length when using krb5_c_decrypt() + +For some enctypes, krb5_c_decrypt() will add padding bytes which are +included in the returned length. However, functions which use the +objects we're storing aren't always prepared for that: in particular, +gss_import_cred() will declare a token invalid if there's trailing +garbage. + +Work around this by including 4 bytes of length on encrypted objects. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #244 +(cherry picked from commit 87957caf541114f6f15a495dd7d30556dc5801d9) +--- + proxy/src/gp_export.c | 35 +++++++++++++++++++++++++++++++---- + 1 file changed, 31 insertions(+), 4 deletions(-) + +diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c +index 7ad8037..aa0a8ec 100644 +--- a/proxy/src/gp_export.c ++++ b/proxy/src/gp_export.c +@@ -193,6 +193,9 @@ done: + return ret_maj; + } + ++/* We need to include a length in our payloads because krb5_c_decrypt() will ++ * pad the contents for some enctypes, and gss_import_cred() doesn't like ++ * having extra bytes on tokens. */ + static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + size_t len, void *buf, octet_string *out) + { +@@ -200,9 +203,27 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + krb5_data data_in; + krb5_enc_data enc_handle; + size_t cipherlen; ++ char *packed = NULL; ++ uint32_t netlen; + +- data_in.length = len; +- data_in.data = buf; ++ if (len > (uint32_t)(-1)) { ++ /* Needs to fit in 4 bytes of payload, so... */ ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ packed = malloc(len); ++ if (!packed) { ++ ret = errno; ++ goto done; ++ } ++ ++ netlen = htonl(len); ++ memcpy(packed, (uint8_t *)&netlen, 4); ++ memcpy(packed + 4, buf, len); ++ ++ data_in.length = len + 4; ++ data_in.data = packed; + + memset(&enc_handle, '\0', sizeof(krb5_enc_data)); + +@@ -240,16 +261,19 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key, + } + + done: ++ free(packed); + free(enc_handle.ciphertext.data); + return ret; + } + ++/* See comment above on gp_encrypt_buffer(). */ + static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key, +- octet_string *in, size_t *len, void *buf) ++ octet_string *in, size_t *len, char *buf) + { + int ret; + krb5_data data_out; + krb5_enc_data enc_handle; ++ uint32_t netlen; + + memset(&enc_handle, '\0', sizeof(krb5_enc_data)); + +@@ -270,7 +294,10 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key, + return ret; + } + +- *len = data_out.length; ++ /* And handle the padding. */ ++ memcpy(&netlen, buf, 4); ++ *len = ntohl(netlen); ++ memmove(buf, buf + 4, *len); + + return 0; + } diff --git a/SOURCES/Make-proc-file-failure-loud-but-nonfatal.patch b/SOURCES/Make-proc-file-failure-loud-but-nonfatal.patch new file mode 100644 index 0000000..18a58df --- /dev/null +++ b/SOURCES/Make-proc-file-failure-loud-but-nonfatal.patch @@ -0,0 +1,75 @@ +From 938bd1adc15342e8ebed3d4e135d862e362a619e Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 25 May 2017 13:06:17 -0400 +Subject: [PATCH] Make proc file failure loud but nonfatal + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Resolves: #190 +(cherry picked from commit 4f60bf02a1a68cbb26251e764357b753f80790f3) +--- + proxy/src/gp_init.c | 34 +++++++++++++++------------------- + 1 file changed, 15 insertions(+), 19 deletions(-) + +diff --git a/proxy/src/gp_init.c b/proxy/src/gp_init.c +index bb7ba6b..d367f92 100644 +--- a/proxy/src/gp_init.c ++++ b/proxy/src/gp_init.c +@@ -144,11 +144,11 @@ void init_proc_nfsd(struct gp_config *cfg) + { + char buf[] = "1"; + bool enabled = false; +- int fd, i, ret; ++ int fd, ret; + + /* check first if any service enabled kernel support */ +- for (i = 0; i < cfg->num_svcs; i++) { +- if (cfg->svcs[i]->kernel_nfsd == true) { ++ for (int i = 0; i < cfg->num_svcs; i++) { ++ if (cfg->svcs[i]->kernel_nfsd) { + enabled = true; + break; + } +@@ -161,30 +161,26 @@ void init_proc_nfsd(struct gp_config *cfg) + fd = open(LINUX_PROC_USE_GSS_PROXY_FILE, O_RDWR); + if (fd == -1) { + ret = errno; +- fprintf(stderr, "GSS-Proxy is not supported by this kernel since " +- "file %s could not be found: %d (%s)\n", +- LINUX_PROC_USE_GSS_PROXY_FILE, +- ret, gp_strerror(ret)); +- exit(1); ++ GPDEBUG("Kernel doesn't support GSS-Proxy (can't open %s: %d (%s))\n", ++ LINUX_PROC_USE_GSS_PROXY_FILE, ret, gp_strerror(ret)); ++ goto fail; + } + + ret = write(fd, buf, 1); + if (ret != 1) { + ret = errno; +- fprintf(stderr, "Failed to write to %s: %d (%s)\n", +- LINUX_PROC_USE_GSS_PROXY_FILE, +- ret, gp_strerror(ret)); +- exit(1); ++ GPDEBUG("Failed to write to %s: %d (%s)\n", ++ LINUX_PROC_USE_GSS_PROXY_FILE, ret, gp_strerror(ret)); + } + +- ret = close(fd); +- if (ret == -1) { +- ret = errno; +- fprintf(stderr, "Failed to close %s: %d (%s)\n", +- LINUX_PROC_USE_GSS_PROXY_FILE, +- ret, gp_strerror(ret)); +- exit(1); ++ close(fd); ++ if (ret != 0) { ++ goto fail; + } ++ ++ return; ++fail: ++ GPDEBUG("Problem with kernel communication! NFS server will not work\n"); + } + + void write_pid(void) diff --git a/SOURCES/Only-empty-FILE-ccaches-when-storing-remote-creds.patch b/SOURCES/Only-empty-FILE-ccaches-when-storing-remote-creds.patch new file mode 100644 index 0000000..06edf09 --- /dev/null +++ b/SOURCES/Only-empty-FILE-ccaches-when-storing-remote-creds.patch @@ -0,0 +1,55 @@ +From 1fa33903be640f8d22757d21da294e70f0812698 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 10 Oct 2017 18:00:45 -0400 +Subject: [PATCH] Only empty FILE ccaches when storing remote creds + +This mitigates issues when services share a ccache between two +processes. We cannot fix this for FILE ccaches without introducing +other issues. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #216 +(cherry picked from commit d09e87f47a21dd250bfd7a9c59a5932b5c995057) +--- + proxy/src/mechglue/gpp_creds.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c +index 9fe9bd1..6bdff45 100644 +--- a/proxy/src/mechglue/gpp_creds.c ++++ b/proxy/src/mechglue/gpp_creds.c +@@ -147,6 +147,7 @@ uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, + char cred_name[creds->desired_name.display_name.octet_string_len + 1]; + XDR xdrctx; + bool xdrok; ++ const char *cc_type; + + *min = 0; + +@@ -193,13 +194,20 @@ uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, + } + cred.ticket.length = xdr_getpos(&xdrctx); + +- /* Always initialize and destroy any existing contents to avoid pileup of +- * entries */ +- ret = krb5_cc_initialize(ctx, ccache, cred.client); +- if (ret == 0) { +- ret = krb5_cc_store_cred(ctx, ccache, &cred); ++ cc_type = krb5_cc_get_type(ctx, ccache); ++ if (strcmp(cc_type, "FILE") == 0) { ++ /* FILE ccaches don't handle updates properly: if they have the same ++ * principal name, they are blackholed. We either have to change the ++ * name (at which point the file grows forever) or flash the cache on ++ * every update. */ ++ ret = krb5_cc_initialize(ctx, ccache, cred.client); ++ if (ret != 0) { ++ goto done; ++ } + } + ++ ret = krb5_cc_store_cred(ctx, ccache, &cred); ++ + done: + if (ctx) { + krb5_free_cred_contents(ctx, &cred); diff --git a/SOURCES/Prevent-uninitialized-read-in-error-path-of-XDR-cont.patch b/SOURCES/Prevent-uninitialized-read-in-error-path-of-XDR-cont.patch new file mode 100644 index 0000000..e922183 --- /dev/null +++ b/SOURCES/Prevent-uninitialized-read-in-error-path-of-XDR-cont.patch @@ -0,0 +1,28 @@ +From 8a7fc8e280e31fd8c277adc4f74cc26c341a71b4 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 12 Sep 2017 12:40:27 -0400 +Subject: [PATCH] Prevent uninitialized read in error path of XDR contexts + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #211 +(cherry picked from commit 8ba0f42f06bc7d0ed68cb2eb3ef2794fc860ac2d) +--- + proxy/src/client/gpm_common.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index c65c69d..d0f99d6 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -656,8 +656,8 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) + { + struct gpm_ctx *gpmctx; + gp_rpc_msg msg; +- XDR xdr_call_ctx; +- XDR xdr_reply_ctx; ++ XDR xdr_call_ctx = {0}; ++ XDR xdr_reply_ctx = {0}; + char *send_buffer = NULL; + char *recv_buffer = NULL; + uint32_t send_length; diff --git a/SOURCES/Properly-initialize-ccaches-before-storing-into-them.patch b/SOURCES/Properly-initialize-ccaches-before-storing-into-them.patch new file mode 100644 index 0000000..617c6e2 --- /dev/null +++ b/SOURCES/Properly-initialize-ccaches-before-storing-into-them.patch @@ -0,0 +1,38 @@ +From 2d91093925c8546d68f9314546353226b4f41569 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 5 Dec 2017 13:14:29 -0500 +Subject: [PATCH] Properly initialize ccaches before storing into them + +krb5_cc_new_unique() doesn't initialize ccaches, which results in the +krb5 libraries being aware of their presence within the collection but +being unable to manipulate them. + +This is transparent to most gssproxy consumers because we just +re-fetch the ccache on error. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #223 +(cherry picked from commit be7df45b6a56631033de387d28a2c06b7658c36a) +--- + proxy/src/mechglue/gpp_creds.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c +index 187ada7..f8ab320 100644 +--- a/proxy/src/mechglue/gpp_creds.c ++++ b/proxy/src/mechglue/gpp_creds.c +@@ -247,6 +247,13 @@ uint32_t gpp_store_remote_creds(uint32_t *min, bool store_as_default_cred, + + ret = krb5_cc_new_unique(ctx, cc_type, NULL, &ccache); + free(cc_type); ++ if (ret) ++ goto done; ++ ++ /* krb5_cc_new_unique() doesn't initialize, and we need to initialize ++ * before storing into the ccache. Note that this will only clobber ++ * the ccache handle, not the whole collection. */ ++ ret = krb5_cc_initialize(ctx, ccache, cred.client); + } + if (ret) + goto done; diff --git a/SOURCES/Properly-locate-credentials-in-collection-caches-in-.patch b/SOURCES/Properly-locate-credentials-in-collection-caches-in-.patch new file mode 100644 index 0000000..ff32fb0 --- /dev/null +++ b/SOURCES/Properly-locate-credentials-in-collection-caches-in-.patch @@ -0,0 +1,145 @@ +From 5fa4e2d5d484df17ebd9a585a6dfdf4522320426 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Mon, 20 Nov 2017 14:09:04 -0500 +Subject: [PATCH] Properly locate credentials in collection caches in mechglue + +Previously, we would just put the credentials in the default cache for +a collection type, which lead to some mysterious failures. + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #221 +(cherry picked from commit 670240a6cd4d5e2ecf13e481621098693cdbaa89) +--- + proxy/src/mechglue/gpp_creds.c | 77 ++++++++++++++++++++++++--------- + proxy/src/mechglue/gss_plugin.h | 2 +- + 2 files changed, 57 insertions(+), 22 deletions(-) + +diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c +index 3ebd726..187ada7 100644 +--- a/proxy/src/mechglue/gpp_creds.c ++++ b/proxy/src/mechglue/gpp_creds.c +@@ -170,7 +170,16 @@ static krb5_error_code gpp_construct_cred(gssx_cred *creds, krb5_context ctx, + return 0; + } + +-uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, ++/* Store creds from remote in a local ccache, updating where possible. ++ * ++ * If store_as_default_cred is true, the cred is made default for its ++ * collection, if there is one. Note that if the ccache is not of a ++ * collection type, the creds will overwrite the ccache. ++ * ++ * If no "ccache" entry is specified in cred_store, the default ccache for a ++ * new context will be used. ++ */ ++uint32_t gpp_store_remote_creds(uint32_t *min, bool store_as_default_cred, + gss_const_key_value_set_t cred_store, + gssx_cred *creds) + { +@@ -179,7 +188,7 @@ uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, + krb5_creds cred; + krb5_error_code ret; + char cred_name[creds->desired_name.display_name.octet_string_len + 1]; +- const char *cc_type; ++ const char *cc_name; + + *min = 0; + +@@ -191,38 +200,64 @@ uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, + goto done; + } + +- if (cred_store) { +- for (unsigned i = 0; i < cred_store->count; i++) { +- if (strcmp(cred_store->elements[i].key, "ccache") == 0) { +- ret = krb5_cc_resolve(ctx, cred_store->elements[i].value, +- &ccache); +- if (ret) goto done; +- break; +- } ++ for (unsigned i = 0; cred_store && i < cred_store->count; i++) { ++ if (strcmp(cred_store->elements[i].key, "ccache") == 0) { ++ /* krb5 creates new ccaches based off the default name. */ ++ ret = krb5_cc_set_default_name(ctx, ++ cred_store->elements[i].value); ++ if (ret) ++ goto done; ++ ++ break; + } + } +- if (!ccache) { +- if (!default_creds) { +- ret = ENOMEDIUM; +- goto done; +- } +- ret = krb5_cc_default(ctx, &ccache); +- if (ret) goto done; +- } + +- cc_type = krb5_cc_get_type(ctx, ccache); +- if (strcmp(cc_type, "FILE") == 0) { ++ cc_name = krb5_cc_default_name(ctx); ++ if (strncmp(cc_name, "FILE:", 5) == 0 || !strchr(cc_name, ':')) { + /* FILE ccaches don't handle updates properly: if they have the same + * principal name, they are blackholed. We either have to change the + * name (at which point the file grows forever) or flash the cache on + * every update. */ ++ ret = krb5_cc_default(ctx, &ccache); ++ if (ret) ++ goto done; ++ + ret = krb5_cc_initialize(ctx, ccache, cred.client); +- if (ret != 0) { ++ if (ret != 0) ++ goto done; ++ ++ ret = krb5_cc_store_cred(ctx, ccache, &cred); ++ goto done; ++ } ++ ++ ret = krb5_cc_cache_match(ctx, cred.client, &ccache); ++ if (ret == KRB5_CC_NOTFOUND) { ++ /* A new ccache within the collection whose name is based off the ++ * default_name for the context. krb5_cc_new_unique only accepts the ++ * leading component of a name as a type. */ ++ char *cc_type; ++ const char *p; ++ ++ p = strchr(cc_name, ':'); /* can't be FILE here */ ++ cc_type = strndup(cc_name, p - cc_name); ++ if (!cc_type) { ++ ret = ENOMEM; + goto done; + } ++ ++ ret = krb5_cc_new_unique(ctx, cc_type, NULL, &ccache); ++ free(cc_type); + } ++ if (ret) ++ goto done; + + ret = krb5_cc_store_cred(ctx, ccache, &cred); ++ if (ret) ++ goto done; ++ ++ if (store_as_default_cred) { ++ ret = krb5_cc_switch(ctx, ccache); ++ } + + done: + if (ctx) { +diff --git a/proxy/src/mechglue/gss_plugin.h b/proxy/src/mechglue/gss_plugin.h +index 333d63c..c0e8870 100644 +--- a/proxy/src/mechglue/gss_plugin.h ++++ b/proxy/src/mechglue/gss_plugin.h +@@ -76,7 +76,7 @@ uint32_t gpp_cred_handle_init(uint32_t *min, bool defcred, const char *ccache, + struct gpp_cred_handle **out_handle); + uint32_t gpp_cred_handle_free(uint32_t *min, struct gpp_cred_handle *handle); + bool gpp_creds_are_equal(gssx_cred *a, gssx_cred *b); +-uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, ++uint32_t gpp_store_remote_creds(uint32_t *min, bool store_as_default_cred, + gss_const_key_value_set_t cred_store, + gssx_cred *creds); + diff --git a/SOURCES/Properly-renew-expired-credentials.patch b/SOURCES/Properly-renew-expired-credentials.patch new file mode 100644 index 0000000..a4b3005 --- /dev/null +++ b/SOURCES/Properly-renew-expired-credentials.patch @@ -0,0 +1,75 @@ +From fc748ba83eb29f10fd44b6572b04709fa27dc587 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Mon, 13 Mar 2017 08:06:12 -0400 +Subject: [PATCH] Properly renew expired credentials + +When a caller imports expired credentials, we aim to actually renew them +if we can. However due to incorrect checks and not clearing of the +ret_maj variable after checks we end up returning an error instead. + +Also fix mechglue to also save and properly report the first call errors +when both remote and local fail. + +Resolves: #170 + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +(cherry picked from commit dc462321226f59ceaab0d3db47446a694a8ecba2) +--- + proxy/src/gp_creds.c | 14 +++++++++----- + proxy/src/mechglue/gpp_acquire_cred.c | 5 +++++ + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c +index 5d84904..171a724 100644 +--- a/proxy/src/gp_creds.c ++++ b/proxy/src/gp_creds.c +@@ -629,8 +629,12 @@ uint32_t gp_add_krb5_creds(uint32_t *min, + ret_maj = gp_check_cred(&ret_min, in_cred, desired_name, cred_usage); + if (ret_maj == GSS_S_COMPLETE) { + return GSS_S_COMPLETE; +- } else if (ret_maj != GSS_S_CREDENTIALS_EXPIRED && +- ret_maj != GSS_S_NO_CRED) { ++ } else if (ret_maj == GSS_S_CREDENTIALS_EXPIRED || ++ ret_maj == GSS_S_NO_CRED) { ++ /* continue and try to obtain new creds */ ++ ret_maj = 0; ++ ret_min = 0; ++ } else { + *min = ret_min; + return GSS_S_CRED_UNAVAIL; + } +@@ -639,14 +643,14 @@ uint32_t gp_add_krb5_creds(uint32_t *min, + if (acquire_type == ACQ_NORMAL) { + ret_min = gp_get_cred_environment(gpcall, desired_name, &req_name, + &cred_usage, &cred_store); ++ if (ret_min) { ++ ret_maj = GSS_S_CRED_UNAVAIL; ++ } + } else if (desired_name) { + ret_maj = gp_conv_gssx_to_name(&ret_min, desired_name, &req_name); + } + if (ret_maj) { + goto done; +- } else if (ret_min) { +- ret_maj = GSS_S_CRED_UNAVAIL; +- goto done; + } + + if (!try_impersonate(gpcall->service, cred_usage, acquire_type)) { +diff --git a/proxy/src/mechglue/gpp_acquire_cred.c b/proxy/src/mechglue/gpp_acquire_cred.c +index d876699..514fdd1 100644 +--- a/proxy/src/mechglue/gpp_acquire_cred.c ++++ b/proxy/src/mechglue/gpp_acquire_cred.c +@@ -186,6 +186,11 @@ OM_uint32 gssi_acquire_cred_from(OM_uint32 *minor_status, + } + + if (behavior == GPP_REMOTE_FIRST) { ++ if (maj != GSS_S_COMPLETE) { ++ /* save errors */ ++ tmaj = maj; ++ tmin = min; ++ } + /* So remote failed, but we can fallback to local, try that */ + maj = acquire_local(&min, NULL, name, + time_req, desired_mechs, cred_usage, cred_store, diff --git a/SOURCES/Remove-gpm_release_ctx-to-fix-double-unlock.patch b/SOURCES/Remove-gpm_release_ctx-to-fix-double-unlock.patch new file mode 100644 index 0000000..cce478c --- /dev/null +++ b/SOURCES/Remove-gpm_release_ctx-to-fix-double-unlock.patch @@ -0,0 +1,37 @@ +From 9e2bdfeee30331254d21eaf9e9c000fb9e642fe9 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Thu, 23 Mar 2017 13:42:55 -0400 +Subject: [PATCH] Remove gpm_release_ctx() to fix double unlock + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #173 +(cherry picked from commit b50a863b20649b80cc44c88aa325c6c3220af61b) +--- + proxy/src/client/gpm_common.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 8c96986..69f4741 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -312,11 +312,6 @@ static struct gpm_ctx *gpm_get_ctx(void) + return &gpm_global_ctx; + } + +-static void gpm_release_ctx(struct gpm_ctx *gpmctx) +-{ +- gpm_release_sock(gpmctx); +-} +- + OM_uint32 gpm_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer) + { +@@ -503,7 +498,6 @@ done: + xdr_free((xdrproc_t)xdr_gp_rpc_msg, (char *)&msg); + xdr_destroy(&xdr_call_ctx); + xdr_destroy(&xdr_reply_ctx); +- gpm_release_ctx(gpmctx); + return ret; + } + diff --git a/SOURCES/Separate-cred-and-ccache-manipulation-in-gpp_store_r.patch b/SOURCES/Separate-cred-and-ccache-manipulation-in-gpp_store_r.patch new file mode 100644 index 0000000..dbc8dd4 --- /dev/null +++ b/SOURCES/Separate-cred-and-ccache-manipulation-in-gpp_store_r.patch @@ -0,0 +1,107 @@ +From 1451b65fec69ff35e029b4770dcb4927ba57060a Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Fri, 17 Nov 2017 13:53:37 -0500 +Subject: [PATCH] Separate cred and ccache manipulation in + gpp_store_remote_creds() + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +(cherry picked from commit 221b553bfb4082085d05b40da9a04c1f7e4af533) +--- + proxy/src/mechglue/gpp_creds.c | 62 +++++++++++++++++++++------------- + 1 file changed, 39 insertions(+), 23 deletions(-) + +diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c +index 6bdff45..3ebd726 100644 +--- a/proxy/src/mechglue/gpp_creds.c ++++ b/proxy/src/mechglue/gpp_creds.c +@@ -136,6 +136,40 @@ bool gpp_creds_are_equal(gssx_cred *a, gssx_cred *b) + return true; + } + ++static krb5_error_code gpp_construct_cred(gssx_cred *creds, krb5_context ctx, ++ krb5_creds *cred, char *cred_name) ++{ ++ XDR xdrctx; ++ bool xdrok; ++ krb5_error_code ret = 0; ++ ++ memset(cred, 0, sizeof(*cred)); ++ ++ memcpy(cred_name, creds->desired_name.display_name.octet_string_val, ++ creds->desired_name.display_name.octet_string_len); ++ cred_name[creds->desired_name.display_name.octet_string_len] = '\0'; ++ ++ ret = krb5_parse_name(ctx, cred_name, &cred->client); ++ if (ret) { ++ return ret; ++ } ++ ++ ret = krb5_parse_name(ctx, GPKRB_SRV_NAME, &cred->server); ++ if (ret) { ++ return ret; ++ } ++ ++ cred->ticket.data = malloc(GPKRB_MAX_CRED_SIZE); ++ xdrmem_create(&xdrctx, cred->ticket.data, GPKRB_MAX_CRED_SIZE, ++ XDR_ENCODE); ++ xdrok = xdr_gssx_cred(&xdrctx, creds); ++ if (!xdrok) { ++ return ENOSPC; ++ } ++ cred->ticket.length = xdr_getpos(&xdrctx); ++ return 0; ++} ++ + uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, + gss_const_key_value_set_t cred_store, + gssx_cred *creds) +@@ -145,17 +179,18 @@ uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, + krb5_creds cred; + krb5_error_code ret; + char cred_name[creds->desired_name.display_name.octet_string_len + 1]; +- XDR xdrctx; +- bool xdrok; + const char *cc_type; + + *min = 0; + +- memset(&cred, 0, sizeof(cred)); +- + ret = krb5_init_context(&ctx); + if (ret) return ret; + ++ ret = gpp_construct_cred(creds, ctx, &cred, cred_name); ++ if (ret) { ++ goto done; ++ } ++ + if (cred_store) { + for (unsigned i = 0; i < cred_store->count; i++) { + if (strcmp(cred_store->elements[i].key, "ccache") == 0) { +@@ -175,25 +210,6 @@ uint32_t gpp_store_remote_creds(uint32_t *min, bool default_creds, + if (ret) goto done; + } + +- memcpy(cred_name, creds->desired_name.display_name.octet_string_val, +- creds->desired_name.display_name.octet_string_len); +- cred_name[creds->desired_name.display_name.octet_string_len] = '\0'; +- +- ret = krb5_parse_name(ctx, cred_name, &cred.client); +- if (ret) goto done; +- +- ret = krb5_parse_name(ctx, GPKRB_SRV_NAME, &cred.server); +- if (ret) goto done; +- +- cred.ticket.data = malloc(GPKRB_MAX_CRED_SIZE); +- xdrmem_create(&xdrctx, cred.ticket.data, GPKRB_MAX_CRED_SIZE, XDR_ENCODE); +- xdrok = xdr_gssx_cred(&xdrctx, creds); +- if (!xdrok) { +- ret = ENOSPC; +- goto done; +- } +- cred.ticket.length = xdr_getpos(&xdrctx); +- + cc_type = krb5_cc_get_type(ctx, ccache); + if (strcmp(cc_type, "FILE") == 0) { + /* FILE ccaches don't handle updates properly: if they have the same diff --git a/SOURCES/Simplify-setting-NONBLOCK-on-socket.patch b/SOURCES/Simplify-setting-NONBLOCK-on-socket.patch new file mode 100644 index 0000000..1762d69 --- /dev/null +++ b/SOURCES/Simplify-setting-NONBLOCK-on-socket.patch @@ -0,0 +1,53 @@ +From 6d12deeb19cc2e231463427db27f8755649450d1 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Thu, 14 Sep 2017 10:57:12 -0500 +Subject: [PATCH] Simplify setting NONBLOCK on socket + +Signed-off-by: Alexander Scheel +Reviewed-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #213 +[rharwood@redhat.com: fixup commit message] +(cherry picked from commit ec808ee6a5e6746ed35acc865f253425701be352) +--- + proxy/src/client/gpm_common.c | 15 +-------------- + 1 file changed, 1 insertion(+), 14 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index d0f99d6..7d1158e 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -80,7 +80,6 @@ static int gpm_open_socket(struct gpm_ctx *gpmctx) + struct sockaddr_un addr = {0}; + char name[PATH_MAX]; + int ret; +- unsigned flags; + int fd = -1; + + ret = get_pipe_name(name); +@@ -92,24 +91,12 @@ static int gpm_open_socket(struct gpm_ctx *gpmctx) + strncpy(addr.sun_path, name, sizeof(addr.sun_path)-1); + addr.sun_path[sizeof(addr.sun_path)-1] = '\0'; + +- fd = socket(AF_UNIX, SOCK_STREAM, 0); ++ fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (fd == -1) { + ret = errno; + goto done; + } + +- ret = fcntl(fd, F_GETFD, &flags); +- if (ret != 0) { +- ret = errno; +- goto done; +- } +- +- ret = fcntl(fd, F_SETFD, flags | O_NONBLOCK); +- if (ret != 0) { +- ret = errno; +- goto done; +- } +- + ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret == -1) { + ret = errno; diff --git a/SOURCES/Tolerate-NULL-pointers-in-gp_same.patch b/SOURCES/Tolerate-NULL-pointers-in-gp_same.patch new file mode 100644 index 0000000..9f2a147 --- /dev/null +++ b/SOURCES/Tolerate-NULL-pointers-in-gp_same.patch @@ -0,0 +1,31 @@ +From 05a2677920f0240ea302e67d699546665687dd14 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 13 Jun 2017 14:22:44 -0400 +Subject: [PATCH] Tolerate NULL pointers in gp_same + +Fixes potential NULL derefs of program names + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #195 +(cherry picked from commit afe4c2fe6f7f939df914959dda11131bd80ccec6) +--- + proxy/src/gp_util.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/proxy/src/gp_util.c b/proxy/src/gp_util.c +index f158b84..5442992 100644 +--- a/proxy/src/gp_util.c ++++ b/proxy/src/gp_util.c +@@ -12,10 +12,9 @@ + + bool gp_same(const char *a, const char *b) + { +- if ((a == b) || strcmp(a, b) == 0) { ++ if (a == b || (a && b && strcmp(a, b) == 0)) { + return true; + } +- + return false; + } + diff --git a/SOURCES/Turn-on-Wextra.patch b/SOURCES/Turn-on-Wextra.patch new file mode 100644 index 0000000..bfec8e4 --- /dev/null +++ b/SOURCES/Turn-on-Wextra.patch @@ -0,0 +1,26 @@ +From a50ea0aa3dfd39ab4a3c39dde35c12fc51fe40d5 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 15 Mar 2017 13:28:26 -0400 +Subject: [PATCH] Turn on -Wextra + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #173 +(cherry picked from commit 85bc3d794efa52aba4c32f6109e7e7741521ec5f) +--- + proxy/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/proxy/Makefile.am b/proxy/Makefile.am +index e1fbac1..5cd2255 100644 +--- a/proxy/Makefile.am ++++ b/proxy/Makefile.am +@@ -44,7 +44,7 @@ AM_CFLAGS += -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith \ + -Wcast-qual -Wcast-align -Wwrite-strings \ + -fstrict-aliasing -Wstrict-aliasing -Werror=strict-aliasing \ + -Werror-implicit-function-declaration \ +- -Werror=format-security ++ -Werror=format-security -Wextra + if BUILD_HARDENING + AM_CPPFLAGS += -D_FORTIFY_SOURCE=2 -Wdate-time + AM_CFLAGS += -fPIE -fstack-protector-strong diff --git a/SOURCES/Update-docs-to-reflect-actual-behavior-of-krb5_princ.patch b/SOURCES/Update-docs-to-reflect-actual-behavior-of-krb5_princ.patch new file mode 100644 index 0000000..a94074d --- /dev/null +++ b/SOURCES/Update-docs-to-reflect-actual-behavior-of-krb5_princ.patch @@ -0,0 +1,31 @@ +From c97c8e8b4a1db36a2658d1f054a33e830dbcfa7c Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Tue, 2 Oct 2018 14:52:18 -0400 +Subject: [PATCH] Update docs to reflect actual behavior of krb5_principal + +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +Merges: #235 +(cherry picked from commit ffb05b5eeb9aa818690e5eece5ab6d84cf8fc24b) +--- + proxy/man/gssproxy.conf.5.xml | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/proxy/man/gssproxy.conf.5.xml b/proxy/man/gssproxy.conf.5.xml +index abb6745..7874c6e 100644 +--- a/proxy/man/gssproxy.conf.5.xml ++++ b/proxy/man/gssproxy.conf.5.xml +@@ -307,7 +307,12 @@ + + krb5_principal (string) + +- The krb5 principal to be used by this service. ++ ++ The krb5 principal to be used preferred for this ++ service, if one isn't requested by the ++ application. Note that this does not enforce use ++ of this specific name; it only sets a default. ++ + Default: krb5_principal = + + diff --git a/SOURCES/Update-systemd-file.patch b/SOURCES/Update-systemd-file.patch new file mode 100644 index 0000000..6b2345b --- /dev/null +++ b/SOURCES/Update-systemd-file.patch @@ -0,0 +1,35 @@ +From 90d7a614b3eb451f0067dfacf0f0b6f41eb00180 Mon Sep 17 00:00:00 2001 +From: Robbie Harwood +Date: Wed, 26 Apr 2017 21:02:47 -0400 +Subject: [PATCH] Update systemd file + +Add `reload` capability, and remove dependency on nfs-utils. + +Closes: #127 +Signed-off-by: Robbie Harwood +Reviewed-by: Simo Sorce +(cherry picked from commit c7e8b4066575508a91a38bb6a44694c8a171f0c5) +--- + proxy/systemd/gssproxy.service.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/proxy/systemd/gssproxy.service.in b/proxy/systemd/gssproxy.service.in +index dae39ee..f50f526 100644 +--- a/proxy/systemd/gssproxy.service.in ++++ b/proxy/systemd/gssproxy.service.in +@@ -3,7 +3,6 @@ Description=GSSAPI Proxy Daemon + # GSSPROXY will not be started until syslog is + After=syslog.target + Before=nfs-secure.service nfs-secure-server.service +-Requires=proc-fs-nfsd.mount + + [Service] + Environment=KRB5RCACHEDIR=/var/lib/gssproxy/rcache +@@ -12,6 +11,7 @@ ExecStart=@sbindir@/gssproxy -D + # consult systemd.service(5) for more details + Type=forking + PIDFile=@localstatedir@/run/gssproxy.pid ++ExecReload=/bin/kill -HUP $MAINPID + + [Install] + WantedBy=multi-user.target diff --git a/SOURCES/Use-pthread-keys-for-thread-local-storage.patch b/SOURCES/Use-pthread-keys-for-thread-local-storage.patch new file mode 100644 index 0000000..ba59036 --- /dev/null +++ b/SOURCES/Use-pthread-keys-for-thread-local-storage.patch @@ -0,0 +1,150 @@ +From 17dbcfaff5e7d917eb48579dc8e5f60c95a30981 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Thu, 20 Sep 2018 17:37:53 -0400 +Subject: [PATCH] Use pthread keys for thread local storage + +This interface is slower but also more portable, and more importantly +it provides a way to specify destructor that is called when a thread +is canceled so we stop leaking memory. + +Signed-off-by: Simo Sorce +Reviewed-by: Robbie Harwood +Merges: #233 +(cherry picked from commit 0faccc1441bc7a6b3e8bd806f22c8a961e5f586e) +(cherry picked from commit 89dc0ee157caa4617d32fd72287849296d7fe26d) +--- + proxy/src/client/gpm_common.c | 2 + + proxy/src/client/gpm_display_status.c | 57 ++++++++++++++++++--------- + proxy/src/client/gssapi_gpm.h | 1 + + 3 files changed, 42 insertions(+), 18 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 0d314fa..b482efb 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -55,6 +55,8 @@ static void gpm_init_once(void) + gpm_global_ctx.next_xid = rand_r(&seedp); + + pthread_mutexattr_destroy(&attr); ++ ++ gpm_display_status_init_once(); + } + + static int get_pipe_name(char *name) +diff --git a/proxy/src/client/gpm_display_status.c b/proxy/src/client/gpm_display_status.c +index bbb546f..e3aa4ea 100644 +--- a/proxy/src/client/gpm_display_status.c ++++ b/proxy/src/client/gpm_display_status.c +@@ -1,27 +1,47 @@ + /* Copyright (C) 2011 the GSS-PROXY contributors, see COPYING for license */ + + #include "gssapi_gpm.h" ++#include + +-__thread gssx_status *tls_last_status = NULL; ++static pthread_key_t gpm_last_status; + +-/* Thread local storage for return status. +- * FIXME: it's not the most portable construct, so may need fixing in future */ ++static void gpm_destroy_last_status(void *arg) ++{ ++ gssx_status *status = (gssx_status *)arg; ++ xdr_free((xdrproc_t)xdr_gssx_status, (char *)status); ++ free(status); ++} ++ ++void gpm_display_status_init_once(void) ++{ ++ (void)pthread_key_create(&gpm_last_status, gpm_destroy_last_status); ++} ++ ++/* Portable thread local storage for return status. */ + void gpm_save_status(gssx_status *status) + { ++ gssx_status *last_status; + int ret; + +- if (tls_last_status) { +- xdr_free((xdrproc_t)xdr_gssx_status, (char *)tls_last_status); +- free(tls_last_status); ++ last_status = (gssx_status *)pthread_getspecific(gpm_last_status); ++ if (last_status != NULL) { ++ /* store NULL first so we do not risk a double free if we are ++ * racing on a pthread_cancel */ ++ pthread_setspecific(gpm_last_status, NULL); ++ gpm_destroy_last_status(last_status); + } + +- ret = gp_copy_gssx_status_alloc(status, &tls_last_status); +- if (ret) { +- /* make sure tls_last_status is zeored on error */ +- tls_last_status = NULL; ++ ret = gp_copy_gssx_status_alloc(status, &last_status); ++ if (ret == 0) { ++ pthread_setspecific(gpm_last_status, last_status); + } + } + ++gssx_status *gpm_get_saved_status(void) ++{ ++ return (gssx_status *)pthread_getspecific(gpm_last_status); ++} ++ + /* This funciton is used to record internal mech errors that are + * generated by the proxy client code */ + void gpm_save_internal_status(uint32_t err, char *err_str) +@@ -47,15 +67,16 @@ OM_uint32 gpm_display_status(OM_uint32 *minor_status, + OM_uint32 *message_context, + gss_buffer_t status_string) + { ++ gssx_status *last_status = gpm_get_saved_status(); + utf8string tmp; + int ret; + + switch(status_type) { + case GSS_C_GSS_CODE: +- if (tls_last_status && +- tls_last_status->major_status == status_value && +- tls_last_status->major_status_string.utf8string_len) { +- ret = gp_copy_utf8string(&tls_last_status->major_status_string, ++ if (last_status && ++ last_status->major_status == status_value && ++ last_status->major_status_string.utf8string_len) { ++ ret = gp_copy_utf8string(&last_status->major_status_string, + &tmp); + if (ret) { + *minor_status = ret; +@@ -70,9 +91,9 @@ OM_uint32 gpm_display_status(OM_uint32 *minor_status, + return GSS_S_UNAVAILABLE; + } + case GSS_C_MECH_CODE: +- if (tls_last_status && +- tls_last_status->minor_status == status_value && +- tls_last_status->minor_status_string.utf8string_len) { ++ if (last_status && ++ last_status->minor_status == status_value && ++ last_status->minor_status_string.utf8string_len) { + + if (*message_context) { + /* we do not support multiple messages for now */ +@@ -80,7 +101,7 @@ OM_uint32 gpm_display_status(OM_uint32 *minor_status, + return GSS_S_FAILURE; + } + +- ret = gp_copy_utf8string(&tls_last_status->minor_status_string, ++ ret = gp_copy_utf8string(&last_status->minor_status_string, + &tmp); + if (ret) { + *minor_status = ret; +diff --git a/proxy/src/client/gssapi_gpm.h b/proxy/src/client/gssapi_gpm.h +index 22beecf..61124e0 100644 +--- a/proxy/src/client/gssapi_gpm.h ++++ b/proxy/src/client/gssapi_gpm.h +@@ -23,6 +23,7 @@ OM_uint32 gpm_release_name(OM_uint32 *minor_status, + OM_uint32 gpm_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer); + ++void gpm_display_status_init_once(void); + void gpm_save_status(gssx_status *status); + void gpm_save_internal_status(uint32_t err, char *err_str); + diff --git a/SOURCES/client-Switch-to-non-blocking-sockets.patch b/SOURCES/client-Switch-to-non-blocking-sockets.patch new file mode 100644 index 0000000..2d0b34b --- /dev/null +++ b/SOURCES/client-Switch-to-non-blocking-sockets.patch @@ -0,0 +1,485 @@ +From 1962e6128a4d86a7c54977577e1e4224cadbb5f7 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Wed, 2 Aug 2017 15:11:49 -0400 +Subject: [PATCH] [client] Switch to non-blocking sockets + +Switch the gssproxy client library to non-blocking sockets, allowing +for timeout and retry operations. The client will automatically retry +both send() and recv() operations three times on ETIMEDOUT. If the +combined send() and recv() hit the three time limit, ETIMEDOUT will be +exposed to the caller in the minor status. + +Signed-off-by: Alexander Scheel +Reviewed-by: Simo Sorce +[rharwood@redhat.com: commit message cleanups, rebased] +Reviewed-by: Robbie Harwood +(cherry picked from commit d035646c8feb0b78f0c157580ca02c46cd00dd7e) +--- + proxy/src/client/gpm_common.c | 317 +++++++++++++++++++++++++++++++--- + 1 file changed, 295 insertions(+), 22 deletions(-) + +diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c +index 2133618..dba23a6 100644 +--- a/proxy/src/client/gpm_common.c ++++ b/proxy/src/client/gpm_common.c +@@ -7,9 +7,15 @@ + #include + #include + #include ++#include ++#include ++#include + + #define FRAGMENT_BIT (1 << 31) + ++#define RESPONSE_TIMEOUT 15 ++#define MAX_TIMEOUT_RETRY 3 ++ + struct gpm_ctx { + pthread_mutex_t lock; + int fd; +@@ -20,6 +26,9 @@ struct gpm_ctx { + gid_t gid; + + int next_xid; ++ ++ int epollfd; ++ int timerfd; + }; + + /* a single global struct is not particularly efficient, +@@ -39,6 +48,8 @@ static void gpm_init_once(void) + pthread_mutex_init(&gpm_global_ctx.lock, &attr); + + gpm_global_ctx.fd = -1; ++ gpm_global_ctx.epollfd = -1; ++ gpm_global_ctx.timerfd = -1; + + seedp = time(NULL) + getpid() + pthread_self(); + gpm_global_ctx.next_xid = rand_r(&seedp); +@@ -69,6 +80,7 @@ static int gpm_open_socket(struct gpm_ctx *gpmctx) + struct sockaddr_un addr = {0}; + char name[PATH_MAX]; + int ret; ++ unsigned flags; + int fd = -1; + + ret = get_pipe_name(name); +@@ -86,6 +98,18 @@ static int gpm_open_socket(struct gpm_ctx *gpmctx) + goto done; + } + ++ ret = fcntl(fd, F_GETFD, &flags); ++ if (ret != 0) { ++ ret = errno; ++ goto done; ++ } ++ ++ ret = fcntl(fd, F_SETFD, flags | O_NONBLOCK); ++ if (ret != 0) { ++ ret = errno; ++ goto done; ++ } ++ + ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret == -1) { + ret = errno; +@@ -163,6 +187,158 @@ static int gpm_release_sock(struct gpm_ctx *gpmctx) + return pthread_mutex_unlock(&gpmctx->lock); + } + ++static void gpm_timer_close(struct gpm_ctx *gpmctx) { ++ if (gpmctx->timerfd < 0) { ++ return; ++ } ++ ++ close(gpmctx->timerfd); ++ gpmctx->timerfd = -1; ++} ++ ++static int gpm_timer_setup(struct gpm_ctx *gpmctx, int timeout_seconds) { ++ int ret; ++ struct itimerspec its; ++ ++ if (gpmctx->timerfd >= 0) { ++ gpm_timer_close(gpmctx); ++ } ++ ++ gpmctx->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); ++ if (gpmctx->timerfd < 0) { ++ return errno; ++ } ++ ++ its.it_interval.tv_sec = timeout_seconds; ++ its.it_interval.tv_nsec = 0; ++ its.it_value.tv_sec = timeout_seconds; ++ its.it_value.tv_nsec = 0; ++ ++ ret = timerfd_settime(gpmctx->timerfd, 0, &its, NULL); ++ if (ret) { ++ ret = errno; ++ gpm_timer_close(gpmctx); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void gpm_epoll_close(struct gpm_ctx *gpmctx) { ++ if (gpmctx->epollfd < 0) { ++ return; ++ } ++ ++ close(gpmctx->epollfd); ++ gpmctx->epollfd = -1; ++} ++ ++static int gpm_epoll_setup(struct gpm_ctx *gpmctx) { ++ struct epoll_event ev; ++ int ret; ++ ++ if (gpmctx->epollfd >= 0) { ++ gpm_epoll_close(gpmctx); ++ } ++ ++ gpmctx->epollfd = epoll_create1(EPOLL_CLOEXEC); ++ if (gpmctx->epollfd == -1) { ++ return errno; ++ } ++ ++ /* Add timer */ ++ ev.events = EPOLLIN; ++ ev.data.fd = gpmctx->timerfd; ++ ret = epoll_ctl(gpmctx->epollfd, EPOLL_CTL_ADD, gpmctx->timerfd, &ev); ++ if (ret == -1) { ++ ret = errno; ++ gpm_epoll_close(gpmctx); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) { ++ int ret; ++ int epoll_ret; ++ struct epoll_event ev; ++ struct epoll_event events[2]; ++ uint64_t timer_read; ++ ++ if (gpmctx->epollfd < 0) { ++ ret = gpm_epoll_setup(gpmctx); ++ if (ret) ++ return ret; ++ } ++ ++ ev.events = event_flags; ++ ev.data.fd = gpmctx->fd; ++ epoll_ret = epoll_ctl(gpmctx->epollfd, EPOLL_CTL_ADD, gpmctx->fd, &ev); ++ if (epoll_ret == -1) { ++ ret = errno; ++ gpm_epoll_close(gpmctx); ++ return ret; ++ } ++ ++ do { ++ epoll_ret = epoll_wait(gpmctx->epollfd, events, 2, -1); ++ } while (epoll_ret < 0 && errno == EINTR); ++ ++ if (epoll_ret < 0) { ++ /* Error while waiting that isn't EINTR */ ++ ret = errno; ++ gpm_epoll_close(gpmctx); ++ } else if (epoll_ret == 0) { ++ /* Shouldn't happen as timeout == -1; treat it like a timeout ++ * occurred. */ ++ ret = ETIMEDOUT; ++ gpm_epoll_close(gpmctx); ++ } else if (epoll_ret == 1 && events[0].data.fd == gpmctx->timerfd) { ++ /* Got an event which is only our timer */ ++ ret = read(gpmctx->timerfd, &timer_read, sizeof(uint64_t)); ++ if (ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { ++ /* In the case when reading from the timer failed, don't hide the ++ * timer error behind ETIMEDOUT such that it isn't retried */ ++ ret = errno; ++ } else { ++ /* If ret == 0, then we definitely timed out. Else, if ret == -1 ++ * and errno == EAGAIN or errno == EWOULDBLOCK, we're in a weird ++ * edge case where epoll thinks the timer can be read, but it ++ * is blocking more; treat it like a TIMEOUT and retry, as ++ * nothing around us would handle EAGAIN from timer and retry ++ * it. */ ++ ret = ETIMEDOUT; ++ } ++ gpm_epoll_close(gpmctx); ++ } else { ++ /* If ret == 2, then we ignore the timerfd; that way if the next ++ * operation cannot be performed immediately, we timeout and retry. ++ * If ret == 1 and data.fd == gpmctx->fd, return 0. */ ++ ret = 0; ++ } ++ ++ epoll_ret = epoll_ctl(gpmctx->epollfd, EPOLL_CTL_DEL, gpmctx->fd, NULL); ++ if (epoll_ret == -1) { ++ /* If we previously had an error, expose that error instead of ++ * clobbering it with errno; else if no error, then assume it is ++ * better to notify of the error deleting the event than it is ++ * to continue. */ ++ if (ret == 0) ++ ret = errno; ++ gpm_epoll_close(gpmctx); ++ } ++ ++ return ret; ++} ++ ++static int gpm_retry_socket(struct gpm_ctx *gpmctx) ++{ ++ gpm_epoll_close(gpmctx); ++ gpm_close_socket(gpmctx); ++ return gpm_open_socket(gpmctx); ++} ++ + /* must be called after the lock has been grabbed */ + static int gpm_send_buffer(struct gpm_ctx *gpmctx, + char *buffer, uint32_t length) +@@ -183,8 +359,13 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx, + retry = false; + do { + do { ++ ret = gpm_epoll_wait(gpmctx, EPOLLOUT); ++ if (ret != 0) { ++ goto done; ++ } ++ + ret = 0; +- wn = send(gpmctx->fd, &size, sizeof(uint32_t), MSG_NOSIGNAL); ++ wn = write(gpmctx->fd, &size, sizeof(uint32_t)); + if (wn == -1) { + ret = errno; + } +@@ -192,8 +373,7 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx, + if (wn != 4) { + /* reopen and retry once */ + if (retry == false) { +- gpm_close_socket(gpmctx); +- ret = gpm_open_socket(gpmctx); ++ ret = gpm_retry_socket(gpmctx); + if (ret == 0) { + retry = true; + continue; +@@ -208,9 +388,14 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx, + + pos = 0; + while (length > pos) { +- wn = send(gpmctx->fd, buffer + pos, length - pos, MSG_NOSIGNAL); ++ ret = gpm_epoll_wait(gpmctx, EPOLLOUT); ++ if (ret) { ++ goto done; ++ } ++ ++ wn = write(gpmctx->fd, buffer + pos, length - pos); + if (wn == -1) { +- if (errno == EINTR) { ++ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + continue; + } + ret = errno; +@@ -231,7 +416,7 @@ done: + + /* must be called after the lock has been grabbed */ + static int gpm_recv_buffer(struct gpm_ctx *gpmctx, +- char *buffer, uint32_t *length) ++ char **buffer, uint32_t *length) + { + uint32_t size; + ssize_t rn; +@@ -239,6 +424,11 @@ static int gpm_recv_buffer(struct gpm_ctx *gpmctx, + int ret; + + do { ++ ret = gpm_epoll_wait(gpmctx, EPOLLIN); ++ if (ret) { ++ goto done; ++ } ++ + ret = 0; + rn = read(gpmctx->fd, &size, sizeof(uint32_t)); + if (rn == -1) { +@@ -258,11 +448,22 @@ static int gpm_recv_buffer(struct gpm_ctx *gpmctx, + goto done; + } + ++ *buffer = malloc(*length); ++ if (*buffer == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ + pos = 0; + while (*length > pos) { +- rn = read(gpmctx->fd, buffer + pos, *length - pos); ++ ret = gpm_epoll_wait(gpmctx, EPOLLIN); ++ if (ret) { ++ goto done; ++ } ++ ++ rn = read(gpmctx->fd, *buffer + pos, *length - pos); + if (rn == -1) { +- if (errno == EINTR) { ++ if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + continue; + } + ret = errno; +@@ -281,6 +482,7 @@ done: + if (ret) { + /* on errors we can only close the fd and return */ + gpm_close_socket(gpmctx); ++ gpm_epoll_close(gpmctx); + } + return ret; + } +@@ -309,6 +511,63 @@ static struct gpm_ctx *gpm_get_ctx(void) + return &gpm_global_ctx; + } + ++static int gpm_send_recv_loop(struct gpm_ctx *gpmctx, char *send_buffer, ++ uint32_t send_length, char** recv_buffer, ++ uint32_t *recv_length) ++{ ++ int ret; ++ int retry_count; ++ ++ /* setup timer */ ++ ret = gpm_timer_setup(gpmctx, RESPONSE_TIMEOUT); ++ if (ret) ++ return ret; ++ ++ for (retry_count = 0; retry_count < MAX_TIMEOUT_RETRY; retry_count++) { ++ /* send to proxy */ ++ ret = gpm_send_buffer(gpmctx, send_buffer, send_length); ++ ++ if (ret == 0) { ++ /* No error, continue to recv */ ++ } else if (ret == ETIMEDOUT) { ++ /* Close and reopen socket before trying again */ ++ ret = gpm_retry_socket(gpmctx); ++ if (ret != 0) ++ return ret; ++ ret = ETIMEDOUT; ++ ++ /* RETRY entire send */ ++ continue; ++ } else { ++ /* Other error */ ++ return ret; ++ } ++ ++ /* receive answer */ ++ ret = gpm_recv_buffer(gpmctx, recv_buffer, recv_length); ++ if (ret == 0) { ++ /* No error */ ++ break; ++ } else if (ret == ETIMEDOUT) { ++ /* Close and reopen socket before trying again */ ++ ret = gpm_retry_socket(gpmctx); ++ ++ /* Free buffer and set it to NULL to prevent free(xdr_reply_ctx) */ ++ free(recv_buffer); ++ recv_buffer = NULL; ++ ++ if (ret != 0) ++ return ret; ++ ret = ETIMEDOUT; ++ } else { ++ /* Other error */ ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++ + OM_uint32 gpm_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer) + { +@@ -399,15 +658,20 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) + gp_rpc_msg msg; + XDR xdr_call_ctx; + XDR xdr_reply_ctx; +- char buffer[MAX_RPC_SIZE]; +- uint32_t length; ++ char *send_buffer = NULL; ++ char *recv_buffer = NULL; ++ uint32_t send_length; ++ uint32_t recv_length; + uint32_t xid; + bool xdrok; + bool sockgrab = false; + int ret; + +- xdrmem_create(&xdr_call_ctx, buffer, MAX_RPC_SIZE, XDR_ENCODE); +- xdrmem_create(&xdr_reply_ctx, buffer, MAX_RPC_SIZE, XDR_DECODE); ++ send_buffer = malloc(MAX_RPC_SIZE); ++ if (send_buffer == NULL) ++ return ENOMEM; ++ ++ xdrmem_create(&xdr_call_ctx, send_buffer, MAX_RPC_SIZE, XDR_ENCODE); + + memset(&msg, 0, sizeof(gp_rpc_msg)); + msg.header.type = GP_RPC_CALL; +@@ -450,22 +714,22 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) + goto done; + } + +- /* send to proxy */ +- ret = gpm_send_buffer(gpmctx, buffer, xdr_getpos(&xdr_call_ctx)); +- if (ret) { +- goto done; +- } ++ /* set send_length */ ++ send_length = xdr_getpos(&xdr_call_ctx); + +- /* receive answer */ +- ret = gpm_recv_buffer(gpmctx, buffer, &length); +- if (ret) { ++ /* Send request, receive response with timeout */ ++ ret = gpm_send_recv_loop(gpmctx, send_buffer, send_length, &recv_buffer, ++ &recv_length); ++ if (ret) + goto done; +- } + + /* release the lock */ + gpm_release_sock(gpmctx); + sockgrab = false; + ++ /* Create the reply context */ ++ xdrmem_create(&xdr_reply_ctx, recv_buffer, recv_length, XDR_DECODE); ++ + /* decode header */ + memset(&msg, 0, sizeof(gp_rpc_msg)); + xdrok = xdr_gp_rpc_msg(&xdr_reply_ctx, &msg); +@@ -489,12 +753,21 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) + } + + done: ++ gpm_timer_close(gpmctx); ++ gpm_epoll_close(gpmctx); ++ + if (sockgrab) { + gpm_release_sock(gpmctx); + } + xdr_free((xdrproc_t)xdr_gp_rpc_msg, (char *)&msg); + xdr_destroy(&xdr_call_ctx); +- xdr_destroy(&xdr_reply_ctx); ++ ++ if (recv_buffer != NULL) ++ xdr_destroy(&xdr_reply_ctx); ++ ++ free(send_buffer); ++ free(recv_buffer); ++ + return ret; + } + diff --git a/SOURCES/rwtab b/SOURCES/rwtab new file mode 100644 index 0000000..f4cdfb5 --- /dev/null +++ b/SOURCES/rwtab @@ -0,0 +1 @@ +dirs /var/lib/gssproxy diff --git a/SOURCES/server-Add-detailed-request-logging.patch b/SOURCES/server-Add-detailed-request-logging.patch new file mode 100644 index 0000000..778c755 --- /dev/null +++ b/SOURCES/server-Add-detailed-request-logging.patch @@ -0,0 +1,123 @@ +From f413cc257c6c1e60090c72163152ae7fd2180c41 Mon Sep 17 00:00:00 2001 +From: Alexander Scheel +Date: Fri, 4 Aug 2017 16:09:20 -0400 +Subject: [PATCH] [server] Add detailed request logging + +Add request logging to track requests through gssproxy. Requests are +logged as they are read, processed, handled, and replies sent. These +are identified by buffer memory address and size. + +Signed-off-by: Alexander Scheel +Reviewed-by: Simo Sorce +[rharwood@redhat.com: commit message cleanups, rebase] +Reviewed-by: Robbie Harwood +Merges: #205 +(cherry picked from commit 4097dafad3f276c3cf7b1255fe0540e16d59ae03) +--- + proxy/src/gp_rpc_process.c | 6 ++++++ + proxy/src/gp_socket.c | 12 ++++++++++++ + proxy/src/gp_workers.c | 5 +++++ + 3 files changed, 23 insertions(+) + +diff --git a/proxy/src/gp_rpc_process.c b/proxy/src/gp_rpc_process.c +index 0ea17f0..eaffc55 100644 +--- a/proxy/src/gp_rpc_process.c ++++ b/proxy/src/gp_rpc_process.c +@@ -372,9 +372,12 @@ int gp_rpc_process_call(struct gp_call_ctx *gpcall, + xdrmem_create(&xdr_reply_ctx, reply_buffer, MAX_RPC_SIZE, XDR_ENCODE); + + /* decode request */ ++ GPDEBUGN(3, "[status] Processing request [%p (%zu)]\n", inbuf, inlen); + ret = gp_rpc_decode_call(&xdr_call_ctx, &xid, &proc, &arg, &acc, &rej); + if (!ret) { + /* execute request */ ++ GPDEBUGN(3, "[status] Executing request %d (%s) from [%p (%zu)]\n", ++ proc, gp_rpc_procname(proc), inbuf, inlen); + ret = gp_rpc_execute(gpcall, proc, &arg, &res); + if (ret) { + acc = GP_RPC_SYSTEM_ERR; +@@ -388,6 +391,9 @@ int gp_rpc_process_call(struct gp_call_ctx *gpcall, + /* return encoded buffer */ + ret = gp_rpc_return_buffer(&xdr_reply_ctx, + reply_buffer, outbuf, outlen); ++ GPDEBUGN(3, "[status] Returned buffer %d (%s) from [%p (%zu)]: " ++ "[%p (%zu)]\n", proc, gp_rpc_procname(proc), inbuf, inlen, ++ *outbuf, *outlen); + } + /* free resources */ + gp_rpc_free_xdrs(proc, &arg, &res); +diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c +index 5064e51..8675a0e 100644 +--- a/proxy/src/gp_socket.c ++++ b/proxy/src/gp_socket.c +@@ -441,6 +441,8 @@ void gp_socket_send_data(verto_ctx *vctx, struct gp_conn *conn, + + wbuf = calloc(1, sizeof(struct gp_buffer)); + if (!wbuf) { ++ GPDEBUGN(3, "[status] OOM in gp_socket_send_data: %p (%zu)\n", ++ buffer, buflen); + /* too bad, must kill the client connection now */ + gp_conn_free(conn); + return; +@@ -467,6 +469,8 @@ static void gp_socket_write(verto_ctx *vctx, verto_ev *ev) + + vecs = 0; + ++ GPDEBUGN(3, "[status] Sending data: %p (%zu)\n", wbuf->data, wbuf->size); ++ + if (wbuf->pos == 0) { + /* first write, send the buffer size as packet header */ + size = wbuf->size | FRAGMENT_BIT; +@@ -489,6 +493,9 @@ static void gp_socket_write(verto_ctx *vctx, verto_ev *ev) + gp_socket_schedule_write(vctx, wbuf); + } else { + /* error on socket, close and release it */ ++ GPDEBUGN(3, "[status] Error %d in gp_socket_write on writing for " ++ "[%p (%zu:%zu)]\n", errno, wbuf->data, wbuf->pos, ++ wbuf->size); + gp_conn_free(wbuf->conn); + gp_buffer_free(wbuf); + } +@@ -498,6 +505,8 @@ static void gp_socket_write(verto_ctx *vctx, verto_ev *ev) + if (wn < (ssize_t) sizeof(size)) { + /* don't bother trying to handle sockets that can't + * buffer even 4 bytes */ ++ GPDEBUGN(3, "[status] Sending data [%p (%zu)]: failed with short " ++ "write of %d\n", wbuf->data, wbuf->size, wn); + gp_conn_free(wbuf->conn); + gp_buffer_free(wbuf); + return; +@@ -505,6 +514,9 @@ static void gp_socket_write(verto_ctx *vctx, verto_ev *ev) + wn -= sizeof(size); + } + ++ GPDEBUGN(3, "[status] Sending data [%p (%zu)]: successful write of %d\n", ++ wbuf->data, wbuf->size, wn); ++ + wbuf->pos += wn; + if (wbuf->size > wbuf->pos) { + /* short write, reschedule */ +diff --git a/proxy/src/gp_workers.c b/proxy/src/gp_workers.c +index d37e57c..2a33c21 100644 +--- a/proxy/src/gp_workers.c ++++ b/proxy/src/gp_workers.c +@@ -319,6 +319,7 @@ static void gp_handle_reply(verto_ctx *vctx, verto_ev *ev) + break; + + case GP_QUERY_OUT: ++ GPDEBUGN(3, "[status] Handling query reply: %p (%zu)\n", q->buffer, q->buflen); + gp_socket_send_data(vctx, q->conn, q->buffer, q->buflen); + gp_query_free(q, false); + break; +@@ -381,7 +382,11 @@ static void *gp_worker_main(void *pvt) + gp_debug_set_conn_id(gp_conn_get_cid(q->conn)); + + /* handle the client request */ ++ GPDEBUGN(3, "[status] Handling query input: %p (%zu)\n", q->buffer, ++ q->buflen); + gp_handle_query(t->pool, q); ++ GPDEBUGN(3 ,"[status] Handling query output: %p (%zu)\n", q->buffer, ++ q->buflen); + + /* now get lock on main queue, to play with the reply list */ + /* ======> POOL LOCK */ diff --git a/SPECS/gssproxy.spec b/SPECS/gssproxy.spec new file mode 100644 index 0000000..154df99 --- /dev/null +++ b/SPECS/gssproxy.spec @@ -0,0 +1,547 @@ +Name: gssproxy +Version: 0.7.0 +Release: 28%{?dist} +Summary: GSSAPI Proxy + +Group: System Environment/Libraries +License: MIT +URL: https://pagure.io/gssproxy +Source0: https://releases.pagure.org/gssproxy/gssproxy-%{version}.tar.gz +Source1: rwtab +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +%global servicename gssproxy +%global pubconfpath %{_sysconfdir}/gssproxy +%global gpstatedir %{_localstatedir}/lib/gssproxy + +### Patches ### +Patch0: Properly-renew-expired-credentials.patch +Patch1: Change-impersonator-check-code.patch +Patch2: Allow-connection-to-self-when-impersonator-set.patch +Patch3: Make-proc-file-failure-loud-but-nonfatal.patch +Patch4: Turn-on-Wextra.patch +Patch5: Fix-unused-variables.patch +Patch6: Fix-mismatched-sign-comparisons.patch +Patch7: Fix-error-checking-on-get_impersonator_fallback.patch +Patch8: Remove-gpm_release_ctx-to-fix-double-unlock.patch +Patch9: Appease-gcc-7-s-fallthrough-detection.patch +Patch10: Fix-memory-leak.patch +Patch11: Fix-most-memory-leaks.patch +Patch12: Fix-segfault-when-no-config-files-are-present.patch +Patch13: Update-systemd-file.patch +Patch14: Fix-error-handling-in-gp_config_from_dir.patch +Patch15: Fix-silent-crash-with-duplicate-config-sections.patch +Patch16: Do-not-call-gpm_grab_sock-twice.patch +Patch18: Only-empty-FILE-ccaches-when-storing-remote-creds.patch +Patch19: Handle-outdated-encrypted-ccaches.patch +Patch20: Separate-cred-and-ccache-manipulation-in-gpp_store_r.patch +Patch21: Properly-locate-credentials-in-collection-caches-in-.patch +Patch22: Properly-initialize-ccaches-before-storing-into-them.patch +Patch23: Include-header-for-writev.patch +Patch24: Tolerate-NULL-pointers-in-gp_same.patch +Patch25: Add-Client-ID-to-debug-messages.patch +Patch26: client-Switch-to-non-blocking-sockets.patch +Patch27: server-Add-detailed-request-logging.patch +Patch28: Fix-potential-free-of-non-heap-address.patch +Patch29: Prevent-uninitialized-read-in-error-path-of-XDR-cont.patch +Patch30: Simplify-setting-NONBLOCK-on-socket.patch +Patch31: Fix-handling-of-non-EPOLLIN-EPOLLOUT-events.patch +Patch32: Fix-error-handling-in-gpm_send_buffer-gpm_recv_buffe.patch +Patch33: Emit-debug-on-queue-errors.patch +Patch34: Conditionally-reload-kernel-interface-on-SIGHUP.patch +Patch35: Don-t-leak-mech_type-when-CONTINUE_NEEDED-from-init_.patch +Patch36: Always-use-the-encype-we-selected.patch +Patch37: Clarify-debug-and-debug_level-in-man-pages.patch +Patch38: Always-choose-highest-requested-debug-level.patch +Patch39: Use-pthread-keys-for-thread-local-storage.patch +Patch40: Close-epoll-fd-within-the-lock.patch +Patch41: Add-a-safety-timeout-to-epoll.patch +Patch42: Always-initialize-out-cred-in-gp_import_gssx_cred.patch +Patch43: Handle-gss_import_cred-failure-when-importing-gssx-c.patch +Patch44: Include-length-when-using-krb5_c_decrypt.patch +Patch45: Change-the-way-we-handle-encrypted-buffers.patch +Patch46: Avoid-uninitialized-free-when-allocating-buffers.patch +Patch47: Update-docs-to-reflect-actual-behavior-of-krb5_princ.patch +Patch48: Fix-double-free-of-popt-context-when-querying-versio.patch + +### Dependencies ### + +# From rhbz#1458913 and rhbz#1507607 (and friends) +Requires: libini_config >= 1.3.1-31 + +Requires: krb5-libs >= 1.15 +Requires: keyutils-libs +Requires: libverto-module-base +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units + +# Currently from rhbz#1458850 and friends +Conflicts: selinux-policy < 3.13.1-166.el7.noarch + +### Build Dependencies ### + +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: coreutils +BuildRequires: docbook-style-xsl +BuildRequires: doxygen +BuildRequires: findutils +BuildRequires: gettext-devel +BuildRequires: keyutils-libs-devel +BuildRequires: krb5-devel >= 1.15 +BuildRequires: libini_config-devel >= 1.3.1-28 +BuildRequires: libselinux-devel +BuildRequires: libtool +BuildRequires: libverto-devel +BuildRequires: libxml2 +BuildRequires: libxslt +BuildRequires: m4 +BuildRequires: pkgconfig +BuildRequires: popt-devel +BuildRequires: sed +BuildRequires: systemd-units + + +%description +A proxy for GSSAPI credential handling + + +%prep +%setup -q +%patch0 -p2 -b .Properly-renew-expired-credentials +%patch1 -p2 -b .Change-impersonator-check-code +%patch2 -p2 -b .Allow-connection-to-self-when-impersonator-set +%patch3 -p2 -b .Make-proc-file-failure-loud-but-nonfatal +%patch4 -p2 -b .Turn-on-Wextra +%patch5 -p2 -b .Fix-unused-variables +%patch6 -p2 -b .Fix-mismatched-sign-comparisons +%patch7 -p2 -b .Fix-error-checking-on-get_impersonator_fallback +%patch8 -p2 -b .Remove-gpm_release_ctx-to-fix-double-unlock +%patch9 -p2 -b .Appease-gcc-7-s-fallthrough-detection +%patch10 -p2 -b .Fix-memory-leak +%patch11 -p2 -b .Fix-most-memory-leaks +%patch12 -p2 -b .Fix-segfault-when-no-config-files-are-present +%patch13 -p2 -b .Update-systemd-file +%patch14 -p2 -b .Fix-error-handling-in-gp_config_from_dir +%patch15 -p2 -b .Fix-silent-crash-with-duplicate-config-sections +%patch16 -p2 -b .Do-not-call-gpm_grab_sock-twice +%patch18 -p2 -b .Only-empty-FILE-ccaches-when-storing-remote-creds +%patch19 -p2 -b .Handle-outdated-encrypted-ccaches +%patch20 -p2 -b .Separate-cred-and-ccache-manipulation-in-gpp_store_r +%patch21 -p2 -b .Properly-locate-credentials-in-collection-caches-in- +%patch22 -p2 -b .Properly-initialize-ccaches-before-storing-into-them +%patch23 -p2 -b .Include-header-for-writev +%patch24 -p2 -b .Tolerate-NULL-pointers-in-gp_same +%patch25 -p2 -b .Add-Client-ID-to-debug-messages +%patch26 -p2 -b .client-Switch-to-non-blocking-sockets +%patch27 -p2 -b .server-Add-detailed-request-logging +%patch28 -p2 -b .Fix-potential-free-of-non-heap-address +%patch29 -p2 -b .Prevent-uninitialized-read-in-error-path-of-XDR-cont +%patch30 -p2 -b .Simplify-setting-NONBLOCK-on-socket +%patch31 -p2 -b .Fix-handling-of-non-EPOLLIN-EPOLLOUT-events +%patch32 -p2 -b .Fix-error-handling-in-gpm_send_buffer-gpm_recv_buffe +%patch33 -p2 -b .Emit-debug-on-queue-errors +%patch34 -p2 -b .Conditionally-reload-kernel-interface-on-SIGHUP +%patch35 -p2 -b .Don-t-leak-mech_type-when-CONTINUE_NEEDED-from-init_ +%patch36 -p2 -b .Always-use-the-encype-we-selected +%patch37 -p2 -b .Clarify-debug-and-debug_level-in-man-pages +%patch38 -p2 -b .Always-choose-highest-requested-debug-level +%patch39 -p2 -b .Use-pthread-keys-for-thread-local-storage +%patch40 -p2 -b .Close-epoll-fd-within-the-lock +%patch41 -p2 -b .Add-a-safety-timeout-to-epoll +%patch42 -p2 -b .Always-initialize-out-cred-in-gp_import_gssx_cred +%patch43 -p2 -b .Handle-gss_import_cred-failure-when-importing-gssx-c +%patch44 -p2 -b .Include-length-when-using-krb5_c_decrypt +%patch45 -p2 -b .Change-the-way-we-handle-encrypted-buffers +%patch46 -p2 -b .Avoid-uninitialized-free-when-allocating-buffers +%patch47 -p2 -b .Update-docs-to-reflect-actual-behavior-of-krb5_princ +%patch48 -p2 -b .Fix-double-free-of-popt-context-when-querying-versio + +%build +autoreconf -f -i +%configure \ + --with-pubconf-path=%{pubconfpath} \ + --with-initscript=systemd \ + --disable-static \ + --disable-rpath \ + --with-gpp-default-behavior=REMOTE_FIRST \ + CFLAGS="$CFLAGS -fPIE -fstack-protector-all" \ + LDFLAGS="$LDFLAGS -fPIE -pie -Wl,-z,now" +make %{?_smp_mflags} all +make test_proxymech + +%install +rm -rf -- "%{buildroot}" +make install DESTDIR=%{buildroot} +rm -f -- %{buildroot}%{_libdir}/gssproxy/proxymech.la +install -d -m755 %{buildroot}%{_sysconfdir}/gssproxy +install -m644 examples/gssproxy.conf %{buildroot}%{_sysconfdir}/gssproxy/gssproxy.conf +install -m644 examples/99-nfs-client.conf %{buildroot}%{_sysconfdir}/gssproxy/99-nfs-client.conf +mkdir -p %{buildroot}%{_sysconfdir}/gss/mech.d +install -m644 examples/mech %{buildroot}%{_sysconfdir}/gss/mech.d/gssproxy.conf +mkdir -p %{buildroot}/var/lib/gssproxy/rcache +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/rwtab.d +install -m644 %{SOURCE1} $RPM_BUILD_ROOT/%{_sysconfdir}/rwtab.d/gssproxy + +%clean +rm -rf -- "%{buildroot}" + + +%files +%defattr(-,root,root,-) +%doc COPYING +%{_unitdir}/gssproxy.service +%{_sbindir}/gssproxy +%attr(755,root,root) %dir %{pubconfpath} +%attr(755,root,root) %dir %{gpstatedir} +%attr(700,root,root) %dir %{gpstatedir}/clients +%attr(0600,root,root) %config(noreplace) /%{_sysconfdir}/gssproxy/gssproxy.conf +%attr(0600,root,root) %config(noreplace) /%{_sysconfdir}/gssproxy/99-nfs-client.conf +%attr(0644,root,root) %config(noreplace) /%{_sysconfdir}/gss/mech.d/gssproxy.conf +%attr(700,root,root) %dir /var/lib/gssproxy/rcache +%{_libdir}/gssproxy/proxymech.so +%{_mandir}/man5/gssproxy.conf.5* +%{_mandir}/man8/gssproxy.8* +%{_mandir}/man8/gssproxy-mech.8* +%config(noreplace) %{_sysconfdir}/rwtab.d/gssproxy + +%post +%systemd_post gssproxy.service + + +%preun +%systemd_preun gssproxy.service + + +%postun +%systemd_postun_with_restart gssproxy.service + + +%changelog +* Thu Sep 19 2019 Robbie Harwood 0.7.0-28 +- Fix double free of popt context when querying version +- Resolves: #1752810 + +* Mon Jul 22 2019 Robbie Harwood 0.7.0-27 +- Update docs to reflect actual behavior of krb5_principal +- Resolves: #1553094 + +* Wed May 01 2019 Robbie Harwood 0.7.0-26 +- Avoid uninitialized free when allocating buffers +- Resolves: #1699331 + +* Tue Apr 30 2019 Robbie Harwood 0.7.0-25 +- Fix explicit NULL deref on some enctypes +- Resolves: #1699331 + +* Mon Mar 18 2019 Robbie Harwood 0.7.0-24 +- Add a safety timeout to epoll +- Resolves: #1687899 + +* Mon Dec 17 2018 Robbie Harwood 0.7.0-23 +- Use pthread keys for thread local storage +- Resolves: #1618375 + +* Tue Dec 11 2018 Robbie Harwood 0.7.0-22 +- Add hack to support read-only root +- Resolves: #1542567 + +* Fri Jun 08 2018 Robbie Harwood 0.7.0-21 +- Always choose highest requested debug level +- Resolves: #1505741 + +* Fri Apr 27 2018 Robbie Harwood 0.7.0-20 +- Clean up debug man page + behavior +- Resolves: #1554249 + +* Fri Apr 27 2018 Robbie Harwood 0.7.0-19 +- Always use the encype we selected +- Resolves: #1549684 + +* Fri Apr 27 2018 Robbie Harwood 0.7.0-18 +- Don't leak mech_type when CONTINUE_NEEDED from init_sec_context +- Resolves: #1553819 + +* Wed Dec 13 2017 Robbie Harwood 0.7.0-17 +- Conditionally reload kernel interface on SIGHUP +- Resolves: #1507817 + +* Tue Dec 12 2017 Robbie Harwood 0.7.0-16 +- Backport epoll() logic +- Resolves: #1507817 + +* Wed Dec 06 2017 Robbie Harwood 0.7.0-15 +- Properly initialize ccaches before storing into them +- Resolves: #1488629 + +* Fri Dec 01 2017 Robbie Harwood 0.7.0-14 +- Properly locate credentials in collection caches in mechglue +- Resolves: #1488629 + +* Tue Oct 31 2017 Robbie Harwood 0.7.0-13 +- Handle outdated encrypted ccaches +- Resolves: #1488629 + +* Tue Oct 31 2017 Robbie Harwood 0.7.0-12 +- Handle outdated encrypted ccaches +- Resolves: #1488629 + +* Mon Oct 30 2017 Robbie Harwood 0.7.0-11 +- Fix error message handling in gp_config_from_dir() +- Resolves: #1458913 + +* Fri Oct 27 2017 Robbie Harwood 0.7.0-10 +- Fix concurrency issue around server socket handling +- Resolves: #1462974 + +* Tue Oct 17 2017 Robbie Harwood 0.7.0-9 +- Log useful warning and merge when config file has duplicate sections +- Resolves: #1458913 + +* Mon Oct 02 2017 Robbie Harwood 0.7.0-8 +- Add Conflicts: line for old selinux-policy +- Resolves: #1458850 + +* Thu Sep 21 2017 Robbie Harwood 0.7.0-7 +- Backport NFS-related gssproxy.service changes +- Resolves: #1326440 + +* Mon Sep 11 2017 Robbie Harwood 0.7.0-6 +- Fix segfault when no config files are present +- Resolves: #1451255 + +* Thu Aug 17 2017 Robbie Harwood 0.7.0-5 +- Backport hardening improvements +- Resolves: #1462974 + +* Wed May 31 2017 Robbie Harwood 0.7.0-4 +- Make proc file failure loud but nonfatal +- Resolves: #1449238 + +* Tue Mar 28 2017 Robbie Harwood 0.7.0-3 +- Stop shipping NFS server snippet (nfs-utils takes it instead) +- Resolves: #1379836 + +* Tue Mar 14 2017 Robbie Harwood 0.7.0-2 +- Fix credential handling with mod_auth_gssapi that we broke +- Resolves: #1379836 + +* Fri Mar 10 2017 Robbie Harwood 0.7.0-1 +- New upstream version - 0.7.0 +- Resolves: #1379836 + +* Tue Feb 28 2017 Robbie Harwood 0.6.2-4 +- Include fixes for NULL-termination +- Resolves: #1379836 + +* Thu Feb 23 2017 Robbie Harwood 0.6.2-3 +- Document debug_level option +- Resolves: #1379836 + +* Tue Feb 21 2017 Robbie Harwood 0.6.2-2 +- Enable running the test suite +- Resolves: #1379836 + +* Thu Feb 16 2017 Robbie Harwood 0.6.2-1 +- Rebase to latest version since we have krb5-1.15 +- Resolves: #1379836 +- Resolves: #1344518 +- Resolves: #1366782 +- Resolves: #1379005 +- Resolves: #1379482 +- Resolves: #1379616 +- Resolves: #1380490 +- Resolves: #1378600 +- Resolves: #1285012 +- Resolves: #1333813 + +* Tue Sep 06 2016 Robbie Harwood 0.4.1-13 +- Third try is the charm +- Resolves: #1092515 + +* Tue Sep 06 2016 Robbie Harwood 0.4.1-12 +- Restore _FORTIFY_SOURCE behavior +- Resolves: #1092515 + +* Tue Sep 06 2016 Robbie Harwood 0.4.1-11 +- Actually harden build with PIE and RELRO +- Resolves: #1092515 + +* Fri Jun 10 2016 Robbie Harwood 0.4.1-10 +- Fix behavior with multiple keys in a keytab +- Resolves: #1285012 + +* Tue Jun 07 2016 Robbie Harwood 0.4.1-9 +- Re-open socket in mechglue if client forks/changes privilege +- Resolves: #1340259 + +* Wed Mar 30 2016 Robbie Harwood 0.4.1-8 +- Make GSS-Proxy work with krb5-1.14 +- resolves: #1292487 + +* Tue Sep 29 2015 Simo Sorce 0.4.1-7 +- Fix loop cause by imporper EINTR handling +- resolves: #1266564 + +* Mon Aug 24 2015 Roland Mainz 0.4.1-6 +- Remove extra whitespaces from #1208640/#1194299 patches +- spec file cleanup +related: #1208640 #1194299 + +* Wed Aug 19 2015 Robbie Harwood 0.4.1-5 +- Carry service/HTTP default conf section +- resolves: #1208640 + +* Wed Aug 19 2015 Robbie Harwood 0.4.1-4 +- Set default rcache location patch +- resolves: #1194299 + +* Mon Jul 13 2015 Roland Mainz 0.4.1-3 +- Bug #1213852 ("[gssproxy] NFS clients cannot mount with + sec=krb5 if the NFS server is running gssproxy") was + fixed by the rebase to 0.4.1 in bug ("[RFE] Rebase + gssproxy to the latest to match expectations of other + projects"). + Note that the same bug was also fixed in the kernel with + "9507271 svcrpc: fix potential GSSX_ACCEPT_SEC_CONTEXT + decoding failures" (see + https://bugzilla.redhat.com/show_bug.cgi?id=1213852#c2 + and RH Bug #1120860 ("[NFS] NFS clients cannot mount with + sec=krb5 if the NFS server is running gssproxy")) to + handle various corner cases not covered by gssproxy, + for example individual krb5 ticket fields exceeding + the kernel's buffer size. + +* Thu Jul 9 2015 Roland Mainz 0.4.1-2 +- The following bugs have been fixed by the rebase to 0.4.1 + in bug ("[RFE] Rebase gssproxy to the latest to match + expectations of other projects"): + - Bug #1196371 ("rpc.gssd segfaults in gssproxy (proxymech.so)") + Upstream tickets { #137, #144 } + - Bug #1053730 ("KrbLocalUserMapping does not work with + Apache & GSS-Proxy") + Upstream ticket #101 + - Bug #1168962 ("gssproxy is not working with httpd on ppc64 and s390x") + Upstream ticket #146 + +* Thu Jul 9 2015 Roland Mainz 0.4.1-1 +- Add patch to remove -fno-strict-aliasing (gssproxy ticket #140, + a dependicy for the fix for bug #1092515 (see below)) +- Add patch to fix bug #1092515 ("gssproxy - PIE and RELRO check") + +* Fri Jun 5 2015 Roland Mainz 0.4.1-0 +- Rebase gssproxy to 0.4.1 per bug #1132389 ("[RFE] Rebase + gssproxy to the latest to match expectations of other + projects"). + +* Fri Jan 23 2015 Simo Sorce 0.3.0-10 +- Fix crash bug affecting updated rpc.gssd +- resolves: #1184531 + +* 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) + * Add support for new rpc.gssd mode of operation that forks and changes uid + * Add 2 new options allow_any_uid and cred_usage + +* Fri Oct 18 2013 Guenther Deschner 0.2.3-8 +- Fix default proxymech documentation and fix LOCAL_FIRST implementation +- resolves: https://fedorahosted.org/gss-proxy/ticket/105 + +* Wed Jul 24 2013 Guenther Deschner 0.2.3-6 +- Add better default gssproxy.conf file for nfs client and server usage + +* Thu Jun 06 2013 Guenther Deschner 0.2.3-5 +- New upstream release + +* Fri May 31 2013 Guenther Deschner 0.2.2-5 +- Require libverto-tevent to make sure libverto initialization succeeds + +* Wed May 29 2013 Guenther Deschner 0.2.2-4 +- Modify systemd unit files for nfs-secure services + +* Wed May 22 2013 Guenther Deschner 0.2.2-3 +- Fix cred_store handling w/o client keytab + +* Thu May 16 2013 Guenther Deschner 0.2.2-2 +- New upstream release + +* Tue May 07 2013 Guenther Deschner 0.2.1-2 +- New upstream release + +* Wed Apr 24 2013 Guenther Deschner 0.2.0-1 +- New upstream release + +* Mon Apr 01 2013 Simo Sorce - 0.1.0-0 +- New upstream release + +* Thu Feb 14 2013 Fedora Release Engineering - 0.0.3-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Nov 06 2012 Guenther Deschner 0.0.3-7 +- Update to 0.0.3 + +* Wed Aug 22 2012 Guenther Deschner 0.0.2-6 +- Use new systemd-rpm macros +- resolves: #850139 + +* Wed Jul 18 2012 Guenther Deschner 0.0.2-5 +- More spec file fixes + +* Mon Jul 16 2012 Guenther Deschner 0.0.2-4 +- Fix systemd service file + +* Fri Jul 13 2012 Guenther Deschner 0.0.2-3 +- Fix various packaging issues + +* Mon Jul 02 2012 Guenther Deschner 0.0.1-2 +- Add systemd packaging + +* Wed Mar 28 2012 Guenther Deschner 0.0.1-1 +- Various fixes + +* Mon Dec 12 2011 Simo Sorce - 0.0.2-0 +- Automated build of the gssproxy daemon