diff --git a/lib/gssapi/gssapi_mech.h b/lib/gssapi/gssapi_mech.h index fa027f805..07682ca7f 100644 --- a/lib/gssapi/gssapi_mech.h +++ b/lib/gssapi/gssapi_mech.h @@ -553,6 +553,7 @@ struct gss_mech_compat_desc_struct; /* gm_flags */ #define GM_USE_MG_CRED 1 /* uses mech glue credentials */ +#define GM_USE_MG_NAME 2 /* uses mech glue names */ typedef struct gssapi_mech_interface_desc { unsigned gm_version; diff --git a/lib/gssapi/mech/gss_accept_sec_context.c b/lib/gssapi/mech/gss_accept_sec_context.c index 8a5b5021e..6dd8fa985 100644 --- a/lib/gssapi/mech/gss_accept_sec_context.c +++ b/lib/gssapi/mech/gss_accept_sec_context.c @@ -182,12 +182,11 @@ gss_accept_sec_context(OM_uint32 *minor_status, * and we have to try all mechs (that we have a cred element * for, if we have a cred). */ - ctx = malloc(sizeof(struct _gss_context)); + ctx = calloc(1, sizeof(struct _gss_context)); if (!ctx) { *minor_status = ENOMEM; return (GSS_S_DEFECTIVE_TOKEN); } - memset(ctx, 0, sizeof(struct _gss_context)); if (mech_oid != GSS_C_NO_OID) { m = ctx->gc_mech = __gss_get_mechanism(mech_oid); if (!m) { @@ -334,11 +333,18 @@ got_one: } if (mech_type) - *mech_type = mech_ret_type; + *mech_type = mech_ret_type; - if (src_name && src_mn) { + if (src_name && src_mn && (ctx->gc_mech->gm_flags & GM_USE_MG_NAME)) { + /* Negotiation mechanisms use mechglue names as names */ + *src_name = src_mn; + src_mn = GSS_C_NO_NAME; + } else if (src_name && src_mn) { /* * Make a new name and mark it as an MN. + * + * Note that _gss_create_name() consumes `src_mn' but doesn't + * take a pointer, so it can't set it to GSS_C_NO_NAME. */ struct _gss_name *name = _gss_create_name(src_mn, m); @@ -348,6 +354,7 @@ got_one: return (GSS_S_FAILURE); } *src_name = (gss_name_t) name; + src_mn = GSS_C_NO_NAME; } else if (src_mn) { m->gm_release_name(minor_status, &src_mn); } diff --git a/lib/gssapi/mech/gss_canonicalize_name.c b/lib/gssapi/mech/gss_canonicalize_name.c index 8ffeec78f..859c6880e 100644 --- a/lib/gssapi/mech/gss_canonicalize_name.c +++ b/lib/gssapi/mech/gss_canonicalize_name.c @@ -67,7 +67,11 @@ gss_canonicalize_name(OM_uint32 *minor_status, gss_name_t new_canonical_name; *minor_status = 0; - *output_name = 0; + *output_name = GSS_C_NO_NAME; + + if ((m = __gss_get_mechanism(mech_type)) == NULL || + (m->gm_flags & GM_USE_MG_NAME)) + return GSS_S_BAD_MECH; major_status = _gss_find_mn(minor_status, name, mech_type, &mn); if (major_status) diff --git a/lib/gssapi/mech/gss_import_name.c b/lib/gssapi/mech/gss_import_name.c index d268b5e45..d7559981d 100644 --- a/lib/gssapi/mech/gss_import_name.c +++ b/lib/gssapi/mech/gss_import_name.c @@ -120,7 +120,7 @@ _gss_import_export_name(OM_uint32 *minor_status, return (GSS_S_BAD_NAME); m = __gss_get_mechanism(&mech_oid); - if (!m) + if (!m || !m->gm_import_name) return (GSS_S_BAD_MECH); /* @@ -242,6 +242,9 @@ gss_import_name(OM_uint32 *minor_status, HEIM_TAILQ_FOREACH(m, &_gss_mechs, gm_link) { int present = 0; + if ((m->gm_mech.gm_flags & GM_USE_MG_NAME)) + continue; + major_status = gss_test_oid_set_member(minor_status, name_type, m->gm_name_types, &present); diff --git a/lib/gssapi/mech/gss_init_sec_context.c b/lib/gssapi/mech/gss_init_sec_context.c index 250eafef2..6d28938ce 100644 --- a/lib/gssapi/mech/gss_init_sec_context.c +++ b/lib/gssapi/mech/gss_init_sec_context.c @@ -158,6 +158,7 @@ gss_init_sec_context(OM_uint32 * minor_status, { OM_uint32 major_status; gssapi_mech_interface m; + gss_const_name_t mn_inner = GSS_C_NO_NAME; struct _gss_name *name = (struct _gss_name *) target_name; struct _gss_mechanism_name *mn; struct _gss_context *ctx = (struct _gss_context *) *context_handle; @@ -216,12 +217,18 @@ gss_init_sec_context(OM_uint32 * minor_status, /* * Find the MN for this mechanism. */ - major_status = _gss_find_mn(minor_status, name, mech_type, &mn); - if (major_status != GSS_S_COMPLETE) { - if (allocated_ctx) - free(ctx); - return major_status; - } + if ((m->gm_flags & GM_USE_MG_NAME)) { + mn_inner = target_name; + } else { + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (major_status != GSS_S_COMPLETE) { + if (allocated_ctx) + free(ctx); + return major_status; + } + if (mn) + mn_inner = mn->gmn_name; + } /* * If we have a cred, find the cred for this mechanism. @@ -246,7 +253,7 @@ gss_init_sec_context(OM_uint32 * minor_status, major_status = m->gm_init_sec_context(minor_status, cred_handle, &ctx->gc_ctx, - mn ? mn->gmn_name : GSS_C_NO_NAME, + mn_inner, mech_type, req_flags, time_req, diff --git a/lib/gssapi/mech/gss_inquire_context.c b/lib/gssapi/mech/gss_inquire_context.c index e7466a461..614069688 100644 --- a/lib/gssapi/mech/gss_inquire_context.c +++ b/lib/gssapi/mech/gss_inquire_context.c @@ -82,7 +82,11 @@ gss_inquire_context(OM_uint32 *minor_status, return (major_status); } - if (src_name) { + if (src_name && (m->gm_flags & GM_USE_MG_NAME)) { + *src_name = src_mn; + src_mn = GSS_C_NO_NAME; + } else if (src_name && src_mn) { + /* _gss_create_name() consumes `src_mn' on success */ name = _gss_create_name(src_mn, m); if (!name) { if (mech_type) @@ -92,9 +96,12 @@ gss_inquire_context(OM_uint32 *minor_status, return (GSS_S_FAILURE); } *src_name = (gss_name_t) name; + src_mn = GSS_C_NO_NAME; } - if (targ_name) { + if (targ_name && (m->gm_flags & GM_USE_MG_NAME)) { + *targ_name = targ_mn; + } else if (targ_name && targ_mn) { name = _gss_create_name(targ_mn, m); if (!name) { if (mech_type) @@ -106,6 +113,7 @@ gss_inquire_context(OM_uint32 *minor_status, return (GSS_S_FAILURE); } *targ_name = (gss_name_t) name; + targ_mn = GSS_C_NO_NAME; } return (GSS_S_COMPLETE); diff --git a/lib/gssapi/mech/gss_names.c b/lib/gssapi/mech/gss_names.c index b39c2761d..729e7f2ad 100644 --- a/lib/gssapi/mech/gss_names.c +++ b/lib/gssapi/mech/gss_names.c @@ -74,7 +74,7 @@ _gss_find_mn(OM_uint32 *minor_status, return GSS_S_BAD_NAME; m = __gss_get_mechanism(mech); - if (!m) + if (!m || !m->gm_import_name) return (GSS_S_BAD_MECH); mn = malloc(sizeof(struct _gss_mechanism_name)); diff --git a/lib/gssapi/spnego/context_stubs.c b/lib/gssapi/spnego/context_stubs.c index 88f37adcd..27e4bfb7e 100644 --- a/lib/gssapi/spnego/context_stubs.c +++ b/lib/gssapi/spnego/context_stubs.c @@ -228,55 +228,6 @@ OM_uint32 GSSAPI_CALLCONV _gss_spnego_unwrap qop_state); } -OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name - (OM_uint32 *minor_status, - gss_const_name_t name1, - gss_const_name_t name2, - int * name_equal - ) -{ - return gss_compare_name(minor_status, name1, name2, name_equal); -} - -OM_uint32 GSSAPI_CALLCONV _gss_spnego_display_name - (OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_buffer_t output_name_buffer, - gss_OID * output_name_type - ) -{ - return gss_display_name(minor_status, input_name, - output_name_buffer, output_name_type); -} - -OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_name - (OM_uint32 * minor_status, - const gss_buffer_t name_buffer, - const gss_OID name_type, - gss_name_t * output_name - ) -{ - return gss_import_name(minor_status, name_buffer, - name_type, output_name); -} - -OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_name - (OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_buffer_t exported_name - ) -{ - return gss_export_name(minor_status, input_name, exported_name); -} - -OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name - (OM_uint32 * minor_status, - gss_name_t * input_name - ) -{ - return gss_release_name(minor_status, input_name); -} - OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_context ( OM_uint32 * minor_status, gss_const_ctx_id_t context_handle, @@ -469,47 +420,6 @@ out: return ret; } -OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_mechs_for_name ( - OM_uint32 * minor_status, - gss_const_name_t input_name, - gss_OID_set * mech_types - ) -{ - OM_uint32 ret, junk; - - ret = gss_create_empty_oid_set(minor_status, mech_types); - if (ret) - return ret; - - ret = gss_add_oid_set_member(minor_status, - GSS_SPNEGO_MECHANISM, - mech_types); - if (ret) - gss_release_oid_set(&junk, mech_types); - - return ret; -} - -OM_uint32 GSSAPI_CALLCONV _gss_spnego_canonicalize_name ( - OM_uint32 * minor_status, - gss_const_name_t input_name, - const gss_OID mech_type, - gss_name_t * output_name - ) -{ - /* XXX */ - return gss_duplicate_name(minor_status, input_name, output_name); -} - -OM_uint32 GSSAPI_CALLCONV _gss_spnego_duplicate_name ( - OM_uint32 * minor_status, - gss_const_name_t src_name, - gss_name_t * dest_name - ) -{ - return gss_duplicate_name(minor_status, src_name, dest_name); -} - OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap_iov(OM_uint32 * minor_status, gss_ctx_id_t context_handle, diff --git a/lib/gssapi/spnego/external.c b/lib/gssapi/spnego/external.c index 99b3412d8..b66f97dab 100644 --- a/lib/gssapi/spnego/external.c +++ b/lib/gssapi/spnego/external.c @@ -88,7 +88,7 @@ static gssapi_mech_interface_desc spnego_mech = { GMI_VERSION, "spnego", {6, rk_UNCONST("\x2b\x06\x01\x05\x05\x02") }, - GM_USE_MG_CRED, + GM_USE_MG_CRED | GM_USE_MG_NAME, NULL, /* gm_acquire_cred */ NULL, /* gm_release_cred */ _gss_spnego_init_sec_context, @@ -102,11 +102,11 @@ static gssapi_mech_interface_desc spnego_mech = { _gss_spnego_unwrap, NULL, /* gm_display_status */ NULL, /* gm_indicate_mechs */ - _gss_spnego_compare_name, - _gss_spnego_display_name, - _gss_spnego_import_name, - _gss_spnego_export_name, - _gss_spnego_release_name, + NULL, /* gm_compare_name */ + NULL, /* gm_display_name */ + NULL, /* gm_import_name */ + NULL, /* gm_export_name */ + NULL, /* gm_release_name */ NULL, /* gm_inquire_cred */ _gss_spnego_inquire_context, _gss_spnego_wrap_size_limit, @@ -114,10 +114,10 @@ static gssapi_mech_interface_desc spnego_mech = { NULL, /* gm_inquire_cred_by_mech */ _gss_spnego_export_sec_context, _gss_spnego_import_sec_context, - NULL /* _gss_spnego_inquire_names_for_mech */, - _gss_spnego_inquire_mechs_for_name, - _gss_spnego_canonicalize_name, - _gss_spnego_duplicate_name, + NULL, /* gm_spnego_inquire_names_for_mech */ + NULL, /* gm_spnego_inquire_mechs_for_name */ + NULL, /* gm_spnego_canonicalize_name */ + NULL, /* gm_spnego_duplicate_name */ _gss_spnego_inquire_sec_context_by_oid, NULL, /* gm_inquire_cred_by_oid */ _gss_spnego_set_sec_context_option, diff --git a/lib/gssapi/test_context.c b/lib/gssapi/test_context.c index b59bbd83a..b31a94771 100644 --- a/lib/gssapi/test_context.c +++ b/lib/gssapi/test_context.c @@ -44,8 +44,10 @@ static char *type_string; static char *mech_string; static char *mechs_string; static char *ret_mech_string; +static char *localname_string; static char *client_name; static char *client_password; +static char *localname_string; static int dns_canon_flag = -1; static int mutual_auth_flag = 0; static int dce_style_flag = 0; @@ -161,7 +163,7 @@ loop(gss_OID mechoid, int server_done = 0, client_done = 0; int num_loops = 0; OM_uint32 maj_stat, min_stat; - gss_name_t gss_target_name; + gss_name_t gss_target_name, src_name; gss_buffer_desc input_token, output_token; OM_uint32 flags = 0, ret_cflags, ret_sflags; gss_OID actual_mech_client; @@ -236,7 +238,7 @@ loop(gss_OID mechoid, GSS_C_NO_CREDENTIAL, &output_token, GSS_C_NO_CHANNEL_BINDINGS, - NULL, + &src_name, &actual_mech_server, &input_token, &ret_sflags, @@ -275,6 +277,49 @@ loop(gss_OID mechoid, errx(1, "mech mismatch"); *actual_mech = actual_mech_server; + if (localname_string) { + gss_buffer_desc lname; + + maj_stat = gss_localname(&min_stat, src_name, GSS_C_NO_OID, &lname); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "localname: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + if (verbose_flag) + printf("localname: %.*s\n", (int)lname.length, + (char *)lname.value); + if (lname.length != strlen(localname_string) || + strncmp(localname_string, lname.value, lname.length)) + errx(1, "localname: expected \"%s\", got \"%.*s\" (1)", + localname_string, (int)lname.length, (char *)lname.value); + gss_release_buffer(&min_stat, &lname); + maj_stat = gss_localname(&min_stat, src_name, actual_mech_server, + &lname); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "localname: %s", + gssapi_err(maj_stat, min_stat, actual_mech_server)); + if (lname.length != strlen(localname_string) || + strncmp(localname_string, lname.value, lname.length)) + errx(1, "localname: expected \"%s\", got \"%.*s\" (2)", + localname_string, (int)lname.length, (char *)lname.value); + gss_release_buffer(&min_stat, &lname); + + if (!gss_userok(src_name, localname_string)) + errx(1, "localname is not userok"); + if (gss_userok(src_name, "nosuchuser:no")) + errx(1, "gss_userok() appears broken"); + } + if (verbose_flag) { + gss_buffer_desc iname; + + maj_stat = gss_display_name(&min_stat, src_name, &iname, NULL); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "display_name: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); + printf("client name: %.*s\n", (int)iname.length, (char *)iname.value); + gss_release_buffer(&min_stat, &iname); + } + gss_release_name(&min_stat, &src_name); + if (max_loops && num_loops > max_loops) errx(1, "num loops %d was lager then max loops %d", num_loops, max_loops); @@ -593,6 +638,7 @@ static struct getargs args[] = { "server should get a credential", NULL }, {"export-import-context",0, arg_flag, &ei_ctx_flag, "test export/import context", NULL }, {"export-import-cred",0, arg_flag, &ei_cred_flag, "test export/import cred", NULL }, + {"localname",0, arg_string, &localname_string, "expected localname for client", "USERNAME"}, {"gsskrb5-acceptor-identity", 0, arg_string, &gsskrb5_acceptor_identity, "keytab", NULL }, {"session-enctype", 0, arg_string, &session_enctype_string, "enctype", NULL }, {"client-time-offset", 0, arg_integer, &client_time_offset, "time", NULL }, diff --git a/tests/gss/check-context.in b/tests/gss/check-context.in index 97e2e0c01..0b657fc17 100644 --- a/tests/gss/check-context.in +++ b/tests/gss/check-context.in @@ -217,6 +217,7 @@ for mech in krb5 krb5iov spnego spnegoiov; do echo "${mech} no-mutual ${iov}" ; > messages.log ${context} --mech-type=${mech} \ --wrapunwrap ${iov} \ + --localname=mapped_user1 \ --name-type=hostbased-service host@lucid.test.h5l.se || \ { eval "$testfailed"; } diff --git a/tests/gss/krb5.conf.in b/tests/gss/krb5.conf.in index 2e469ecd3..69c16ad7e 100644 --- a/tests/gss/krb5.conf.in +++ b/tests/gss/krb5.conf.in @@ -4,10 +4,17 @@ include @srcdirabs@/include-krb5.conf default_keytab_name = @objdir@/server.keytab enable-kx509 = yes kx509_store = PEM-FILE:/tmp/cert_%{euid}.pem + default_realm = TEST.H5L.SE + kuserok = SYSTEM-K5LOGIN:@srcdir@/../kdc/k5login + kuserok = USER-K5LOGIN + kuserok = SIMPLE [realms] TEST.H5L.SE = { kdc = localhost:@port@ + auth_to_local_names = { + user1 = mapped_user1 + } } [kdc] diff --git a/tests/kdc/an2ln-db.txt b/tests/kdc/an2ln-db.txt index 39e1a5018..0b2fe383e 100644 --- a/tests/kdc/an2ln-db.txt +++ b/tests/kdc/an2ln-db.txt @@ -73,6 +73,7 @@ mapped1@TEST2.H5L.SE m1 mapped1@TEST3.H5L.SE mapped1 mapped2@TEST2.H5L.SE m2 mapped2@TEST3.H5L.SE mapped2 +user1@@TEST.H5L.SE mapped_user1 z008213d189aac2b junk z07644c5c50f29d5 junk z094067ad439189c junk diff --git a/tests/kdc/k5login/mapped_user1 b/tests/kdc/k5login/mapped_user1 new file mode 100644 index 000000000..a7857c259 --- /dev/null +++ b/tests/kdc/k5login/mapped_user1 @@ -0,0 +1 @@ +user1@TEST.H5L.SE