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 2004 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 	status = mech->gss_inquire_cred_by_mech(mech->context, minor_status,
238 						mech_cred, mech_type,
239 						name ? &internal_name : NULL,
240 						initiator_lifetime,
241 						acceptor_lifetime, cred_usage);
242 
243 	if (status != GSS_S_COMPLETE)
244 		return (status);
245 
246 	if (name) {
247 		/*
248 		 * Convert internal_name into a union_name equivalent.
249 		 */
250 		status = __gss_convert_name_to_union_name(
251 						&temp_minor_status, mech,
252 						internal_name, name);
253 		if (status != GSS_S_COMPLETE) {
254 			*minor_status = temp_minor_status;
255 			return (status);
256 		}
257 	}
258 
259 	return (GSS_S_COMPLETE);
260 }
261