9af0d9
From 2ca80c193ffa13c89b9b63fb9cb690a9789d5842 Mon Sep 17 00:00:00 2001
9af0d9
From: Simo Sorce <simo@redhat.com>
9af0d9
Date: Thu, 27 Aug 2020 11:34:45 -0400
9af0d9
Subject: [PATCH] Expand use of global static mechs to conform to SPI
9af0d9
9af0d9
GSSAPI requires some specific APIs to return "static" OIDs that the user
9af0d9
does not have to free.  The krb5 mechglue in fact requires mechanisms to
9af0d9
also honor this or the mech oid will be irretrievably leaked in some
9af0d9
cases.
9af0d9
9af0d9
To accomodate this, expand use of global mechs structure we already
9af0d9
allocate for the gss_inidicate_mechs case so we can return "static" OIDs
9af0d9
from calls like ISC and ASC.
9af0d9
9af0d9
Signed-off-by: Simo Sorce <simo@redhat.com>
9af0d9
[rharwood@redhat.com: commit message fixups]
9af0d9
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
9af0d9
(cherry picked from commit a3f13b30ef3c90ff7344c3913f6e26e55b82451f)
9af0d9
(cherry picked from commit b7ccb627f4663ca949e3483486478add8f61cb27)
9af0d9
---
9af0d9
 src/client/gpm_accept_sec_context.c | 22 ++++++-------------
9af0d9
 src/client/gpm_common.c             |  1 -
9af0d9
 src/client/gpm_indicate_mechs.c     | 34 +++++++++++++++++++++++++++++
9af0d9
 src/client/gpm_init_sec_context.c   | 19 +++++-----------
9af0d9
 src/client/gssapi_gpm.h             |  3 +++
9af0d9
 src/mechglue/gss_plugin.c           |  5 +++++
9af0d9
 6 files changed, 55 insertions(+), 29 deletions(-)
9af0d9
9af0d9
diff --git a/src/client/gpm_accept_sec_context.c b/src/client/gpm_accept_sec_context.c
9af0d9
index ef5e79c..ab20b03 100644
9af0d9
--- a/src/client/gpm_accept_sec_context.c
9af0d9
+++ b/src/client/gpm_accept_sec_context.c
9af0d9
@@ -21,7 +21,6 @@ OM_uint32 gpm_accept_sec_context(OM_uint32 *minor_status,
9af0d9
     gssx_res_accept_sec_context *res = &ures.accept_sec_context;
9af0d9
     gssx_ctx *ctx = NULL;
9af0d9
     gssx_name *name = NULL;
9af0d9
-    gss_OID_desc *mech = NULL;
9af0d9
     gss_buffer_t outbuf = NULL;
9af0d9
     uint32_t ret_maj;
9af0d9
     int ret;
9af0d9
@@ -70,15 +69,6 @@ OM_uint32 gpm_accept_sec_context(OM_uint32 *minor_status,
9af0d9
         goto done;
9af0d9
     }
9af0d9
 
9af0d9
-    if (mech_type) {
9af0d9
-        if (res->status.mech.octet_string_len) {
9af0d9
-            ret = gp_conv_gssx_to_oid_alloc(&res->status.mech, &mech);
9af0d9
-            if (ret) {
9af0d9
-                goto done;
9af0d9
-            }
9af0d9
-        }
9af0d9
-    }
9af0d9
-
9af0d9
     ctx = res->context_handle;
9af0d9
     /* we are stealing the delegated creds on success, so we do not want
9af0d9
      * it to be freed by xdr_free */
9af0d9
@@ -101,8 +91,14 @@ OM_uint32 gpm_accept_sec_context(OM_uint32 *minor_status,
9af0d9
     }
9af0d9
 
9af0d9
     if (mech_type) {
9af0d9
-        *mech_type = mech;
9af0d9
+        gss_OID_desc mech;
9af0d9
+        gp_conv_gssx_to_oid(&res->status.mech, &mech);
9af0d9
+        ret = gpm_mech_to_static(&mech, mech_type);
9af0d9
+        if (ret) {
9af0d9
+            goto done;
9af0d9
+        }
9af0d9
     }
9af0d9
+
9af0d9
     if (src_name) {
9af0d9
         *src_name = name;
9af0d9
     }
9af0d9
@@ -145,10 +141,6 @@ done:
9af0d9
             xdr_free((xdrproc_t)xdr_gssx_name, (char *)name);
9af0d9
             free(name);
9af0d9
         }
