Home | History | Annotate | Download | only in libgss
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 /*
     30  *  glue routine for gss_init_sec_context
     31  */
     32 #include <mechglueP.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 
     37 OM_uint32
     38 gss_init_sec_context(minor_status,
     39 			claimant_cred_handle,
     40 			context_handle,
     41 			target_name,
     42 			req_mech_type,
     43 			req_flags,
     44 			time_req,
     45 			input_chan_bindings,
     46 			input_token,
     47 			actual_mech_type,
     48 			output_token,
     49 			ret_flags,
     50 			time_rec)
     51 
     52 OM_uint32 *			minor_status;
     53 const gss_cred_id_t		claimant_cred_handle;
     54 gss_ctx_id_t 			*context_handle;
     55 const gss_name_t		target_name;
     56 const gss_OID			req_mech_type;
     57 OM_uint32			req_flags;
     58 OM_uint32			time_req;
     59 const gss_channel_bindings_t	input_chan_bindings;
     60 const gss_buffer_t		input_token;
     61 gss_OID *			actual_mech_type;
     62 gss_buffer_t			output_token;
     63 OM_uint32 *			ret_flags;
     64 OM_uint32 *			time_rec;
     65 
     66 {
     67 	OM_uint32		status, temp_minor_status;
     68 	gss_union_name_t	union_name;
     69 	gss_union_cred_t	union_cred;
     70 	gss_name_t		internal_name;
     71 	gss_union_ctx_id_t	union_ctx_id;
     72 	gss_OID			mech_type = GSS_C_NULL_OID;
     73 	gss_mechanism		mech;
     74 	gss_cred_id_t		input_cred_handle;
     75 
     76 	if (minor_status == NULL)
     77 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     78 	*minor_status = 0;
     79 
     80 	/* clear output values */
     81 	if (actual_mech_type)
     82 		*actual_mech_type = NULL;
     83 
     84 	if (context_handle == NULL)
     85 		return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
     86 
     87 	if (target_name == NULL)
     88 		return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
     89 
     90 	if (output_token == NULL)
     91 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     92 
     93 	output_token->value = NULL;
     94 	output_token->length = 0;
     95 
     96 
     97 	if (req_mech_type)
     98 		mech_type = (gss_OID)req_mech_type;
     99 
    100 	union_name = (gss_union_name_t)target_name;
    101 
    102 	/*
    103 	 * obtain the gss mechanism information for the requested
    104 	 * mechanism.  If mech_type is NULL, set it to the resultant
    105 	 * mechanism
    106 	 */
    107 	mech = __gss_get_mechanism(mech_type);
    108 	if (mech == NULL)
    109 		return (GSS_S_BAD_MECH);
    110 
    111 	if (mech->gss_init_sec_context == NULL)
    112 		return (GSS_S_UNAVAILABLE);
    113 
    114 	if (mech_type == GSS_C_NULL_OID)
    115 		mech_type = &mech->mech_type;
    116 
    117 	/*
    118 	 * If target_name is mechanism_specific, then it must match the
    119 	 * mech_type that we're about to use.  Otherwise, do an import on
    120 	 * the external_name form of the target name.
    121 	 */
    122 	if (union_name->mech_type &&
    123 			g_OID_equal(union_name->mech_type, mech_type)) {
    124 		internal_name = union_name->mech_name;
    125 	} else {
    126 		if ((status = __gss_import_internal_name(minor_status,
    127 					mech_type, union_name,
    128 					&internal_name)) != GSS_S_COMPLETE)
    129 			return (status);
    130 	}
    131 
    132 	/*
    133 	 * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
    134 	 * descriptor to hold the mech type information as well as the
    135 	 * underlying mechanism context handle. Otherwise, cast the
    136 	 * value of *context_handle to the union context variable.
    137 	 */
    138 	if (*context_handle == GSS_C_NO_CONTEXT) {
    139 		status = GSS_S_FAILURE;
    140 		union_ctx_id = (gss_union_ctx_id_t)
    141 			malloc(sizeof (gss_union_ctx_id_desc));
    142 		if (union_ctx_id == NULL)
    143 			goto end;
    144 
    145 		if (generic_gss_copy_oid(&temp_minor_status, mech_type,
    146 				&union_ctx_id->mech_type) != GSS_S_COMPLETE) {
    147 			free(union_ctx_id);
    148 			goto end;
    149 		}
    150 
    151 		/* copy the supplied context handle */
    152 		union_ctx_id->internal_ctx_id = *context_handle;
    153 	} else
    154 		union_ctx_id = (gss_union_ctx_id_t)*context_handle;
    155 
    156 	/*
    157 	 * get the appropriate cred handle from the union cred struct.
    158 	 * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
    159 	 * use the default credential.
    160 	 */
    161 	union_cred = (gss_union_cred_t)claimant_cred_handle;
    162 	input_cred_handle = __gss_get_mechanism_cred(union_cred, mech_type);
    163 
    164 	/*
    165 	 * now call the approprate underlying mechanism routine
    166 	 */
    167 
    168 	status = mech->gss_init_sec_context(
    169 				mech->context,
    170 				minor_status,
    171 				input_cred_handle,
    172 				&union_ctx_id->internal_ctx_id,
    173 				internal_name,
    174 				mech_type,
    175 				req_flags,
    176 				time_req,
    177 				input_chan_bindings,
    178 				input_token,
    179 				actual_mech_type,
    180 				output_token,
    181 				ret_flags,
    182 				time_rec);
    183 
    184 	if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
    185 		/*
    186 		 * the spec says (the preferred) method is to delete all
    187 		 * context info on the first call to init, and on all
    188 		 * subsequent calls make the caller responsible for
    189 		 * calling gss_delete_sec_context
    190 		 */
    191 		if (*context_handle == GSS_C_NO_CONTEXT) {
    192 			free(union_ctx_id->mech_type->elements);
    193 			free(union_ctx_id->mech_type);
    194 			free(union_ctx_id);
    195 		}
    196 	} else if (*context_handle == GSS_C_NO_CONTEXT)
    197 		*context_handle = (gss_ctx_id_t)union_ctx_id;
    198 
    199 end:
    200 	if (union_name->mech_name == NULL ||
    201 		union_name->mech_name != internal_name) {
    202 		(void) __gss_release_internal_name(&temp_minor_status,
    203 					mech_type, &internal_name);
    204 	}
    205 
    206 	return (status);
    207 }
    208