diff --git a/lib/gssapi/gssapi_mech.h b/lib/gssapi/gssapi_mech.h index 2c31d1acb..6afc7be96 100644 --- a/lib/gssapi/gssapi_mech.h +++ b/lib/gssapi/gssapi_mech.h @@ -616,6 +616,12 @@ int _gss_mo_get_option_1(gss_const_OID, gss_mo_desc *, gss_buffer_t); int _gss_mo_get_option_0(gss_const_OID, gss_mo_desc *, gss_buffer_t); int _gss_mo_get_ctx_as_string(gss_const_OID, gss_mo_desc *, gss_buffer_t); +struct _gss_name_type { + gss_OID gnt_name_type; + OM_uint32 (*gnt_parse)(OM_uint32 *, gss_const_OID, const gss_buffer_t, + gss_const_OID, gss_name_t *); +}; + struct _gss_oid_name_table { gss_OID oid; const char *name; diff --git a/lib/gssapi/mech/gss_export_name.c b/lib/gssapi/mech/gss_export_name.c index 885375421..92b7a8f1e 100644 --- a/lib/gssapi/mech/gss_export_name.c +++ b/lib/gssapi/mech/gss_export_name.c @@ -2,6 +2,8 @@ * Copyright (c) 2005 Doug Rabson * All rights reserved. * + * Portions Copyright (c) 2010 Apple Inc. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -66,3 +68,46 @@ gss_export_name(OM_uint32 *minor_status, return mn->gmn_mech->gm_export_name(minor_status, mn->gmn_name, exported_name); } + +OM_uint32 +gss_mg_export_name(OM_uint32 *minor_status, + const gss_const_OID mech, + const void *name, + size_t length, + gss_buffer_t exported_name) +{ + uint8_t *buf; + + exported_name->length = 10 + length + mech->length; + exported_name->value = malloc(exported_name->length); + if (exported_name->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + buf = exported_name->value; + memcpy(buf, "\x04\x01", 2); + buf += 2; + buf[0] = ((mech->length + 2) >> 8) & 0xff; + buf[1] = (mech->length + 2) & 0xff; + buf+= 2; + buf[0] = 0x06; + buf[1] = (mech->length) & 0xFF; + buf+= 2; + + memcpy(buf, mech->elements, mech->length); + buf += mech->length; + + buf[0] = (length >> 24) & 0xff; + buf[1] = (length >> 16) & 0xff; + buf[2] = (length >> 8) & 0xff; + buf[3] = (length) & 0xff; + buf += 4; + + memcpy (buf, name, length); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/mech/gss_get_name_attribute.c b/lib/gssapi/mech/gss_get_name_attribute.c index f2e4169e1..1b7bee549 100644 --- a/lib/gssapi/mech/gss_get_name_attribute.c +++ b/lib/gssapi/mech/gss_get_name_attribute.c @@ -57,6 +57,8 @@ gss_get_name_attribute(OM_uint32 *minor_status, if (input_name == GSS_C_NO_NAME) return GSS_S_BAD_NAME; + _gss_mg_check_name(input_name); + HEIM_TAILQ_FOREACH(mn, &name->gn_mn, gmn_link) { gssapi_mech_interface m = mn->gmn_mech; diff --git a/lib/gssapi/mech/gss_init_sec_context.c b/lib/gssapi/mech/gss_init_sec_context.c index 5d9180abb..f18adbde3 100644 --- a/lib/gssapi/mech/gss_init_sec_context.c +++ b/lib/gssapi/mech/gss_init_sec_context.c @@ -173,6 +173,8 @@ gss_init_sec_context(OM_uint32 * minor_status, if (time_rec) *time_rec = 0; + _gss_mg_check_name(target_name); + if (_gss_mg_log_level(1)) log_init_sec_context(ctx, name, req_flags, (struct _gss_cred *)initiator_cred_handle, diff --git a/lib/gssapi/mech/gss_names.c b/lib/gssapi/mech/gss_names.c index eda87bdde..b39c2761d 100644 --- a/lib/gssapi/mech/gss_names.c +++ b/lib/gssapi/mech/gss_names.c @@ -30,6 +30,20 @@ #include "mech_locl.h" +gss_name_t +_gss_mg_get_underlying_mech_name(gss_name_t name, + gss_const_OID mech) +{ + struct _gss_name *n = (struct _gss_name *)name; + struct _gss_mechanism_name *mn; + + HEIM_TAILQ_FOREACH(mn, &n->gn_mn, gmn_link) { + if (gss_oid_equal(mech, mn->gmn_mech_oid)) + return mn->gmn_name; + } + return GSS_C_NO_NAME; +} + OM_uint32 _gss_find_mn(OM_uint32 *minor_status, struct _gss_name *name, @@ -138,3 +152,111 @@ _gss_mg_release_name(struct _gss_name *name) gss_release_buffer(&junk, &name->gn_value); free(name); } + +void +_gss_mg_check_name(gss_const_name_t name) +{ + if (name == NULL) return; +} + +/* + * + */ + +OM_uint32 +_gss_mech_import_name(OM_uint32 * minor_status, + gss_const_OID mech, + struct _gss_name_type *names, + const gss_buffer_t input_name_buffer, + gss_const_OID input_name_type, + gss_name_t *output_name) +{ + struct _gss_name_type *name; + gss_buffer_t name_buffer = input_name_buffer; + gss_buffer_desc export_name; + + *minor_status = 0; + + if (output_name == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *output_name = GSS_C_NO_NAME; + + /* + * If its a exported name, strip of the mech glue. + */ + + if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) { + unsigned char *p; + uint32_t length; + + if (name_buffer->length < 10 + mech->length) + return GSS_S_BAD_NAME; + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + p = name_buffer->value; + + if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 || + p[3] != mech->length + 2 || + p[4] != 0x06 || + p[5] != mech->length || + memcmp(&p[6], mech->elements, mech->length) != 0) + return GSS_S_BAD_NAME; + + p += 6 + mech->length; + + length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + p += 4; + + if (length > name_buffer->length - 10 - mech->length) + return GSS_S_BAD_NAME; + + /* + * Point this to the mech specific name part, don't modifity + * orignal input_name_buffer. + */ + + export_name.length = length; + export_name.value = p; + + name_buffer = &export_name; + } + + for (name = names; name->gnt_parse != NULL; name++) { + if (gss_oid_equal(input_name_type, name->gnt_name_type) + || (name->gnt_name_type == GSS_C_NO_OID && input_name_type == GSS_C_NO_OID)) + return name->gnt_parse(minor_status, mech, name_buffer, + input_name_type, output_name); + } + + return GSS_S_BAD_NAMETYPE; +} + +OM_uint32 +_gss_mech_inquire_names_for_mech(OM_uint32 * minor_status, + struct _gss_name_type *names, + gss_OID_set *name_types) +{ + struct _gss_name_type *name; + OM_uint32 ret, junk; + + ret = gss_create_empty_oid_set(minor_status, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + for (name = names; name->gnt_parse != NULL; name++) { + if (name->gnt_name_type == GSS_C_NO_OID) + continue; + ret = gss_add_oid_set_member(minor_status, + name->gnt_name_type, + name_types); + if (ret != GSS_S_COMPLETE) + break; + } + + if (ret != GSS_S_COMPLETE) + gss_release_oid_set(&junk, name_types); + + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/mech/name.h b/lib/gssapi/mech/name.h index 80dfee99c..4a034860e 100644 --- a/lib/gssapi/mech/name.h +++ b/lib/gssapi/mech/name.h @@ -47,3 +47,31 @@ OM_uint32 struct _gss_name * _gss_create_name(gss_name_t new_mn, gssapi_mech_interface m); void _gss_mg_release_name(struct _gss_name *); + + +void _gss_mg_check_name(gss_const_name_t name); + +gss_name_t + _gss_mg_get_underlying_mech_name(gss_name_t name, gss_const_OID mech); + +OM_uint32 +_gss_mech_import_name(OM_uint32 * minor_status, + gss_const_OID mech, + struct _gss_name_type *names, + const gss_buffer_t input_name_buffer, + gss_const_OID input_name_type, + gss_name_t *output_name); + +OM_uint32 +gss_mg_export_name(OM_uint32 *minor_status, + const gss_const_OID mech, + const void *name, + size_t length, + gss_buffer_t exported_name); + +OM_uint32 +_gss_mech_inquire_names_for_mech(OM_uint32 * minor_status, + struct _gss_name_type *names, + gss_OID_set *name_types); + +