xref: /freebsd/crypto/heimdal/lib/gssapi/mech/gss_add_cred.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1*ae771770SStanislav Sedov /*-
2*ae771770SStanislav Sedov  * Copyright (c) 2005 Doug Rabson
3*ae771770SStanislav Sedov  * All rights reserved.
4*ae771770SStanislav Sedov  *
5*ae771770SStanislav Sedov  * Redistribution and use in source and binary forms, with or without
6*ae771770SStanislav Sedov  * modification, are permitted provided that the following conditions
7*ae771770SStanislav Sedov  * are met:
8*ae771770SStanislav Sedov  * 1. Redistributions of source code must retain the above copyright
9*ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer.
10*ae771770SStanislav Sedov  * 2. Redistributions in binary form must reproduce the above copyright
11*ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer in the
12*ae771770SStanislav Sedov  *    documentation and/or other materials provided with the distribution.
13*ae771770SStanislav Sedov  *
14*ae771770SStanislav Sedov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*ae771770SStanislav Sedov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*ae771770SStanislav Sedov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*ae771770SStanislav Sedov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*ae771770SStanislav Sedov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*ae771770SStanislav Sedov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*ae771770SStanislav Sedov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*ae771770SStanislav Sedov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*ae771770SStanislav Sedov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*ae771770SStanislav Sedov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*ae771770SStanislav Sedov  * SUCH DAMAGE.
25*ae771770SStanislav Sedov  *
26*ae771770SStanislav Sedov  *	$FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $
27*ae771770SStanislav Sedov  */
28*ae771770SStanislav Sedov 
29*ae771770SStanislav Sedov #include "mech_locl.h"
30*ae771770SStanislav Sedov 
31*ae771770SStanislav Sedov struct _gss_mechanism_cred *
_gss_copy_cred(struct _gss_mechanism_cred * mc)32*ae771770SStanislav Sedov _gss_copy_cred(struct _gss_mechanism_cred *mc)
33*ae771770SStanislav Sedov {
34*ae771770SStanislav Sedov 	struct _gss_mechanism_cred *new_mc;
35*ae771770SStanislav Sedov 	gssapi_mech_interface m = mc->gmc_mech;
36*ae771770SStanislav Sedov 	OM_uint32 major_status, minor_status;
37*ae771770SStanislav Sedov 	gss_name_t name;
38*ae771770SStanislav Sedov 	gss_cred_id_t cred;
39*ae771770SStanislav Sedov 	OM_uint32 initiator_lifetime, acceptor_lifetime;
40*ae771770SStanislav Sedov 	gss_cred_usage_t cred_usage;
41*ae771770SStanislav Sedov 
42*ae771770SStanislav Sedov 	major_status = m->gm_inquire_cred_by_mech(&minor_status,
43*ae771770SStanislav Sedov 	    mc->gmc_cred, mc->gmc_mech_oid,
44*ae771770SStanislav Sedov 	    &name, &initiator_lifetime, &acceptor_lifetime, &cred_usage);
45*ae771770SStanislav Sedov 	if (major_status) {
46*ae771770SStanislav Sedov 		_gss_mg_error(m, major_status, minor_status);
47*ae771770SStanislav Sedov 		return (0);
48*ae771770SStanislav Sedov 	}
49*ae771770SStanislav Sedov 
50*ae771770SStanislav Sedov 	major_status = m->gm_add_cred(&minor_status,
51*ae771770SStanislav Sedov 	    GSS_C_NO_CREDENTIAL, name, mc->gmc_mech_oid,
52*ae771770SStanislav Sedov 	    cred_usage, initiator_lifetime, acceptor_lifetime,
53*ae771770SStanislav Sedov 	    &cred, 0, 0, 0);
54*ae771770SStanislav Sedov 	m->gm_release_name(&minor_status, &name);
55*ae771770SStanislav Sedov 
56*ae771770SStanislav Sedov 	if (major_status) {
57*ae771770SStanislav Sedov 		_gss_mg_error(m, major_status, minor_status);
58*ae771770SStanislav Sedov 		return (0);
59*ae771770SStanislav Sedov 	}
60*ae771770SStanislav Sedov 
61*ae771770SStanislav Sedov 	new_mc = malloc(sizeof(struct _gss_mechanism_cred));
62*ae771770SStanislav Sedov 	if (!new_mc) {
63*ae771770SStanislav Sedov 		m->gm_release_cred(&minor_status, &cred);
64*ae771770SStanislav Sedov 		return (0);
65*ae771770SStanislav Sedov 	}
66*ae771770SStanislav Sedov 	new_mc->gmc_mech = m;
67*ae771770SStanislav Sedov 	new_mc->gmc_mech_oid = &m->gm_mech_oid;
68*ae771770SStanislav Sedov 	new_mc->gmc_cred = cred;
69*ae771770SStanislav Sedov 
70*ae771770SStanislav Sedov 	return (new_mc);
71*ae771770SStanislav Sedov }
72*ae771770SStanislav Sedov 
73*ae771770SStanislav Sedov GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_add_cred(OM_uint32 * minor_status,const gss_cred_id_t input_cred_handle,const gss_name_t desired_name,const gss_OID desired_mech,gss_cred_usage_t cred_usage,OM_uint32 initiator_time_req,OM_uint32 acceptor_time_req,gss_cred_id_t * output_cred_handle,gss_OID_set * actual_mechs,OM_uint32 * initiator_time_rec,OM_uint32 * acceptor_time_rec)74*ae771770SStanislav Sedov gss_add_cred(OM_uint32 *minor_status,
75*ae771770SStanislav Sedov     const gss_cred_id_t input_cred_handle,
76*ae771770SStanislav Sedov     const gss_name_t desired_name,
77*ae771770SStanislav Sedov     const gss_OID desired_mech,
78*ae771770SStanislav Sedov     gss_cred_usage_t cred_usage,
79*ae771770SStanislav Sedov     OM_uint32 initiator_time_req,
80*ae771770SStanislav Sedov     OM_uint32 acceptor_time_req,
81*ae771770SStanislav Sedov     gss_cred_id_t *output_cred_handle,
82*ae771770SStanislav Sedov     gss_OID_set *actual_mechs,
83*ae771770SStanislav Sedov     OM_uint32 *initiator_time_rec,
84*ae771770SStanislav Sedov     OM_uint32 *acceptor_time_rec)
85*ae771770SStanislav Sedov {
86*ae771770SStanislav Sedov 	OM_uint32 major_status;
87*ae771770SStanislav Sedov 	gssapi_mech_interface m;
88*ae771770SStanislav Sedov 	struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle;
89*ae771770SStanislav Sedov 	struct _gss_cred *new_cred;
90*ae771770SStanislav Sedov 	gss_cred_id_t release_cred;
91*ae771770SStanislav Sedov 	struct _gss_mechanism_cred *mc, *target_mc, *copy_mc;
92*ae771770SStanislav Sedov 	struct _gss_mechanism_name *mn;
93*ae771770SStanislav Sedov 	OM_uint32 junk;
94*ae771770SStanislav Sedov 
95*ae771770SStanislav Sedov 	*minor_status = 0;
96*ae771770SStanislav Sedov 	*output_cred_handle = GSS_C_NO_CREDENTIAL;
97*ae771770SStanislav Sedov 	if (initiator_time_rec)
98*ae771770SStanislav Sedov 	    *initiator_time_rec = 0;
99*ae771770SStanislav Sedov 	if (acceptor_time_rec)
100*ae771770SStanislav Sedov 	    *acceptor_time_rec = 0;
101*ae771770SStanislav Sedov 	if (actual_mechs)
102*ae771770SStanislav Sedov 	    *actual_mechs = GSS_C_NO_OID_SET;
103*ae771770SStanislav Sedov 
104*ae771770SStanislav Sedov 	new_cred = malloc(sizeof(struct _gss_cred));
105*ae771770SStanislav Sedov 	if (!new_cred) {
106*ae771770SStanislav Sedov 		*minor_status = ENOMEM;
107*ae771770SStanislav Sedov 		return (GSS_S_FAILURE);
108*ae771770SStanislav Sedov 	}
109*ae771770SStanislav Sedov 	HEIM_SLIST_INIT(&new_cred->gc_mc);
110*ae771770SStanislav Sedov 
111*ae771770SStanislav Sedov 	/*
112*ae771770SStanislav Sedov 	 * We go through all the mc attached to the input_cred_handle
113*ae771770SStanislav Sedov 	 * and check the mechanism. If it matches, we call
114*ae771770SStanislav Sedov 	 * gss_add_cred for that mechanism, otherwise we copy the mc
115*ae771770SStanislav Sedov 	 * to new_cred.
116*ae771770SStanislav Sedov 	 */
117*ae771770SStanislav Sedov 	target_mc = 0;
118*ae771770SStanislav Sedov 	if (cred) {
119*ae771770SStanislav Sedov 		HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
120*ae771770SStanislav Sedov 			if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) {
121*ae771770SStanislav Sedov 				target_mc = mc;
122*ae771770SStanislav Sedov 			}
123*ae771770SStanislav Sedov 			copy_mc = _gss_copy_cred(mc);
124*ae771770SStanislav Sedov 			if (!copy_mc) {
125*ae771770SStanislav Sedov 				release_cred = (gss_cred_id_t)new_cred;
126*ae771770SStanislav Sedov 				gss_release_cred(&junk, &release_cred);
127*ae771770SStanislav Sedov 				*minor_status = ENOMEM;
128*ae771770SStanislav Sedov 				return (GSS_S_FAILURE);
129*ae771770SStanislav Sedov 			}
130*ae771770SStanislav Sedov 			HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, copy_mc, gmc_link);
131*ae771770SStanislav Sedov 		}
132*ae771770SStanislav Sedov 	}
133*ae771770SStanislav Sedov 
134*ae771770SStanislav Sedov 	/*
135*ae771770SStanislav Sedov 	 * Figure out a suitable mn, if any.
136*ae771770SStanislav Sedov 	 */
137*ae771770SStanislav Sedov 	if (desired_name) {
138*ae771770SStanislav Sedov 		major_status = _gss_find_mn(minor_status,
139*ae771770SStanislav Sedov 					    (struct _gss_name *) desired_name,
140*ae771770SStanislav Sedov 					    desired_mech,
141*ae771770SStanislav Sedov 					    &mn);
142*ae771770SStanislav Sedov 		if (major_status != GSS_S_COMPLETE) {
143*ae771770SStanislav Sedov 			free(new_cred);
144*ae771770SStanislav Sedov 			return major_status;
145*ae771770SStanislav Sedov 		}
146*ae771770SStanislav Sedov 	} else {
147*ae771770SStanislav Sedov 		mn = 0;
148*ae771770SStanislav Sedov 	}
149*ae771770SStanislav Sedov 
150*ae771770SStanislav Sedov 	m = __gss_get_mechanism(desired_mech);
151*ae771770SStanislav Sedov 
152*ae771770SStanislav Sedov 	mc = malloc(sizeof(struct _gss_mechanism_cred));
153*ae771770SStanislav Sedov 	if (!mc) {
154*ae771770SStanislav Sedov 		release_cred = (gss_cred_id_t)new_cred;
155*ae771770SStanislav Sedov 		gss_release_cred(&junk, &release_cred);
156*ae771770SStanislav Sedov 		*minor_status = ENOMEM;
157*ae771770SStanislav Sedov 		return (GSS_S_FAILURE);
158*ae771770SStanislav Sedov 	}
159*ae771770SStanislav Sedov 	mc->gmc_mech = m;
160*ae771770SStanislav Sedov 	mc->gmc_mech_oid = &m->gm_mech_oid;
161*ae771770SStanislav Sedov 
162*ae771770SStanislav Sedov 	major_status = m->gm_add_cred(minor_status,
163*ae771770SStanislav Sedov 	    target_mc ? target_mc->gmc_cred : GSS_C_NO_CREDENTIAL,
164*ae771770SStanislav Sedov 	    desired_name ? mn->gmn_name : GSS_C_NO_NAME,
165*ae771770SStanislav Sedov 	    desired_mech,
166*ae771770SStanislav Sedov 	    cred_usage,
167*ae771770SStanislav Sedov 	    initiator_time_req,
168*ae771770SStanislav Sedov 	    acceptor_time_req,
169*ae771770SStanislav Sedov 	    &mc->gmc_cred,
170*ae771770SStanislav Sedov 	    actual_mechs,
171*ae771770SStanislav Sedov 	    initiator_time_rec,
172*ae771770SStanislav Sedov 	    acceptor_time_rec);
173*ae771770SStanislav Sedov 
174*ae771770SStanislav Sedov 	if (major_status) {
175*ae771770SStanislav Sedov 		_gss_mg_error(m, major_status, *minor_status);
176*ae771770SStanislav Sedov 		release_cred = (gss_cred_id_t)new_cred;
177*ae771770SStanislav Sedov 		gss_release_cred(&junk, &release_cred);
178*ae771770SStanislav Sedov 		free(mc);
179*ae771770SStanislav Sedov 		return (major_status);
180*ae771770SStanislav Sedov 	}
181*ae771770SStanislav Sedov 	HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link);
182*ae771770SStanislav Sedov 	*output_cred_handle = (gss_cred_id_t) new_cred;
183*ae771770SStanislav Sedov 
184*ae771770SStanislav Sedov 	return (GSS_S_COMPLETE);
185*ae771770SStanislav Sedov }
186*ae771770SStanislav Sedov 
187