9af0d9
-        if (mech) {
9af0d9
-            free(mech->elements);
9af0d9
-            free(mech);
9af0d9
-        }
9af0d9
         if (outbuf) {
9af0d9
             free(outbuf->value);
9af0d9
             free(outbuf);
9af0d9
diff --git a/src/client/gpm_common.c b/src/client/gpm_common.c
9af0d9
index d932ba2..02325c4 100644
9af0d9
--- a/src/client/gpm_common.c
9af0d9
+++ b/src/client/gpm_common.c
9af0d9
@@ -795,4 +795,3 @@ void gpm_free_xdrs(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res)
9af0d9
     xdr_free(gpm_xdr_set[proc].arg_fn, (char *)arg);
9af0d9
     xdr_free(gpm_xdr_set[proc].res_fn, (char *)res);
9af0d9
 }
9af0d9
-
9af0d9
diff --git a/src/client/gpm_indicate_mechs.c b/src/client/gpm_indicate_mechs.c
9af0d9
index b019a96..86c7de3 100644
9af0d9
--- a/src/client/gpm_indicate_mechs.c
9af0d9
+++ b/src/client/gpm_indicate_mechs.c
9af0d9
@@ -300,6 +300,40 @@ static int gpmint_init_global_mechs(void)
9af0d9
     return 0;
9af0d9
 }
9af0d9
 
9af0d9
+/* GSSAPI requires some APIs to return "static" mechs that callers do not need
9af0d9
+ * to free. So match a radom mech and return from our global "static" array */
9af0d9
+int gpm_mech_to_static(gss_OID mech_type, gss_OID *mech_static)
9af0d9
+{
9af0d9
+    int ret;
9af0d9
+
9af0d9
+    ret = gpmint_init_global_mechs();
9af0d9
+    if (ret) {
9af0d9
+        return ret;
9af0d9
+    }
9af0d9
+
9af0d9
+    *mech_static = GSS_C_NO_OID;
9af0d9
+    for (size_t i = 0; i < global_mechs.mech_set->count; i++) {
9af0d9
+        if (gpm_equal_oids(&global_mechs.mech_set->elements[i], mech_type)) {
9af0d9
+            *mech_static = &global_mechs.mech_set->elements[i];
9af0d9
+            return 0;
9af0d9
+        }
9af0d9
+    }
9af0d9
+    /* TODO: potentially in future add the mech to the list if missing */
9af0d9
+    return ENOENT;
9af0d9
+}
9af0d9
+
9af0d9
+bool gpm_mech_is_static(gss_OID mech_type)
9af0d9
+{
9af0d9
+    if (global_mechs.mech_set) {
9af0d9
+        for (size_t i = 0; i < global_mechs.mech_set->count; i++) {
9af0d9
+            if (&global_mechs.mech_set->elements[i] == mech_type) {
9af0d9
+                return true;
9af0d9
+            }
9af0d9
+        }
9af0d9
+    }
9af0d9
+    return false;
9af0d9
+}
9af0d9
+
9af0d9
 OM_uint32 gpm_indicate_mechs(OM_uint32 *minor_status, gss_OID_set *mech_set)
