xref: /onnv-gate/usr/src/lib/gss_mechs/mech_dh/backend/mech/cred.c (revision 0:68f95e015346)
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