gss: merge gss_name_to_oid and gss_mg_name_to_oid

The recently introduced gss_mg_name_to_oid() function supported looking up
dynamically loaded mechanisms by name, but did not support partial matches or
the legacy "Kerberos 5" name as supported by gss_name_to_oid().

Consolidate these into a single function, and also add support for dynamically
loaded mechanisms to gss_oid_to_name().

API behavior difference: the Kerberos mechanism is now referred to by "krb5"
rather tha "Kerberos 5", although for legacy compatibility gss_name_to_oid()
will recognize the old name. However, gss_oid_to_name() will return "krb5". The
anticipated impact is minimal as these are not standard GSS-APIs and do not
appear to have any public usage outside Heimdal.
This commit is contained in:
Luke Howard
2021-08-08 11:28:32 +10:00
parent 5966c00701
commit 18c18d84b1
8 changed files with 97 additions and 114 deletions

View File

@@ -1144,9 +1144,12 @@ GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_duplicate_cred (
gss_const_cred_id_t /*input_cred_handle*/, gss_const_cred_id_t /*input_cred_handle*/,
gss_cred_id_t * /*output_cred_handle*/ gss_cred_id_t * /*output_cred_handle*/
); );
/* Return a mechanism short name from an OID */
GSSAPI_LIB_FUNCTION const char * GSSAPI_LIB_CALL GSSAPI_LIB_FUNCTION const char * GSSAPI_LIB_CALL
gss_oid_to_name(gss_const_OID oid); gss_oid_to_name(gss_const_OID oid);
/* Return a mechanism OID from a short name or dotted OID */
GSSAPI_LIB_FUNCTION gss_OID GSSAPI_LIB_CALL GSSAPI_LIB_FUNCTION gss_OID GSSAPI_LIB_CALL
gss_name_to_oid(const char *name); gss_name_to_oid(const char *name);

View File

@@ -701,9 +701,6 @@ gss_cred_id_t
_gss_mg_find_mech_cred(gss_const_cred_id_t cred_handle, _gss_mg_find_mech_cred(gss_const_cred_id_t cred_handle,
gss_const_OID mech_type); gss_const_OID mech_type);
GSSAPI_LIB_FUNCTION gss_const_OID
GSSAPI_CALLCONV gss_mg_name_to_oid(const char *);
#include <krb5.h> #include <krb5.h>
/* /*

View File

@@ -328,7 +328,7 @@ static gss_mo_desc krb5_mo[] = {
static gssapi_mech_interface_desc krb5_mech = { static gssapi_mech_interface_desc krb5_mech = {
GMI_VERSION, GMI_VERSION,
"kerberos 5", "krb5",
{9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }, {9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") },
0, 0,
NULL, /* gm_acquire_cred */ NULL, /* gm_acquire_cred */

View File

@@ -69,7 +69,6 @@ EXPORTS
gss_krb5_set_allowable_enctypes gss_krb5_set_allowable_enctypes
gss_localname gss_localname
gss_mg_collect_error gss_mg_collect_error
gss_mg_name_to_oid
gss_mo_get gss_mo_get
gss_mo_set gss_mo_set
gss_mo_list gss_mo_list

View File