9af0d9
 {
9af0d9
     uint32_t ret_min;
9af0d9
diff --git a/src/client/gpm_init_sec_context.c b/src/client/gpm_init_sec_context.c
9af0d9
index bea2010..b84ff94 100644
9af0d9
--- a/src/client/gpm_init_sec_context.c
9af0d9
+++ b/src/client/gpm_init_sec_context.c
9af0d9
@@ -43,7 +43,6 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status,
9af0d9
     gssx_arg_init_sec_context *arg = &uarg.init_sec_context;
9af0d9
     gssx_res_init_sec_context *res = &ures.init_sec_context;
9af0d9
     gssx_ctx *ctx = NULL;
9af0d9
-    gss_OID_desc *mech = NULL;
9af0d9
     gss_buffer_t outbuf = NULL;
9af0d9
     uint32_t ret_maj = GSS_S_COMPLETE;
9af0d9
     uint32_t ret_min = 0;
9af0d9
@@ -100,11 +99,12 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status,
9af0d9
 
9af0d9
     /* return values */
9af0d9
     if (actual_mech_type) {
9af0d9
-        if (res->status.mech.octet_string_len) {
9af0d9
-            ret = gp_conv_gssx_to_oid_alloc(&res->status.mech, &mech);
9af0d9
-            if (ret) {
9af0d9
-                goto done;
9af0d9
-            }
9af0d9
+        gss_OID_desc mech;
9af0d9
+        gp_conv_gssx_to_oid(&res->status.mech, &mech);
9af0d9
+        ret = gpm_mech_to_static(&mech, actual_mech_type);
9af0d9
+        if (ret) {
9af0d9
+            gpm_save_internal_status(ret, gp_strerror(ret));
9af0d9
+            goto done;
9af0d9
         }
9af0d9
     }
9af0d9
 
9af0d9
@@ -151,9 +151,6 @@ done:
9af0d9
     gpm_free_xdrs(GSSX_INIT_SEC_CONTEXT, &uarg, &ures);
9af0d9
 
9af0d9
     if (ret_maj == GSS_S_COMPLETE || ret_maj == GSS_S_CONTINUE_NEEDED) {
9af0d9
-        if (actual_mech_type) {
9af0d9
-            *actual_mech_type = mech;
9af0d9
-        }
9af0d9
         if (outbuf) {
9af0d9
             *output_token = *outbuf;
9af0d9
             free(outbuf);
9af0d9
@@ -170,10 +167,6 @@ done:
9af0d9
             free(ctx);
9af0d9
             ctx = NULL;
9af0d9
         }
9af0d9
-        if (mech) {
9af0d9
-            free(mech->elements);
9af0d9
-            free(mech);
9af0d9
-        }
9af0d9
         if (outbuf) {
9af0d9
             free(outbuf->value);
9af0d9
             free(outbuf);
9af0d9
diff --git a/src/client/gssapi_gpm.h b/src/client/gssapi_gpm.h
9af0d9
index 61124e0..b7ba04b 100644
9af0d9
--- a/src/client/gssapi_gpm.h
9af0d9
+++ b/src/client/gssapi_gpm.h
9af0d9
@@ -27,6 +27,9 @@ void gpm_display_status_init_once(void);
9af0d9
 void gpm_save_status(gssx_status *status);
9af0d9
 void gpm_save_internal_status(uint32_t err, char *err_str);
9af0d9
 
9af0d9
+int gpm_mech_to_static(gss_OID mech_type, gss_OID *mech_static);
9af0d9
+bool gpm_mech_is_static(gss_OID mech_type);
9af0d9
+
9af0d9
 OM_uint32 gpm_display_status(OM_uint32 *minor_status,
9af0d9
                              OM_uint32 status_value,
9af0d9
                              int status_type,
9af0d9
diff --git a/src/mechglue/gss_plugin.c b/src/mechglue/gss_plugin.c
9af0d9
index 8b799cf..bf70d87 100644
9af0d9
--- a/src/mechglue/gss_plugin.c
9af0d9
+++ b/src/mechglue/gss_plugin.c
9af0d9
@@ -377,6 +377,11 @@ OM_uint32 gssi_internal_release_oid(OM_uint32 *minor_status, gss_OID *oid)
9af0d9
         item = gpp_next_special_oids(item);
9af0d9
     }
9af0d9
 
9af0d9
+    if (gpm_mech_is_static(*oid)) {
9af0d9
+        *oid = GSS_C_NO_OID;
9af0d9
+        return GSS_S_COMPLETE;
9af0d9
+    }
9af0d9
+
9af0d9
     /* none matched, it's not ours */
9af0d9
     return GSS_S_CONTINUE_NEEDED;
9af0d9
 }