Home | History | Annotate | Line # | Download | only in mech
      1 /*	$NetBSD: gss_init_sec_context.c,v 1.2 2017/01/28 21:31:46 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2005 Doug Rabson
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  *
     28  *	$FreeBSD: src/lib/libgssapi/gss_init_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
     29  */
     30 
     31 #include "mech_locl.h"
     32 
     33 static gss_cred_id_t
     34 _gss_mech_cred_find(gss_const_cred_id_t cred_handle, gss_OID mech_type)
     35 {
     36 	struct _gss_cred *cred = (struct _gss_cred *)cred_handle;
     37 	struct _gss_mechanism_cred *mc;
     38 
     39 	if (cred == NULL)
     40 		return GSS_C_NO_CREDENTIAL;
     41 
     42 	HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
     43 		if (gss_oid_equal(mech_type, mc->gmc_mech_oid))
     44 			return mc->gmc_cred;
     45 	}
     46 	return GSS_C_NO_CREDENTIAL;
     47 }
     48 
     49 /**
     50  * As the initiator build a context with an acceptor.
     51  *
     52  * Returns in the major
     53  * - GSS_S_COMPLETE - if the context if build
     54  * - GSS_S_CONTINUE_NEEDED -  if the caller needs  to continue another
     55  *	round of gss_i nit_sec_context
     56  * - error code - any other error code
     57  *
     58  * @param minor_status minor status code.
     59  *
     60  * @param initiator_cred_handle the credential to use when building
     61  *        the context, if GSS_C_NO_CREDENTIAL is passed, the default
     62  *        credential for the mechanism will be used.
     63  *
     64  * @param context_handle a pointer to a context handle, will be
     65  * 	  returned as long as there is not an error.
     66  *
     67  * @param target_name the target name of acceptor, created using
     68  * 	  gss_import_name(). The name is can be of any name types the
     69  * 	  mechanism supports, check supported name types with
     70  * 	  gss_inquire_names_for_mech().
     71  *
     72  * @param input_mech_type mechanism type to use, if GSS_C_NO_OID is
     73  *        used, Kerberos (GSS_KRB5_MECHANISM) will be tried. Other
     74  *        available mechanism are listed in the @ref gssapi_mechs_intro
     75  *        section.
     76  *
     77  * @param req_flags flags using when building the context, see @ref
     78  *        gssapi_context_flags
     79  *
     80  * @param time_req time requested this context should be valid in
     81  *        seconds, common used value is GSS_C_INDEFINITE
     82  *
     83  * @param input_chan_bindings Channel bindings used, if not exepected
     84  *        otherwise, used GSS_C_NO_CHANNEL_BINDINGS
     85  *
     86  * @param input_token input token sent from the acceptor, for the
     87  * 	  initial packet the buffer of { NULL, 0 } should be used.
     88  *
     89  * @param actual_mech_type the actual mech used, MUST NOT be freed
     90  *        since it pointing to static memory.
     91  *
     92  * @param output_token if there is an output token, regardless of
     93  * 	  complete, continue_needed, or error it should be sent to the
     94  * 	  acceptor
     95  *
     96  * @param ret_flags return what flags was negotitated, caller should
     97  * 	  check if they are accetable. For example, if
     98  * 	  GSS_C_MUTUAL_FLAG was negotiated with the acceptor or not.
     99  *
    100  * @param time_rec amount of time this context is valid for
    101  *
    102  * @returns a gss_error code, see gss_display_status() about printing
    103  *          the error code.
    104  *
    105  * @ingroup gssapi
    106  */
    107 
    108 
    109 
    110 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
    111 gss_init_sec_context(OM_uint32 * minor_status,
    112     gss_const_cred_id_t initiator_cred_handle,
    113     gss_ctx_id_t * context_handle,
    114     gss_const_name_t target_name,
    115     const gss_OID input_mech_type,
    116     OM_uint32 req_flags,
    117     OM_uint32 time_req,
    118     const gss_channel_bindings_t input_chan_bindings,
    119     const gss_buffer_t input_token,
    120     gss_OID * actual_mech_type,
    121     gss_buffer_t output_token,
    122     OM_uint32 * ret_flags,
    123     OM_uint32 * time_rec)
    124 {
    125 	OM_uint32 major_status;
    126 	gssapi_mech_interface m;
    127 	struct _gss_name *name = (struct _gss_name *) target_name;
    128 	struct _gss_mechanism_name *mn;
    129 	struct _gss_context *ctx = (struct _gss_context *) *context_handle;
    130 	gss_const_cred_id_t cred_handle;
    131 	int allocated_ctx;
    132 	gss_OID mech_type = input_mech_type;
    133 
    134 	*minor_status = 0;
    135 
    136 	_mg_buffer_zero(output_token);
    137 	if (actual_mech_type)
    138 	    *actual_mech_type = GSS_C_NO_OID;
    139 	if (ret_flags)
    140 	    *ret_flags = 0;
    141 	if (time_rec)
    142 	    *time_rec = 0;
    143 
    144 	/*
    145 	 * If we haven't allocated a context yet, do so now and lookup
    146 	 * the mechanism switch table. If we have one already, make
    147 	 * sure we use the same mechanism switch as before.
    148 	 */
    149 	if (!ctx) {
    150 		if (mech_type == NULL)
    151 			mech_type = GSS_KRB5_MECHANISM;
    152 
    153 		ctx = malloc(sizeof(struct _gss_context));
    154 		if (!ctx) {
    155 			*minor_status = ENOMEM;
    156 			return (GSS_S_FAILURE);
    157 		}
    158 		memset(ctx, 0, sizeof(struct _gss_context));
    159 		m = ctx->gc_mech = __gss_get_mechanism(mech_type);
    160 		if (!m) {
    161 			free(ctx);
    162 			return (GSS_S_BAD_MECH);
    163 		}
    164 		allocated_ctx = 1;
    165 	} else {
    166 		m = ctx->gc_mech;
    167 		mech_type = &ctx->gc_mech->gm_mech_oid;
    168 		allocated_ctx = 0;
    169 	}
    170 
    171 	/*
    172 	 * Find the MN for this mechanism.
    173 	 */
    174 	major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
    175 	if (major_status != GSS_S_COMPLETE) {
    176 		if (allocated_ctx)
    177                     free(ctx);
    178 		return major_status;
    179 	}
    180 
    181 	/*
    182 	 * If we have a cred, find the cred for this mechanism.
    183 	 */
    184 	if (m->gm_flags & GM_USE_MG_CRED)
    185 		cred_handle = initiator_cred_handle;
    186 	else
    187 		cred_handle = _gss_mech_cred_find(initiator_cred_handle, mech_type);
    188 
    189         if (initiator_cred_handle != GSS_C_NO_CREDENTIAL &&
    190             cred_handle == NULL) {
    191             if (allocated_ctx)
    192                 free(ctx);
    193             return GSS_S_NO_CRED;
    194         }
    195 
    196 	major_status = m->gm_init_sec_context(minor_status,
    197 	    cred_handle,
    198 	    &ctx->gc_ctx,
    199 	    mn->gmn_name,
    200 	    mech_type,
    201 	    req_flags,
    202 	    time_req,
    203 	    input_chan_bindings,
    204 	    input_token,
    205 	    actual_mech_type,
    206 	    output_token,
    207 	    ret_flags,
    208 	    time_rec);
    209 
    210 	if (major_status != GSS_S_COMPLETE
    211 	    && major_status != GSS_S_CONTINUE_NEEDED) {
    212 		if (allocated_ctx)
    213 			free(ctx);
    214 		_mg_buffer_zero(output_token);
    215 		_gss_mg_error(m, major_status, *minor_status);
    216 	} else {
    217 		*context_handle = (gss_ctx_id_t) ctx;
    218 	}
    219 
    220 	return (major_status);
    221 }
    222