2N/A/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2N/A/*
2N/A * Copyright 1993 by OpenVision Technologies, Inc.
2N/A *
2N/A * Permission to use, copy, modify, distribute, and sell this software
2N/A * and its documentation for any purpose is hereby granted without fee,
2N/A * provided that the above copyright notice appears in all copies and
2N/A * that both that copyright notice and this permission notice appear in
2N/A * supporting documentation, and that the name of OpenVision not be used
2N/A * in advertising or publicity pertaining to distribution of the software
2N/A * without specific, written prior permission. OpenVision makes no
2N/A * representations about the suitability of this software for any
2N/A * purpose. It is provided "as is" without express or implied warranty.
2N/A *
2N/A * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
2N/A * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
2N/A * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
2N/A * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
2N/A * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2N/A * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2N/A * PERFORMANCE OF THIS SOFTWARE.
2N/A */
2N/A/*
2N/A * Copyright (c) 2006-2008, Novell, Inc.
2N/A * All rights reserved.
2N/A *
2N/A * Redistribution and use in source and binary forms, with or without
2N/A * modification, are permitted provided that the following conditions are met:
2N/A *
2N/A * * Redistributions of source code must retain the above copyright notice,
2N/A * this list of conditions and the following disclaimer.
2N/A * * Redistributions in binary form must reproduce the above copyright
2N/A * notice, this list of conditions and the following disclaimer in the
2N/A * documentation and/or other materials provided with the distribution.
2N/A * * The copyright holder's name is not used to endorse or promote products
2N/A * derived from this software without specific prior written permission.
2N/A *
2N/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2N/A * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2N/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2N/A * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2N/A * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2N/A * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2N/A * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2N/A * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2N/A * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2N/A * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2N/A * POSSIBILITY OF SUCH DAMAGE.
2N/A */
2N/A
2N/A/*
2N/A * $Id: krb5_gss_glue.c 23393 2009-11-30 22:29:48Z tsitkova $
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A#include "gssapiP_krb5.h"
2N/A#include "mglueP.h" /* Solaris Kerberos */
2N/A
2N/AOM_uint32 KRB5_CALLCONV
2N/Agss_krb5_get_tkt_flags(OM_uint32 *minor_status,
2N/A gss_ctx_id_t context_handle,
2N/A krb5_flags *ticket_flags)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH,
2N/A GSS_KRB5_GET_TKT_FLAGS_OID };
2N/A OM_uint32 major_status;
2N/A gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
2N/A
2N/A if (ticket_flags == NULL)
2N/A return GSS_S_CALL_INACCESSIBLE_WRITE;
2N/A
2N/A major_status = gss_inquire_sec_context_by_oid(minor_status,
2N/A context_handle,
2N/A (gss_OID)&req_oid,
2N/A &data_set);
2N/A if (major_status != GSS_S_COMPLETE)
2N/A return major_status;
2N/A
2N/A if (data_set == GSS_C_NO_BUFFER_SET ||
2N/A data_set->count != 1 ||
2N/A data_set->elements[0].length != sizeof(*ticket_flags)) {
2N/A *minor_status = EINVAL;
2N/A return GSS_S_FAILURE;
2N/A }
2N/A
2N/A *ticket_flags = *((krb5_flags *)data_set->elements[0].value);
2N/A
2N/A gss_release_buffer_set(minor_status, &data_set);
2N/A
2N/A *minor_status = 0;
2N/A
2N/A return GSS_S_COMPLETE;
2N/A}
2N/A
2N/AOM_uint32 KRB5_CALLCONV
2N/Agss_krb5_copy_ccache(OM_uint32 *minor_status,
2N/A gss_cred_id_t cred_handle,
2N/A krb5_ccache out_ccache)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_COPY_CCACHE_OID_LENGTH,
2N/A GSS_KRB5_COPY_CCACHE_OID };
2N/A OM_uint32 major_status;
2N/A gss_buffer_desc req_buffer;
2N/A
2N/A if (out_ccache == NULL)
2N/A return GSS_S_CALL_INACCESSIBLE_WRITE;
2N/A
2N/A req_buffer.value = out_ccache;
2N/A req_buffer.length = sizeof(out_ccache);
2N/A
2N/A /*
2N/A * Solaris Kerberos: we don't support calling libgss from the krb mech so
2N/A * we call krb mech interface krb5_gssspi_set_cred_option directly. Done
2N/A * several times below.
2N/A */
2N/A major_status = krb5_gssspi_set_cred_option(minor_status,
2N/A cred_handle,
2N/A (gss_OID)&req_oid,
2N/A &req_buffer);
2N/A
2N/A return major_status;
2N/A}
2N/A
2N/A/* Solaris Kerberos: not supported yet */
2N/A#if 0 /************** Begin IFDEF'ed OUT *******************************/
2N/AOM_uint32 KRB5_CALLCONV
2N/Agss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
2N/A gss_ctx_id_t *context_handle,
2N/A OM_uint32 version,
2N/A void **kctx)
2N/A{
2N/A unsigned char oid_buf[GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH + 6];
2N/A gss_OID_desc req_oid;
2N/A OM_uint32 major_status, minor;
2N/A gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
2N/A
2N/A if (kctx == NULL)
2N/A return GSS_S_CALL_INACCESSIBLE_WRITE;
2N/A
2N/A *kctx = NULL;
2N/A
2N/A req_oid.elements = oid_buf;
2N/A req_oid.length = sizeof(oid_buf);
2N/A
2N/A major_status = generic_gss_oid_compose(minor_status,
2N/A GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID,
2N/A GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH,
2N/A (int)version,
2N/A &req_oid);
2N/A if (GSS_ERROR(major_status))
2N/A return major_status;
2N/A
2N/A major_status = gss_inquire_sec_context_by_oid(minor_status,
2N/A *context_handle,
2N/A &req_oid,
2N/A &data_set);
2N/A if (GSS_ERROR(major_status))
2N/A return major_status;
2N/A
2N/A if (data_set == GSS_C_NO_BUFFER_SET ||
2N/A data_set->count != 1 ||
2N/A data_set->elements[0].length != sizeof(void *)) {
2N/A *minor_status = EINVAL;
2N/A return GSS_S_FAILURE;
2N/A }
2N/A
2N/A *kctx = *((void **)data_set->elements[0].value);
2N/A
2N/A /* Clean up the context state (it is an error for
2N/A * someone to attempt to use this context again)
2N/A */
2N/A (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
2N/A *context_handle = GSS_C_NO_CONTEXT;
2N/A
2N/A generic_gss_release_buffer_set(&minor, &data_set);
2N/A
2N/A return GSS_S_COMPLETE;
2N/A}
2N/A#endif /**************** END IFDEF'ed OUT *******************************/
2N/A
2N/AOM_uint32 KRB5_CALLCONV
2N/Agss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
2N/A gss_cred_id_t cred,
2N/A OM_uint32 num_ktypes,
2N/A krb5_enctype *ktypes)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH,
2N/A GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID };
2N/A OM_uint32 major_status;
2N/A struct krb5_gss_set_allowable_enctypes_req req;
2N/A gss_buffer_desc req_buffer;
2N/A
2N/A req.num_ktypes = num_ktypes;
2N/A req.ktypes = ktypes;
2N/A
2N/A req_buffer.length = sizeof(req);
2N/A req_buffer.value = &req;
2N/A
2N/A major_status = krb5_gssspi_set_cred_option(minor_status,
2N/A cred,
2N/A (gss_OID)&req_oid,
2N/A &req_buffer);
2N/A
2N/A return major_status;
2N/A}
2N/A
2N/AOM_uint32 KRB5_CALLCONV
2N/Agss_krb5_ccache_name(OM_uint32 *minor_status,
2N/A const char *name,
2N/A const char **out_name)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_CCACHE_NAME_OID_LENGTH,
2N/A GSS_KRB5_CCACHE_NAME_OID };
2N/A OM_uint32 major_status;
2N/A struct krb5_gss_ccache_name_req req;
2N/A gss_buffer_desc req_buffer;
2N/A
2N/A req.name = name;
2N/A req.out_name = out_name;
2N/A
2N/A req_buffer.length = sizeof(req);
2N/A req_buffer.value = &req;
2N/A
2N/A /*
2N/A * Solaris Kerberos: we don't support calling libgss from the krb mech so
2N/A * we call krb mech interface krb5_gssspi_mech_invoke directly. Done
2N/A * several times below.
2N/A */
2N/A major_status = krb5_gssspi_mech_invoke(minor_status,
2N/A (gss_OID)gss_mech_krb5,
2N/A (gss_OID)&req_oid,
2N/A &req_buffer);
2N/A
2N/A return major_status;
2N/A}
2N/A
2N/AOM_uint32 KRB5_CALLCONV
2N/Agss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *kctx)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH,
2N/A GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID };
2N/A OM_uint32 major_status;
2N/A gss_buffer_desc req_buffer;
2N/A
2N/A req_buffer.length = sizeof(kctx);
2N/A req_buffer.value = kctx;
2N/A
2N/A major_status = krb5_gssspi_mech_invoke(minor_status,
2N/A (gss_OID)gss_mech_krb5,
2N/A (gss_OID)&req_oid,
2N/A &req_buffer);
2N/A
2N/A return major_status;
2N/A}
2N/A
2N/AOM_uint32 KRB5_CALLCONV
2N/Akrb5_gss_register_acceptor_identity(const char *keytab)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH,
2N/A GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID };
2N/A OM_uint32 major_status;
2N/A OM_uint32 minor_status;
2N/A gss_buffer_desc req_buffer;
2N/A
2N/A req_buffer.length = strlen(keytab);
2N/A req_buffer.value = (char *)keytab;
2N/A
2N/A major_status = krb5_gssspi_mech_invoke(&minor_status,
2N/A (gss_OID)gss_mech_krb5,
2N/A (gss_OID)&req_oid,
2N/A &req_buffer);
2N/A
2N/A return major_status;
2N/A}
2N/A
2N/Akrb5_error_code
2N/Akrb5_gss_use_kdc_context(void)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH,
2N/A GSS_KRB5_USE_KDC_CONTEXT_OID };
2N/A OM_uint32 major_status;
2N/A OM_uint32 minor_status;
2N/A gss_buffer_desc req_buffer;
2N/A krb5_error_code ret;
2N/A
2N/A req_buffer.length = 0;
2N/A req_buffer.value = NULL;
2N/A
2N/A major_status = krb5_gssspi_mech_invoke(&minor_status,
2N/A (gss_OID)gss_mech_krb5,
2N/A (gss_OID)&req_oid,
2N/A &req_buffer);
2N/A
2N/A if (major_status != GSS_S_COMPLETE) {
2N/A if (minor_status != 0)
2N/A ret = (krb5_error_code)minor_status;
2N/A else
2N/A ret = KRB5KRB_ERR_GENERIC;
2N/A } else
2N/A ret = 0;
2N/A
2N/A return ret;
2N/A}
2N/A
2N/A/*
2N/A * This API should go away and be replaced with an accessor
2N/A * into a gss_name_t.
2N/A */
2N/AOM_uint32 KRB5_CALLCONV
2N/Agsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
2N/A gss_ctx_id_t context_handle,
2N/A int ad_type,
2N/A gss_buffer_t ad_data)
2N/A{
2N/A gss_OID_desc req_oid;
2N/A unsigned char oid_buf[GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH + 6];
2N/A OM_uint32 major_status;
2N/A gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
2N/A
2N/A if (ad_data == NULL)
2N/A return GSS_S_CALL_INACCESSIBLE_WRITE;
2N/A
2N/A req_oid.elements = oid_buf;
2N/A req_oid.length = sizeof(oid_buf);
2N/A
2N/A major_status = generic_gss_oid_compose(minor_status,
2N/A GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID,
2N/A GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH,
2N/A ad_type,
2N/A &req_oid);
2N/A if (GSS_ERROR(major_status))
2N/A return major_status;
2N/A
2N/A major_status = gss_inquire_sec_context_by_oid(minor_status,
2N/A context_handle,
2N/A (gss_OID)&req_oid,
2N/A &data_set);
2N/A if (major_status != GSS_S_COMPLETE) {
2N/A return major_status;
2N/A }
2N/A
2N/A /* Solaris Kerberos */
2N/A if (data_set == GSS_C_NO_BUFFER_SET || data_set->count == 0) {
2N/A gss_release_buffer_set(minor_status, &data_set);
2N/A *minor_status = EINVAL;
2N/A return GSS_S_FAILURE;
2N/A }
2N/A
2N/A ad_data->length = data_set->elements[0].length;
2N/A ad_data->value = data_set->elements[0].value;
2N/A
2N/A data_set->elements[0].length = 0;
2N/A data_set->elements[0].value = NULL;
2N/A
2N/A gss_release_buffer_set(minor_status, &data_set);
2N/A
2N/A return GSS_S_COMPLETE;
2N/A}
2N/A
2N/A/* Solaris Kerberos: not supported yet */
2N/AOM_uint32 KRB5_CALLCONV
2N/Agss_krb5_set_cred_rcache(OM_uint32 *minor_status,
2N/A gss_cred_id_t cred,
2N/A krb5_rcache rcache)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH,
2N/A GSS_KRB5_SET_CRED_RCACHE_OID };
2N/A OM_uint32 major_status;
2N/A gss_buffer_desc req_buffer;
2N/A
2N/A req_buffer.length = sizeof(rcache);
2N/A req_buffer.value = rcache;
2N/A
2N/A major_status = krb5_gssspi_set_cred_option(minor_status,
2N/A cred,
2N/A (gss_OID)&req_oid,
2N/A &req_buffer);
2N/A
2N/A return major_status;
2N/A}
2N/A
2N/AOM_uint32 KRB5_CALLCONV
2N/Agsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
2N/A gss_ctx_id_t context_handle,
2N/A krb5_timestamp *authtime)
2N/A{
2N/A static const gss_OID_desc req_oid = {
2N/A GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH,
2N/A GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID };
2N/A OM_uint32 major_status;
2N/A gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
2N/A
2N/A if (authtime == NULL)
2N/A return GSS_S_CALL_INACCESSIBLE_WRITE;
2N/A
2N/A major_status = gss_inquire_sec_context_by_oid(minor_status,
2N/A context_handle,
2N/A (gss_OID)&req_oid,
2N/A &data_set);
2N/A if (major_status != GSS_S_COMPLETE)
2N/A return major_status;
2N/A
2N/A if (data_set == GSS_C_NO_BUFFER_SET ||
2N/A data_set->count != 1 ||
2N/A data_set->elements[0].length != sizeof(*authtime)) {
2N/A *minor_status = EINVAL;
2N/A return GSS_S_FAILURE;
2N/A }
2N/A
2N/A *authtime = *((krb5_timestamp *)data_set->elements[0].value);
2N/A
2N/A gss_release_buffer_set(minor_status, &data_set);
2N/A
2N/A *minor_status = 0;
2N/A
2N/A return GSS_S_COMPLETE;
2N/A}