@@ -491,20 +491,77 @@ _gss_mg_support_mechanism(gss_const_OID mech)
return NULL; return NULL;
} }
GSSAPI_LIB_FUNCTION gss_const_OID GSSAPI_CALLCONV enum mech_name_match {
gss_mg_name_to_oid(const char *name) MATCH_NONE = 0,
MATCH_COMPLETE,
MATCH_PARTIAL
};
static enum mech_name_match
match_mech_name(const char *gm_mech_name,
const char *name,
size_t namelen)
{ {
struct _gss_mech_switch *m; if (gm_mech_name == NULL)
return MATCH_NONE;
else if (strcasecmp(gm_mech_name, name) == 0)
return MATCH_COMPLETE;
else if (strncasecmp(gm_mech_name, name, namelen) == 0)
return MATCH_PARTIAL;
else
return MATCH_NONE;
}
/*
* Return an OID for a built-in or dynamically loaded mechanism. For
* API compatibility with previous versions, we treat "Kerberos 5"
* as an alias for "krb5". Unique partial matches are supported.
*/
GSSAPI_LIB_FUNCTION gss_OID GSSAPI_CALLCONV
gss_name_to_oid(const char *name)
{
struct _gss_mech_switch *m, *partial = NULL;
gss_OID oid = GSS_C_NO_OID; gss_OID oid = GSS_C_NO_OID;
size_t namelen = strlen(name);
if (isdigit(name[0]) && _gss_string_to_oid(name, &oid) == 0) if (isdigit(name[0]) && _gss_string_to_oid(name, &oid) == 0)
return oid; return oid;
_gss_load_mech(); _gss_load_mech();
HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
if (m->gm_mech.gm_name && enum mech_name_match match;
strcmp(m->gm_mech.gm_name, name) == 0)
match = match_mech_name(m->gm_mech.gm_name, name, namelen);
if (match == MATCH_NONE &&
gss_oid_equal(m->gm_mech_oid, GSS_KRB5_MECHANISM))
match = match_mech_name("Kerberos 5", name, namelen);
if (match == MATCH_COMPLETE)
return m->gm_mech_oid; return m->gm_mech_oid;
else if (match == MATCH_PARTIAL) {
if (partial)
return NULL;
else
partial = m;
} }
}
if (partial)
return partial->gm_mech_oid;
return NULL;
}
GSSAPI_LIB_FUNCTION const char * GSSAPI_LIB_CALL
gss_oid_to_name(gss_const_OID oid)
{
struct _gss_mech_switch *m;
_gss_load_mech();
HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) {
if (gss_oid_equal(m->gm_mech_oid, oid))
return m->gm_mech.gm_name;
}
return NULL; return NULL;
} }

View File

@@ -65,34 +65,3 @@ gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str)
*minor_status = 0; *minor_status = 0;
return GSS_S_COMPLETE; return GSS_S_COMPLETE;
} }
GSSAPI_LIB_FUNCTION const char * GSSAPI_LIB_CALL
gss_oid_to_name(gss_const_OID oid)
{
size_t i;
for (i = 0; _gss_ont_mech[i].oid; i++) {
if (gss_oid_equal(oid, _gss_ont_mech[i].oid))
return _gss_ont_mech[i].name;
}
return NULL;
}
GSSAPI_LIB_FUNCTION gss_OID GSSAPI_LIB_CALL
gss_name_to_oid(const char *name)
{
size_t i, partial = (size_t)-1;
for (i = 0; _gss_ont_mech[i].oid; i++) {
if (strcasecmp(name, _gss_ont_mech[i].short_desc) == 0)
return _gss_ont_mech[i].oid;
if (strncasecmp(name, _gss_ont_mech[i].short_desc, strlen(name)) == 0) {
if (partial != (size_t)-1)
return NULL;
partial = i;
}
}
if (partial != (size_t)-1)
return _gss_ont_mech[partial].oid;
return NULL;
}

View File

