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