#include "gssapiP_krb5.h"
#include "mglueP.h"
#ifndef NO_PASSWORD
#include <pwd.h>
#endif
#define NO_CI_FLAGS_X_OID_LENGTH 6
#define NO_CI_FLAGS_X_OID "\x2a\x85\x70\x2b\x0d\x1d"
#define GET_CRED_IMPERSONATOR_OID_LENGTH 11
#define GET_CRED_IMPERSONATOR_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0e"
const gss_OID_desc krb5_gss_oid_array[] = {
{GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID},
{GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID},
{GSS_MECH_KRB5_WRONG_OID_LENGTH, GSS_MECH_KRB5_WRONG_OID},
{GSS_MECH_IAKERB_OID_LENGTH, GSS_MECH_IAKERB_OID},
{9, "\052\206\110\206\367\022\001\002\003"},
{10, "\052\206\110\206\367\022\001\002\002\001"},
{10, "\052\206\110\206\367\022\001\002\002\002"},
{NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID},
{GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID},
{10, "\052\206\110\206\367\022\001\002\002\006"},
{10, "\052\206\110\206\367\022\001\002\002\007"},
{ 0, 0 }
};
#define kg_oids ((gss_OID)krb5_gss_oid_array)
const gss_OID gss_mech_krb5 = &kg_oids[0];
const gss_OID gss_mech_krb5_old = &kg_oids[1];
const gss_OID gss_mech_krb5_wrong = &kg_oids[2];
const gss_OID gss_mech_iakerb = &kg_oids[3];
const gss_OID gss_nt_krb5_name = &kg_oids[5];
const gss_OID gss_nt_krb5_principal = &kg_oids[6];
const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &kg_oids[5];
const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X = &kg_oids[7];
const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR = &kg_oids[8];
const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME = &kg_oids[9];
const gss_OID GSS_KRB5_NT_X509_CERT = &kg_oids[10];
static const gss_OID_set_desc oidsets[] = {
{1, &kg_oids[0]},
{1, &kg_oids[1]},
{3, &kg_oids[0]},
{4, &kg_oids[0]},
};
#define kg_oidsets ((gss_OID_set)oidsets)
const gss_OID_set gss_mech_set_krb5 = &kg_oidsets[0];
const gss_OID_set gss_mech_set_krb5_old = &kg_oidsets[1];
const gss_OID_set gss_mech_set_krb5_both = &kg_oidsets[2];
const gss_OID_set kg_all_mechs = &kg_oidsets[3];
OM_uint32
kg_get_defcred(OM_uint32 *minor_status, gss_cred_id_t *cred)
{
OM_uint32 major;
if ((major = krb5_gss_acquire_cred(minor_status,
(gss_name_t) NULL, GSS_C_INDEFINITE,
GSS_C_NULL_OID_SET, GSS_C_INITIATE,
cred, NULL, NULL)) && GSS_ERROR(major)) {
return(major);
}
*minor_status = 0;
return(GSS_S_COMPLETE);
}
OM_uint32
kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status)
{
OM_uint32 err = 0;
if (!err) {
err = krb5_cc_set_default_name(context,
(char *) k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME));
}
*minor_status = err;
return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
}
OM_uint32
kg_caller_provided_ccache_name (OM_uint32 *minor_status,
int *out_caller_provided_name)
{
if (out_caller_provided_name) {
*out_caller_provided_name =
(k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME) != NULL);
}
*minor_status = 0;
return GSS_S_COMPLETE;
}
OM_uint32
kg_get_ccache_name(OM_uint32 *minor_status, char **out_name)
{
char *kg_ccache_name;
const char *def_name;
OM_uint32 err;
krb5_context context;
*out_name = NULL;
kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
if (kg_ccache_name != NULL) {
*out_name = strdup(kg_ccache_name);
err = (*out_name == NULL) ? ENOMEM : 0;
} else {
err = krb5_gss_init_context(&context);
if (err)
goto cleanup;
def_name = krb5_cc_default_name(context);
*out_name = (def_name != NULL) ? strdup(def_name) : NULL;
err = (*out_name == NULL) ? ENOMEM : 0;
krb5_free_context(context);
}
cleanup:
*minor_status = err;
return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE;
}
OM_uint32
kg_set_ccache_name (OM_uint32 *minor_status, const char *name)
{
char *new_name = NULL;
char *swap = NULL;
char *kg_ccache_name;
krb5_error_code kerr;
if (name) {
new_name = strdup(name);
if (new_name == NULL) {
*minor_status = ENOMEM;
return GSS_S_FAILURE;
}
}
kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME);
swap = kg_ccache_name;
kg_ccache_name = new_name;
new_name = swap;
kerr = k5_setspecific(K5_KEY_GSS_KRB5_CCACHE_NAME, kg_ccache_name);
if (kerr != 0) {
free(kg_ccache_name);
*minor_status = kerr;
return GSS_S_FAILURE;
}
free (new_name);
*minor_status = 0;
return GSS_S_COMPLETE;
}
#define g_OID_prefix_equal(o1, o2) \
(((o1)->length >= (o2)->length) && \
(memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0))
static struct {
gss_OID_desc oid;
OM_uint32 (*func)(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *);
} krb5_gss_inquire_sec_context_by_oid_ops[] = {
{
{GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, GSS_KRB5_GET_TKT_FLAGS_OID},
gss_krb5int_get_tkt_flags
},
{
{GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID},
gss_krb5int_extract_authz_data_from_sec_context
},
{
{GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID},
gss_krb5int_inq_sspi_session_key
},
{
{GSS_KRB5_INQ_ODBC_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_ODBC_SESSION_KEY_OID},
gss_krb5int_inq_odbc_session_key
},
{
{GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID},
gss_krb5int_export_lucid_sec_context
},
{
{GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID},
gss_krb5int_extract_authtime_from_sec_context
},
{
{GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH, GET_SEC_CONTEXT_SASL_SSF_OID},
gss_krb5int_sec_context_sasl_ssf
}
};
OM_uint32 KRB5_CALLCONV
krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
const gss_ctx_id_t context_handle,
const gss_OID desired_object,
gss_buffer_set_t *data_set)
{
krb5_gss_ctx_id_rec *ctx;
size_t i;
if (minor_status == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*minor_status = 0;
if (desired_object == GSS_C_NO_OID)
return GSS_S_CALL_INACCESSIBLE_READ;
if (data_set == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*data_set = GSS_C_NO_BUFFER_SET;
ctx = (krb5_gss_ctx_id_rec *) context_handle;
if (ctx->terminated || !ctx->established)
return GSS_S_NO_CONTEXT;
for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/
sizeof(krb5_gss_inquire_sec_context_by_oid_ops[0]); i++) {
if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_sec_context_by_oid_ops[i].oid)) {
return (*krb5_gss_inquire_sec_context_by_oid_ops[i].func)(minor_status,
context_handle,
desired_object,
data_set);
}
}
*minor_status = EINVAL;
return GSS_S_UNAVAILABLE;
}
static struct {
gss_OID_desc oid;
OM_uint32 (*func)(OM_uint32 *, const gss_cred_id_t, const gss_OID, gss_buffer_set_t *);
} krb5_gss_inquire_cred_by_oid_ops[] = {
{
{GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID},
gss_krb5int_get_cred_impersonator
}
};
static OM_uint32 KRB5_CALLCONV
krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status,
const gss_cred_id_t cred_handle,
const gss_OID desired_object,
gss_buffer_set_t *data_set)
{
OM_uint32 major_status = GSS_S_FAILURE;
size_t i;
if (minor_status == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*minor_status = 0;
if (desired_object == GSS_C_NO_OID)
return GSS_S_CALL_INACCESSIBLE_READ;
if (data_set == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*data_set = GSS_C_NO_BUFFER_SET;
if (cred_handle == GSS_C_NO_CREDENTIAL) {
*minor_status = (OM_uint32)KRB5_NOCREDS_SUPPLIED;
return GSS_S_NO_CRED;
}
major_status = krb5_gss_validate_cred(minor_status, cred_handle);
if (GSS_ERROR(major_status))
return major_status;
for (i = 0; i < sizeof(krb5_gss_inquire_cred_by_oid_ops)/
sizeof(krb5_gss_inquire_cred_by_oid_ops[0]); i++) {
if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_cred_by_oid_ops[i].oid)) {
return (*krb5_gss_inquire_cred_by_oid_ops[i].func)(minor_status,
cred_handle,
desired_object,
data_set);
}
}
*minor_status = EINVAL;
return GSS_S_UNAVAILABLE;
}
OM_uint32 KRB5_CALLCONV
krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
gss_ctx_id_t *context_handle,
const gss_OID desired_object,
const gss_buffer_t value)
{
if (minor_status == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*minor_status = 0;
if (context_handle == NULL)
return GSS_S_CALL_INACCESSIBLE_READ;
if (desired_object == GSS_C_NO_OID)
return GSS_S_CALL_INACCESSIBLE_READ;
*minor_status = EINVAL;
return GSS_S_UNAVAILABLE;
}
static OM_uint32
no_ci_flags(OM_uint32 *minor_status,
gss_cred_id_t *cred_handle,
const gss_OID desired_oid,
const gss_buffer_t value)
{
krb5_gss_cred_id_t cred;
cred = (krb5_gss_cred_id_t) *cred_handle;
cred->suppress_ci_flags = 1;
*minor_status = 0;
return GSS_S_COMPLETE;
}
static struct {
gss_OID_desc oid;
OM_uint32 (*func)(OM_uint32 *, gss_cred_id_t *, const gss_OID, const gss_buffer_t);
} krb5_gssspi_set_cred_option_ops[] = {
{
{GSS_KRB5_COPY_CCACHE_OID_LENGTH, GSS_KRB5_COPY_CCACHE_OID},
gss_krb5int_copy_ccache
},
{
{GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID},
gss_krb5int_set_allowable_enctypes
},
{
{GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH, GSS_KRB5_SET_CRED_RCACHE_OID},
gss_krb5int_set_cred_rcache
},
{
{GSS_KRB5_IMPORT_CRED_OID_LENGTH, GSS_KRB5_IMPORT_CRED_OID},
gss_krb5int_import_cred
},
{
{NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID},
no_ci_flags
},
};
static OM_uint32 KRB5_CALLCONV
krb5_gssspi_set_cred_option(OM_uint32 *minor_status,
gss_cred_id_t *cred_handle,
const gss_OID desired_object,
const gss_buffer_t value)
{
OM_uint32 major_status = GSS_S_FAILURE;
size_t i;
if (minor_status == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
if (cred_handle == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*minor_status = 0;
if (desired_object == GSS_C_NO_OID)
return GSS_S_CALL_INACCESSIBLE_READ;
if (*cred_handle != GSS_C_NO_CREDENTIAL) {
major_status = krb5_gss_validate_cred(minor_status, *cred_handle);
if (GSS_ERROR(major_status))
return major_status;
}
for (i = 0; i < sizeof(krb5_gssspi_set_cred_option_ops)/
sizeof(krb5_gssspi_set_cred_option_ops[0]); i++) {
if (g_OID_prefix_equal(desired_object, &krb5_gssspi_set_cred_option_ops[i].oid)) {
return (*krb5_gssspi_set_cred_option_ops[i].func)(minor_status,
cred_handle,
desired_object,
value);
}
}
*minor_status = EINVAL;
return GSS_S_UNAVAILABLE;
}
static struct {
gss_OID_desc oid;
OM_uint32 (*func)(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t);
} krb5_gssspi_mech_invoke_ops[] = {
{
{GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID},
gss_krb5int_register_acceptor_identity
},
{
{GSS_KRB5_CCACHE_NAME_OID_LENGTH, GSS_KRB5_CCACHE_NAME_OID},
gss_krb5int_ccache_name
},
{
{GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID},
gss_krb5int_free_lucid_sec_context
},
#ifndef _WIN32
{
{GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH, GSS_KRB5_USE_KDC_CONTEXT_OID},
krb5int_gss_use_kdc_context
},
#endif
};
static OM_uint32 KRB5_CALLCONV
krb5_gssspi_mech_invoke (OM_uint32 *minor_status,
const gss_OID desired_mech,
const gss_OID desired_object,
gss_buffer_t value)
{
size_t i;
if (minor_status == NULL)
return GSS_S_CALL_INACCESSIBLE_WRITE;
*minor_status = 0;
if (desired_mech == GSS_C_NO_OID)
return GSS_S_BAD_MECH;
if (desired_object == GSS_C_NO_OID)
return GSS_S_CALL_INACCESSIBLE_READ;
for (i = 0; i < sizeof(krb5_gssspi_mech_invoke_ops)/
sizeof(krb5_gssspi_mech_invoke_ops[0]); i++) {
if (g_OID_prefix_equal(desired_object, &krb5_gssspi_mech_invoke_ops[i].oid)) {
return (*krb5_gssspi_mech_invoke_ops[i].func)(minor_status,
desired_mech,
desired_object,
value);
}
}
*minor_status = EINVAL;
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_CALLCONV
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_CALLCONV
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_CALLCONV
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);
MA_SUPPORTED(GSS_C_MA_NOT_DFLT_MECH);
} 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 OM_uint32 KRB5_CALLCONV
krb5_gss_localname(OM_uint32 *minor,
const gss_name_t pname,
const gss_const_OID mech_type,
gss_buffer_t localname)
{
krb5_context context;
krb5_error_code code;
krb5_gss_name_t kname;
char lname[BUFSIZ];
code = krb5_gss_init_context(&context);
if (code != 0) {
*minor = code;
return GSS_S_FAILURE;
}
kname = (krb5_gss_name_t)pname;
code = krb5_aname_to_localname(context, kname->princ,
sizeof(lname), lname);
if (code != 0) {
*minor = KRB5_NO_LOCALNAME;
krb5_free_context(context);
return GSS_S_FAILURE;
}
krb5_free_context(context);
localname->value = gssalloc_strdup(lname);
localname->length = strlen(lname);
return GSS_S_COMPLETE;
}
static OM_uint32 KRB5_CALLCONV
krb5_gss_authorize_localname(OM_uint32 *minor,
const gss_name_t pname,
gss_const_buffer_t local_user,
gss_const_OID name_type)
{
krb5_context context;
krb5_error_code code;
krb5_gss_name_t kname;
char *user;
int user_ok;
if (name_type != GSS_C_NO_OID &&
!g_OID_equal(name_type, GSS_C_NT_USER_NAME)) {
return GSS_S_BAD_NAMETYPE;
}
kname = (krb5_gss_name_t)pname;
code = krb5_gss_init_context(&context);
if (code != 0) {
*minor = code;
return GSS_S_FAILURE;
}
user = k5memdup0(local_user->value, local_user->length, &code);
if (user == NULL) {
*minor = code;
krb5_free_context(context);
return GSS_S_FAILURE;
}
user_ok = krb5_kuserok(context, kname->princ, user);
free(user);
krb5_free_context(context);
*minor = 0;
return user_ok ? GSS_S_COMPLETE : GSS_S_UNAUTHORIZED;
}
static struct gss_config krb5_mechanism = {
{ GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
NULL,
krb5_gss_acquire_cred,
krb5_gss_release_cred,
krb5_gss_init_sec_context,
#ifdef LEAN_CLIENT
NULL,
#else
krb5_gss_accept_sec_context,
#endif
krb5_gss_process_context_token,
krb5_gss_delete_sec_context,
krb5_gss_context_time,
krb5_gss_get_mic,
krb5_gss_verify_mic,
#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
NULL,
#else
krb5_gss_wrap,
#endif
#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
NULL,
#else
krb5_gss_unwrap,
#endif
krb5_gss_display_status,
krb5_gss_indicate_mechs,
krb5_gss_compare_name,
krb5_gss_display_name,
krb5_gss_import_name,
krb5_gss_release_name,
krb5_gss_inquire_cred,
NULL,
#ifdef LEAN_CLIENT
NULL,
NULL,
#else
krb5_gss_export_sec_context,
krb5_gss_import_sec_context,
#endif
krb5_gss_inquire_cred_by_mech,
krb5_gss_inquire_names_for_mech,
krb5_gss_inquire_context,
krb5_gss_internal_release_oid,
krb5_gss_wrap_size_limit,
krb5_gss_localname,
krb5_gss_authorize_localname,
krb5_gss_export_name,
krb5_gss_duplicate_name,
krb5_gss_store_cred,
krb5_gss_inquire_sec_context_by_oid,
krb5_gss_inquire_cred_by_oid,
krb5_gss_set_sec_context_option,
krb5_gssspi_set_cred_option,
krb5_gssspi_mech_invoke,
NULL,
NULL,
krb5_gss_wrap_iov,
krb5_gss_unwrap_iov,
krb5_gss_wrap_iov_length,
NULL,
krb5_gss_acquire_cred_impersonate_name,
NULL,
NULL,
krb5_gss_inquire_name,
krb5_gss_get_name_attribute,
krb5_gss_set_name_attribute,
krb5_gss_delete_name_attribute,
krb5_gss_export_name_composite,
krb5_gss_map_name_to_any,
krb5_gss_release_any_name_mapping,
krb5_gss_pseudo_random,
NULL,
krb5_gss_inquire_saslname_for_mech,
krb5_gss_inquire_mech_for_saslname,
krb5_gss_inquire_attrs_for_mech,
krb5_gss_acquire_cred_from,
krb5_gss_store_cred_into,
krb5_gss_acquire_cred_with_password,
krb5_gss_export_cred,
krb5_gss_import_cred,
NULL,
NULL,
NULL,
krb5_gss_get_mic_iov,
krb5_gss_verify_mic_iov,
krb5_gss_get_mic_iov_length,
};
static struct gss_config iakerb_mechanism = {
{ GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
NULL,
iakerb_gss_acquire_cred,
krb5_gss_release_cred,
iakerb_gss_init_sec_context,
#ifdef LEAN_CLIENT
NULL,
#else
iakerb_gss_accept_sec_context,
#endif
iakerb_gss_process_context_token,
iakerb_gss_delete_sec_context,
iakerb_gss_context_time,
iakerb_gss_get_mic,
iakerb_gss_verify_mic,
#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
NULL,
#else
iakerb_gss_wrap,
#endif
#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
NULL,
#else
iakerb_gss_unwrap,
#endif
krb5_gss_display_status,
krb5_gss_indicate_mechs,
krb5_gss_compare_name,
krb5_gss_display_name,
iakerb_gss_import_name,
krb5_gss_release_name,
krb5_gss_inquire_cred,
NULL,
#ifdef LEAN_CLIENT
NULL,
NULL,
#else
iakerb_gss_export_sec_context,
iakerb_gss_import_sec_context,
#endif
krb5_gss_inquire_cred_by_mech,
krb5_gss_inquire_names_for_mech,
iakerb_gss_inquire_context,
krb5_gss_internal_release_oid,
iakerb_gss_wrap_size_limit,
krb5_gss_localname,
krb5_gss_authorize_localname,
krb5_gss_export_name,
krb5_gss_duplicate_name,
krb5_gss_store_cred,
iakerb_gss_inquire_sec_context_by_oid,
krb5_gss_inquire_cred_by_oid,
iakerb_gss_set_sec_context_option,
krb5_gssspi_set_cred_option,
krb5_gssspi_mech_invoke,
NULL,
NULL,
iakerb_gss_wrap_iov,
iakerb_gss_unwrap_iov,
iakerb_gss_wrap_iov_length,
NULL,
NULL,
NULL,
NULL,
krb5_gss_inquire_name,
krb5_gss_get_name_attribute,
krb5_gss_set_name_attribute,
krb5_gss_delete_name_attribute,
krb5_gss_export_name_composite,
krb5_gss_map_name_to_any,
krb5_gss_release_any_name_mapping,
iakerb_gss_pseudo_random,
NULL,
krb5_gss_inquire_saslname_for_mech,
krb5_gss_inquire_mech_for_saslname,
krb5_gss_inquire_attrs_for_mech,
iakerb_gss_acquire_cred_from,
krb5_gss_store_cred_into,
iakerb_gss_acquire_cred_with_password,
krb5_gss_export_cred,
krb5_gss_import_cred,
NULL,
NULL,
NULL,
iakerb_gss_get_mic_iov,
iakerb_gss_verify_mic_iov,
iakerb_gss_get_mic_iov_length,
};
#ifdef _GSS_STATIC_LINK
#include "mglueP.h"
static int gss_iakerbmechglue_init(void)
{
struct gss_mech_config mech_iakerb;
memset(&mech_iakerb, 0, sizeof(mech_iakerb));
mech_iakerb.mech = &iakerb_mechanism;
mech_iakerb.mechNameStr = "iakerb";
mech_iakerb.mech_type = (gss_OID)gss_mech_iakerb;
gssint_register_mechinfo(&mech_iakerb);
return 0;
}
static int gss_krb5mechglue_init(void)
{
struct gss_mech_config mech_krb5;
memset(&mech_krb5, 0, sizeof(mech_krb5));
mech_krb5.mech = &krb5_mechanism;
mech_krb5.mechNameStr = "kerberos_v5";
mech_krb5.mech_type = (gss_OID)gss_mech_krb5;
gssint_register_mechinfo(&mech_krb5);
mech_krb5.mechNameStr = "kerberos_v5_old";
mech_krb5.mech_type = (gss_OID)gss_mech_krb5_old;
gssint_register_mechinfo(&mech_krb5);
mech_krb5.mechNameStr = "mskrb";
mech_krb5.mech_type = (gss_OID)gss_mech_krb5_wrong;
gssint_register_mechinfo(&mech_krb5);
return 0;
}
#else
MAKE_INIT_FUNCTION(gss_krb5int_lib_init);
MAKE_FINI_FUNCTION(gss_krb5int_lib_fini);
gss_mechanism KRB5_CALLCONV
gss_mech_initialize(void)
{
return &krb5_mechanism;
}
#endif
int gss_krb5int_lib_init(void)
{
int err;
#ifdef SHOW_INITFINI_FUNCS
printf("gss_krb5int_lib_init\n");
#endif
add_error_table(&et_k5g_error_table);
#ifndef LEAN_CLIENT
err = k5_mutex_finish_init(&gssint_krb5_keytab_lock);
if (err)
return err;
#endif
err = k5_key_register(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, free);
if (err)
return err;
err = k5_key_register(K5_KEY_GSS_KRB5_CCACHE_NAME, free);
if (err)
return err;
err = k5_key_register(K5_KEY_GSS_KRB5_ERROR_MESSAGE,
krb5_gss_delete_error_info);
if (err)
return err;
#ifndef _WIN32
err = k5_mutex_finish_init(&kg_kdc_flag_mutex);
if (err)
return err;
#endif
#ifdef _GSS_STATIC_LINK
err = gss_krb5mechglue_init();
if (err)
return err;
err = gss_iakerbmechglue_init();
if (err)
return err;
#endif
return 0;
}
void gss_krb5int_lib_fini(void)
{
#ifndef _GSS_STATIC_LINK
if (!INITIALIZER_RAN(gss_krb5int_lib_init) || PROGRAM_EXITING()) {
# ifdef SHOW_INITFINI_FUNCS
printf("gss_krb5int_lib_fini: skipping\n");
# endif
return;
}
#endif
#ifdef SHOW_INITFINI_FUNCS
printf("gss_krb5int_lib_fini\n");
#endif
remove_error_table(&et_k5g_error_table);
k5_key_delete(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
k5_key_delete(K5_KEY_GSS_KRB5_CCACHE_NAME);
k5_key_delete(K5_KEY_GSS_KRB5_ERROR_MESSAGE);
#ifndef _WIN32
k5_mutex_destroy(&kg_kdc_flag_mutex);
#endif
#ifndef LEAN_CLIENT
k5_mutex_destroy(&gssint_krb5_keytab_lock);
#endif
}
#ifdef _GSS_STATIC_LINK
extern OM_uint32 gssint_lib_init(void);
#endif
OM_uint32 gss_krb5int_initialize_library (void)
{
#ifdef _GSS_STATIC_LINK
return gssint_mechglue_initialize_library();
#else
return CALL_INIT_FUNCTION(gss_krb5int_lib_init);
#endif
}