@@ -87,49 +87,10 @@ static char *a_channel_bindings = NULL;
static krb5_context context; static krb5_context context;
static krb5_enctype limit_enctype = 0; static krb5_enctype limit_enctype = 0;
static gss_OID_desc test_negoex_1_mech = { 6, "\x69\x85\xa2\xc0\xac\x66" };
static gss_OID_desc test_negoex_2_mech = { 6, "\x69\x84\xb0\xd1\xa8\x2c" };
static struct {
const char *name;
gss_OID oid;
} o2n[] = {
{ "krb5", NULL /* GSS_KRB5_MECHANISM */ },
{ "spnego", NULL /* GSS_SPNEGO_MECHANISM */ },
{ "ntlm", NULL /* GSS_NTLM_MECHANISM */ },
{ "sasl-digest-md5", NULL /* GSS_SASL_DIGEST_MD5_MECHANISM */ },
{ "sanon-x25519", NULL /* GSS_SASL_SANON_X25519_MECHANISM */ },
{ "test_negoex_1", NULL },
{ "test_negoex_2", NULL },
};
static void static void
init_o2n(void) string_to_oids(gss_OID_set *oidsetp, char *names)
{
o2n[0].oid = GSS_KRB5_MECHANISM;
o2n[1].oid = GSS_SPNEGO_MECHANISM;
o2n[2].oid = GSS_NTLM_MECHANISM;
o2n[3].oid = GSS_SASL_DIGEST_MD5_MECHANISM;
o2n[4].oid = GSS_SANON_X25519_MECHANISM;
o2n[5].oid = &test_negoex_1_mech;
o2n[6].oid = &test_negoex_2_mech;
}
static gss_OID
string_to_oid(const char *name)
{
size_t i;
for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
if (strcasecmp(name, o2n[i].name) == 0)
return o2n[i].oid;
errx(1, "name '%s' not known", name);
}
static void
string_to_oids(gss_OID_set *oidsetp, gss_OID_set oidset,
gss_OID_desc *oidarray, size_t oidarray_len,
char *names)
{ {
OM_uint32 maj_stat, min_stat;
char *name; char *name;
char *s; char *s;
@@ -138,32 +99,31 @@ string_to_oids(gss_OID_set *oidsetp, gss_OID_set oidset,
return; return;
} }
oidset->elements = &oidarray[0];
if (strcasecmp(names, "all") == 0) { if (strcasecmp(names, "all") == 0) {
if (sizeof(o2n)/sizeof(o2n[0]) > oidarray_len) maj_stat = gss_indicate_mechs(&min_stat, oidsetp);
errx(1, "internal error: oidarray must be enlarged"); if (GSS_ERROR(maj_stat))
for (oidset->count = 0; oidset->count < oidarray_len; oidset->count++) errx(1, "gss_indicate_mechs: %s",
oidset->elements[oidset->count] = *o2n[oidset->count].oid; gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
} else { } else {
for (oidset->count = 0, name = strtok_r(names, ", ", &s); maj_stat = gss_create_empty_oid_set(&min_stat, oidsetp);
name != NULL; if (GSS_ERROR(maj_stat))
oidset->count++, name = strtok_r(NULL, ", ", &s)) { errx(1, "gss_create_empty_oid_set: %s",
if (oidset->count >= oidarray_len) gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
errx(1, "too many mech names given");
oidset->elements[oidset->count] = *string_to_oid(name);
}
}
*oidsetp = oidset;
}
static const char * for (name = strtok_r(names, ", ", &s);
oid_to_string(const gss_OID oid) name != NULL;
{ name = strtok_r(NULL, ", ", &s)) {
size_t i; gss_OID oid = gss_name_to_oid(name);
for (i = 0; i < sizeof(o2n)/sizeof(o2n[0]); i++)
if (gss_oid_equal(oid, o2n[i].oid)) if (oid == GSS_C_NO_OID)
return o2n[i].name; errx(1, "gss_name_to_oid: unknown mech %s", name);
return "unknown oid";
maj_stat = gss_add_oid_set_member(&min_stat, oid, oidsetp);
if (GSS_ERROR(maj_stat))
errx(1, "gss_add_oid_set_member: %s",
gssapi_err(maj_stat, min_stat, GSS_C_NO_OID));
}
}
} }
static void static void
@@ -817,8 +777,6 @@ main(int argc, char **argv)
setprogname(argv[0]); setprogname(argv[0]);
init_o2n();
if (krb5_init_context(&context)) if (krb5_init_context(&context))
errx(1, "krb5_init_context"); errx(1, "krb5_init_context");
@@ -856,7 +814,7 @@ main(int argc, char **argv)
if (mech_string == NULL) if (mech_string == NULL)
mechoid = GSS_KRB5_MECHANISM; mechoid = GSS_KRB5_MECHANISM;
else else
mechoid = string_to_oid(mech_string); mechoid = gss_name_to_oid(mech_string);
if (mechs_string == NULL) { if (mechs_string == NULL) {
/* /*
@@ -885,8 +843,7 @@ main(int argc, char **argv)
mechoid_descs.count = 1; mechoid_descs.count = 1;
mechoids = &mechoid_descs; mechoids = &mechoid_descs;
} else { } else {
string_to_oids(&mechoids, &mechoid_descs, string_to_oids(&mechoids, mechs_string);
oids, sizeof(oids)/sizeof(oids[0]), mechs_string);
} }
if (gsskrb5_acceptor_identity) { if (gsskrb5_acceptor_identity) {
@@ -976,7 +933,7 @@ main(int argc, char **argv)
printf("cred mechs:"); printf("cred mechs:");
for (i = 0; i < actual_mechs->count; i++) for (i = 0; i < actual_mechs->count; i++)
printf(" %s", oid_to_string(&actual_mechs->elements[i])); printf(" %s", gss_oid_to_name(&actual_mechs->elements[i]));
printf("\n"); printf("\n");
} }
@@ -1036,12 +993,12 @@ main(int argc, char **argv)
&sctx, &cctx, &actual_mech, &deleg_cred); &sctx, &cctx, &actual_mech, &deleg_cred);
if (verbose_flag) if (verbose_flag)
printf("resulting mech: %s\n", oid_to_string(actual_mech)); printf("resulting mech: %s\n", gss_oid_to_name(actual_mech));
if (ret_mech_string) { if (ret_mech_string) {
gss_OID retoid; gss_OID retoid;
retoid = string_to_oid(ret_mech_string); retoid = gss_name_to_oid(ret_mech_string);
if (gss_oid_equal(retoid, actual_mech) == 0) if (gss_oid_equal(retoid, actual_mech) == 0)
errx(1, "actual_mech mech is not the expected type %s", errx(1, "actual_mech mech is not the expected type %s",
@@ -1393,7 +1350,7 @@ main(int argc, char **argv)
if (verbose_flag) if (verbose_flag)
printf("checking actual mech (%s) on delegated cred\n", printf("checking actual mech (%s) on delegated cred\n",
oid_to_string(actual_mech)); gss_oid_to_name(actual_mech));
loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2); loop(actual_mech, nameoid, argv[0], deleg_cred, &sctx, &cctx, &actual_mech2, &cred2);
gss_delete_sec_context(&min_stat, &cctx, NULL); gss_delete_sec_context(&min_stat, &cctx, NULL);
@@ -1438,7 +1395,7 @@ main(int argc, char **argv)
if (verbose_flag) if (verbose_flag)
printf("checking actual mech (%s) on export/imported cred\n", printf("checking actual mech (%s) on export/imported cred\n",
oid_to_string(actual_mech)); gss_oid_to_name(actual_mech));
loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx, loop(actual_mech, nameoid, argv[0], cred2, &sctx, &cctx,
&actual_mech2, &deleg_cred); &actual_mech2, &deleg_cred);
@@ -1471,6 +1428,8 @@ main(int argc, char **argv)
gss_release_cred(&min_stat, &client_cred); gss_release_cred(&min_stat, &client_cred);
gss_release_oid_set(&min_stat, &actual_mechs); gss_release_oid_set(&min_stat, &actual_mechs);
if (mechoids != GSS_C_NO_OID_SET && mechoids != &mechoid_descs)
gss_release_oid_set(&min_stat, &mechoids);
empty_release(); empty_release();
krb5_free_context(context); krb5_free_context(context);

View File

@@ -69,7 +69,6 @@ HEIMDAL_GSS_2.0 {
gss_krb5_set_allowable_enctypes; gss_krb5_set_allowable_enctypes;
gss_localname; gss_localname;
gss_mg_collect_error; gss_mg_collect_error;
gss_mg_name_to_oid;
gss_oid_equal; gss_oid_equal;
gss_oid_to_str; gss_oid_to_str;
gss_pname_to_uid; gss_pname_to_uid;