From cd1d7f4be7d31388ab79c797acaf6d7730113112 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 5 Aug 2009 11:25:50 +1000 Subject: s4:heimdal: import lorikeet-heimdal-200908050050 (commit 8714779fa7376fd9f7761587639e68b48afc8c9c) This also adds a new hdb-glue.c file, to cope with Heimdal's uncondtional enabling of SQLITE. (Very reasonable, but not required for Samba4's use). Andrew Bartlett --- source4/heimdal/lib/gssapi/gssapi/gssapi.h | 27 ++- source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h | 8 +- source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h | 8 +- source4/heimdal/lib/gssapi/gssapi_mech.h | 11 + .../heimdal/lib/gssapi/krb5/accept_sec_context.c | 12 +- source4/heimdal/lib/gssapi/krb5/acquire_cred.c | 4 +- .../heimdal/lib/gssapi/krb5/canonicalize_name.c | 2 +- source4/heimdal/lib/gssapi/krb5/copy_ccache.c | 10 +- source4/heimdal/lib/gssapi/krb5/creds.c | 253 +++++++++++++++++++++ source4/heimdal/lib/gssapi/krb5/external.c | 5 +- source4/heimdal/lib/gssapi/krb5/import_name.c | 13 +- source4/heimdal/lib/gssapi/krb5/init_sec_context.c | 2 +- source4/heimdal/lib/gssapi/krb5/set_cred_option.c | 4 +- source4/heimdal/lib/gssapi/krb5/store_cred.c | 116 ++++++++++ source4/heimdal/lib/gssapi/mech/gss_aeap.c | 16 +- source4/heimdal/lib/gssapi/mech/gss_cred.c | 224 ++++++++++++++++++ source4/heimdal/lib/gssapi/mech/gss_release_name.c | 35 +-- source4/heimdal/lib/gssapi/spnego/cred_stubs.c | 36 +++ source4/heimdal/lib/gssapi/spnego/external.c | 8 +- 19 files changed, 727 insertions(+), 67 deletions(-) create mode 100644 source4/heimdal/lib/gssapi/krb5/creds.c create mode 100644 source4/heimdal/lib/gssapi/krb5/store_cred.c create mode 100644 source4/heimdal/lib/gssapi/mech/gss_cred.c (limited to 'source4/heimdal/lib/gssapi') diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi/gssapi.h index 91141808f5..6052ec8134 100644 --- a/source4/heimdal/lib/gssapi/gssapi/gssapi.h +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi.h @@ -63,6 +63,14 @@ #endif #endif +#ifdef __cplusplus +#define GSSAPI_CPP_START extern "C" { +#define GSSAPI_CPP_END } +#else +#define GSSAPI_CPP_START +#define GSSAPI_CPP_END +#endif + /* * Now define the three implementation-dependent types. */ @@ -243,9 +251,7 @@ typedef OM_uint32 gss_qop_t; #define GSS_IOV_BUFFER_TYPE(_t) ((_t) & ~GSS_IOV_BUFFER_TYPE_FLAG_MASK) #define GSS_IOV_BUFFER_FLAGS(_t) ((_t) & GSS_IOV_BUFFER_TYPE_FLAG_MASK) -#ifdef __cplusplus -extern "C" { -#endif +GSSAPI_CPP_START /* * The implementation must reserve static storage for a @@ -894,8 +900,17 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_release_iov_buffer(OM_uint32 *, gss_iov_buffer_desc *, int); -#ifdef __cplusplus -} -#endif +OM_uint32 GSSAPI_LIB_FUNCTION +gss_export_cred(OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred_handle */, + gss_buffer_t /* cred_token */); + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_import_cred(OM_uint32 * /* minor_status */, + gss_buffer_t /* cred_token */, + gss_cred_id_t * /* cred_handle */); + + +GSSAPI_CPP_END #endif /* GSSAPI_GSSAPI_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h index 0baccf5098..4d004d90b5 100644 --- a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h @@ -38,9 +38,7 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +GSSAPI_CPP_START #if !defined(__GNUC__) && !defined(__attribute__) #define __attribute__(x) @@ -246,8 +244,6 @@ gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, OM_uint32 num_enctypes, int32_t *enctypes); -#ifdef __cplusplus -} -#endif +GSSAPI_CPP_END #endif /* GSSAPI_SPNEGO_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h index 3c4869f08d..c5d372d6dc 100644 --- a/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h @@ -38,9 +38,7 @@ #include -#ifdef __cplusplus -extern "C" { -#endif +GSSAPI_CPP_START /* * RFC2478, SPNEGO: @@ -51,8 +49,6 @@ extern "C" { extern GSSAPI_LIB_VARIABLE gss_OID GSS_SPNEGO_MECHANISM; #define gss_mech_spnego GSS_SPNEGO_MECHANISM -#ifdef __cplusplus -} -#endif +GSSAPI_CPP_END #endif /* GSSAPI_SPNEGO_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi_mech.h b/source4/heimdal/lib/gssapi/gssapi_mech.h index 6470df30a0..206a24ef74 100644 --- a/source4/heimdal/lib/gssapi/gssapi_mech.h +++ b/source4/heimdal/lib/gssapi/gssapi_mech.h @@ -343,6 +343,15 @@ _gss_store_cred_t(OM_uint32 *minor_status, gss_OID_set *elements_stored, gss_cred_usage_t *cred_usage_stored); +typedef OM_uint32 +_gss_export_cred_t(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t cred_token); + +typedef OM_uint32 +_gss_import_cred_t(OM_uint32 * minor_status, + gss_buffer_t cred_token, + gss_cred_id_t * cred_handle); #define GMI_VERSION 2 @@ -389,6 +398,8 @@ typedef struct gssapi_mech_interface_desc { _gss_unwrap_iov_t *gm_unwrap_iov; _gss_wrap_iov_length_t *gm_wrap_iov_length; _gss_store_cred_t *gm_store_cred; + _gss_export_cred_t *gm_export_cred; + _gss_import_cred_t *gm_import_cred; } gssapi_mech_interface_desc, *gssapi_mech_interface; gssapi_mech_interface diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c index 8d998ed098..355d1c4332 100644 --- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -170,12 +170,12 @@ gsskrb5_accept_delegated_token if (delegated_cred_handle) { gsskrb5_cred handle; - - ret = _gsskrb5_import_cred(minor_status, - ccache, - NULL, - NULL, - delegated_cred_handle); + + ret = _gsskrb5_krb5_import_cred(minor_status, + ccache, + NULL, + NULL, + delegated_cred_handle); if (ret != GSS_S_COMPLETE) goto out; diff --git a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c index 4f6f38e674..696171dcfa 100644 --- a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c @@ -339,8 +339,8 @@ OM_uint32 _gsskrb5_acquire_cred if (desired_name != GSS_C_NO_NAME) { - ret = _gsskrb5_canon_name(minor_status, context, 0, desired_name, - &handle->principal); + ret = _gsskrb5_canon_name(minor_status, context, 0, NULL, + desired_name, &handle->principal); if (ret) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); free(handle); diff --git a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c index 7e0c3fe727..3de55d6e32 100644 --- a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c +++ b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c @@ -48,7 +48,7 @@ OM_uint32 _gsskrb5_canonicalize_name ( GSSAPI_KRB5_INIT (&context); - ret = _gsskrb5_canon_name(minor_status, context, 1, input_name, &name); + ret = _gsskrb5_canon_name(minor_status, context, 1, NULL, input_name, &name); if (ret) return ret; diff --git a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c index a4b28f91ed..4e65fc1cf3 100644 --- a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c +++ b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c @@ -63,11 +63,11 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status, OM_uint32 -_gsskrb5_import_cred(OM_uint32 *minor_status, - krb5_ccache id, - krb5_principal keytab_principal, - krb5_keytab keytab, - gss_cred_id_t *cred) +_gsskrb5_krb5_import_cred(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal keytab_principal, + krb5_keytab keytab, + gss_cred_id_t *cred) { krb5_context context; krb5_error_code kret; diff --git a/source4/heimdal/lib/gssapi/krb5/creds.c b/source4/heimdal/lib/gssapi/krb5/creds.c new file mode 100644 index 0000000000..c9befe9d77 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/creds.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 +_gsskrb5_export_cred(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t cred_token) +{ + gsskrb5_cred handle = (gsskrb5_cred)cred_handle; + krb5_context context; + krb5_error_code ret; + krb5_storage *sp; + krb5_data data, mech; + const char *type; + char *str; + + GSSAPI_KRB5_INIT (&context); + + if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_FAILURE; + } + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + type = krb5_cc_get_type(context, handle->ccache); + if (strcmp(type, "MEMORY") == 0) { + krb5_creds *creds; + ret = krb5_store_uint32(sp, 0); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = _krb5_get_krbtgt(context, handle->ccache, + handle->principal->realm, + &creds); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_store_creds(sp, creds); + krb5_free_creds(context, creds); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + } else { + ret = krb5_store_uint32(sp, 1); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_get_full_name(context, handle->ccache, &str); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_store_string(sp, str); + free(str); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + } + ret = krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_data_free(&data); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + mech.data = GSS_KRB5_MECHANISM->elements; + mech.length = GSS_KRB5_MECHANISM->length; + + ret = krb5_store_data(sp, mech); + if (ret) { + krb5_data_free(&data); + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_store_data(sp, data); + krb5_data_free(&data); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + cred_token->value = data.data; + cred_token->length = data.length; + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_import_cred(OM_uint32 * minor_status, + gss_buffer_t cred_token, + gss_cred_id_t * cred_handle) +{ + krb5_context context; + krb5_error_code ret; + gsskrb5_cred handle; + krb5_ccache id; + krb5_storage *sp; + char *str; + uint32_t type; + int flags = 0; + + *cred_handle = GSS_C_NO_CREDENTIAL; + + GSSAPI_KRB5_INIT (&context); + + sp = krb5_storage_from_mem(cred_token->value, cred_token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = krb5_ret_uint32(sp, &type); + if (ret) { + krb5_storage_free(sp); + *minor_status = ret; + return GSS_S_FAILURE; + } + switch (type) { + case 0: { + krb5_creds creds; + + ret = krb5_ret_creds(sp, &creds); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_initialize(context, id, creds.client); + if (ret) { + krb5_cc_destroy(context, id); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_store_cred(context, id, &creds); + krb5_free_cred_contents(context, &creds); + + flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + + break; + } + case 1: + ret = krb5_ret_string(sp, &str); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_cc_resolve(context, str, &id); + krb5_xfree(str); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + break; + + default: + krb5_storage_free(sp); + *minor_status = 0; + return GSS_S_NO_CRED; + } + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + krb5_cc_close(context, id); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + handle->usage = GSS_C_INITIATE; + krb5_cc_get_principal(context, id, &handle->principal); + handle->ccache = id; + handle->cred_flags = flags; + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/external.c b/source4/heimdal/lib/gssapi/krb5/external.c index df23776a63..fc835bd845 100644 --- a/source4/heimdal/lib/gssapi/krb5/external.c +++ b/source4/heimdal/lib/gssapi/krb5/external.c @@ -470,7 +470,10 @@ static gssapi_mech_interface_desc krb5_mech = { _gsskrb5_pseudo_random, _gk_wrap_iov, _gk_unwrap_iov, - _gk_wrap_iov_length + _gk_wrap_iov_length, + _gsskrb5_store_cred, + _gsskrb5_export_cred, + _gsskrb5_import_cred }; gssapi_mech_interface diff --git a/source4/heimdal/lib/gssapi/krb5/import_name.c b/source4/heimdal/lib/gssapi/krb5/import_name.c index d488ce754b..f1aca93ffd 100644 --- a/source4/heimdal/lib/gssapi/krb5/import_name.c +++ b/source4/heimdal/lib/gssapi/krb5/import_name.c @@ -83,9 +83,10 @@ import_krb5_name (OM_uint32 *minor_status, OM_uint32 _gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context, - int use_dns, gss_name_t name, krb5_principal *out) + int use_dns, krb5_const_principal sourcename, gss_name_t targetname, + krb5_principal *out) { - krb5_principal p = (krb5_principal)name; + krb5_principal p = (krb5_principal)targetname; krb5_error_code ret; char *hostname = NULL, *service; @@ -96,8 +97,11 @@ _gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context, ret = krb5_copy_principal(context, p, out); } else if (!use_dns) { ret = krb5_copy_principal(context, p, out); - if (ret == 0) - krb5_principal_set_type(context, *out, KRB5_NT_SRV_HST); + if (ret) + goto out; + krb5_principal_set_type(context, *out, KRB5_NT_SRV_HST); + if (sourcename) + ret = krb5_principal_set_realm(context, *out, sourcename->realm); } else { if (p->name.name_string.len == 0) return GSS_S_BAD_NAME; @@ -113,6 +117,7 @@ _gsskrb5_canon_name(OM_uint32 *minor_status, krb5_context context, out); } + out: if (ret) { *minor_status = ret; return GSS_S_FAILURE; diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c index 35ab9dd88d..b269d06798 100644 --- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -191,7 +191,7 @@ gsskrb5_get_creds( } ret = _gsskrb5_canon_name(minor_status, context, use_dns, - target_name, &ctx->target); + ctx->source, target_name, &ctx->target); if (ret) return ret; diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c index 15d7632e4c..ee29bf8c66 100644 --- a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -119,8 +119,8 @@ import_cred(OM_uint32 *minor_status, free(str); str = NULL; - major_stat = _gsskrb5_import_cred(minor_status, id, keytab_principal, - keytab, cred_handle); + major_stat = _gsskrb5_krb5_import_cred(minor_status, id, keytab_principal, + keytab, cred_handle); out: if (id) krb5_cc_close(context, id); diff --git a/source4/heimdal/lib/gssapi/krb5/store_cred.c b/source4/heimdal/lib/gssapi/krb5/store_cred.c new file mode 100644 index 0000000000..675a1d8e95 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/store_cred.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gsskrb5_locl.h" + +OM_uint32 +_gsskrb5_store_cred(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + krb5_context context; + krb5_error_code ret; + gsskrb5_cred cred; + krb5_ccache id; + int destroy = 0; + + *minor_status = 0; + + if (cred_usage != GSS_C_INITIATE) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) + return GSS_S_BAD_MECH; + + cred = (gsskrb5_cred)input_cred_handle; + if (cred == NULL) + return GSS_S_NO_CRED; + + GSSAPI_KRB5_INIT (&context); + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return(GSS_S_FAILURE); + } + + if (cred->principal == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = GSS_KRB5_S_KG_TGT_MISSING; + return(GSS_S_FAILURE); + } + + /* write out cred to credential cache */ + + ret = krb5_cc_cache_match(context, cred->principal, &id); + if (ret) { + ret = krb5_cc_new_unique(context, NULL, NULL, &id); + if (ret) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ret; + return(GSS_S_FAILURE); + } + destroy = 1; + } + + ret = krb5_cc_initialize(context, id, cred->principal); + if (ret == 0) + ret = krb5_cc_copy_match_f(context, cred->ccache, id, NULL, NULL, NULL); + if (ret) { + if (destroy) + krb5_cc_destroy(context, id); + else + krb5_cc_close(context, id); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ret; + return(GSS_S_FAILURE); + } + + if (default_cred) + krb5_cc_switch(context, id); + + krb5_cc_close(context, id); + + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_aeap.c b/source4/heimdal/lib/gssapi/mech/gss_aeap.c index 9c784f42de..9a1835a039 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_aeap.c +++ b/source4/heimdal/lib/gssapi/mech/gss_aeap.c @@ -66,11 +66,8 @@ gss_wrap_iov(OM_uint32 * minor_status, m = ctx->gc_mech; - if (m->gm_wrap_iov == NULL) { - if (minor_status) - *minor_status = 0; + if (m->gm_wrap_iov == NULL) return GSS_S_UNAVAILABLE; - } return (m->gm_wrap_iov)(minor_status, ctx->gc_ctx, conf_req_flag, qop_req, conf_state, @@ -108,10 +105,8 @@ gss_unwrap_iov(OM_uint32 *minor_status, m = ctx->gc_mech; - if (m->gm_unwrap_iov == NULL) { - *minor_status = 0; + if (m->gm_unwrap_iov == NULL) return GSS_S_UNAVAILABLE; - } return (m->gm_unwrap_iov)(minor_status, ctx->gc_ctx, conf_state, qop_state, @@ -152,10 +147,8 @@ gss_wrap_iov_length(OM_uint32 * minor_status, m = ctx->gc_mech; - if (m->gm_wrap_iov_length == NULL) { - *minor_status = 0; + if (m->gm_wrap_iov_length == NULL) return GSS_S_UNAVAILABLE; - } return (m->gm_wrap_iov_length)(minor_status, ctx->gc_ctx, conf_req_flag, qop_req, conf_state, @@ -213,7 +206,8 @@ gss_context_query_attributes(OM_uint32 *minor_status, void *data, size_t len) { - *minor_status = 0; + if (minor_status) + *minor_status = 0; if (gss_oid_equal(GSS_C_ATTR_STREAM_SIZES, attribute)) { memset(data, 0, len); diff --git a/source4/heimdal/lib/gssapi/mech/gss_cred.c b/source4/heimdal/lib/gssapi/mech/gss_cred.c new file mode 100644 index 0000000000..66df50b55e --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_cred.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "mech_locl.h" +#include + +/* + * format: any number of: + * mech-len: int32 + * mech-data: char * (not alligned) + * cred-len: int32 + * cred-data char * (not alligned) +*/ + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_export_cred(OM_uint32 * minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t token) +{ + struct _gss_cred *cred = (struct _gss_cred *)cred_handle; + struct _gss_mechanism_cred *mc; + gss_buffer_desc buffer; + krb5_error_code ret; + krb5_storage *sp; + OM_uint32 major; + krb5_data data; + + _mg_buffer_zero(token); + + if (cred == NULL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + if (mc->gmc_mech->gm_export_cred == NULL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + } + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + + major = mc->gmc_mech->gm_export_cred(minor_status, + mc->gmc_cred, &buffer); + if (major) { + krb5_storage_free(sp); + return major; + } + + ret = krb5_storage_write(sp, buffer.value, buffer.length); + if (ret != buffer.length) { + gss_release_buffer(minor_status, &buffer); + krb5_storage_free(sp); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + gss_release_buffer(minor_status, &buffer); + } + + ret = krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + token->value = data.data; + token->length = data.length; + + return GSS_S_COMPLETE; +} + +OM_uint32 GSSAPI_LIB_FUNCTION +gss_import_cred(OM_uint32 * minor_status, + gss_buffer_t token, + gss_cred_id_t * cred_handle) +{ + gssapi_mech_interface m; + krb5_error_code ret; + struct _gss_cred *cred; + krb5_storage *sp = NULL; + OM_uint32 major, junk; + krb5_data data; + + *cred_handle = GSS_C_NO_CREDENTIAL; + + if (token->length == 0) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + sp = krb5_storage_from_readonly_mem(token->value, token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + cred = calloc(1, sizeof(struct _gss_cred)); + if (cred == NULL) { + krb5_storage_free(sp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + SLIST_INIT(&cred->gc_mc); + + *cred_handle = (gss_cred_id_t)cred; + + while(1) { + struct _gss_mechanism_cred *mc; + gss_buffer_desc buffer; + gss_cred_id_t mcred; + gss_OID_desc oid; + + ret = krb5_ret_data(sp, &data); + if (ret == HEIM_ERR_EOF) { + break; + } else if (ret) { + *minor_status = ret; + major = GSS_S_FAILURE; + goto out; + } + oid.elements = data.data; + oid.length = data.length; + + m = __gss_get_mechanism(&oid); + krb5_data_free(&data); + if (!m) { + *minor_status = 0; + major = GSS_S_BAD_MECH; + goto out; + } + + if (m->gm_import_cred == NULL) { + *minor_status = 0; + major = GSS_S_BAD_MECH; + goto out; + } + + ret = krb5_ret_data(sp, &data); + if (ret) { + *minor_status = ret; + major = GSS_S_FAILURE; + goto out; + } + + buffer.value = data.data; + buffer.length = data.length; + + major = m->gm_import_cred(minor_status, + &buffer, &mcred); + krb5_data_free(&data); + if (major) { + goto out; + } + + mc = malloc(sizeof(struct _gss_mechanism_cred)); + if (mc == NULL) { + *minor_status = EINVAL; + major = GSS_S_FAILURE; + goto out; + } + + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + mc->gmc_cred = mcred; + + SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); + } + krb5_storage_free(sp); + sp = NULL; + + if (SLIST_EMPTY(&cred->gc_mc)) { + major = GSS_S_NO_CRED; + goto out; + } + + return GSS_S_COMPLETE; + + out: + if (sp) + krb5_storage_free(sp); + + gss_release_cred(&junk, cred_handle); + + return major; + +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_name.c b/source4/heimdal/lib/gssapi/mech/gss_release_name.c index ad07c60bda..c5e348d5c0 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_release_name.c +++ b/source4/heimdal/lib/gssapi/mech/gss_release_name.c @@ -33,23 +33,28 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name) { - struct _gss_name *name = (struct _gss_name *) *input_name; + struct _gss_name *name; *minor_status = 0; - if (name) { - if (name->gn_type.elements) - free(name->gn_type.elements); - while (SLIST_FIRST(&name->gn_mn)) { - struct _gss_mechanism_name *mn; - mn = SLIST_FIRST(&name->gn_mn); - SLIST_REMOVE_HEAD(&name->gn_mn, gmn_link); - mn->gmn_mech->gm_release_name(minor_status, - &mn->gmn_name); - free(mn); - } - gss_release_buffer(minor_status, &name->gn_value); - free(name); - *input_name = GSS_C_NO_NAME; + + if (input_name == NULL || *input_name == NULL) + return GSS_S_COMPLETE; + + name = (struct _gss_name *) *input_name; + + if (name->gn_type.elements) + free(name->gn_type.elements); + while (SLIST_FIRST(&name->gn_mn)) { + struct _gss_mechanism_name *mn; + mn = SLIST_FIRST(&name->gn_mn); + SLIST_REMOVE_HEAD(&name->gn_mn, gmn_link); + mn->gmn_mech->gm_release_name(minor_status, + &mn->gmn_name); + free(mn); } + gss_release_buffer(minor_status, &name->gn_value); + free(name); + *input_name = GSS_C_NO_NAME; + return (GSS_S_COMPLETE); } diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c index a3a984e22c..a10a10f1ef 100644 --- a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c +++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c @@ -354,3 +354,39 @@ _gss_spnego_set_cred_option (OM_uint32 *minor_status, value); } + +OM_uint32 +_gss_spnego_export_cred (OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t value) +{ + gssspnego_cred cred = (gssspnego_cred)cred_handle; + + return gss_export_cred(minor_status, cred->negotiated_cred_id, value); +} + +OM_uint32 +_gss_spnego_import_cred (OM_uint32 *minor_status, + gss_buffer_t value, + gss_cred_id_t *cred_handle) +{ + gssspnego_cred cred; + OM_uint32 major; + + *cred_handle = GSS_C_NO_CREDENTIAL; + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + major = gss_import_cred(minor_status, value, &cred->negotiated_cred_id); + if (major == GSS_S_COMPLETE) + *cred_handle = (gss_cred_id_t)cred; + else + free(cred); + + return major; +} + diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c index 2dc809bbba..f3edcba389 100644 --- a/source4/heimdal/lib/gssapi/spnego/external.c +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -79,7 +79,13 @@ static gssapi_mech_interface_desc spnego_mech = { _gss_spnego_inquire_cred_by_oid, _gss_spnego_set_sec_context_option, _gss_spnego_set_cred_option, - _gss_spnego_pseudo_random + _gss_spnego_pseudo_random, + NULL, + NULL, + NULL, + NULL, + _gss_spnego_export_cred, + _gss_spnego_import_cred }; gssapi_mech_interface -- cgit