summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/appl/gss-sample/gss-client.c42
-rw-r--r--src/appl/gss-sample/gss-server.c84
-rw-r--r--src/lib/gssapi/generic/gssapi.hin83
-rw-r--r--src/lib/gssapi/generic/gssapiP_generic.h9
-rw-r--r--src/lib/gssapi/generic/gssapi_generic.c260
-rw-r--r--src/lib/gssapi/generic/util_buffer.c3
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c113
-rw-r--r--src/lib/gssapi/libgssapi_krb5.exports32
-rw-r--r--src/lib/gssapi/mechglue/Makefile.in6
-rw-r--r--src/lib/gssapi/mechglue/g_initialize.c5
-rw-r--r--src/lib/gssapi/mechglue/g_mechattr.c224
-rw-r--r--src/lib/gssapi/mechglue/g_saslname.c210
-rw-r--r--src/lib/gssapi/mechglue/mglueP.h25
-rw-r--r--src/lib/gssapi/spnego/gssapiP_spnego.h27
-rw-r--r--src/lib/gssapi/spnego/spnego_mech.c100
-rw-r--r--src/tests/gssapi/Makefile.in10
-rw-r--r--src/tests/gssapi/t_saslname.c188
17 files changed, 1407 insertions, 14 deletions
diff --git a/src/appl/gss-sample/gss-client.c b/src/appl/gss-sample/gss-client.c
index d922cc3bd5..d439f23fbc 100644
--- a/src/appl/gss-sample/gss-client.c
+++ b/src/appl/gss-sample/gss-client.c
@@ -69,12 +69,17 @@
#include "gss-misc.h"
static int verbose = 1;
+static int spnego = 0;
+static gss_OID_desc gss_spnego_mechanism_oid_desc =
+ {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
static void
usage()
{
- fprintf(stderr, "Usage: gss-client [-port port] [-mech mechanism] [-d]\n");
- fprintf(stderr, " [-seq] [-noreplay] [-nomutual] [-user user] [-pass pw]");
+ fprintf(stderr, "Usage: gss-client [-port port] [-mech mechanism] "
+ "[-spnego] [-d]\n");
+ fprintf(stderr, " [-seq] [-noreplay] [-nomutual] [-user user] "
+ "[-pass pw]");
#ifdef _WIN32
fprintf(stderr, " [-threads num]");
#endif
@@ -176,10 +181,17 @@ client_establish_context(int s, char *service_name, OM_uint32 gss_flags,
gss_name_t gss_username = GSS_C_NO_NAME;
gss_OID_set_desc mechs, *mechsp = GSS_C_NO_OID_SET;
- if (oid != GSS_C_NO_OID) {
+ if (spnego) {
+ mechs.elements = &gss_spnego_mechanism_oid_desc;
+ mechs.count = 1;
+ mechsp = &mechs;
+ } else if (oid != GSS_C_NO_OID) {
mechs.elements = oid;
mechs.count = 1;
mechsp = &mechs;
+ } else {
+ mechs.elements = NULL;
+ mechs.count = 0;
}
if (username != NULL) {
@@ -218,6 +230,20 @@ client_establish_context(int s, char *service_name, OM_uint32 gss_flags,
gss_release_name(&min_stat, &gss_username);
return -1;
}
+ if (spnego && oid != GSS_C_NO_OID) {
+ gss_OID_set_desc neg_mechs;
+
+ neg_mechs.elements = oid;
+ neg_mechs.count = 1;
+
+ maj_stat = gss_set_neg_mechs(&min_stat, cred, &neg_mechs);
+ if (maj_stat != GSS_S_COMPLETE) {
+ display_status("setting neg mechs", maj_stat, min_stat);
+ gss_release_name(&min_stat, &gss_username);
+ gss_release_cred(&min_stat, &cred);
+ return -1;
+ }
+ }
gss_release_name(&min_stat, &gss_username);
/*
@@ -264,7 +290,8 @@ client_establish_context(int s, char *service_name, OM_uint32 gss_flags,
do {
maj_stat = gss_init_sec_context(&init_sec_min_stat,
cred, gss_context,
- target_name, oid, gss_flags, 0,
+ target_name, mechs.elements,
+ gss_flags, 0,
NULL, /* channel bindings */
token_ptr, NULL, /* mech type */
&send_tok, ret_flags,
@@ -409,7 +436,7 @@ call_server(host, port, oid, service_name, gss_flags, auth_flag,
char *username;
char *password;
{
- gss_ctx_id_t context;
+ gss_ctx_id_t context = GSS_C_NO_CONTEXT;
gss_buffer_desc in_buf, out_buf;
int s, state;
OM_uint32 ret_flags;
@@ -523,7 +550,7 @@ call_server(host, port, oid, service_name, gss_flags, auth_flag,
} else {
/* Seal the message */
in_buf.value = msg;
- in_buf.length = strlen(msg);
+ in_buf.length = strlen((char *)in_buf.value);
}
for (i = 0; i < mcount; i++) {
@@ -611,6 +638,7 @@ call_server(host, port, oid, service_name, gss_flags, auth_flag,
}
(void) close(s);
+
return 0;
}
@@ -776,7 +804,7 @@ main(argc, argv)
} else if (strcmp(*argv, "-iakerb") == 0) {
mechanism = "{ 1 3 6 1 5 2 5 }";
} else if (strcmp(*argv, "-spnego") == 0) {
- mechanism = "{ 1 3 6 1 5 5 2 }";
+ spnego = 1;
} else if (strcmp(*argv, "-krb5") == 0) {
mechanism = "{ 1 3 5 1 5 2 }";
#ifdef _WIN32
diff --git a/src/appl/gss-sample/gss-server.c b/src/appl/gss-sample/gss-server.c
index 0ddfaeee87..e83326791a 100644
--- a/src/appl/gss-sample/gss-server.c
+++ b/src/appl/gss-sample/gss-server.c
@@ -67,6 +67,9 @@
#include <strings.h>
#endif
+static OM_uint32
+enumerateAttributes(OM_uint32 *minor, gss_name_t name, int noisy);
+
static void
usage()
{
@@ -104,6 +107,7 @@ int verbose = 0;
* fails, an error message is displayed and -1 is returned; otherwise,
* 0 is returned.
*/
+
static int
server_acquire_creds(char *service_name, gss_cred_id_t *server_creds)
{
@@ -121,7 +125,7 @@ server_acquire_creds(char *service_name, gss_cred_id_t *server_creds)
}
maj_stat = gss_acquire_cred(&min_stat, server_name, 0,
- GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+ GSS_C_NO_OID_SET, GSS_C_ACCEPT,
server_creds, NULL, NULL);
if (maj_stat != GSS_S_COMPLETE) {
display_status("acquiring credentials", maj_stat, min_stat);
@@ -262,6 +266,7 @@ server_establish_context(int s, gss_cred_id_t server_creds,
display_status("displaying name", maj_stat, min_stat);
return -1;
}
+ enumerateAttributes(&min_stat, client, TRUE);
maj_stat = gss_release_name(&min_stat, &client);
if (maj_stat != GSS_S_COMPLETE) {
display_status("releasing name", maj_stat, min_stat);
@@ -410,7 +415,8 @@ sign_server(int s, gss_cred_id_t server_creds, int export)
gss_buffer_desc client_name, xmit_buf, msg_buf;
gss_ctx_id_t context;
OM_uint32 maj_stat, min_stat;
- int i, conf_state, ret_flags;
+ int i, conf_state;
+ OM_uint32 ret_flags;
char *cp;
int token_flags;
@@ -796,3 +802,77 @@ main(int argc, char **argv)
return 0;
}
+
+static void
+dumpAttribute(OM_uint32 *minor,
+ gss_name_t name,
+ gss_buffer_t attribute,
+ int noisy)
+{
+ OM_uint32 major, tmp;
+ gss_buffer_desc value;
+ gss_buffer_desc display_value;
+ int authenticated = 0;
+ int complete = 0;
+ int more = -1;
+ unsigned int i;
+
+ while (more != 0) {
+ value.value = NULL;
+ display_value.value = NULL;
+
+ major = gss_get_name_attribute(minor, name, attribute, &authenticated,
+ &complete, &value, &display_value,
+ &more);
+ if (GSS_ERROR(major)) {
+ display_status("gss_get_name_attribute", major, *minor);
+ break;
+ }
+
+ printf("Attribute %.*s %s %s\n\n%.*s\n",
+ (int)attribute->length, (char *)attribute->value,
+ authenticated ? "Authenticated" : "",
+ complete ? "Complete" : "",
+ (int)display_value.length, (char *)display_value.value);
+
+ if (noisy) {
+ for (i = 0; i < value.length; i++) {
+ if ((i % 32) == 0)
+ printf("\n");
+ printf("%02x", ((char *)value.value)[i] & 0xFF);
+ }
+ printf("\n\n");
+ }
+
+ gss_release_buffer(&tmp, &value);
+ gss_release_buffer(&tmp, &display_value);
+ }
+}
+
+static OM_uint32
+enumerateAttributes(OM_uint32 *minor,
+ gss_name_t name,
+ int noisy)
+{
+ OM_uint32 major, tmp;
+ int name_is_MN;
+ gss_OID mech = GSS_C_NO_OID;
+ gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
+ unsigned int i;
+
+ major = gss_inquire_name(minor, name, &name_is_MN, &mech, &attrs);
+ if (GSS_ERROR(major)) {
+ display_status("gss_inquire_name", major, *minor);
+ return major;
+ }
+
+ if (attrs != GSS_C_NO_BUFFER_SET) {
+ for (i = 0; i < attrs->count; i++)
+ dumpAttribute(minor, name, &attrs->elements[i], noisy);
+ }
+
+ gss_release_oid(&tmp, &mech);
+ gss_release_buffer_set(&tmp, &attrs);
+
+ return major;
+}
diff --git a/src/lib/gssapi/generic/gssapi.hin b/src/lib/gssapi/generic/gssapi.hin
index fb82e3c4f5..15d685d8c0 100644
--- a/src/lib/gssapi/generic/gssapi.hin
+++ b/src/lib/gssapi/generic/gssapi.hin
@@ -289,6 +289,8 @@ typedef int gss_cred_usage_t;
(((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_NAME_NOT_MN \
(((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_MECH_ATTR \
+ (((OM_uint32) 19ul) << GSS_C_ROUTINE_ERROR_OFFSET)
/*
* Supplementary info bits:
@@ -831,4 +833,85 @@ gss_set_neg_mechs(
/* XXXX This is a necessary evil until the spec is fixed */
#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
+/*
+ * RFC 5587
+ */
+typedef const gss_buffer_desc *gss_const_buffer_t;
+typedef const struct gss_channel_bindings_struct *gss_const_channel_bindings_t;
+typedef const struct gss_ctx_id_struct gss_const_ctx_id_t;
+typedef const struct gss_cred_id_struct gss_const_cred_id_t;
+typedef const struct gss_name_struct gss_const_name_t;
+typedef const gss_OID_desc *gss_const_OID;
+typedef const gss_OID_set_desc *gss_const_OID_set;
+
+OM_uint32 KRB5_CALLCONV
+gss_indicate_mechs_by_attrs(
+ OM_uint32 *, /* minor_status */
+ gss_const_OID_set, /* desired_mech_attrs */
+ gss_const_OID_set, /* except_mech_attrs */
+ gss_const_OID_set, /* critical_mech_attrs */
+ gss_OID_set *); /* mechs */
+
+OM_uint32 KRB5_CALLCONV
+gss_inquire_attrs_for_mech(
+ OM_uint32 *, /* minor_status */
+ gss_const_OID, /* mech */
+ gss_OID_set *, /* mech_attrs */
+ gss_OID_set *); /* known_mech_attrs */
+
+OM_uint32 KRB5_CALLCONV
+gss_display_mech_attr(
+ OM_uint32 *, /* minor_status */
+ gss_const_OID, /* mech_attr */
+ gss_buffer_t, /* name */
+ gss_buffer_t, /* short_desc */
+ gss_buffer_t); /* long_desc */
+
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_CONCRETE;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_PSEUDO;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_COMPOSITE;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_NEGO;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_GLUE;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_NOT_MECH;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_DEPRECATED;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_NOT_DFLT_MECH;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_ITOK_FRAMED;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_INIT;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_TARG;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_INIT_INIT;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_TARG_INIT;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_INIT_ANON;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_TARG_ANON;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_DELEG_CRED;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_INTEG_PROT;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_CONF_PROT;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_MIC;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_WRAP;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_PROT_READY;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_REPLAY_DET;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_OOS_DET;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_CBINDINGS;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_PFS;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_COMPRESS;
+GSS_DLLIMP extern gss_const_OID GSS_C_MA_CTX_TRANS;
+
+/*
+ * RFC 5801
+ */
+OM_uint32 KRB5_CALLCONV
+gss_inquire_saslname_for_mech(
+ OM_uint32 *, /* minor_status */
+ const gss_OID, /* desired_mech */
+ gss_buffer_t, /* sasl_mech_name */
+ gss_buffer_t, /* mech_name */
+ gss_buffer_t /* mech_description */
+);
+
+OM_uint32 KRB5_CALLCONV
+gss_inquire_mech_for_saslname(
+ OM_uint32 *, /* minor_status */
+ const gss_buffer_t, /* sasl_mech_name */
+ gss_OID * /* mech_type */
+);
+
#endif /* _GSSAPI_H_ */
diff --git a/src/lib/gssapi/generic/gssapiP_generic.h b/src/lib/gssapi/generic/gssapiP_generic.h
index cb2340a4bc..f3af8a4d11 100644
--- a/src/lib/gssapi/generic/gssapiP_generic.h
+++ b/src/lib/gssapi/generic/gssapiP_generic.h
@@ -294,4 +294,13 @@ OM_uint32 generic_gss_copy_oid_set
const gss_OID_set_desc *, /* const oidset*/
gss_OID_set * /*new_oidset*/);
+extern gss_OID_set gss_ma_known_attrs;
+
+OM_uint32 generic_gss_display_mech_attr(
+ OM_uint32 *minor_status,
+ gss_const_OID mech_attr,
+ gss_buffer_t name,
+ gss_buffer_t short_desc,
+ gss_buffer_t long_desc);
+
#endif /* _GSSAPIP_GENERIC_H_ */
diff --git a/src/lib/gssapi/generic/gssapi_generic.c b/src/lib/gssapi/generic/gssapi_generic.c
index 1d77d3f815..f8d2c426c2 100644
--- a/src/lib/gssapi/generic/gssapi_generic.c
+++ b/src/lib/gssapi/generic/gssapi_generic.c
@@ -122,6 +122,35 @@ static const gss_OID_desc const_oids[] = {
/* GSS_C_INQ_SSPI_SESSION_KEY 1.2.840.113554.1.2.2.5.5 */
{11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"},
+
+ /* RFC 5587 attributes, see below */
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x01"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x02"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x03"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x04"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x05"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x06"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x07"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x08"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x09"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0a"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0b"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0c"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0d"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0e"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0f"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x10"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x11"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x12"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x13"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x14"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x15"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x16"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x17"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x18"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x19"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1a"},
+ {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1b"},
};
/* Here are the constants which point to the static structure above.
@@ -152,3 +181,234 @@ GSS_DLLIMP gss_OID GSS_C_NT_EXPORT_NAME = oids+6;
gss_OID gss_nt_exported_name = oids+6;
GSS_DLLIMP gss_OID GSS_C_INQ_SSPI_SESSION_KEY = oids+7;
+
+GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_CONCRETE = oids+8;
+GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_PSEUDO = oids+9;
+GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_COMPOSITE = oids+10;
+GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_NEGO = oids+11;
+GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_GLUE = oids+12;
+GSS_DLLIMP gss_const_OID GSS_C_MA_NOT_MECH = oids+13;
+GSS_DLLIMP gss_const_OID GSS_C_MA_DEPRECATED = oids+14;
+GSS_DLLIMP gss_const_OID GSS_C_MA_NOT_DFLT_MECH = oids+15;
+GSS_DLLIMP gss_const_OID GSS_C_MA_ITOK_FRAMED = oids+16;
+GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_INIT = oids+17;
+GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_TARG = oids+18;
+GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_INIT_INIT = oids+19;
+GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_TARG_INIT = oids+20;
+GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_INIT_ANON = oids+21;
+GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_TARG_ANON = oids+22;
+GSS_DLLIMP gss_const_OID GSS_C_MA_DELEG_CRED = oids+23;
+GSS_DLLIMP gss_const_OID GSS_C_MA_INTEG_PROT = oids+24;
+GSS_DLLIMP gss_const_OID GSS_C_MA_CONF_PROT = oids+25;
+GSS_DLLIMP gss_const_OID GSS_C_MA_MIC = oids+26;
+GSS_DLLIMP gss_const_OID GSS_C_MA_WRAP = oids+27;
+GSS_DLLIMP gss_const_OID GSS_C_MA_PROT_READY = oids+28;
+GSS_DLLIMP gss_const_OID GSS_C_MA_REPLAY_DET = oids+29;
+GSS_DLLIMP gss_const_OID GSS_C_MA_OOS_DET = oids+30;
+GSS_DLLIMP gss_const_OID GSS_C_MA_CBINDINGS = oids+31;
+GSS_DLLIMP gss_const_OID GSS_C_MA_PFS = oids+32;
+GSS_DLLIMP gss_const_OID GSS_C_MA_COMPRESS = oids+33;
+GSS_DLLIMP gss_const_OID GSS_C_MA_CTX_TRANS = oids+34;
+
+static gss_OID_set_desc gss_ma_known_attrs_desc = { 27, oids+8 };
+gss_OID_set gss_ma_known_attrs = &gss_ma_known_attrs_desc;
+
+#define STRING_BUFFER(x) { sizeof((x) - 1), (x) }
+
+static struct mech_attr_info_desc {
+ gss_OID mech_attr;
+ gss_buffer_desc name;
+ gss_buffer_desc short_desc;
+ gss_buffer_desc long_desc;
+} mech_attr_info[] = {
+ {
+ oids+8,
+ STRING_BUFFER("GSS_C_MA_MECH_CONCRETE"),
+ STRING_BUFFER("Mechanism is neither a pseudo-mechanism nor a "
+ "composite mechanism."),
+ },
+ {
+ oids+9,
+ STRING_BUFFER("GSS_C_MA_MECH_PSEUDO"),
+ STRING_BUFFER("Mechanism is a pseudo-mechanism"),
+ },
+ {
+ oids+10,
+ STRING_BUFFER("GSS_C_MA_MECH_COMPOSITE"),
+ STRING_BUFFER("Mechanism is a composite of other mechanisms."),
+ },
+ {
+ oids+11,
+ STRING_BUFFER("GSS_C_MA_MECH_NEGO"),
+ STRING_BUFFER("Mechanism negotiates other mechanisms."),
+ },
+ {
+ oids+12,
+ STRING_BUFFER("GSS_C_MA_MECH_GLUE"),
+ STRING_BUFFER("OID is not a mechanism but the GSS-API itself."),
+ },
+ {
+ oids+13,
+ STRING_BUFFER("GSS_C_MA_NOT_MECH"),
+ STRING_BUFFER("Known OID but not a mechanism OID."),
+ },
+ {
+ oids+14,
+ STRING_BUFFER("GSS_C_MA_DEPRECATED"),
+ STRING_BUFFER("Mechanism is deprecated."),
+ },
+ {
+ oids+15,
+ STRING_BUFFER("GSS_C_MA_NOT_DFLT_MECH"),
+ STRING_BUFFER("Mechanism must not be used as a default mechanism."),
+ },
+ {
+ oids+16,
+ STRING_BUFFER("GSS_C_MA_ITOK_FRAMED"),
+ STRING_BUFFER("Mechanism's initial contexts are properly framed."),
+ },
+ {
+ oids+17,
+ STRING_BUFFER("GSS_C_MA_AUTH_INIT"),
+ STRING_BUFFER("Mechanism supports authentication of initiator to "
+ "acceptor."),
+ },
+ {
+ oids+18,
+ STRING_BUFFER("GSS_C_MA_AUTH_TARG"),
+ STRING_BUFFER("Mechanism supports authentication of acceptor to "
+ "initiator."),
+ },
+ {
+ oids+19,
+ STRING_BUFFER("GSS_C_MA_AUTH_INIT_INIT"),
+ STRING_BUFFER("Mechanism supports authentication of initiator using "
+ "initial credentials."),
+ },
+ {
+ oids+20,
+ STRING_BUFFER("GSS_C_MA_AUTH_TARG_INIT"),
+ STRING_BUFFER("Mechanism supports authentication of acceptor using "
+ "initial credentials."),
+ },
+ {
+ oids+21,
+ STRING_BUFFER("GSS_C_MA_AUTH_INIT_ANON"),
+ STRING_BUFFER("Mechanism supports GSS_C_NT_ANONYMOUS as an initiator "
+ "name."),
+ },
+ {
+ oids+22,
+ STRING_BUFFER("GSS_C_MA_AUTH_TARG_ANON"),
+ STRING_BUFFER("Mechanism supports GSS_C_NT_ANONYMOUS as an acceptor "
+ "name."),
+ },
+ {
+ oids+23,
+ STRING_BUFFER("GSS_C_MA_DELEG_CRED"),
+ STRING_BUFFER("Mechanism supports credential delegation."),
+ },
+ {
+ oids+24,
+ STRING_BUFFER("GSS_C_MA_INTEG_PROT"),
+ STRING_BUFFER("Mechanism supports per-message integrity protection."),
+ },
+ {
+ oids+25,
+ STRING_BUFFER("GSS_C_MA_CONF_PROT"),
+ STRING_BUFFER("Mechanism supports per-message confidentiality"
+ "protection."),
+ },
+ {
+ oids+26,
+ STRING_BUFFER("GSS_C_MA_MIC"),
+ STRING_BUFFER("Mechanism supports Message Integrity Code (MIC) "
+ "tokens."),
+ },
+ {
+ oids+27,
+ STRING_BUFFER("GSS_C_MA_WRAP"),
+ STRING_BUFFER("Mechanism supports wrap tokens."),
+ },
+ {
+ oids+28,
+ STRING_BUFFER("GSS_C_MA_PROT_READY"),
+ STRING_BUFFER("Mechanism supports per-message proteciton prior to "
+ "full context establishment."),
+ },
+ {
+ oids+29,
+ STRING_BUFFER("GSS_C_MA_REPLAY_DET"),
+ STRING_BUFFER("Mechanism supports replay detection."),
+ },
+ {
+ oids+30,
+ STRING_BUFFER("GSS_C_MA_OOS_DET"),
+ STRING_BUFFER("Mechanism supports out-of-sequence detection."),
+ },
+ {
+ oids+31,
+ STRING_BUFFER("GSS_C_MA_CBINDINGS"),
+ STRING_BUFFER("Mechanism supports channel bindings."),
+ },
+ {
+ oids+32,
+ STRING_BUFFER("GSS_C_MA_PFS"),
+ STRING_BUFFER("Mechanism supports Perfect Forward Security."),
+ },
+ {
+ oids+33,
+ STRING_BUFFER("GSS_C_MA_COMPRESS"),
+ STRING_BUFFER("Mechanism supports compression of data inputs to "
+ "gss_wrap()."),
+ },
+ {
+ oids+34,
+ STRING_BUFFER("GSS_C_MA_CTX_TRANS"),
+ STRING_BUFFER("Mechanism supports security context export/import."),
+ },
+};
+
+OM_uint32
+generic_gss_display_mech_attr(
+ OM_uint32 *minor_status,
+ gss_const_OID mech_attr,
+ gss_buffer_t name,
+ gss_buffer_t short_desc,
+ gss_buffer_t long_desc)
+{
+ size_t i;
+
+ if (name != GSS_C_NO_BUFFER) {
+ name->length = 0;
+ name->value = NULL;
+ }
+ if (short_desc != GSS_C_NO_BUFFER) {
+ short_desc->length = 0;
+ short_desc->value = NULL;
+ }
+ if (long_desc != GSS_C_NO_BUFFER) {
+ long_desc->length = 0;
+ long_desc->value = NULL;
+ }
+ for (i = 0; i < sizeof(mech_attr_info)/sizeof(mech_attr_info[0]); i++) {
+ struct mech_attr_info_desc *mai = &mech_attr_info[i];
+
+ if (g_OID_equal(mech_attr, mai->mech_attr)) {
+ if (name != GSS_C_NO_BUFFER &&
+ !g_make_string_buffer((char *)mai->name.value, name)) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ if (short_desc != GSS_C_NO_BUFFER &&
+ !g_make_string_buffer((char *)mai->short_desc.value,
+ short_desc)) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ return GSS_S_COMPLETE;
+ }
+ }
+
+ return GSS_S_BAD_MECH_ATTR;
+}
diff --git a/src/lib/gssapi/generic/util_buffer.c b/src/lib/gssapi/generic/util_buffer.c
index cd16862f6d..81d86fc760 100644
--- a/src/lib/gssapi/generic/util_buffer.c
+++ b/src/lib/gssapi/generic/util_buffer.c
@@ -34,6 +34,9 @@
int g_make_string_buffer(const char *str, gss_buffer_t buffer)
{
+ if (buffer == GSS_C_NO_BUFFER)
+ return (1);
+
buffer->length = strlen(str);
if ((buffer->value = strdup(str)) == NULL) {
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index 8b074d6168..25534e56b6 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -630,6 +630,116 @@ krb5_gssspi_mech_invoke (OM_uint32 *minor_status,
return GSS_S_UNAVAILABLE;
}
+#define GS2_KRB5_SASL_NAME "GS2-KRB5"
+#define GS2_KRB5_SASL_NAME_LEN (sizeof(GS2_KRB5_SASL_NAME) - 1)
+
+#define GS2_IAKERB_SASL_NAME "GS2-IAKERB"
+#define GS2_IAKERB_SASL_NAME_LEN (sizeof(GS2_IAKERB_SASL_NAME) - 1)
+
+static OM_uint32
+krb5_gss_inquire_mech_for_saslname(OM_uint32 *minor_status,
+ const gss_buffer_t sasl_mech_name,
+ gss_OID *mech_type)
+{
+ *minor_status = 0;
+
+ if (sasl_mech_name->length == GS2_KRB5_SASL_NAME_LEN &&
+ memcmp(sasl_mech_name->value,
+ GS2_KRB5_SASL_NAME, GS2_KRB5_SASL_NAME_LEN) == 0) {
+ if (mech_type != NULL)
+ *mech_type = (gss_OID)gss_mech_krb5;
+ return GSS_S_COMPLETE;
+ } else if (sasl_mech_name->length == GS2_IAKERB_SASL_NAME_LEN &&
+ memcmp(sasl_mech_name->value,
+ GS2_IAKERB_SASL_NAME, GS2_IAKERB_SASL_NAME_LEN) == 0) {
+ if (mech_type != NULL)
+ *mech_type = (gss_OID)gss_mech_iakerb;
+ return GSS_S_COMPLETE;
+ }
+
+ return GSS_S_BAD_MECH;
+}
+
+static OM_uint32
+krb5_gss_inquire_saslname_for_mech(OM_uint32 *minor_status,
+ const gss_OID desired_mech,
+ gss_buffer_t sasl_mech_name,
+ gss_buffer_t mech_name,
+ gss_buffer_t mech_description)
+{
+ if (g_OID_equal(desired_mech, gss_mech_iakerb)) {
+ if (!g_make_string_buffer(GS2_IAKERB_SASL_NAME, sasl_mech_name) ||
+ !g_make_string_buffer("iakerb", mech_name) ||
+ !g_make_string_buffer("Initial and Pass Through Authentication "
+ "Kerberos Mechanism (IAKERB)", mech_description))
+ goto fail;
+ } else {
+ if (!g_make_string_buffer(GS2_KRB5_SASL_NAME, sasl_mech_name) ||
+ !g_make_string_buffer("krb5", mech_name) ||
+ !g_make_string_buffer("Kerberos 5 GSS-API Mechanism",
+ mech_description))
+ goto fail;
+ }
+
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+
+fail:
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+}
+
+static OM_uint32
+krb5_gss_inquire_attrs_for_mech(OM_uint32 *minor_status,
+ gss_const_OID mech,
+ gss_OID_set *mech_attrs,
+ gss_OID_set *known_mech_attrs)
+{
+ OM_uint32 major, tmpMinor;
+
+ if (mech_attrs == NULL) {
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+ }
+
+ major = gss_create_empty_oid_set(minor_status, mech_attrs);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+#define MA_SUPPORTED(ma) do { \
+ major = gss_add_oid_set_member(minor_status, (gss_OID)ma, mech_attrs); \
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
+ MA_SUPPORTED(GSS_C_MA_MECH_CONCRETE);
+ MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED);
+ MA_SUPPORTED(GSS_C_MA_AUTH_INIT);
+ MA_SUPPORTED(GSS_C_MA_AUTH_TARG);
+ MA_SUPPORTED(GSS_C_MA_DELEG_CRED);
+ MA_SUPPORTED(GSS_C_MA_INTEG_PROT);
+ MA_SUPPORTED(GSS_C_MA_CONF_PROT);
+ MA_SUPPORTED(GSS_C_MA_MIC);
+ MA_SUPPORTED(GSS_C_MA_WRAP);
+ MA_SUPPORTED(GSS_C_MA_PROT_READY);
+ MA_SUPPORTED(GSS_C_MA_REPLAY_DET);
+ MA_SUPPORTED(GSS_C_MA_OOS_DET);
+ MA_SUPPORTED(GSS_C_MA_CBINDINGS);
+ MA_SUPPORTED(GSS_C_MA_CTX_TRANS);
+
+ if (g_OID_equal(mech, gss_mech_iakerb)) {
+ MA_SUPPORTED(GSS_C_MA_AUTH_INIT_INIT);
+ } else if (!g_OID_equal(mech, gss_mech_krb5)) {
+ MA_SUPPORTED(GSS_C_MA_DEPRECATED);
+ }
+
+cleanup:
+ if (GSS_ERROR(major))
+ gss_release_oid_set(&tmpMinor, mech_attrs);
+
+ return major;
+}
+
static struct gss_config krb5_mechanism = {
{ GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
NULL,
@@ -701,6 +811,9 @@ static struct gss_config krb5_mechanism = {
krb5_gss_release_any_name_mapping,
krb5_gss_pseudo_random,
NULL, /* set_neg_mechs */
+ krb5_gss_inquire_saslname_for_mech,
+ krb5_gss_inquire_mech_for_saslname,
+ krb5_gss_inquire_attrs_for_mech,
};
static struct gss_config_ext krb5_mechanism_ext = {
diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
index 707fe52eee..fee99c994e 100644
--- a/src/lib/gssapi/libgssapi_krb5.exports
+++ b/src/lib/gssapi/libgssapi_krb5.exports
@@ -7,6 +7,33 @@ GSS_C_NT_MACHINE_UID_NAME
GSS_C_NT_STRING_UID_NAME
GSS_C_NT_USER_NAME
GSS_KRB5_NT_PRINCIPAL_NAME
+GSS_C_MA_MECH_CONCRETE
+GSS_C_MA_MECH_PSEUDO
+GSS_C_MA_MECH_COMPOSITE
+GSS_C_MA_MECH_NEGO
+GSS_C_MA_MECH_GLUE
+GSS_C_MA_NOT_MECH
+GSS_C_MA_DEPRECATED
+GSS_C_MA_NOT_DFLT_MECH
+GSS_C_MA_ITOK_FRAMED
+GSS_C_MA_AUTH_INIT
+GSS_C_MA_AUTH_TARG
+GSS_C_MA_AUTH_INIT_INIT
+GSS_C_MA_AUTH_TARG_INIT
+GSS_C_MA_AUTH_INIT_ANON
+GSS_C_MA_AUTH_TARG_ANON
+GSS_C_MA_DELEG_CRED
+GSS_C_MA_INTEG_PROT
+GSS_C_MA_CONF_PROT
+GSS_C_MA_MIC
+GSS_C_MA_WRAP
+GSS_C_MA_PROT_READY
+GSS_C_MA_REPLAY_DET
+GSS_C_MA_OOS_DET
+GSS_C_MA_CBINDINGS
+GSS_C_MA_PFS
+GSS_C_MA_COMPRESS
+GSS_C_MA_CTX_TRANS
gss_accept_sec_context
gss_acquire_cred
gss_acquire_cred_with_password
@@ -23,6 +50,7 @@ gss_create_empty_buffer_set
gss_create_empty_oid_set
gss_delete_name_attribute
gss_delete_sec_context
+gss_display_mech_attr
gss_display_name
gss_display_name_ext
gss_display_status
@@ -36,12 +64,16 @@ gss_import_name
gss_import_sec_context
gss_indicate_mechs
gss_init_sec_context
+gss_indicate_mechs_by_attrs
+gss_inquire_attrs_for_mech
gss_inquire_context
gss_inquire_cred
gss_inquire_cred_by_mech
gss_inquire_cred_by_oid
+gss_inquire_mech_for_saslname
gss_inquire_mechs_for_name
gss_inquire_names_for_mech
+gss_inquire_saslname_for_mech
gss_inquire_sec_context_by_oid
gss_krb5_ccache_name
gss_krb5_copy_ccache
diff --git a/src/lib/gssapi/mechglue/Makefile.in b/src/lib/gssapi/mechglue/Makefile.in
index 92cd6c99cc..d2dccb46be 100644
--- a/src/lib/gssapi/mechglue/Makefile.in
+++ b/src/lib/gssapi/mechglue/Makefile.in
@@ -42,6 +42,7 @@ SRCS = \
$(srcdir)/g_inq_names.c \
$(srcdir)/g_map_name_to_any.c \
$(srcdir)/g_mech_invoke.c \
+ $(srcdir)/g_mechattr.c \
$(srcdir)/g_mechname.c \
$(srcdir)/g_oid_ops.c \
$(srcdir)/g_prf.c \
@@ -51,6 +52,7 @@ SRCS = \
$(srcdir)/g_rel_name.c \
$(srcdir)/g_rel_name_mapping.c \
$(srcdir)/g_rel_oid_set.c \
+ $(srcdir)/g_saslname.c \
$(srcdir)/g_seal.c \
$(srcdir)/g_set_context_option.c \
$(srcdir)/g_set_cred_option.c \
@@ -98,6 +100,7 @@ OBJS = \
$(OUTPRE)g_inq_names.$(OBJEXT) \
$(OUTPRE)g_map_name_to_any.$(OBJEXT) \
$(OUTPRE)g_mech_invoke.$(OBJEXT) \
+ $(OUTPRE)g_mechattr.$(OBJEXT) \
$(OUTPRE)g_mechname.$(OBJEXT) \
$(OUTPRE)g_oid_ops.$(OBJEXT) \
$(OUTPRE)g_prf.$(OBJEXT) \
@@ -107,6 +110,7 @@ OBJS = \
$(OUTPRE)g_rel_name.$(OBJEXT) \
$(OUTPRE)g_rel_name_mapping.$(OBJEXT) \
$(OUTPRE)g_rel_oid_set.$(OBJEXT) \
+ $(OUTPRE)g_saslname.$(OBJEXT) \
$(OUTPRE)g_seal.$(OBJEXT) \
$(OUTPRE)g_set_context_option.$(OBJEXT) \
$(OUTPRE)g_set_cred_option.$(OBJEXT) \
@@ -154,6 +158,7 @@ STLIBOBJS = \
g_inq_names.o \
g_map_name_to_any.o \
g_mech_invoke.o \
+ g_mechattr.o \
g_mechname.o \
g_oid_ops.o \
g_prf.o \
@@ -163,6 +168,7 @@ STLIBOBJS = \
g_rel_name.o \
g_rel_name_mapping.o \
g_rel_oid_set.o \
+ g_saslname.o \
g_seal.o \
g_set_context_option.o \
g_set_cred_option.o \
diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c
index a393a53095..d8b4956404 100644
--- a/src/lib/gssapi/mechglue/g_initialize.c
+++ b/src/lib/gssapi/mechglue/g_initialize.c
@@ -791,6 +791,11 @@ build_dynamicMech(void *dl, const gss_OID mech_type)
GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_pseudo_random);
/* RFC 4178 (introduced in 1.8; gss_get_neg_mechs not implemented) */
GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_set_neg_mechs);
+ /* draft-ietf-sasl-gs2 */
+ GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_saslname_for_mech);
+ GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_mech_for_saslname);
+ /* RFC 5587 */
+ GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_attrs_for_mech);
assert(mech_type != GSS_C_NO_OID);
diff --git a/src/lib/gssapi/mechglue/g_mechattr.c b/src/lib/gssapi/mechglue/g_mechattr.c
new file mode 100644
index 0000000000..63ec35768a
--- /dev/null
+++ b/src/lib/gssapi/mechglue/g_mechattr.c
@@ -0,0 +1,224 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * src/lib/gssapi/mechglue/g_mechattr.c
+ *
+ * Copyright (C) 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ *
+ */
+#include "mglueP.h"
+
+static int
+testMechAttr(gss_const_OID attr,
+ gss_const_OID_set against)
+{
+ int present = 0;
+ OM_uint32 minor;
+
+ if (GSS_ERROR(generic_gss_test_oid_set_member(&minor, attr,
+ (gss_OID_set)against,
+ &present)))
+ return 0;
+
+ return present;
+}
+
+/*
+ * Return TRUE iff all the elements of desired and none of the elements
+ * of except exist in available.
+ */
+static int
+testMechAttrsOffered(gss_const_OID_set desired,
+ gss_const_OID_set except,
+ gss_const_OID_set available)
+{
+ size_t i;
+
+ if (desired != GSS_C_NO_OID_SET) {
+ for (i = 0; i < desired->count; i++) {
+ if (!testMechAttr(&desired->elements[i], available))
+ return 0;
+ }
+ }
+
+ if (except != GSS_C_NO_OID_SET) {
+ for (i = 0; i < except->count; i++) {
+ if (testMechAttr(&except->elements[i], available))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Return TRUE iff all the elements of critical exist in known.
+ */
+static int
+testMechAttrsKnown(gss_const_OID_set critical,
+ gss_const_OID_set known)
+{
+ size_t i;
+
+ if (critical != GSS_C_NO_OID_SET) {
+ for (i = 0; i < critical->count; i++) {
+ if (!testMechAttr(&critical->elements[i], known))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+OM_uint32 gss_indicate_mechs_by_attrs(
+ OM_uint32 *minor,
+ gss_const_OID_set desired_mech_attrs,
+ gss_const_OID_set except_mech_attrs,
+ gss_const_OID_set critical_mech_attrs,
+ gss_OID_set *mechs)
+{
+ OM_uint32 status, tmpMinor;
+ gss_OID_set allMechs = GSS_C_NO_OID_SET;
+ size_t i;
+
+ if (minor == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *minor = 0;
+
+ if (mechs == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *mechs = GSS_C_NO_OID_SET;
+
+ status = gss_indicate_mechs(minor, &allMechs);
+ if (GSS_ERROR(status))
+ goto cleanup;
+
+ status = generic_gss_create_empty_oid_set(minor, mechs);
+ if (GSS_ERROR(status))
+ goto cleanup;
+
+ for (i = 0; i < allMechs->count; i++) {
+ gss_OID_set supportedAttrs = GSS_C_NO_OID_SET;
+ gss_OID_set knownAttrs = GSS_C_NO_OID_SET;
+
+ status = gss_inquire_attrs_for_mech(minor, &allMechs->elements[i],
+ &supportedAttrs, &knownAttrs);
+ if (GSS_ERROR(status))
+ continue;
+
+ if (testMechAttrsOffered(desired_mech_attrs,
+ except_mech_attrs, supportedAttrs) &&
+ testMechAttrsKnown(critical_mech_attrs, knownAttrs)) {
+ status = gss_add_oid_set_member(minor, &allMechs->elements[i],
+ mechs);
+ if (GSS_ERROR(status)) {
+ gss_release_oid_set(&tmpMinor, &supportedAttrs);
+ gss_release_oid_set(&tmpMinor, &knownAttrs);
+ goto cleanup;
+ }
+ }
+
+ gss_release_oid_set(&tmpMinor, &supportedAttrs);
+ gss_release_oid_set(&tmpMinor, &knownAttrs);
+ }
+
+ *minor = 0;
+ status = GSS_S_COMPLETE;
+
+cleanup:
+ gss_release_oid_set(&tmpMinor, &allMechs);
+
+ return status;
+}
+
+OM_uint32 gss_inquire_attrs_for_mech(
+ OM_uint32 *minor,
+ gss_const_OID mech_oid,
+ gss_OID_set *mech_attrs,
+ gss_OID_set *known_mech_attrs)
+{
+ OM_uint32 status, tmpMinor;
+ gss_mechanism mech;
+
+ if (minor == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *minor = 0;
+
+ if (mech_attrs != NULL)
+ *mech_attrs = GSS_C_NO_OID_SET;
+
+ if (known_mech_attrs != NULL)
+ *known_mech_attrs = GSS_C_NO_OID_SET;
+
+ mech = gssint_get_mechanism((gss_OID)mech_oid);
+ if (mech != NULL && mech->gss_inquire_attrs_for_mech != NULL) {
+ status = mech->gss_inquire_attrs_for_mech(minor,
+ mech_oid,
+ mech_attrs,
+ known_mech_attrs);
+ if (GSS_ERROR(status))
+ return status;
+ }
+
+ if (mech_attrs != NULL && mech != gssint_get_mechanism(NULL)) {
+ if (*mech_attrs == GSS_C_NO_OID_SET) {
+ status = generic_gss_create_empty_oid_set(minor, mech_attrs);
+ if (GSS_ERROR(status))
+ return status;
+ }
+
+ status = generic_gss_add_oid_set_member(minor, GSS_C_MA_NOT_DFLT_MECH,
+ mech_attrs);
+ if (GSS_ERROR(status)) {
+ gss_release_oid_set(&tmpMinor, mech_attrs);
+ return status;
+ }
+ }
+
+ if (known_mech_attrs != NULL && *known_mech_attrs == GSS_C_NO_OID_SET) {
+ status = generic_gss_copy_oid_set(minor,
+ gss_ma_known_attrs,
+ known_mech_attrs);
+ if (GSS_ERROR(status)) {
+ gss_release_oid_set(&tmpMinor, mech_attrs);
+ *mech_attrs = GSS_C_NO_OID_SET;
+ }
+ }
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_display_mech_attr(
+ OM_uint32 *minor,
+ gss_const_OID mech_attr,
+ gss_buffer_t name,
+ gss_buffer_t short_desc,
+ gss_buffer_t long_desc)
+{
+ return generic_gss_display_mech_attr(minor, mech_attr,
+ name, short_desc, long_desc);
+}
diff --git a/src/lib/gssapi/mechglue/g_saslname.c b/src/lib/gssapi/mechglue/g_saslname.c
new file mode 100644
index 0000000000..4bffdd6026
--- /dev/null
+++ b/src/lib/gssapi/mechglue/g_saslname.c
@@ -0,0 +1,210 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * src/lib/gssapi/mechglue/g_saslname.c
+ *
+ * Copyright (C) 2010 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ *
+ *
+ */
+#include "mglueP.h"
+#include <krb5/krb5.h>
+
+static char basis_32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+
+#define OID_SASL_NAME_LENGTH (sizeof("GS2-XXXXXXXXXXX") - 1)
+
+static OM_uint32
+oidToSaslName(OM_uint32 *minor, const gss_OID mech,
+ char sasl_name[OID_SASL_NAME_LENGTH + 1])
+{
+ unsigned char derBuf[2];
+ krb5_crypto_iov iov[3];
+ unsigned char cksumBuf[20], *q = cksumBuf;
+ char *p = sasl_name;
+
+ if (mech->length > 127) {
+ *minor = ERANGE;
+ return GSS_S_BAD_MECH;
+ }
+
+ derBuf[0] = 0x06;
+ derBuf[1] = (unsigned char)mech->length;
+
+ iov[0].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ iov[0].data.length = 2;
+ iov[0].data.data = (char *)derBuf;
+ iov[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ iov[1].data.length = mech->length;
+ iov[1].data.data = (char *)mech->elements;
+ iov[2].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
+ iov[2].data.length = sizeof(cksumBuf);
+ iov[2].data.data = (char *)cksumBuf;
+
+ *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_NIST_SHA,
+ NULL, 0, iov, 3);
+ if (*minor != 0)
+ return GSS_S_FAILURE;
+
+ memcpy(p, "GS2-", 4);
+ p += 4;
+
+ *p++ = basis_32[q[0] >> 3];
+ *p++ = basis_32[((q[0] & 7) << 2) | (q[1] >> 6)];
+ *p++ = basis_32[(q[1] & 0x3f) >> 1];
+ *p++ = basis_32[((q[1] & 1) << 4) | (q[2] >> 4)];
+ *p++ = basis_32[((q[2] & 0xf) << 1) | (q[3] >> 7)];
+ *p++ = basis_32[(q[3] & 0x7f) >> 2];
+ *p++ = basis_32[((q[3] & 3) << 3) | (q[4] >> 5)];
+ *p++ = basis_32[(q[4] & 0x1f)];
+ *p++ = basis_32[q[5] >> 3];
+ *p++ = basis_32[((q[5] & 7) << 2) | (q[6] >> 6)];
+ *p++ = basis_32[(q[6] & 0x3f) >> 1];
+
+ *p++ = '\0';
+
+ *minor = 0;
+ return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+oidToSaslNameAlloc(OM_uint32 *minor, const gss_OID mech,
+ gss_buffer_t sasl_name)
+{
+ OM_uint32 status, tmpMinor;
+
+ sasl_name->value = malloc(OID_SASL_NAME_LENGTH + 1);
+ if (sasl_name->value == NULL) {
+ *minor = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ sasl_name->length = OID_SASL_NAME_LENGTH;
+
+ status = oidToSaslName(minor, mech, (char *)sasl_name->value);
+ if (GSS_ERROR(status)) {
+ gss_release_buffer(&tmpMinor, sasl_name);
+ return status;
+ }
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 KRB5_CALLCONV gss_inquire_saslname_for_mech(
+ OM_uint32 *minor_status,
+ const gss_OID desired_mech,
+ gss_buffer_t sasl_mech_name,
+ gss_buffer_t mech_name,
+ gss_buffer_t mech_description)
+{
+ OM_uint32 status = GSS_S_BAD_MECH;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *minor_status = 0;
+
+ if (sasl_mech_name != GSS_C_NO_BUFFER) {
+ sasl_mech_name->length = 0;
+ sasl_mech_name->value = NULL;
+ }
+
+ if (mech_name != GSS_C_NO_BUFFER) {
+ mech_name->length = 0;
+ mech_name->value = NULL;
+ }
+
+ if (mech_description != GSS_C_NO_BUFFER) {
+ mech_description->length = 0;
+ mech_description->value = NULL;
+ }
+
+ mech = gssint_get_mechanism(desired_mech);
+ if (mech != NULL && mech->gss_inquire_saslname_for_mech != NULL) {
+ status = mech->gss_inquire_saslname_for_mech(minor_status,
+ desired_mech,
+ sasl_mech_name,
+ mech_name,
+ mech_description);
+ }
+ if (status == GSS_S_BAD_MECH) {
+ if (sasl_mech_name != GSS_C_NO_BUFFER)
+ status = oidToSaslNameAlloc(minor_status, desired_mech,
+ sasl_mech_name);
+ else
+ status = GSS_S_COMPLETE;
+ }
+
+ return status;
+}
+
+OM_uint32 KRB5_CALLCONV gss_inquire_mech_for_saslname(
+ OM_uint32 *minor_status,
+ const gss_buffer_t sasl_mech_name,
+ gss_OID *mech_type)
+{
+ OM_uint32 status, tmpMinor;
+ gss_OID_set mechSet = GSS_C_NO_OID_SET;
+ size_t i;
+
+ if (minor_status == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *minor_status = 0;
+
+ if (mech_type != NULL)
+ *mech_type = GSS_C_NO_OID;
+
+ status = gss_indicate_mechs(minor_status, &mechSet);
+ if (status != GSS_S_COMPLETE)
+ return status;
+
+ for (i = 0, status = GSS_S_BAD_MECH; i < mechSet->count; i++) {
+ gss_mechanism mech;
+ char mappedName[OID_SASL_NAME_LENGTH + 1];
+
+ mech = gssint_get_mechanism(&mechSet->elements[i]);
+ if (mech != NULL && mech->gss_inquire_mech_for_saslname != NULL) {
+ status = mech->gss_inquire_mech_for_saslname(minor_status,
+ sasl_mech_name,
+ mech_type);
+ if (status == GSS_S_COMPLETE)
+ break;
+ }
+ if (status == GSS_S_BAD_MECH &&
+ sasl_mech_name->length == OID_SASL_NAME_LENGTH &&
+ oidToSaslName(&tmpMinor, &mechSet->elements[i],
+ mappedName) == GSS_S_COMPLETE &&
+ memcmp(sasl_mech_name->value, mappedName,
+ OID_SASL_NAME_LENGTH) == 0) {
+ if (mech_type != NULL)
+ *mech_type = &mech->mech_type;
+ status = GSS_S_COMPLETE;
+ break;
+ }
+ }
+
+ gss_release_oid_set(&tmpMinor, &mechSet);
+
+ return status;
+}
diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
index da427f4a67..63d89c7717 100644
--- a/src/lib/gssapi/mechglue/mglueP.h
+++ b/src/lib/gssapi/mechglue/mglueP.h
@@ -588,6 +588,31 @@ typedef struct gss_config {
gss_cred_id_t, /* cred_handle */
const gss_OID_set /* mech_set */
/* */);
+
+ OM_uint32 (*gss_inquire_saslname_for_mech)
+ (
+ OM_uint32 *, /* minor_status */
+ const gss_OID, /* desired_mech */
+ gss_buffer_t, /* sasl_mech_name */
+ gss_buffer_t, /* mech_name */
+ gss_buffer_t /* mech_description */
+ /* */);
+
+ OM_uint32 (*gss_inquire_mech_for_saslname)
+ (
+ OM_uint32 *, /* minor_status */
+ const gss_buffer_t, /* sasl_mech_name */
+ gss_OID * /* mech_type */
+ /* */);
+
+ OM_uint32 (*gss_inquire_attrs_for_mech)
+ (
+ OM_uint32 *, /* minor_status */
+ gss_const_OID, /* mech */
+ gss_OID_set *, /* mech_attrs */
+ gss_OID_set * /* known_mech_attrs */
+ /* */);
+
} *gss_mechanism;
/* This structure MUST NOT be used by any code outside libgss */
diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h
index e146508c5d..50f05678d6 100644
--- a/src/lib/gssapi/spnego/gssapiP_spnego.h
+++ b/src/lib/gssapi/spnego/gssapiP_spnego.h
@@ -565,6 +565,33 @@ spnego_gss_set_neg_mechs
const gss_OID_set mech_list
);
+OM_uint32
+spnego_gss_inquire_mech_for_saslname
+(
+ OM_uint32 *minor_status,
+ const gss_buffer_t sasl_mech_name,
+ gss_OID *mech_type
+);
+
+OM_uint32
+spnego_gss_inquire_saslname_for_mech
+(
+ OM_uint32 *minor_status,
+ const gss_OID desired_mech,
+ gss_buffer_t sasl_mech_name,
+ gss_buffer_t mech_name,
+ gss_buffer_t mech_description
+);
+
+OM_uint32
+spnego_gss_inquire_attrs_for_mech
+(
+ OM_uint32 *minor_status,
+ gss_const_OID mech,
+ gss_OID_set *mech_attrs,
+ gss_OID_set *known_mech_attrs
+);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
index 9c5a6140dd..d8706af927 100644
--- a/src/lib/gssapi/spnego/spnego_mech.c
+++ b/src/lib/gssapi/spnego/spnego_mech.c
@@ -272,6 +272,9 @@ static struct gss_config spnego_mechanism =
spnego_gss_release_any_name_mapping,
spnego_gss_pseudo_random,
spnego_gss_set_neg_mechs,
+ spnego_gss_inquire_saslname_for_mech,
+ spnego_gss_inquire_mech_for_saslname,
+ spnego_gss_inquire_attrs_for_mech,
};
static struct gss_config_ext spnego_mechanism_ext =
@@ -2257,7 +2260,6 @@ spnego_gss_set_cred_option(
gss_cred_id_t mcred;
mcred = (spcred == NULL) ? GSS_C_NO_CREDENTIAL : spcred->mcred;
-
ret = gss_set_cred_option(minor_status,
&mcred,
desired_object,
@@ -2279,6 +2281,23 @@ spnego_gss_set_cred_option(
*cred_handle = (gss_cred_id_t)spcred;
}
+ if (ret == GSS_S_COMPLETE && spcred == NULL) {
+ /*
+ * If the mechanism allocated a new credential handle, then
+ * we need to wrap it up in an SPNEGO credential handle.
+ */
+
+ spcred = malloc(sizeof(spnego_gss_cred_id_rec));
+ if (spcred == NULL) {
+ gss_release_cred(&tmp_minor_status, &mcred);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ spcred->mcred = mcred;
+ spcred->neg_mechs = GSS_C_NULL_OID_SET;
+ *cred_handle = (gss_cred_id_t)spcred;
+ }
+
return (ret);
}
@@ -2686,6 +2705,85 @@ spnego_gss_set_neg_mechs(OM_uint32 *minor_status,
return (ret);
}
+#define SPNEGO_SASL_NAME "SPNEGO"
+#define SPNEGO_SASL_NAME_LEN (sizeof(SPNEGO_SASL_NAME) - 1)
+
+OM_uint32
+spnego_gss_inquire_mech_for_saslname(OM_uint32 *minor_status,
+ const gss_buffer_t sasl_mech_name,
+ gss_OID *mech_type)
+{
+ if (sasl_mech_name->length == SPNEGO_SASL_NAME_LEN &&
+ memcmp(sasl_mech_name->value, SPNEGO_SASL_NAME,
+ SPNEGO_SASL_NAME_LEN) == 0) {
+ if (mech_type != NULL)
+ *mech_type = (gss_OID)gss_mech_spnego;
+ return (GSS_S_COMPLETE);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
+
+OM_uint32
+spnego_gss_inquire_saslname_for_mech(OM_uint32 *minor_status,
+ const gss_OID desired_mech,
+ gss_buffer_t sasl_mech_name,
+ gss_buffer_t mech_name,
+ gss_buffer_t mech_description)
+{
+ *minor_status = 0;
+
+ if (!g_OID_equal(desired_mech, gss_mech_spnego))
+ return (GSS_S_BAD_MECH);
+
+ if (!g_make_string_buffer(SPNEGO_SASL_NAME, sasl_mech_name) ||
+ !g_make_string_buffer("spnego", mech_name) ||
+ !g_make_string_buffer("Simple and Protected GSS-API "
+ "Negotiation Mechanism", mech_description))
+ goto fail;
+
+ return (GSS_S_COMPLETE);
+
+fail:
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+}
+
+OM_uint32
+spnego_gss_inquire_attrs_for_mech(OM_uint32 *minor_status,
+ gss_const_OID mech,
+ gss_OID_set *mech_attrs,
+ gss_OID_set *known_mech_attrs)
+{
+ OM_uint32 major, tmpMinor;
+
+ /* known_mech_attrs is handled by mechglue */
+ *minor_status = 0;
+
+ if (mech_attrs == NULL)
+ return (GSS_S_COMPLETE);
+
+ major = gss_create_empty_oid_set(minor_status, mech_attrs);
+ if (GSS_ERROR(major))
+ goto cleanup;
+
+#define MA_SUPPORTED(ma) do { \
+ major = gss_add_oid_set_member(minor_status, \
+ (gss_OID)ma, mech_attrs); \
+ if (GSS_ERROR(major)) \
+ goto cleanup; \
+ } while (0)
+
+ MA_SUPPORTED(GSS_C_MA_MECH_NEGO);
+ MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED);
+
+cleanup:
+ if (GSS_ERROR(major))
+ gss_release_oid_set(&tmpMinor, mech_attrs);
+
+ return (major);
+}
+
/*
* We will release everything but the ctx_handle so that it
* can be passed back to init/accept context. This routine should
diff --git a/src/tests/gssapi/Makefile.in b/src/tests/gssapi/Makefile.in
index 2ba81de61f..4002d001ef 100644
--- a/src/tests/gssapi/Makefile.in
+++ b/src/tests/gssapi/Makefile.in
@@ -4,11 +4,11 @@ DEFINES = -DUSE_AUTOCONF_H
PROG_LIBPATH=-L$(TOPLIBD)
PROG_RPATH=$(KRB5_LIBDIR)
-SRCS= $(srcdir)/t_imp_name.c $(srcdir)/t_s4u.c $(srcdir)/t_namingexts.c $(srcdir)/t_gssexts.c
+SRCS= $(srcdir)/t_imp_name.c $(srcdir)/t_s4u.c $(srcdir)/t_namingexts.c $(srcdir)/t_gssexts.c $(srcdir)/t_saslname.c
-OBJS= t_imp_name.o t_s4u.o t_namingexts.o t_gssexts.o t_spnego.o
+OBJS= t_imp_name.o t_s4u.o t_namingexts.o t_gssexts.o t_spnego.o t_saslname.o
-all:: t_imp_name t_s4u t_namingexts t_gssexts t_spnego
+all:: t_imp_name t_s4u t_namingexts t_gssexts t_spnego t_saslname
check-pytests:: t_spnego
$(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS)
@@ -23,7 +23,9 @@ t_gssexts: t_gssexts.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o t_gssexts t_gssexts.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
t_spnego: t_spnego.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o t_spnego t_spnego.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
+t_saslname: t_saslname.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o t_saslname t_saslname.o $(GSS_LIBS) $(KRB5_BASE_LIBS)
clean::
- $(RM) t_imp_name t_s4u t_namingexts t_gssexts t_spnego
+ $(RM) t_imp_name t_s4u t_namingexts t_gssexts t_spnego t_saslname
diff --git a/src/tests/gssapi/t_saslname.c b/src/tests/gssapi/t_saslname.c
new file mode 100644
index 0000000000..40384f7dc4
--- /dev/null
+++ b/src/tests/gssapi/t_saslname.c
@@ -0,0 +1,188 @@
+/* -*- mode: c; indent-tabs-mode: nil -*- */
+/*
+ * Copyright 2009 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_ext.h>
+
+static void
+displayStatus_1(char *m, OM_uint32 code, int type)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc msg;
+ OM_uint32 msg_ctx;
+
+ msg_ctx = 0;
+ while (1) {
+ maj_stat = gss_display_status(&min_stat, code,
+ type, GSS_C_NULL_OID,
+ &msg_ctx, &msg);
+ fprintf(stderr, "%s: %s\n", m, (char *)msg.value);
+ (void) gss_release_buffer(&min_stat, &msg);
+
+ if (!msg_ctx)
+ break;
+ }
+}
+
+static void
+displayStatus(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat)
+{
+ displayStatus_1(msg, maj_stat, GSS_C_GSS_CODE);
+ displayStatus_1(msg, min_stat, GSS_C_MECH_CODE);
+}
+
+static
+OM_uint32 dumpMechAttrs(OM_uint32 *minor, gss_OID mech)
+{
+ OM_uint32 major, tmpMinor;
+ gss_OID_set mech_attrs = GSS_C_NO_OID_SET;
+ gss_OID_set known_attrs = GSS_C_NO_OID_SET;
+ size_t i;
+
+ major = gss_inquire_attrs_for_mech(minor, mech, &mech_attrs, &known_attrs);
+ if (GSS_ERROR(major)) {
+ displayStatus("gss_inquire_attrs_for_mech", major, *minor);
+ return major;
+ }
+
+ printf("Mech attrs: ");
+
+ for (i = 0; i < mech_attrs->count; i++) {
+ gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc short_desc = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc long_desc = GSS_C_EMPTY_BUFFER;
+
+ major = gss_display_mech_attr(minor, &mech_attrs->elements[i],
+ &name, &short_desc, &long_desc);
+ if (GSS_ERROR(major)) {
+ displayStatus("gss_display_mech_attr", major, *minor);
+ continue;
+ }
+ printf("%.*s ", (int)name.length, (char *)name.value);
+ gss_release_buffer(minor, &name);
+ gss_release_buffer(minor, &short_desc);
+ gss_release_buffer(minor, &long_desc);
+ }
+ printf("\n");
+
+ printf("Known attrs: ");
+
+ for (i = 0; i < known_attrs->count; i++) {
+ gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc short_desc = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc long_desc = GSS_C_EMPTY_BUFFER;
+
+ major = gss_display_mech_attr(minor, &known_attrs->elements[i],
+ &name, &short_desc, &long_desc);
+ if (GSS_ERROR(major)) {
+ displayStatus("gss_display_mech_attr", major, *minor);
+ continue;
+ }
+ printf("%.*s ", (int)name.length, (char *)name.value);
+ gss_release_buffer(minor, &name);
+ gss_release_buffer(minor, &short_desc);
+ gss_release_buffer(minor, &long_desc);
+ }
+ printf("\n");
+
+ gss_release_oid_set(&tmpMinor, &mech_attrs);
+ gss_release_oid_set(&tmpMinor, &known_attrs);
+
+ return GSS_S_COMPLETE;
+}
+
+int main(int argc, char *argv[])
+{
+ gss_OID_set mechs;
+ OM_uint32 major, minor;
+ size_t i;
+
+ major = gss_indicate_mechs(&minor, &mechs);
+ if (GSS_ERROR(major)) {
+ displayStatus("gss_indicate_mechs", major, minor);
+ return major;
+ }
+
+ for (i = 0; i < mechs->count; i++) {
+ gss_buffer_desc oidstr = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER;
+ gss_OID oid = GSS_C_NO_OID;
+
+ major = gss_oid_to_str(&minor, &mechs->elements[i], &oidstr);
+ if (GSS_ERROR(major))
+ continue;
+
+ major = gss_inquire_saslname_for_mech(&minor, &mechs->elements[i],
+ &sasl_mech_name, &mech_name,
+ &mech_description);
+ if (GSS_ERROR(major)) {
+ gss_release_buffer(&minor, &oidstr);
+ continue;
+ }
+
+ printf("-------------------------------------------------------------"
+ "-----------------\n");
+ printf("OID : %.*s\n", (int)oidstr.length,
+ (char *)oidstr.value);
+ printf("SASL mech : %.*s\n", (int)sasl_mech_name.length,
+ (char *)sasl_mech_name.value);
+ printf("Mech name : %.*s\n", (int)mech_name.length,
+ (char *)mech_name.value);
+ printf("Mech desc : %.*s\n", (int)mech_description.length,
+ (char *)mech_description.value);
+ dumpMechAttrs(&minor, &mechs->elements[i]);
+ printf("-------------------------------------------------------------"
+ "-----------------\n");
+
+ if (GSS_ERROR(gss_inquire_mech_for_saslname(&minor, &sasl_mech_name,
+ &oid))) {
+ displayStatus("gss_inquire_mech_for_saslname", major, minor);
+ } else if (oid == GSS_C_NO_OID ||
+ (oid->length != mechs->elements[i].length &&
+ memcmp(oid->elements, mechs->elements[i].elements,
+ oid->length) != 0)) {
+ gss_release_buffer(&minor, &oidstr);
+ (void) gss_oid_to_str(&minor, oid, &oidstr);
+ fprintf(stderr, "Got different OID %.*s for mechanism %.*s\n",
+ (int)oidstr.length, (char *)oidstr.value,
+ (int)sasl_mech_name.length, (char *)sasl_mech_name.value);
+ }
+ gss_release_buffer(&minor, &oidstr);
+ gss_release_buffer(&minor, &sasl_mech_name);
+ gss_release_buffer(&minor, &mech_name);
+ gss_release_buffer(&minor, &mech_description);
+ }
+
+ gss_release_oid_set(&minor, &mechs);
+
+ return GSS_ERROR(major) ? 1 : 0;
+}