/*
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* -*- mode: c; 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.
*/
/*
* 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.
*/
#include "gssapiP_krb5.h"
#include "mechglueP.h" /* SUNW17PACresync */
OM_uint32
krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
acceptor_name, lifetime_rec, mech_type, ret_flags,
locally_initiated, opened)
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_name_t *initiator_name;
gss_name_t *acceptor_name;
OM_uint32 *lifetime_rec;
gss_OID *mech_type;
OM_uint32 *ret_flags;
int *locally_initiated;
int *opened;
{
krb5_context context;
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
krb5_principal initiator, acceptor;
krb5_timestamp now;
krb5_deltat lifetime;
if (initiator_name)
*initiator_name = (gss_name_t) NULL;
if (acceptor_name)
*acceptor_name = (gss_name_t) NULL;
/* validate the context handle */
if (! kg_validate_ctx_id(context_handle)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_NO_CONTEXT);
}
ctx = (krb5_gss_ctx_id_rec *) context_handle;
if (! ctx->established) {
*minor_status = KG_CTX_INCOMPLETE;
return(GSS_S_NO_CONTEXT);
}
initiator = NULL;
acceptor = NULL;
context = ctx->k5_context;
if ((code = krb5_timeofday(context, &now))) {
*minor_status = code;
save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
/* SUNW17PACresync - should be krb_times.endtime (revisit) */
if ((lifetime = ctx->endtime - now) < 0)
lifetime = 0;
if (initiator_name) {
if ((code = krb5_copy_principal(context,
ctx->initiate?ctx->here:ctx->there,
&initiator))) {
*minor_status = code;
save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
if (! kg_save_name((gss_name_t) initiator)) {
krb5_free_principal(context, initiator);
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_FAILURE);
}
}
if (acceptor_name) {
if ((code = krb5_copy_principal(context,
ctx->initiate?ctx->there:ctx->here,
&acceptor))) {
if (initiator) krb5_free_principal(context, initiator);
*minor_status = code;
save_error_info(*minor_status, context);
return(GSS_S_FAILURE);
}
if (! kg_save_name((gss_name_t) acceptor)) {
krb5_free_principal(context, acceptor);
if (initiator) {
kg_delete_name((gss_name_t) initiator);
krb5_free_principal(context, initiator);
}
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_FAILURE);
}
}
if (initiator_name)
*initiator_name = (gss_name_t) initiator;
if (acceptor_name)
*acceptor_name = (gss_name_t) acceptor;
if (lifetime_rec)
*lifetime_rec = lifetime;
if (mech_type)
*mech_type = (gss_OID) ctx->mech_used;
if (ret_flags)
*ret_flags = ctx->gss_flags;
if (locally_initiated)
*locally_initiated = ctx->initiate;
if (opened)
*opened = ctx->established;
*minor_status = 0;
return((lifetime == 0)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE);
}
OM_uint32
gss_krb5int_inq_session_key(
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;
krb5_keyblock *key;
gss_buffer_desc keyvalue, keyinfo;
OM_uint32 major_status, minor;
unsigned char oid_buf[GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH + 6];
gss_OID_desc oid;
ctx = (krb5_gss_ctx_id_rec *) context_handle;
key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey;
keyvalue.value = key->contents;
keyvalue.length = key->length;
major_status = generic_gss_add_buffer_set_member(minor_status, &keyvalue, data_set);
if (GSS_ERROR(major_status))
goto cleanup;
oid.elements = oid_buf;
oid.length = sizeof(oid_buf);
major_status = generic_gss_oid_compose(minor_status,
GSS_KRB5_SESSION_KEY_ENCTYPE_OID,
GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
key->enctype,
&oid);
if (GSS_ERROR(major_status))
goto cleanup;
keyinfo.value = oid.elements;
keyinfo.length = oid.length;
major_status = generic_gss_add_buffer_set_member(minor_status, &keyinfo, data_set);
if (GSS_ERROR(major_status))
goto cleanup;
return GSS_S_COMPLETE;
cleanup:
if (*data_set != GSS_C_NO_BUFFER_SET) {
if ((*data_set)->count != 0)
memset((*data_set)->elements[0].value, 0, (*data_set)->elements[0].length);
gss_release_buffer_set(&minor, data_set);
}
return major_status;
}
OM_uint32
gss_krb5int_extract_authz_data_from_sec_context(
OM_uint32 *minor_status,
const gss_ctx_id_t context_handle,
const gss_OID desired_object,
gss_buffer_set_t *data_set)
{
gss_buffer_desc ad_data;
OM_uint32 major_status;
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
int ad_type = 0;
int i, j;
*data_set = GSS_C_NO_BUFFER_SET;
ctx = (krb5_gss_ctx_id_rec *) context_handle;
major_status = generic_gss_oid_decompose(minor_status,
GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID,
GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH,
desired_object,
&ad_type);
if (major_status != GSS_S_COMPLETE || ad_type == 0) {
*minor_status = ENOENT;
return major_status; /* SUNW17PACresync */
}
if (ctx->authdata != NULL) {
for (i = 0; ctx->authdata[i] != NULL; i++) {
if (ctx->authdata[i]->ad_type == ad_type) {
ad_data.length = ctx->authdata[i]->length;
ad_data.value = ctx->authdata[i]->contents;
major_status = generic_gss_add_buffer_set_member(minor_status,
&ad_data, data_set);
if (GSS_ERROR(major_status))
break;
} else if (ctx->authdata[i]->ad_type == KRB5_AUTHDATA_IF_RELEVANT) {
/*
* Solaris Kerberos (illumos)
* Unwrap the AD-IF-RELEVANT object and look inside.
*/
krb5_authdata **ad_if_relevant = NULL;
code = krb5_decode_authdata_container(ctx->k5_context,
KRB5_AUTHDATA_IF_RELEVANT,
ctx->authdata[i],
&ad_if_relevant);
if (code != 0)
continue;
for (j = 0; ad_if_relevant[j] != NULL; j++) {
if (ad_if_relevant[j]->ad_type == ad_type) {
ad_data.length = ad_if_relevant[j]->length;
ad_data.value = ad_if_relevant[j]->contents;
major_status = generic_gss_add_buffer_set_member(minor_status,
&ad_data, data_set);
if (GSS_ERROR(major_status)) {
krb5_free_authdata(ctx->k5_context, ad_if_relevant);
goto break2;
}
}
}
krb5_free_authdata(ctx->k5_context, ad_if_relevant);
/* Solaris Kerberos (illumos) */
}
}
}
break2:
if (GSS_ERROR(major_status)) {
OM_uint32 tmp;
generic_gss_release_buffer_set(&tmp, data_set);
}
return major_status;
}
OM_uint32
gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status,
const gss_ctx_id_t context_handle,
const gss_OID desired_oid,
gss_buffer_set_t *data_set)
{
krb5_gss_ctx_id_rec *ctx;
gss_buffer_desc rep;
ctx = (krb5_gss_ctx_id_rec *) context_handle;
rep.value = &ctx->krb_times.authtime;
rep.length = sizeof(ctx->krb_times.authtime);
return generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
}