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 (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * glue routine for gss_inquire_cred
27 */
28
29 #include <mechglueP.h>
30 #include "gssapiP_generic.h"
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35
36 OM_uint32
gss_inquire_cred(minor_status,cred_handle,name,lifetime,cred_usage,mechanisms)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 map_error(minor_status, mech);
96 return (status);
97 }
98
99 if (name) {
100 /*
101 * Convert internal_name into a union_name equivalent.
102 */
103 status = __gss_convert_name_to_union_name(
104 &temp_minor_status, mech,
105 internal_name, name);
106 if (status != GSS_S_COMPLETE) {
107 *minor_status = temp_minor_status;
108 map_error(minor_status, mech);
109 if (mechanisms && *mechanisms) {
110 (void) gss_release_oid_set(
111 &temp_minor_status,
112 mechanisms);
113 }
114 return (status);
115 }
116 }
117 return (GSS_S_COMPLETE);
118 }
119
120 /* get the cred_handle cast as a union_credentials structure */
121
122 union_cred = (gss_union_cred_t)cred_handle;
123
124 /*
125 * get the information out of the union_cred structure that was
126 * placed there during gss_acquire_cred.
127 */
128
129 if (cred_usage != NULL)
130 *cred_usage = union_cred->auxinfo.cred_usage;
131
132 if (lifetime != NULL) {
133 elapsed_time = time(0) - union_cred->auxinfo.creation_time;
134 *lifetime = union_cred->auxinfo.time_rec < elapsed_time ? 0 :
135 union_cred->auxinfo.time_rec - elapsed_time;
136 }
137
138 /*
139 * if name is non_null,
140 * call gss_import_name() followed by gss_canonicalize_name()
141 * to get a mechanism specific name passed back to the caller.
142 * If this call fails, return failure to our caller.
143 * XXX The cred_handle may contain an array of mechanism OID's
144 * but we only return the MN for the first mechanism to the caller.
145 * In theory, we should modify this to provide an array of MN's
146 * one per mechanism back to the caller.
147 */
148
149 if (name != NULL) {
150 if (union_cred->auxinfo.name.length == 0) {
151 *name = GSS_C_NO_NAME;
152 } else if ((gss_import_name(minor_status,
153 &union_cred->auxinfo.name,
154 union_cred->auxinfo.name_type,
155 name) != GSS_S_COMPLETE) ||
156 (gss_canonicalize_name(minor_status, *name,
157 &union_cred->mechs_array[0],
158 NULL) != GSS_S_COMPLETE)) {
159 status = GSS_S_DEFECTIVE_CREDENTIAL;
160 goto error;
161 }
162 }
163
164 /*
165 * copy the mechanism set in union_cred into an OID set and return in
166 * the mechanisms parameter.
167 */
168 if (mechanisms != NULL) {
169 status = GSS_S_FAILURE;
170 *mechanisms = (gss_OID_set) malloc(sizeof (gss_OID_set_desc));
171 if (*mechanisms == NULL)
172 goto error;
173
174 (*mechanisms)->count = 0;
175 (*mechanisms)->elements =
176 (gss_OID) malloc(sizeof (gss_OID_desc) *
177 union_cred->count);
178
179 if ((*mechanisms)->elements == NULL) {
180 free(*mechanisms);
181 *mechanisms = NULL;
182 goto error;
183 }
184
185 for (i = 0; i < union_cred->count; i++) {
186 (*mechanisms)->elements[i].elements = (void *)
187 malloc(union_cred->mechs_array[i].length);
188 if ((*mechanisms)->elements[i].elements == NULL)
189 goto error;
190 g_OID_copy(&(*mechanisms)->elements[i],
191 &union_cred->mechs_array[i]);
192 (*mechanisms)->count++;
193 }
194 }
195
196 return (GSS_S_COMPLETE);
197
198 error:
199 /*
200 * cleanup any allocated memory - we can just call
201 * gss_release_oid_set, because the set is constructed so that
202 * count always references the currently copied number of
203 * elements.
204 */
205 if (mechanisms && *mechanisms != NULL)
206 (void) gss_release_oid_set(&temp_minor_status, mechanisms);
207
208 if (name && *name != NULL)
209 (void) gss_release_name(&temp_minor_status, name);
210
211 return (status);
212 }
213
214 OM_uint32
gss_inquire_cred_by_mech(minor_status,cred_handle,mech_type,name,initiator_lifetime,acceptor_lifetime,cred_usage)215 gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
216 initiator_lifetime, acceptor_lifetime, cred_usage)
217 OM_uint32 *minor_status;
218 const gss_cred_id_t cred_handle;
219 const gss_OID mech_type;
220 gss_name_t *name;
221 OM_uint32 *initiator_lifetime;
222 OM_uint32 *acceptor_lifetime;
223 gss_cred_usage_t *cred_usage;
224 {
225 gss_union_cred_t union_cred;
226 gss_cred_id_t mech_cred;
227 gss_mechanism mech;
228 OM_uint32 status, temp_minor_status;
229 gss_name_t internal_name;
230
231 if (minor_status != NULL)
232 *minor_status = 0;
233
234 if (name != NULL)
235 *name = GSS_C_NO_NAME;
236
237 if (minor_status == NULL)
238 return (GSS_S_CALL_INACCESSIBLE_WRITE);
239
240 mech = __gss_get_mechanism(mech_type);
241 if (!mech)
242 return (GSS_S_BAD_MECH);
243 if (!mech->gss_inquire_cred_by_mech)
244 return (GSS_S_UNAVAILABLE);
245
246 union_cred = (gss_union_cred_t)cred_handle;
247 mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
248 if (mech_cred == NULL)
249 return (GSS_S_DEFECTIVE_CREDENTIAL);
250
251 if (mech->gss_inquire_cred_by_mech != NULL) {
252 status = mech->gss_inquire_cred_by_mech(mech->context,
253 minor_status,
254 mech_cred, mech_type,
255 name ? &internal_name : NULL,
256 initiator_lifetime,
257 acceptor_lifetime, cred_usage);
258
259 if (status != GSS_S_COMPLETE) {
260 map_error(minor_status, mech);
261 return (status);
262 }
263
264 if (name) {
265 /*
266 * Convert internal_name into a union_name equivalent.
267 */
268 status = __gss_convert_name_to_union_name(
269 &temp_minor_status, mech,
270 internal_name, name);
271 if (status != GSS_S_COMPLETE) {
272 *minor_status = temp_minor_status;
273 map_error(minor_status, mech);
274 return (status);
275 }
276 }
277 } else {
278 return (GSS_S_UNAVAILABLE);
279 }
280
281 return (GSS_S_COMPLETE);
282 }
283