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