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 2005 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_inquire_cred
     31  */
     32 
     33 #include <mechglueP.h>
     34 #include <stdio.h>
     35 #include <stdlib.h>
     36 #include <string.h>
     37 #include <time.h>
     38 
     39 OM_uint32
     40 gss_inquire_cred(minor_status,
     41 			cred_handle,
     42 			name,
     43 			lifetime,
     44 			cred_usage,
     45 			mechanisms)
     46 
     47 OM_uint32 *minor_status;
     48 const gss_cred_id_t		cred_handle;
     49 gss_name_t *name;
     50 OM_uint32 *lifetime;
     51 int *cred_usage;
     52 gss_OID_set *mechanisms;
     53 
     54 {
     55 	OM_uint32		status, elapsed_time, temp_minor_status;
     56 	gss_union_cred_t	union_cred;
     57 	gss_mechanism		mech;
     58 	gss_name_t		internal_name;
     59 	int			i;
     60 
     61 	/* check parms and set to defaults */
     62 	if (minor_status == NULL)
     63 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     64 	*minor_status = 0;
     65 
     66 	if (name)
     67 		*name = NULL;
     68 
     69 	if (mechanisms)
     70 		*mechanisms = NULL;
     71 
     72 	if (cred_handle == GSS_C_NO_CREDENTIAL) {
     73 	/*
     74 	 * No credential was supplied. This means we can't get a mechanism
     75 	 * pointer to call the mechanism specific gss_inquire_cred.
     76 	 * So, call get_mechanism with an arguement of GSS_C_NULL_OID.
     77 	 * get_mechanism will return the first mechanism in the mech
     78 	 * array, which becomes the default mechanism.
     79 	 */
     80 
     81 		if ((mech = __gss_get_mechanism(GSS_C_NULL_OID)) == NULL)
     82 			return (GSS_S_DEFECTIVE_CREDENTIAL);
     83 
     84 		if (!mech->gss_inquire_cred)
     85 			return (GSS_S_UNAVAILABLE);
     86 
     87 		status = mech->gss_inquire_cred(mech->context, minor_status,
     88 						GSS_C_NO_CREDENTIAL,
     89 						name ? &internal_name : NULL,
     90 						lifetime, cred_usage,
     91 						mechanisms);
     92 
     93 		if (status != GSS_S_COMPLETE)
     94 			return (status);
     95 
     96 		if (name) {
     97 		/*
     98 		 * Convert internal_name into a union_name equivalent.
     99 		 */
    100 			status = __gss_convert_name_to_union_name(
    101 						&temp_minor_status, mech,
    102 						internal_name, name);
    103 			if (status != GSS_S_COMPLETE) {
    104 				*minor_status = temp_minor_status;
    105 				if (mechanisms && *mechanisms) {
    106 					(void) gss_release_oid_set(
    107 						&temp_minor_status,
    108 							mechanisms);
    109 				}
    110 				return (status);
    111 			}
    112 		}
    113 		return (GSS_S_COMPLETE);
    114 	}
    115 
    116 	/* get the cred_handle cast as a union_credentials structure */
    117 
    118 	union_cred = (gss_union_cred_t)cred_handle;
    119 
    120 	/*
    121 	 * get the information out of the union_cred structure that was
    122 	 * placed there during gss_acquire_cred.
    123 	 */
    124 
    125 	if (cred_usage != NULL)
    126 		*cred_usage = union_cred->auxinfo.cred_usage;
    127 
    128 	if (lifetime != NULL) {
    129 		elapsed_time = time(0) - union_cred->auxinfo.creation_time;
    130 		*lifetime = union_cred->auxinfo.time_rec < elapsed_time ? 0 :
    131 		union_cred->auxinfo.time_rec - elapsed_time;
    132 	}
    133 
    134 	/*
    135 	 * if name is non_null,
    136 	 * call gss_import_name() followed by gss_canonicalize_name()
    137 	 * to get a mechanism specific name passed back to the caller.
    138 	 * If this call fails, return failure to our caller.
    139 	 * XXX The cred_handle may contain an array of mechanism OID's
    140 	 * but we only return the MN for the first mechanism to the caller.
    141 	 * In theory, we should modify this to provide an array of MN's
    142 	 * one per mechanism back to the caller.
    143 	 */
    144 
    145 	if (name != NULL) {
    146 		if ((gss_import_name(minor_status,
    147 					&union_cred->auxinfo.name,
    148 					union_cred->auxinfo.name_type,
    149 					name) != GSS_S_COMPLETE) ||
    150 			(gss_canonicalize_name(minor_status, *name,
    151 					&union_cred->mechs_array[0],
    152 					NULL) != GSS_S_COMPLETE)) {
    153 			status = GSS_S_DEFECTIVE_CREDENTIAL;
    154 			goto error;
    155 		}
    156 	}
    157 
    158 	/*
    159 	 * copy the mechanism set in union_cred into an OID set and return in
    160 	 * the mechanisms parameter.
    161 	 */
    162 	if (mechanisms != NULL) {
    163 		status = GSS_S_FAILURE;
    164 		*mechanisms = (gss_OID_set) malloc(sizeof (gss_OID_set_desc));
    165 		if (*mechanisms == NULL)
    166 			goto error;
    167 
    168 		(*mechanisms)->count = 0;
    169 		(*mechanisms)->elements =
    170 			(gss_OID) malloc(sizeof (gss_OID_desc) *
    171 						union_cred->count);
    172 
    173 		if ((*mechanisms)->elements == NULL) {
    174 			free(*mechanisms);
    175 			*mechanisms = NULL;
    176 			goto error;
    177 		}
    178 
    179 		for (i = 0; i < union_cred->count; i++) {
    180 			(*mechanisms)->elements[i].elements = (void *)
    181 				malloc(union_cred->mechs_array[i].length);
    182 			if ((*mechanisms)->elements[i].elements == NULL)
    183 				goto error;
    184 			g_OID_copy(&(*mechanisms)->elements[i],
    185 					&union_cred->mechs_array[i]);
    186 			(*mechanisms)->count++;
    187 		}
    188 	}
    189 
    190 	return (GSS_S_COMPLETE);
    191 
    192 error:
    193 	/*
    194 	 * cleanup any allocated memory - we can just call
    195 	 * gss_release_oid_set, because the set is constructed so that
    196 	 * count always references the currently copied number of
    197 	 * elements.
    198 	 */
    199 	if (mechanisms && *mechanisms != NULL)
    200 		(void) gss_release_oid_set(&temp_minor_status, mechanisms);
    201 
    202 	if (name && *name != NULL)
    203 		(void) gss_release_name(&temp_minor_status, name);
    204 
    205 	return (status);
    206 }
    207 
    208 OM_uint32
    209 gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
    210 			initiator_lifetime, acceptor_lifetime, cred_usage)
    211 	OM_uint32		*minor_status;
    212 	const gss_cred_id_t	cred_handle;
    213 	const gss_OID		mech_type;
    214 	gss_name_t		*name;
    215 	OM_uint32		*initiator_lifetime;
    216 	OM_uint32		*acceptor_lifetime;
    217 	gss_cred_usage_t	*cred_usage;
    218 {
    219 	gss_union_cred_t	union_cred;
    220 	gss_cred_id_t		mech_cred;
    221 	gss_mechanism		mech;
    222 	OM_uint32		status, temp_minor_status;
    223 	gss_name_t		internal_name;
    224 
    225 
    226 	mech = __gss_get_mechanism(mech_type);
    227 	if (!mech)
    228 		return (GSS_S_BAD_MECH);
    229 	if (!mech->gss_inquire_cred_by_mech)
    230 		return (GSS_S_UNAVAILABLE);
    231 
    232 	union_cred = (gss_union_cred_t)cred_handle;
    233 	mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
    234 	if (mech_cred == NULL)
    235 		return (GSS_S_DEFECTIVE_CREDENTIAL);
    236 
    237 	if (mech->gss_inquire_cred_by_mech != NULL) {
    238 		status = mech->gss_inquire_cred_by_mech(mech->context,
    239 					minor_status,
    240 					mech_cred, mech_type,
    241 					name ? &internal_name : NULL,
    242 					initiator_lifetime,
    243 					acceptor_lifetime, cred_usage);
    244 
    245 		if (status != GSS_S_COMPLETE)
    246 			return (status);
    247 
    248 		if (name) {
    249 			/*
    250 			 * Convert internal_name into a union_name equivalent.
    251 			 */
    252 			status = __gss_convert_name_to_union_name(
    253 					&temp_minor_status, mech,
    254 					internal_name, name);
    255 			if (status != GSS_S_COMPLETE) {
    256 				*minor_status = temp_minor_status;
    257 				return (status);
    258 			}
    259 		}
    260 	} else {
    261 		return (GSS_S_UNAVAILABLE);
    262 	}
    263 
    264 	return (GSS_S_COMPLETE);
    265 }
    266