summaryrefslogtreecommitdiff
path: root/src/lib/gssapi/krb5/krb5_gss_glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/gssapi/krb5/krb5_gss_glue.c')
-rw-r--r--src/lib/gssapi/krb5/krb5_gss_glue.c445
1 files changed, 445 insertions, 0 deletions
diff --git a/src/lib/gssapi/krb5/krb5_gss_glue.c b/src/lib/gssapi/krb5/krb5_gss_glue.c
new file mode 100644
index 000000000000..b35a2152344e
--- /dev/null
+++ b/src/lib/gssapi/krb5/krb5_gss_glue.c
@@ -0,0 +1,445 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (c) 2006-2008, Novell, 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:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * 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.
+ * * The copyright holder's name is not used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ krb5_flags *ticket_flags)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH,
+ GSS_KRB5_GET_TKT_FLAGS_OID };
+ OM_uint32 major_status;
+ gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
+
+ if (ticket_flags == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ major_status = gss_inquire_sec_context_by_oid(minor_status,
+ context_handle,
+ (gss_OID)&req_oid,
+ &data_set);
+ if (major_status != GSS_S_COMPLETE)
+ return major_status;
+
+ if (data_set == GSS_C_NO_BUFFER_SET ||
+ data_set->count != 1 ||
+ data_set->elements[0].length != sizeof(*ticket_flags)) {
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+
+ *ticket_flags = *((krb5_flags *)data_set->elements[0].value);
+
+ gss_release_buffer_set(minor_status, &data_set);
+
+ *minor_status = 0;
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_copy_ccache(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ krb5_ccache out_ccache)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_COPY_CCACHE_OID_LENGTH,
+ GSS_KRB5_COPY_CCACHE_OID };
+ OM_uint32 major_status;
+ gss_buffer_desc req_buffer;
+
+ if (out_ccache == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ req_buffer.value = out_ccache;
+ req_buffer.length = sizeof(out_ccache);
+
+ major_status = gss_set_cred_option(minor_status,
+ &cred_handle,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ return major_status;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_import_cred(OM_uint32 *minor_status,
+ krb5_ccache id,
+ krb5_principal keytab_principal,
+ krb5_keytab keytab,
+ gss_cred_id_t *cred)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_IMPORT_CRED_OID_LENGTH,
+ GSS_KRB5_IMPORT_CRED_OID };
+ OM_uint32 major_status;
+ struct krb5_gss_import_cred_req req;
+ gss_buffer_desc req_buffer;
+
+ if (cred == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *cred = GSS_C_NO_CREDENTIAL;
+
+ req.id = id;
+ req.keytab_principal = keytab_principal;
+ req.keytab = keytab;
+
+ req_buffer.value = &req;
+ req_buffer.length = sizeof(req);
+
+ major_status = gss_set_cred_option(minor_status,
+ cred,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ return major_status;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ OM_uint32 version,
+ void **kctx)
+{
+ unsigned char oid_buf[GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH + 6];
+ gss_OID_desc req_oid;
+ OM_uint32 major_status, minor;
+ gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
+
+ if (kctx == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *kctx = NULL;
+
+ req_oid.elements = oid_buf;
+ req_oid.length = sizeof(oid_buf);
+
+ major_status = generic_gss_oid_compose(minor_status,
+ GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID,
+ GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH,
+ (int)version,
+ &req_oid);
+ if (GSS_ERROR(major_status))
+ return major_status;
+
+ major_status = gss_inquire_sec_context_by_oid(minor_status,
+ *context_handle,
+ &req_oid,
+ &data_set);
+ if (GSS_ERROR(major_status))
+ return major_status;
+
+ if (data_set == GSS_C_NO_BUFFER_SET ||
+ data_set->count != 1 ||
+ data_set->elements[0].length != sizeof(void *)) {
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+
+ *kctx = *((void **)data_set->elements[0].value);
+
+ /* Clean up the context state (it is an error for
+ * someone to attempt to use this context again)
+ */
+ (void)gss_delete_sec_context(minor_status, context_handle, NULL);
+ *context_handle = GSS_C_NO_CONTEXT;
+
+ generic_gss_release_buffer_set(&minor, &data_set);
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
+ gss_cred_id_t cred,
+ OM_uint32 num_ktypes,
+ krb5_enctype *ktypes)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH,
+ GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID };
+ OM_uint32 major_status;
+ struct krb5_gss_set_allowable_enctypes_req req;
+ gss_buffer_desc req_buffer;
+
+ req.num_ktypes = num_ktypes;
+ req.ktypes = ktypes;
+
+ req_buffer.length = sizeof(req);
+ req_buffer.value = &req;
+
+ major_status = gss_set_cred_option(minor_status,
+ &cred,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ return major_status;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_ccache_name(OM_uint32 *minor_status,
+ const char *name,
+ const char **out_name)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_CCACHE_NAME_OID_LENGTH,
+ GSS_KRB5_CCACHE_NAME_OID };
+ OM_uint32 major_status;
+ struct krb5_gss_ccache_name_req req;
+ gss_buffer_desc req_buffer;
+
+ req.name = name;
+ req.out_name = out_name;
+
+ req_buffer.length = sizeof(req);
+ req_buffer.value = &req;
+
+ major_status = gssspi_mech_invoke(minor_status,
+ (gss_OID)gss_mech_krb5,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ return major_status;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *kctx)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH,
+ GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID };
+ OM_uint32 major_status;
+ gss_buffer_desc req_buffer;
+
+ req_buffer.length = sizeof(kctx);
+ req_buffer.value = kctx;
+
+ major_status = gssspi_mech_invoke(minor_status,
+ (gss_OID)gss_mech_krb5,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ return major_status;
+}
+
+OM_uint32 KRB5_CALLCONV
+krb5_gss_register_acceptor_identity(const char *keytab)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH,
+ GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID };
+ OM_uint32 major_status;
+ OM_uint32 minor_status;
+ gss_buffer_desc req_buffer;
+
+ req_buffer.length = (keytab == NULL) ? 0 : strlen(keytab);
+ req_buffer.value = (char *)keytab;
+
+ major_status = gssspi_mech_invoke(&minor_status,
+ (gss_OID)gss_mech_krb5,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ return major_status;
+}
+
+#ifndef _WIN32
+krb5_error_code
+krb5_gss_use_kdc_context(void)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH,
+ GSS_KRB5_USE_KDC_CONTEXT_OID };
+ OM_uint32 major_status;
+ OM_uint32 minor_status;
+ gss_buffer_desc req_buffer;
+ krb5_error_code ret;
+
+ req_buffer.length = 0;
+ req_buffer.value = NULL;
+
+ major_status = gssspi_mech_invoke(&minor_status,
+ (gss_OID)gss_mech_krb5,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ if (major_status != GSS_S_COMPLETE) {
+ if (minor_status != 0)
+ ret = (krb5_error_code)minor_status;
+ else
+ ret = KRB5KRB_ERR_GENERIC;
+ } else
+ ret = 0;
+
+ return ret;
+}
+#endif
+
+/*
+ * This API should go away and be replaced with an accessor
+ * into a gss_name_t.
+ */
+OM_uint32 KRB5_CALLCONV
+gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ int ad_type,
+ gss_buffer_t ad_data)
+{
+ gss_OID_desc req_oid;
+ unsigned char oid_buf[GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH + 6];
+ OM_uint32 major_status;
+ gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
+
+ if (ad_data == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ req_oid.elements = oid_buf;
+ req_oid.length = sizeof(oid_buf);
+
+ major_status = generic_gss_oid_compose(minor_status,
+ GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID,
+ GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH,
+ ad_type,
+ &req_oid);
+ if (GSS_ERROR(major_status))
+ return major_status;
+
+ major_status = gss_inquire_sec_context_by_oid(minor_status,
+ context_handle,
+ (gss_OID)&req_oid,
+ &data_set);
+ if (major_status != GSS_S_COMPLETE) {
+ return major_status;
+ }
+
+ if (data_set == GSS_C_NO_BUFFER_SET ||
+ data_set->count != 1) {
+ return GSS_S_FAILURE;
+ }
+
+ ad_data->length = data_set->elements[0].length;
+ ad_data->value = data_set->elements[0].value;
+
+ data_set->elements[0].length = 0;
+ data_set->elements[0].value = NULL;
+
+ data_set->count = 0;
+
+ gss_release_buffer_set(minor_status, &data_set);
+
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_krb5_set_cred_rcache(OM_uint32 *minor_status,
+ gss_cred_id_t cred,
+ krb5_rcache rcache)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH,
+ GSS_KRB5_SET_CRED_RCACHE_OID };
+ OM_uint32 major_status;
+ gss_buffer_desc req_buffer;
+
+ req_buffer.length = sizeof(rcache);
+ req_buffer.value = rcache;
+
+ major_status = gss_set_cred_option(minor_status,
+ &cred,
+ (gss_OID)&req_oid,
+ &req_buffer);
+
+ return major_status;
+}
+
+OM_uint32 KRB5_CALLCONV
+gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ krb5_timestamp *authtime)
+{
+ static const gss_OID_desc req_oid = {
+ GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH,
+ GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID };
+ OM_uint32 major_status;
+ gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
+
+ if (authtime == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ major_status = gss_inquire_sec_context_by_oid(minor_status,
+ context_handle,
+ (gss_OID)&req_oid,
+ &data_set);
+ if (major_status != GSS_S_COMPLETE)
+ return major_status;
+
+ if (data_set == GSS_C_NO_BUFFER_SET ||
+ data_set->count != 1 ||
+ data_set->elements[0].length != sizeof(*authtime)) {
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+
+ *authtime = *((krb5_timestamp *)data_set->elements[0].value);
+
+ gss_release_buffer_set(minor_status, &data_set);
+
+ *minor_status = 0;
+
+ return GSS_S_COMPLETE;
+}