summaryrefslogtreecommitdiffstats
path: root/proxy/src
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2012-05-17 00:31:14 -0400
committerSimo Sorce <simo@redhat.com>2012-08-28 08:25:51 +0200
commitca0ff11fc945f15860086f6c2f76dfb1556018fa (patch)
tree3daa8324aeac6ddebac24a3d66dfa89aa54c42b8 /proxy/src
parentdad1d6295a8d2e04ab283593a18f0a3c5e4f52df (diff)
downloadgss-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/src')
-rw-r--r--proxy/src/client/gpm_common.c1
-rw-r--r--proxy/src/mechglue/gss_plugin.c181
-rw-r--r--proxy/src/mechglue/gss_plugin.h2
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_ */