diff options
author | Simo Sorce <simo@redhat.com> | 2012-05-17 00:31:14 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2012-08-28 08:25:51 +0200 |
commit | ca0ff11fc945f15860086f6c2f76dfb1556018fa (patch) | |
tree | 3daa8324aeac6ddebac24a3d66dfa89aa54c42b8 /proxy | |
parent | dad1d6295a8d2e04ab283593a18f0a3c5e4f52df (diff) | |
download | gss-proxy-ca0ff11fc945f15860086f6c2f76dfb1556018fa.tar.gz gss-proxy-ca0ff11fc945f15860086f6c2f76dfb1556018fa.tar.xz gss-proxy-ca0ff11fc945f15860086f6c2f76dfb1556018fa.zip |
Add function to return a special mech
When the interposer wants to call the mechglue and have it call a real
mechanism it does so by providing a speecial mechanism oid.
This is an oid composed of the procy plugin oid and the real mechanism oid
that the mechglue transforms back into a real OID before selecting the
appropriate mechanism.
Diffstat (limited to 'proxy')
-rw-r--r-- | proxy/src/client/gpm_common.c | 1 | ||||
-rw-r--r-- | proxy/src/mechglue/gss_plugin.c | 181 | ||||
-rw-r--r-- | proxy/src/mechglue/gss_plugin.h | 2 |
3 files changed, 184 insertions, 0 deletions
diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c index 16ea7d6..8bd04d1 100644 --- a/proxy/src/client/gpm_common.c +++ b/proxy/src/client/gpm_common.c @@ -518,3 +518,4 @@ void gpm_free_xdrs(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) xdr_free(gpm_xdr_set[proc].arg_fn, (char *)arg); xdr_free(gpm_xdr_set[proc].res_fn, (char *)res); } + diff --git a/proxy/src/mechglue/gss_plugin.c b/proxy/src/mechglue/gss_plugin.c index 7200182..ff85610 100644 --- a/proxy/src/mechglue/gss_plugin.c +++ b/proxy/src/mechglue/gss_plugin.c @@ -24,6 +24,7 @@ */ #include "gss_plugin.h" +#include <signal.h> #include <gssapi/gssapi_krb5.h> #define KRB5_OID_LEN 9 @@ -133,6 +134,9 @@ gss_OID_set gss_mech_interposer(gss_OID mech_type) } } + /* while there also initiaize special_mechs */ + (void)gpp_special_available_mechs(interposed_mechs); + done: if (maj != 0) { (void)gss_release_oid_set(&min, &interposed_mechs); @@ -142,6 +146,183 @@ done: return interposed_mechs; } +static bool gpp_is_special_oid(const gss_OID n) +{ + if (n->length >= gssproxy_mech_interposer.length && + memcmp(gssproxy_mech_interposer.elements, + n->elements, + gssproxy_mech_interposer.length) == 0) { + return true; + } + return false; +} + +static bool gpp_special_equal(const gss_OID s, const gss_OID n) +{ + int base_len = gssproxy_mech_interposer.length; + + if (s->length - base_len == n->length && + memcmp(s->elements + base_len, n->elements, n->length) == 0) { + return true; + } + return false; +} + +struct gpp_special_oid_list { + gss_OID_desc oid; + struct gpp_special_oid_list *next; + sig_atomic_t next_is_set; +}; + +/* This is an ADD-ONLY list, and the pointer to next is updated + * atomically so that we can avoid using mutexes for mere access + * to the list. */ +static struct gpp_special_oid_list *gpp_s_mechs; +static sig_atomic_t gpp_s_mechs_is_set; + +static const gss_OID gpp_new_special_mech(const gss_OID n) +{ + gss_const_OID base = &gssproxy_mech_interposer; + struct gpp_special_oid_list *l, *t; + int p; + + l = calloc(1, sizeof(struct gpp_special_oid_list)); + if (!l) { + return GSS_C_NO_OID; + } + l->oid.length = base->length + n->length; + l->oid.elements = malloc(l->oid.length); + if (!l->oid.elements) { + free(l); + return GSS_C_NO_OID; + } + + memcpy(l->oid.elements, base->elements, base->length); + memcpy(l->oid.elements + base->length, n->elements, n->length); + + t = NULL; + p = gpp_s_mechs_is_set; + __sync_synchronize(); + if (p != 0) { + t = gpp_s_mechs; + while (t->next_is_set != 0) { + t = t->next; + } + } + + if (t == NULL) { + gpp_s_mechs = l; + __sync_synchronize(); + gpp_s_mechs_is_set = 1; + } else { + t->next = l; + __sync_synchronize(); + t->next_is_set = 1; + } + + return (const gss_OID)&l->oid; +} + +const gss_OID gpp_special_mech(const gss_OID mech_type) +{ + struct gpp_special_oid_list *s = NULL; + int p; + + p = gpp_s_mechs_is_set; + __sync_synchronize(); + if (p != 0) { + s = gpp_s_mechs; + } + + if (mech_type == GSS_C_NO_OID) { + /* return the first special one if none specified */ + if (s) { + return (const gss_OID)&s->oid; + } + return GSS_C_NO_OID; + } + + while (s) { + if (gpp_is_special_oid(mech_type)) { + return mech_type; + } + if (gpp_special_equal(&s->oid, mech_type)) { + return (const gss_OID)&s->oid; + } + p = s->next_is_set; + __sync_synchronize(); + if (p != 0) { + s = s->next; + } + } + + /* none matched, add new special oid to the set */ + return gpp_new_special_mech(mech_type); +} + +gss_OID_set gpp_special_available_mechs(const gss_OID_set mechs) +{ + gss_OID_set amechs = GSS_C_NO_OID_SET; + struct gpp_special_oid_list *t, *s = NULL; + gss_OID n; + uint32_t maj, min; + int i, p; + + p = gpp_s_mechs_is_set; + __sync_synchronize(); + if (p != 0) { + s = gpp_s_mechs; + } + + maj = gss_create_empty_oid_set(&min, &amechs); + if (maj) { + return GSS_C_NO_OID_SET; + } + for (i = 0; i < mechs->count; i++) { + t = s; + while (t) { + if (gpp_is_special_oid(&mechs->elements[i])) { + maj = gss_add_oid_set_member(&min, + &mechs->elements[i], &amechs); + if (maj != GSS_S_COMPLETE) { + goto done; + } + break; + } + if (gpp_special_equal(&t->oid, &mechs->elements[i])) { + maj = gss_add_oid_set_member(&min, &t->oid, &amechs); + if (maj != GSS_S_COMPLETE) { + goto done; + } + break; + } + p = t->next_is_set; + __sync_synchronize(); + if (p != 0) { + t = t->next; + } + } + if (t == NULL) { + /* not found, add to static list */ + n = gpp_new_special_mech(&mechs->elements[i]); + if (n == GSS_C_NO_OID) { + maj = GSS_S_FAILURE; + } else { + maj = gss_add_oid_set_member(&min, n, &amechs); + } + if (maj != GSS_S_COMPLETE) { + goto done; + } + } + } + +done: + if (maj != GSS_S_COMPLETE || amechs->count == 0) { + (void)gss_release_oid_set(&min, &amechs); + } + return amechs; +} + /* gssi_acquire_cred gssi_release_cred diff --git a/proxy/src/mechglue/gss_plugin.h b/proxy/src/mechglue/gss_plugin.h index d44cee6..a45d217 100644 --- a/proxy/src/mechglue/gss_plugin.h +++ b/proxy/src/mechglue/gss_plugin.h @@ -40,5 +40,7 @@ enum gpp_behavior { gss_OID_set gss_mech_interposer(gss_OID mech_type); enum gpp_behavior gpp_get_behavior(void); +const gss_OID gpp_special_mech(const gss_OID mech_type); +gss_OID_set gpp_special_available_mechs(const gss_OID_set mechs); #endif /* _GGS_PLUGIN_H_ */ |