summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2010-10-06 18:25:04 +0000
committerGreg Hudson <ghudson@mit.edu>2010-10-06 18:25:04 +0000
commit014f8057c5328b3e39b5d8660a1ea1a98409006f (patch)
treeda9796d82a6d65d055f4762c411fbf395bb52f37 /src/lib
parent5f2826f6d598a4dd45a55e111a07c0086fe1e38a (diff)
downloadkrb5-014f8057c5328b3e39b5d8660a1ea1a98409006f.tar.gz
krb5-014f8057c5328b3e39b5d8660a1ea1a98409006f.tar.xz
krb5-014f8057c5328b3e39b5d8660a1ea1a98409006f.zip
Merge users/lhoward/sasl-gs2 to trunk
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24436 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib')
-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
13 files changed, 1096 insertions, 1 deletions
diff --git a/src/lib/gssapi/generic/gssapi.hin b/src/lib/gssapi/generic/gssapi.hin
index fb82e3c4f..15d685d8c 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 cb2340a4b..f3af8a4d1 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 1d77d3f81..f8d2c426c 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 cd16862f6..81d86fc76 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 8b074d616..25534e56b 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 707fe52ee..fee99c994 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 92cd6c99c..d2dccb46b 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 a393a5309..d8b495640 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 000000000..63ec35768
--- /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 000000000..4bffdd602
--- /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 da427f4a6..63d89c771 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 e146508c5..50f05678d 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 9c5a6140d..d8706af92 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