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