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 (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  *  glue routine for gss_inquire_cred
     28  */
     29 
     30 #include <mechglueP.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include <time.h>
     35 
     36 OM_uint32
     37 gss_inquire_cred(minor_status,
     38 			cred_handle,
     39 			name,
     40 			lifetime,
     41 			cred_usage,
     42 			mechanisms)
     43 
     44 OM_uint32 *minor_status;
     45 const gss_cred_id_t		cred_handle;
     46 gss_name_t *name;
     47 OM_uint32 *lifetime;
     48 int *cred_usage;
     49 gss_OID_set *mechanisms;
     50 
     51 {
     52 	OM_uint32		status, elapsed_time, temp_minor_status;
     53 	gss_union_cred_t	union_cred;
     54 	gss_mechanism		mech;
     55 	gss_name_t		internal_name;
     56 	int			i;
     57 
     58 	/* Initialize outputs. */
     59 
     60 	if (minor_status != NULL)
     61 		*minor_status = 0;
     62 
     63 	if (name != NULL)
     64 		*name = GSS_C_NO_NAME;
     65 
     66 	if (mechanisms != NULL)
     67 		*mechanisms = GSS_C_NO_OID_SET;
     68 
     69 	/* Validate arguments. */
     70 	if (minor_status == NULL)
     71 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     72 
     73 	if (cred_handle == GSS_C_NO_CREDENTIAL) {
     74 	/*
     75 	 * No credential was supplied. This means we can't get a mechanism
     76 	 * pointer to call the mechanism specific gss_inquire_cred.
     77 	 * So, call get_mechanism with an arguement of GSS_C_NULL_OID.
     78 	 * get_mechanism will return the first mechanism in the mech
     79 	 * array, which becomes the default mechanism.
     80 	 */
     81 
     82 		if ((mech = __gss_get_mechanism(GSS_C_NULL_OID)) == NULL)
     83 			return (GSS_S_DEFECTIVE_CREDENTIAL);
     84 
     85 		if (!mech->gss_inquire_cred)
     86 			return (GSS_S_UNAVAILABLE);
     87 
     88 		status = mech->gss_inquire_cred(mech->context, minor_status,
     89 						GSS_C_NO_CREDENTIAL,
     90 						name ? &internal_name : NULL,
     91 						lifetime, cred_usage,
     92 						mechanisms);
     93 
     94 		if (status != GSS_S_COMPLETE)
     95 			return (status);
     96 
     97 		if (name) {
     98 		/*
     99 		 * Convert internal_name into a union_name equivalent.
    100 		 */
    101 			status = __gss_convert_name_to_union_name(
    102 						&temp_minor_status, mech,
    103 						internal_name, name);
    104 			if (status != GSS_S_COMPLETE) {
    105 				*minor_status = temp_minor_status;
    106 				if (mechanisms && *mechanisms) {
    107 					(void) gss_release_oid_set(
    108 						&temp_minor_status,
    109 							mechanisms);
    110 				}
    111 				return (status);
    112 			}
    113 		}
    114 		return (GSS_S_COMPLETE);
    115 	}
    116 
    117 	/* get the cred_handle cast as a union_credentials structure */
    118 
    119 	union_cred = (gss_union_cred_t)cred_handle;
    120 
    121 	/*
    122 	 * get the information out of the union_cred structure that was
    123 	 * placed there during gss_acquire_cred.
    124 	 */
    125 
    126 	if (cred_usage != NULL)
    127 		*cred_usage = union_cred->auxinfo.cred_usage;
    128 
    129 	if (lifetime != NULL) {
    130 		elapsed_time = time(0) - union_cred->auxinfo.creation_time;
    131 		*lifetime = union_cred->auxinfo.time_rec < elapsed_time ? 0 :
    132 		union_cred->auxinfo.time_rec - elapsed_time;
    133 	}
    134 
    135 	/*
    136 	 * if name is non_null,
    137 	 * call gss_import_name() followed by gss_canonicalize_name()
    138 	 * to get a mechanism specific name passed back to the caller.
    139 	 * If this call fails, return failure to our caller.
    140 	 * XXX The cred_handle may contain an array of mechanism OID's
    141 	 * but we only return the MN for the first mechanism to the caller.
    142 	 * In theory, we should modify this to provide an array of MN's
    143 	 * one per mechanism back to the caller.
    144 	 */
    145 
    146 	if (name != NULL) {
    147 		if ((gss_import_name(minor_status,
    148 					&union_cred->auxinfo.name,
    149 					union_cred->auxinfo.name_type,
    150 					name) != GSS_S_COMPLETE) ||
    151 			(gss_canonicalize_name(minor_status, *name,
    152 					&union_cred->mechs_array[0],
    153 					NULL) != GSS_S_COMPLETE)) {
    154 			status = GSS_S_DEFECTIVE_CREDENTIAL;
    155 			goto error;
    156 		}
    157 	}
    158 
    159 	/*
    160 	 * copy the mechanism set in union_cred into an OID set and return in
    161 	 * the mechanisms parameter.
    162 	 */
    163 	if (mechanisms != NULL) {
    164 		status = GSS_S_FAILURE;
    165 		*mechanisms = (gss_OID_set) malloc(sizeof (gss_OID_set_desc));
    166 		if (*mechanisms == NULL)
    167 			goto error;
    168 
    169 		(*mechanisms)->count = 0;
    170 		(*mechanisms)->elements =
    171 			(gss_OID) malloc(sizeof (gss_OID_desc) *
    172 						union_cred->count);
    173 
    174 		if ((*mechanisms)->elements == NULL) {
    175 			free(*mechanisms);
    176 			*mechanisms = NULL;
    177 			goto error;
    178 		}
    179 
    180 		for (i = 0; i < union_cred->count; i++) {
    181 			(*mechanisms)->elements[i].elements = (void *)
    182 				malloc(union_cred->mechs_array[i].length);
    183 			if ((*mechanisms)->elements[i].elements == NULL)
    184 				goto error;
    185 			g_OID_copy(&(*mechanisms)->elements[i],
    186 					&union_cred->mechs_array[i]);
    187 			(*mechanisms)->count++;
    188 		}
    189 	}
    190 
    191 	return (GSS_S_COMPLETE);
    192 
    193 error:
    194 	/*
    195 	 * cleanup any allocated memory - we can just call
    196 	 * gss_release_oid_set, because the set is constructed so that
    197 	 * count always references the currently copied number of
    198 	 * elements.
    199 	 */
    200 	if (mechanisms && *mechanisms != NULL)
    201 		(void) gss_release_oid_set(&temp_minor_status, mechanisms);
    202 
    203 	if (name && *name != NULL)
    204 		(void) gss_release_name(&temp_minor_status, name);
    205 
    206 	return (status);
    207 }
    208 
    209 OM_uint32
    210 gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
    211 			initiator_lifetime, acceptor_lifetime, cred_usage)
    212 	OM_uint32		*minor_status;
    213 	const gss_cred_id_t	cred_handle;
    214 	const gss_OID		mech_type;
    215 	gss_name_t		*name;
    216 	OM_uint32		*initiator_lifetime;
    217 	OM_uint32		*acceptor_lifetime;
    218 	gss_cred_usage_t	*cred_usage;
    219 {
    220 	gss_union_cred_t	union_cred;
    221 	gss_cred_id_t		mech_cred;
    222 	gss_mechanism		mech;
    223 	OM_uint32		status, temp_minor_status;
    224 	gss_name_t		internal_name;
    225 
    226 	if (minor_status != NULL)
    227 		*minor_status = 0;
    228 
    229 	if (name != NULL)
    230 		*name = GSS_C_NO_NAME;
    231 
    232 	if (minor_status == NULL)
    233 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
    234 
    235 	mech = __gss_get_mechanism(mech_type);
    236 	if (!mech)
    237 		return (GSS_S_BAD_MECH);
    238 	if (!mech->gss_inquire_cred_by_mech)
    239 		return (GSS_S_UNAVAILABLE);
    240 
    241 	union_cred = (gss_union_cred_t)cred_handle;
    242 	mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
    243 	if (mech_cred == NULL)
    244 		return (GSS_S_DEFECTIVE_CREDENTIAL);
    245 
    246 	if (mech->gss_inquire_cred_by_mech != NULL) {
    247 		status = mech->gss_inquire_cred_by_mech(mech->context,
    248 					minor_status,
    249 					mech_cred, mech_type,
    250 					name ? &internal_name : NULL,
    251 					initiator_lifetime,
    252 					acceptor_lifetime, cred_usage);
    253 
    254 		if (status != GSS_S_COMPLETE)
    255 			return (status);
    256 
    257 		if (name) {
    258 			/*
    259 			 * Convert internal_name into a union_name equivalent.
    260 			 */
    261 			status = __gss_convert_name_to_union_name(
    262 					&temp_minor_status, mech,
    263 					internal_name, name);
    264 			if (status != GSS_S_COMPLETE) {
    265 				*minor_status = temp_minor_status;
    266 				return (status);
    267 			}
    268 		}
    269 	} else {
    270 		return (GSS_S_UNAVAILABLE);
    271 	}
    272 
    273 	return (GSS_S_COMPLETE);
    274 }
    275