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  10598   Glenn  * Common Development and Distribution License (the "License").
      6  10598   Glenn  * 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_accept_sec_context
     28      0  stevel  */
     29      0  stevel 
     30      0  stevel #include <mechglueP.h>
     31      0  stevel #ifdef HAVE_STDLIB_H
     32      0  stevel #include <stdlib.h>
     33      0  stevel #endif
     34      0  stevel #include <string.h>
     35      0  stevel #include <errno.h>
     36   9698   Peter 
     37   9698   Peter static OM_uint32
     38   9698   Peter val_acc_sec_ctx_args(
     39   9698   Peter 	OM_uint32 *minor_status,
     40   9698   Peter 	gss_ctx_id_t *context_handle,
     41   9698   Peter 	gss_buffer_t input_token_buffer,
     42   9698   Peter 	gss_name_t *src_name,
     43   9698   Peter 	gss_OID *mech_type,
     44   9698   Peter 	gss_buffer_t output_token,
     45   9698   Peter 	gss_cred_id_t *d_cred)
     46   9698   Peter {
     47   9698   Peter 
     48   9698   Peter 	/* Initialize outputs. */
     49   9698   Peter 
     50   9698   Peter 	if (minor_status != NULL)
     51   9698   Peter 		*minor_status = 0;
     52   9698   Peter 
     53   9698   Peter 	if (src_name != NULL)
     54   9698   Peter 		*src_name = GSS_C_NO_NAME;
     55   9698   Peter 
     56   9698   Peter 	if (mech_type != NULL)
     57   9698   Peter 		*mech_type = GSS_C_NO_OID;
     58   9698   Peter 
     59   9698   Peter 	if (output_token != GSS_C_NO_BUFFER) {
     60   9698   Peter 		output_token->length = 0;
     61   9698   Peter 		output_token->value = NULL;
     62   9698   Peter 	}
     63   9698   Peter 
     64   9698   Peter 	if (d_cred != NULL)
     65   9698   Peter 		*d_cred = GSS_C_NO_CREDENTIAL;
     66   9698   Peter 
     67   9698   Peter 	/* Validate arguments. */
     68   9698   Peter 
     69   9698   Peter 	if (minor_status == NULL)
     70   9698   Peter 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     71   9698   Peter 
     72   9698   Peter 	if (context_handle == NULL)
     73   9698   Peter 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     74   9698   Peter 
     75   9698   Peter 	if (input_token_buffer == GSS_C_NO_BUFFER)
     76   9698   Peter 		return (GSS_S_CALL_INACCESSIBLE_READ);
     77   9698   Peter 
     78   9698   Peter 	if (output_token == GSS_C_NO_BUFFER)
     79   9698   Peter 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     80   9698   Peter 
     81   9698   Peter 	return (GSS_S_COMPLETE);
     82   9698   Peter }
     83      0  stevel 
     84      0  stevel OM_uint32
     85      0  stevel gss_accept_sec_context(minor_status,
     86      0  stevel 			context_handle,
     87      0  stevel 			verifier_cred_handle,
     88      0  stevel 			input_token_buffer,
     89      0  stevel 			input_chan_bindings,
     90      0  stevel 			src_name,
     91      0  stevel 			mech_type,
     92      0  stevel 			output_token,
     93      0  stevel 			ret_flags,
     94      0  stevel 			time_rec,
     95      0  stevel 			d_cred)
     96      0  stevel 
     97      0  stevel OM_uint32 			*minor_status;
     98      0  stevel gss_ctx_id_t			*context_handle;
     99      0  stevel const gss_cred_id_t		verifier_cred_handle;
    100      0  stevel const gss_buffer_t		input_token_buffer;
    101      0  stevel const gss_channel_bindings_t	input_chan_bindings;
    102      0  stevel gss_name_t			*src_name;
    103      0  stevel gss_OID				*mech_type;
    104      0  stevel gss_buffer_t			output_token;
    105      0  stevel OM_uint32			*ret_flags;
    106      0  stevel OM_uint32			*time_rec;
    107      0  stevel gss_cred_id_t			*d_cred; /* delegated cred handle */
    108      0  stevel 
    109      0  stevel {
    110    160  wyllys 	OM_uint32		status, temp_status, t_minstat;
    111      0  stevel 	gss_union_ctx_id_t	union_ctx_id;
    112      0  stevel 	gss_union_cred_t	union_cred;
    113      0  stevel 	gss_cred_id_t	input_cred_handle = GSS_C_NO_CREDENTIAL;
    114      0  stevel 	gss_cred_id_t	tmp_d_cred = GSS_C_NO_CREDENTIAL;
    115      0  stevel 	gss_name_t		internal_name = GSS_C_NO_NAME;
    116      0  stevel 	gss_name_t		tmp_src_name = GSS_C_NO_NAME;
    117      0  stevel 	gss_OID_desc	token_mech_type_desc;
    118      0  stevel 	gss_OID		token_mech_type = &token_mech_type_desc;
    119    160  wyllys 	gss_OID		actual_mech = GSS_C_NO_OID;
    120    160  wyllys 	OM_uint32	flags;
    121      0  stevel 	gss_mechanism	mech;
    122      0  stevel 
    123   9698   Peter 	status = val_acc_sec_ctx_args(minor_status,
    124   9698   Peter 				context_handle,
    125   9698   Peter 				input_token_buffer,
    126   9698   Peter 				src_name,
    127   9698   Peter 				mech_type,
    128   9698   Peter 				output_token,
    129   9698   Peter 				d_cred);
    130   9698   Peter 	if (status != GSS_S_COMPLETE)
    131   9698   Peter 		return (status);
    132      0  stevel 
    133      0  stevel 	/*
    134      0  stevel 	 * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
    135      0  stevel 	 * descriptor to hold the mech type information as well as the
    136      0  stevel 	 * underlying mechanism context handle. Otherwise, cast the
    137      0  stevel 	 * value of *context_handle to the union context variable.
    138      0  stevel 	 */
    139      0  stevel 
    140      0  stevel 	if (*context_handle == GSS_C_NO_CONTEXT) {
    141      0  stevel 
    142  10598   Glenn 		if (input_token_buffer == GSS_C_NO_BUFFER)
    143      0  stevel 			return (GSS_S_CALL_INACCESSIBLE_READ);
    144      0  stevel 
    145      0  stevel 		/* Get the token mech type */
    146      0  stevel 		status = __gss_get_mech_type(token_mech_type,
    147      0  stevel 					input_token_buffer);
    148      0  stevel 
    149      0  stevel 		if (status)
    150      0  stevel 			return (status);
    151      0  stevel 
    152      0  stevel 		status = GSS_S_FAILURE;
    153      0  stevel 		union_ctx_id = (gss_union_ctx_id_t)
    154      0  stevel 			malloc(sizeof (gss_union_ctx_id_desc));
    155      0  stevel 		if (!union_ctx_id)
    156      0  stevel 			return (GSS_S_FAILURE);
    157      0  stevel 
    158      0  stevel 		union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT;
    159    160  wyllys 		status = generic_gss_copy_oid(&t_minstat,
    160      0  stevel 					token_mech_type,
    161      0  stevel 					&union_ctx_id->mech_type);
    162      0  stevel 		if (status != GSS_S_COMPLETE) {
    163      0  stevel 			free(union_ctx_id);
    164      0  stevel 			return (status);
    165      0  stevel 		}
    166      0  stevel 
    167      0  stevel 		/* set the new context handle to caller's data */
    168      0  stevel 		*context_handle = (gss_ctx_id_t)union_ctx_id;
    169      0  stevel 	} else {
    170      0  stevel 		union_ctx_id = (gss_union_ctx_id_t)*context_handle;
    171      0  stevel 		token_mech_type = union_ctx_id->mech_type;
    172      0  stevel 	}
    173      0  stevel 
    174      0  stevel 	/*
    175      0  stevel 	 * get the appropriate cred handle from the union cred struct.
    176      0  stevel 	 * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
    177      0  stevel 	 * use the default credential.
    178      0  stevel 	 */
    179      0  stevel 	union_cred = (gss_union_cred_t)verifier_cred_handle;
    180      0  stevel 	input_cred_handle = __gss_get_mechanism_cred(union_cred,
    181      0  stevel 						token_mech_type);
    182      0  stevel 
    183      0  stevel 	/*
    184      0  stevel 	 * now select the approprate underlying mechanism routine and
    185      0  stevel 	 * call it.
    186      0  stevel 	 */
    187      0  stevel 
    188      0  stevel 	mech = __gss_get_mechanism(token_mech_type);
    189      0  stevel 	if (mech && mech->gss_accept_sec_context) {
    190      0  stevel 		status = mech->gss_accept_sec_context(
    191      0  stevel 					mech->context,
    192      0  stevel 					minor_status,
    193      0  stevel 					&union_ctx_id->internal_ctx_id,
    194      0  stevel 					input_cred_handle,
    195      0  stevel 					input_token_buffer,
    196      0  stevel 					input_chan_bindings,
    197      0  stevel 					&internal_name,
    198    160  wyllys 					&actual_mech,
    199      0  stevel 					output_token,
    200    160  wyllys 					&flags,
    201      0  stevel 					time_rec,
    202      0  stevel 					d_cred ? &tmp_d_cred : NULL);
    203      0  stevel 
    204      0  stevel 		/* If there's more work to do, keep going... */
    205      0  stevel 		if (status == GSS_S_CONTINUE_NEEDED)
    206      0  stevel 			return (GSS_S_CONTINUE_NEEDED);
    207      0  stevel 
    208      0  stevel 		/* if the call failed, return with failure */
    209      0  stevel 		if (status != GSS_S_COMPLETE)
    210      0  stevel 			goto error_out;
    211      0  stevel 
    212    160  wyllys 		if (mech_type != NULL)
    213    160  wyllys 			*mech_type = actual_mech;
    214    160  wyllys 
    215      0  stevel 		/*
    216      0  stevel 		 * if src_name is non-NULL,
    217      0  stevel 		 * convert internal_name into a union name equivalent
    218      0  stevel 		 * First call the mechanism specific display_name()
    219      0  stevel 		 * then call gss_import_name() to create
    220      0  stevel 		 * the union name struct cast to src_name
    221      0  stevel 		 */
    222      0  stevel 		if (internal_name != NULL) {
    223      0  stevel 			temp_status = __gss_convert_name_to_union_name(
    224    160  wyllys 				&t_minstat, mech,
    225      0  stevel 				internal_name, &tmp_src_name);
    226      0  stevel 			if (temp_status != GSS_S_COMPLETE) {
    227    160  wyllys 				*minor_status = t_minstat;
    228      0  stevel 				if (output_token->length)
    229      0  stevel 					(void) gss_release_buffer(
    230    160  wyllys 						&t_minstat,
    231      0  stevel 						output_token);
    232      0  stevel 				if (internal_name != GSS_C_NO_NAME)
    233      0  stevel 					mech->gss_release_name(
    234      0  stevel 						mech->context,
    235    160  wyllys 						&t_minstat,
    236      0  stevel 						&internal_name);
    237      0  stevel 				return (temp_status);
    238      0  stevel 			}
    239      0  stevel 			if (src_name != NULL) {
    240      0  stevel 				*src_name = tmp_src_name;
    241      0  stevel 			}
    242      0  stevel 		} else if (src_name != NULL) {
    243      0  stevel 			*src_name = GSS_C_NO_NAME;
    244      0  stevel 		}
    245      0  stevel 
    246      0  stevel 		/* Ensure we're returning correct creds format */
    247    160  wyllys 		if ((flags & GSS_C_DELEG_FLAG) &&
    248    160  wyllys 		    tmp_d_cred != GSS_C_NO_CREDENTIAL) {
    249    160  wyllys 			/*
    250    160  wyllys 			 * If we got back an OID different from the original
    251    160  wyllys 			 * token OID, assume the delegated_cred is already
    252    160  wyllys 			 * a proper union_cred and just return it.  Don't
    253    160  wyllys 			 * try to re-wrap it.  This is for SPNEGO or other
    254    160  wyllys 			 * pseudo-mechanisms.
    255    160  wyllys 			 */
    256    160  wyllys 			if (actual_mech != GSS_C_NO_OID &&
    257    160  wyllys 			    token_mech_type != GSS_C_NO_OID &&
    258    160  wyllys 			    !g_OID_equal(actual_mech, token_mech_type)) {
    259    160  wyllys 				*d_cred = tmp_d_cred;
    260    160  wyllys 			} else {
    261    160  wyllys 				gss_union_cred_t d_u_cred = NULL;
    262      0  stevel 
    263    160  wyllys 				d_u_cred = malloc(sizeof (gss_union_cred_desc));
    264    160  wyllys 				if (d_u_cred == NULL) {
    265    160  wyllys 					status = GSS_S_FAILURE;
    266    160  wyllys 					goto error_out;
    267    160  wyllys 				}
    268    160  wyllys 				(void) memset(d_u_cred, 0,
    269    160  wyllys 					    sizeof (gss_union_cred_desc));
    270      0  stevel 
    271    160  wyllys 				d_u_cred->count = 1;
    272      0  stevel 
    273    160  wyllys 				status = generic_gss_copy_oid(
    274    160  wyllys 					&t_minstat,
    275    160  wyllys 					actual_mech,
    276    160  wyllys 					&d_u_cred->mechs_array);
    277      0  stevel 
    278    160  wyllys 				if (status != GSS_S_COMPLETE) {
    279    160  wyllys 					free(d_u_cred);
    280    160  wyllys 					goto error_out;
    281    160  wyllys 				}
    282      0  stevel 
    283    160  wyllys 				d_u_cred->cred_array = malloc(
    284    160  wyllys 						sizeof (gss_cred_id_t));
    285    160  wyllys 				if (d_u_cred->cred_array != NULL) {
    286    160  wyllys 					d_u_cred->cred_array[0] = tmp_d_cred;
    287    160  wyllys 				} else {
    288    160  wyllys 					free(d_u_cred);
    289    160  wyllys 					status = GSS_S_FAILURE;
    290    160  wyllys 					goto error_out;
    291    160  wyllys 				}
    292      0  stevel 
    293    160  wyllys 				if (status != GSS_S_COMPLETE) {
    294      0  stevel 					free(d_u_cred->cred_array);
    295      0  stevel 					free(d_u_cred);
    296    160  wyllys 					goto error_out;
    297      0  stevel 				}
    298    160  wyllys 
    299    160  wyllys 				internal_name = GSS_C_NO_NAME;
    300    160  wyllys 
    301    160  wyllys 				d_u_cred->auxinfo.creation_time = time(0);
    302    160  wyllys 				d_u_cred->auxinfo.time_rec = 0;
    303    160  wyllys 
    304    160  wyllys 				if (mech->gss_inquire_cred) {
    305    160  wyllys 					status = mech->gss_inquire_cred(
    306    160  wyllys 						mech->context,
    307    160  wyllys 						minor_status,
    308    160  wyllys 						tmp_d_cred,
    309    160  wyllys 						&internal_name,
    310    160  wyllys 						&d_u_cred->auxinfo.time_rec,
    311    160  wyllys 						&d_u_cred->auxinfo.cred_usage,
    312    160  wyllys 						NULL);
    313    160  wyllys 				}
    314    160  wyllys 
    315    160  wyllys 				if (internal_name != NULL) {
    316    160  wyllys 					temp_status =
    317    160  wyllys 					    __gss_convert_name_to_union_name(
    318    160  wyllys 						&t_minstat, mech,
    319    160  wyllys 						internal_name, &tmp_src_name);
    320    160  wyllys 					if (temp_status != GSS_S_COMPLETE) {
    321    160  wyllys 						*minor_status = t_minstat;
    322    160  wyllys 						if (output_token->length)
    323    160  wyllys 						    (void) gss_release_buffer(
    324    160  wyllys 								&t_minstat,
    325    160  wyllys 								output_token);
    326    160  wyllys 						free(d_u_cred->cred_array);
    327    160  wyllys 						free(d_u_cred);
    328    160  wyllys 						return (temp_status);
    329    160  wyllys 					}
    330    160  wyllys 				}
    331    160  wyllys 
    332    160  wyllys 				if (tmp_src_name != NULL) {
    333    160  wyllys 					status = gss_display_name(
    334    160  wyllys 						&t_minstat,
    335    160  wyllys 						tmp_src_name,
    336    160  wyllys 						&d_u_cred->auxinfo.name,
    337    160  wyllys 						&d_u_cred->auxinfo.name_type);
    338    160  wyllys 				}
    339    160  wyllys 
    340    160  wyllys 				*d_cred = (gss_cred_id_t)d_u_cred;
    341      0  stevel 			}
    342    690  wyllys 		}
    343    690  wyllys 		if (ret_flags != NULL) {
    344    690  wyllys 			*ret_flags = flags;
    345      0  stevel 		}
    346      0  stevel 
    347      0  stevel 		if (src_name == NULL && tmp_src_name != NULL)
    348    160  wyllys 			(void) gss_release_name(&t_minstat,
    349      0  stevel 					&tmp_src_name);
    350      0  stevel 		return	(status);
    351      0  stevel 	} else {
    352      0  stevel 
    353      0  stevel 		status = GSS_S_BAD_MECH;
    354      0  stevel 	}
    355      0  stevel 
    356      0  stevel error_out:
    357      0  stevel 	if (union_ctx_id) {
    358      0  stevel 		if (union_ctx_id->mech_type) {
    359      0  stevel 			if (union_ctx_id->mech_type->elements)
    360      0  stevel 				free(union_ctx_id->mech_type->elements);
    361      0  stevel 			free(union_ctx_id->mech_type);
    362      0  stevel 		}
    363      0  stevel 		free(union_ctx_id);
    364      0  stevel 		*context_handle = GSS_C_NO_CONTEXT;
    365      0  stevel 	}
    366      0  stevel 
    367  10598   Glenn #if 0
    368  10598   Glenn 	/*
    369  10598   Glenn 	 * Solaris Kerberos
    370  10598   Glenn 	 * Don't release, it causes a problem with error token.
    371  10598   Glenn 	 */
    372      0  stevel 	if (output_token->length)
    373    160  wyllys 		(void) gss_release_buffer(&t_minstat, output_token);
    374  10598   Glenn #endif
    375      0  stevel 
    376      0  stevel 	if (src_name)
    377      0  stevel 		*src_name = GSS_C_NO_NAME;
    378      0  stevel 
    379      0  stevel 	if (tmp_src_name != GSS_C_NO_NAME)
    380    160  wyllys 		(void) gss_release_buffer(&t_minstat,
    381      0  stevel 			(gss_buffer_t)tmp_src_name);
    382      0  stevel 
    383      0  stevel 	return (status);
    384      0  stevel }
    385