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 * cred.c
24 *
25 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 *
28 */
29
30 #include <unistd.h>
31 #include <sys/note.h>
32 #include "dh_gssapi.h"
33
34 /*
35 * This module supports the GSS credential family of routines for
36 * Diffie-Hellman mechanism.
37 */
38
39 /*
40 * __dh_gss_acquire_cred: Get the credential associated with principal
41 * with the requested expire time and usage. Return the credential with
42 * the optional set of supported mechs and actual time left on the credential.
43 *
44 * Note in Diffie-Hellman the supplied principal name must be that of
45 * the caller. There is no way to delegate credentials.
46 *
47 * Libgss alwas sets desired_mechs to GSS_C_NO_OID_SET and set the return
48 * set of mechs to NULL.
49 */
50
51 OM_uint32
__dh_gss_acquire_cred(void * ctx,OM_uint32 * minor,gss_name_t principal,OM_uint32 expire_req,gss_OID_set desired_mechs,gss_cred_usage_t usage,gss_cred_id_t * cred,gss_OID_set * mechs,OM_uint32 * expire_rec)52 __dh_gss_acquire_cred(void *ctx, /* Per mechanism context */
53 OM_uint32 *minor, /* Mechanism status */
54 gss_name_t principal, /* Requested principal */
55 OM_uint32 expire_req, /* Requested Expire time */
56 gss_OID_set desired_mechs, /* Set of desired mechs */
57 gss_cred_usage_t usage, /* Usage: init, accept, both */
58 gss_cred_id_t *cred, /* The return credential */
59 gss_OID_set *mechs, /* The return set of mechs */
60 OM_uint32 *expire_rec /* The expire time received*/)
61 {
62 /* Diffie-Hellman mechanism context is ctx */
63 dh_context_t cntx = (dh_context_t)ctx;
64 dh_principal netname;
65 dh_cred_id_t dh_cred;
66
67 /* Need to write to these */
68 if (minor == 0 || cred == 0)
69 return (GSS_S_CALL_INACCESSIBLE_WRITE);
70
71 /* Set sane outputs */
72 *minor = 0;
73 if (mechs)
74 *mechs = GSS_C_NO_OID_SET;
75 if (expire_rec)
76 *expire_rec = 0;
77 *cred = GSS_C_NO_CREDENTIAL;
78
79 /*
80 * If not GSS_C_NO_OID_SET then the set must contain the
81 * Diffie-Hellman mechanism
82 */
83 if (desired_mechs != GSS_C_NO_OID_SET &&
84 !__OID_is_member(desired_mechs, cntx->mech))
85 return (GSS_S_BAD_MECH);
86
87 /* See if the callers secretkey is available */
88 if (!cntx->keyopts->key_secretkey_is_set())
89 return (GSS_S_NO_CRED);
90
91 /* Get the principal name of the caller */
92 if ((netname = cntx->keyopts->get_principal()) == NULL)
93 return (GSS_S_NO_CRED);
94
95 /*
96 * Diffie-Hellman requires the principal to be the principal
97 * of the caller
98 */
99
100 if (principal &&
101 strncmp(netname, (char *)principal, MAXNETNAMELEN) != 0) {
102 Free(netname);
103 return (GSS_S_NO_CRED);
104 }
105
106 /* Allocate the credential */
107 dh_cred = New(dh_cred_id_desc, 1);
108 if (dh_cred == NULL) {
109 Free(netname);
110 *minor = DH_NOMEM_FAILURE;
111 return (GSS_S_FAILURE);
112 }
113
114 /* Set credential state */
115 dh_cred->uid = geteuid();
116 dh_cred->usage = usage;
117 dh_cred->principal = netname;
118 dh_cred->expire = expire_req ? time(0) + expire_req : GSS_C_INDEFINITE;
119
120 /*
121 * If mechs set it to the set that contains the appropriate
122 * Diffie-Hellman mechanism
123 */
124 if (mechs && (*minor = __OID_to_OID_set(mechs, cntx->mech))) {
125 Free(dh_cred);
126 Free(netname);
127 return (GSS_S_FAILURE);
128 }
129
130 /* Register the credential */
131 if ((*minor = __dh_install_cred(dh_cred)) != DH_SUCCESS) {
132 Free(dh_cred);
133 Free(netname);
134 return (GSS_S_FAILURE);
135 }
136
137 if (expire_rec)
138 *expire_rec = expire_req ? expire_req : GSS_C_INDEFINITE;
139
140 /* Return the Diffie-Hellman credential through cred */
141 *cred = (gss_cred_id_t)dh_cred;
142
143 return (GSS_S_COMPLETE);
144 }
145
146
147 /*
148 * __dh_gss_add_cred is currently a no-op. All the work is done at the
149 * libgss layer. That layer will invoke the mechanism specific gss_acquire_cred
150 * routine. This entry point should never be called. The entry point for
151 * this routine is set to NULL in dhmech.c.
152 */
153
154 /*
155 * OM_uint32
156 * __dh_gss_add_cred(void * ctx, OM_uint32 *minor, gss_cred_id_t cred_in,
157 * gss_name_t name, gss_OID mech, gss_cred_usage_t usage,
158 * OM_uint32 init_time_req, OM_uint32 accep_time_req,
159 * gss_cred_id_t *cred_out, gss_OID_set *mechs,
160 * OM_uint32 *init_time_rec, OM_uint32 *accep_time_rec)
161 * {
162 * return (GSS_S_UNAVAILABLE);
163 * }
164 */
165
166 /*
167 * __dh_gss_inquire_cred: Return tracked state of the supplied credential.
168 */
169 OM_uint32
__dh_gss_inquire_cred(void * ctx,OM_uint32 * minor,gss_cred_id_t cred,gss_name_t * name,OM_uint32 * lifetime,gss_cred_usage_t * usage,gss_OID_set * mechs)170 __dh_gss_inquire_cred(void *ctx, /* Per mechanism context */
171 OM_uint32 *minor, /* Mechanism status */
172 gss_cred_id_t cred, /* cred of interest */
173 gss_name_t *name, /* name of principal */
174 OM_uint32 *lifetime, /* return the time remainning */
175 gss_cred_usage_t *usage, /* usage: init, accept, both */
176 gss_OID_set *mechs /* Set containing mech_dh */)
177 {
178 /* cred is a Diffie-Hellman credential */
179 dh_cred_id_t crid = (dh_cred_id_t)cred;
180 /* ctx is a Diffie-Hellman context */
181 dh_context_t cntx = (dh_context_t)ctx;
182 OM_uint32 t = GSS_C_INDEFINITE;
183
184 if (minor == 0)
185 return (GSS_S_CALL_INACCESSIBLE_WRITE);
186 if (cntx == 0)
187 return (GSS_S_CALL_INACCESSIBLE_READ);
188
189 *minor = DH_SUCCESS;
190
191 /* Default case */
192 if (cred == GSS_C_NO_CREDENTIAL) {
193 if (!(*cntx->keyopts->key_secretkey_is_set)())
194 return (GSS_S_NO_CRED);
195 if (name)
196 *name = (gss_name_t)(*cntx->keyopts->get_principal)();
197 if (lifetime)
198 *lifetime = GSS_C_INDEFINITE;
199 if (usage)
200 *usage = GSS_C_BOTH;
201 } else {
202 /* Validate creditial */
203 if ((*minor = __dh_validate_cred(crid)) != DH_SUCCESS)
204 return (GSS_S_DEFECTIVE_CREDENTIAL);
205 if (name)
206 *name = (gss_name_t)strdup(crid->principal);
207 if (lifetime) {
208 if (crid->expire == GSS_C_INDEFINITE)
209 *lifetime = GSS_C_INDEFINITE;
210 else {
211 time_t now = time(0);
212 t = crid->expire > now ? crid->expire-now : 0;
213 *lifetime = t;
214 }
215 }
216 if (usage)
217 *usage = crid->usage;
218 }
219
220 if (name && *name == 0)
221 return (GSS_S_FAILURE);
222
223
224 if (mechs &&
225 (*minor = __OID_to_OID_set(mechs, cntx->mech)) != DH_SUCCESS) {
226 free(name);
227 return (GSS_S_FAILURE);
228 }
229
230 /* Check if the credential is still valid */
231 return (t ? GSS_S_COMPLETE : GSS_S_CREDENTIALS_EXPIRED);
232 }
233
234
235 /*
236 * __dh_gss_inquire_cred_by_mech: Return the information associated with
237 * cred and mech. Since we're a backend, mech must be our mech.
238 *
239 * We verify that passed in mech is correct and use the above routine
240 * to do the work.
241 */
242 OM_uint32
__dh_gss_inquire_cred_by_mech(void * ctx,OM_uint32 * minor,gss_cred_id_t cred,gss_OID mech,gss_name_t * name,OM_uint32 * init_time,OM_uint32 * accept_time,gss_cred_usage_t * usage)243 __dh_gss_inquire_cred_by_mech(void *ctx, /* Per mechananism context */
244 OM_uint32 *minor, /* Mechanism status */
245 gss_cred_id_t cred, /* Cred to iquire about */
246 gss_OID mech, /* Along with the mechanism */
247 gss_name_t *name, /* where to return principal */
248 OM_uint32 *init_time, /* Init time left */
249 OM_uint32 *accept_time, /* Accept time left */
250 gss_cred_usage_t *usage /* cred usage */)
251 {
252 /* ctx is them Diffie-Hellman mechanism context */
253 dh_context_t context = (dh_context_t)ctx;
254 OM_uint32 lifetime;
255 OM_uint32 major;
256 gss_cred_usage_t use;
257
258 /* This should never happen. It would indicate a libgss failure */
259 if (!__OID_equal(mech, context->mech)) {
260 *minor = DH_BAD_CONTEXT;
261 return (GSS_S_FAILURE);
262 }
263
264 /* Fetch cred info */
265 major = __dh_gss_inquire_cred(ctx, minor, cred, name,
266 &lifetime, &use, NULL);
267
268 /* Return option values */
269 if (major == GSS_S_COMPLETE) {
270 /* set init_time if we can */
271 if (init_time)
272 *init_time = (use == GSS_C_BOTH ||
273 use == GSS_C_INITIATE) ? lifetime : 0;
274 /* Ditto for accept time */
275 if (accept_time)
276 *accept_time = (use == GSS_C_BOTH ||
277 use == GSS_C_ACCEPT) ? lifetime : 0;
278 if (usage)
279 *usage = use;
280 }
281
282 return (major);
283 }
284
285 /*
286 * __dh_gss_release_cred: Release the resources associated with cred.
287 */
288 OM_uint32
__dh_gss_release_cred(void * ctx,OM_uint32 * minor,gss_cred_id_t * cred)289 __dh_gss_release_cred(void *ctx, /* Per mechananism context (not used) */
290 OM_uint32 *minor, /* Mechanism status */
291 gss_cred_id_t *cred /* The cred to free */)
292 {
293 _NOTE(ARGUNUSED(ctx))
294 dh_cred_id_t dh_cred = (dh_cred_id_t)*cred;
295
296 /* Check that we can read and write required parameters */
297 if (minor == 0 || cred == 0)
298 return (GSS_S_CALL_INACCESSIBLE_WRITE);
299
300 /* Nothing to do */
301 if (*cred == GSS_C_NO_CREDENTIAL)
302 return (GSS_S_COMPLETE);
303
304 /* Check if the credential is valid */
305 if ((*minor = __dh_validate_cred(dh_cred)) != DH_SUCCESS)
306 return (GSS_S_NO_CRED);
307
308 /* Unregister the credential */
309 *minor = __dh_remove_cred(dh_cred);
310
311 /* Free the principal and the cred itself */
312 Free(dh_cred->principal);
313 Free(dh_cred);
314
315 /* Set cred to no credential */
316 *cred = GSS_C_NO_CREDENTIAL;
317
318 return (GSS_S_COMPLETE);
319 }
320