xref: /freebsd/lib/libgssapi/gss_add_cred.c (revision 5e53a4f90f82c4345f277dd87cc9292f26e04a29)
1c0b9f4feSDoug Rabson /*-
2*5e53a4f9SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*5e53a4f9SPedro F. Giffuni  *
4c0b9f4feSDoug Rabson  * Copyright (c) 2005 Doug Rabson
5c0b9f4feSDoug Rabson  * All rights reserved.
6c0b9f4feSDoug Rabson  *
7c0b9f4feSDoug Rabson  * Redistribution and use in source and binary forms, with or without
8c0b9f4feSDoug Rabson  * modification, are permitted provided that the following conditions
9c0b9f4feSDoug Rabson  * are met:
10c0b9f4feSDoug Rabson  * 1. Redistributions of source code must retain the above copyright
11c0b9f4feSDoug Rabson  *    notice, this list of conditions and the following disclaimer.
12c0b9f4feSDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
13c0b9f4feSDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
14c0b9f4feSDoug Rabson  *    documentation and/or other materials provided with the distribution.
15c0b9f4feSDoug Rabson  *
16c0b9f4feSDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17c0b9f4feSDoug Rabson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c0b9f4feSDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c0b9f4feSDoug Rabson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20c0b9f4feSDoug Rabson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c0b9f4feSDoug Rabson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c0b9f4feSDoug Rabson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c0b9f4feSDoug Rabson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c0b9f4feSDoug Rabson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c0b9f4feSDoug Rabson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c0b9f4feSDoug Rabson  * SUCH DAMAGE.
27c0b9f4feSDoug Rabson  *
28c0b9f4feSDoug Rabson  *	$FreeBSD$
29c0b9f4feSDoug Rabson  */
30c0b9f4feSDoug Rabson 
31c0b9f4feSDoug Rabson #include <gssapi/gssapi.h>
323aebdb89SAlexander Kabaev #include <stdlib.h>
33c0b9f4feSDoug Rabson #include <errno.h>
34c0b9f4feSDoug Rabson 
35c0b9f4feSDoug Rabson #include "mech_switch.h"
36c0b9f4feSDoug Rabson #include "cred.h"
37c0b9f4feSDoug Rabson #include "name.h"
3833f12199SDoug Rabson #include "utils.h"
39c0b9f4feSDoug Rabson 
40c0b9f4feSDoug Rabson static struct _gss_mechanism_cred *
41c0b9f4feSDoug Rabson _gss_copy_cred(struct _gss_mechanism_cred *mc)
42c0b9f4feSDoug Rabson {
43c0b9f4feSDoug Rabson 	struct _gss_mechanism_cred *new_mc;
44c0b9f4feSDoug Rabson 	struct _gss_mech_switch *m = mc->gmc_mech;
45c0b9f4feSDoug Rabson 	OM_uint32 major_status, minor_status;
46c0b9f4feSDoug Rabson 	gss_name_t name;
47c0b9f4feSDoug Rabson 	gss_cred_id_t cred;
48c0b9f4feSDoug Rabson 	OM_uint32 initiator_lifetime, acceptor_lifetime;
49c0b9f4feSDoug Rabson 	gss_cred_usage_t cred_usage;
50c0b9f4feSDoug Rabson 
51c0b9f4feSDoug Rabson 	major_status = m->gm_inquire_cred_by_mech(&minor_status,
52c0b9f4feSDoug Rabson 	    mc->gmc_cred, mc->gmc_mech_oid,
53c0b9f4feSDoug Rabson 	    &name, &initiator_lifetime, &acceptor_lifetime, &cred_usage);
5433f12199SDoug Rabson 	if (major_status) {
5533f12199SDoug Rabson 		_gss_mg_error(m, major_status, minor_status);
56c0b9f4feSDoug Rabson 		return (0);
5733f12199SDoug Rabson 	}
58c0b9f4feSDoug Rabson 
59c0b9f4feSDoug Rabson 	major_status = m->gm_add_cred(&minor_status,
60c0b9f4feSDoug Rabson 	    GSS_C_NO_CREDENTIAL, name, mc->gmc_mech_oid,
61c0b9f4feSDoug Rabson 	    cred_usage, initiator_lifetime, acceptor_lifetime,
62c0b9f4feSDoug Rabson 	    &cred, 0, 0, 0);
63c0b9f4feSDoug Rabson 	m->gm_release_name(&minor_status, &name);
64c0b9f4feSDoug Rabson 
6533f12199SDoug Rabson 	if (major_status) {
6633f12199SDoug Rabson 		_gss_mg_error(m, major_status, minor_status);
67c0b9f4feSDoug Rabson 		return (0);
6833f12199SDoug Rabson 	}
69c0b9f4feSDoug Rabson 
70c0b9f4feSDoug Rabson 	new_mc = malloc(sizeof(struct _gss_mechanism_cred));
71c0b9f4feSDoug Rabson 	if (!new_mc) {
72c0b9f4feSDoug Rabson 		m->gm_release_cred(&minor_status, &cred);
73c0b9f4feSDoug Rabson 		return (0);
74c0b9f4feSDoug Rabson 	}
75c0b9f4feSDoug Rabson 	new_mc->gmc_mech = m;
76c0b9f4feSDoug Rabson 	new_mc->gmc_mech_oid = &m->gm_mech_oid;
77c0b9f4feSDoug Rabson 	new_mc->gmc_cred = cred;
78c0b9f4feSDoug Rabson 
79c0b9f4feSDoug Rabson 	return (new_mc);
80c0b9f4feSDoug Rabson }
81c0b9f4feSDoug Rabson 
82c0b9f4feSDoug Rabson OM_uint32
83c0b9f4feSDoug Rabson gss_add_cred(OM_uint32 *minor_status,
84c0b9f4feSDoug Rabson     const gss_cred_id_t input_cred_handle,
85c0b9f4feSDoug Rabson     const gss_name_t desired_name,
86c0b9f4feSDoug Rabson     const gss_OID desired_mech,
87c0b9f4feSDoug Rabson     gss_cred_usage_t cred_usage,
88c0b9f4feSDoug Rabson     OM_uint32 initiator_time_req,
89c0b9f4feSDoug Rabson     OM_uint32 acceptor_time_req,
90c0b9f4feSDoug Rabson     gss_cred_id_t *output_cred_handle,
91c0b9f4feSDoug Rabson     gss_OID_set *actual_mechs,
92c0b9f4feSDoug Rabson     OM_uint32 *initiator_time_rec,
93c0b9f4feSDoug Rabson     OM_uint32 *acceptor_time_rec)
94c0b9f4feSDoug Rabson {
95c0b9f4feSDoug Rabson 	OM_uint32 major_status;
96c0b9f4feSDoug Rabson 	struct _gss_mech_switch *m;
97c0b9f4feSDoug Rabson 	struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle;
98c0b9f4feSDoug Rabson 	struct _gss_cred *new_cred;
9933f12199SDoug Rabson 	gss_cred_id_t release_cred;
100c0b9f4feSDoug Rabson 	struct _gss_mechanism_cred *mc, *target_mc, *copy_mc;
101c0b9f4feSDoug Rabson 	struct _gss_mechanism_name *mn;
10233f12199SDoug Rabson 	OM_uint32 junk;
103c0b9f4feSDoug Rabson 
104c0b9f4feSDoug Rabson 	*minor_status = 0;
10533f12199SDoug Rabson 	*output_cred_handle = GSS_C_NO_CREDENTIAL;
10633f12199SDoug Rabson 	if (initiator_time_rec)
10733f12199SDoug Rabson 		*initiator_time_rec = 0;
10833f12199SDoug Rabson 	if (acceptor_time_rec)
10933f12199SDoug Rabson 		*acceptor_time_rec = 0;
11033f12199SDoug Rabson 	if (actual_mechs)
11133f12199SDoug Rabson 		*actual_mechs = GSS_C_NO_OID_SET;
112c0b9f4feSDoug Rabson 
113c0b9f4feSDoug Rabson 	new_cred = malloc(sizeof(struct _gss_cred));
114c0b9f4feSDoug Rabson 	if (!new_cred) {
115c0b9f4feSDoug Rabson 		*minor_status = ENOMEM;
116c0b9f4feSDoug Rabson 		return (GSS_S_FAILURE);
117c0b9f4feSDoug Rabson 	}
118c0b9f4feSDoug Rabson 	SLIST_INIT(&new_cred->gc_mc);
119c0b9f4feSDoug Rabson 
120c0b9f4feSDoug Rabson 	/*
121c0b9f4feSDoug Rabson 	 * We go through all the mc attached to the input_cred_handle
122c0b9f4feSDoug Rabson 	 * and check the mechanism. If it matches, we call
123c0b9f4feSDoug Rabson 	 * gss_add_cred for that mechanism, otherwise we copy the mc
124c0b9f4feSDoug Rabson 	 * to new_cred.
125c0b9f4feSDoug Rabson 	 */
1266baf7cc8SPedro F. Giffuni 	target_mc = NULL;
127c0b9f4feSDoug Rabson 	if (cred) {
128c0b9f4feSDoug Rabson 		SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) {
12933f12199SDoug Rabson 			if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) {
130c0b9f4feSDoug Rabson 				target_mc = mc;
131c0b9f4feSDoug Rabson 			}
132c0b9f4feSDoug Rabson 			copy_mc = _gss_copy_cred(mc);
133c0b9f4feSDoug Rabson 			if (!copy_mc) {
13433f12199SDoug Rabson 				release_cred = (gss_cred_id_t) new_cred;
13533f12199SDoug Rabson 				gss_release_cred(&junk, &release_cred);
136c0b9f4feSDoug Rabson 				*minor_status = ENOMEM;
137c0b9f4feSDoug Rabson 				return (GSS_S_FAILURE);
138c0b9f4feSDoug Rabson 			}
139c0b9f4feSDoug Rabson 			SLIST_INSERT_HEAD(&new_cred->gc_mc, copy_mc, gmc_link);
140c0b9f4feSDoug Rabson 		}
141c0b9f4feSDoug Rabson 	}
142c0b9f4feSDoug Rabson 
143c0b9f4feSDoug Rabson 	/*
144c0b9f4feSDoug Rabson 	 * Figure out a suitable mn, if any.
145c0b9f4feSDoug Rabson 	 */
146c0b9f4feSDoug Rabson 	if (desired_name) {
14733f12199SDoug Rabson 		major_status = _gss_find_mn(minor_status,
14833f12199SDoug Rabson 					    (struct _gss_name *) desired_name,
14933f12199SDoug Rabson 					    desired_mech,
15033f12199SDoug Rabson 					    &mn);
15133f12199SDoug Rabson 		if (major_status != GSS_S_COMPLETE) {
152c0b9f4feSDoug Rabson 			free(new_cred);
15333f12199SDoug Rabson 			return (major_status);
154c0b9f4feSDoug Rabson 		}
155c0b9f4feSDoug Rabson 	} else {
1566baf7cc8SPedro F. Giffuni 		mn = NULL;
157c0b9f4feSDoug Rabson 	}
158c0b9f4feSDoug Rabson 
159c0b9f4feSDoug Rabson 	m = _gss_find_mech_switch(desired_mech);
160c0b9f4feSDoug Rabson 
161c0b9f4feSDoug Rabson 	mc = malloc(sizeof(struct _gss_mechanism_cred));
162c0b9f4feSDoug Rabson 	if (!mc) {
16333f12199SDoug Rabson 		release_cred = (gss_cred_id_t) new_cred;
16433f12199SDoug Rabson 		gss_release_cred(&junk, &release_cred);
165c0b9f4feSDoug Rabson 		*minor_status = ENOMEM;
166c0b9f4feSDoug Rabson 		return (GSS_S_FAILURE);
167c0b9f4feSDoug Rabson 	}
168c0b9f4feSDoug Rabson 	mc->gmc_mech = m;
169c0b9f4feSDoug Rabson 	mc->gmc_mech_oid = &m->gm_mech_oid;
170c0b9f4feSDoug Rabson 
171c0b9f4feSDoug Rabson 	major_status = m->gm_add_cred(minor_status,
172c0b9f4feSDoug Rabson 	    target_mc ? target_mc->gmc_cred : GSS_C_NO_CREDENTIAL,
173c0b9f4feSDoug Rabson 	    desired_name ? mn->gmn_name : GSS_C_NO_NAME,
174c0b9f4feSDoug Rabson 	    desired_mech,
175c0b9f4feSDoug Rabson 	    cred_usage,
176c0b9f4feSDoug Rabson 	    initiator_time_req,
177c0b9f4feSDoug Rabson 	    acceptor_time_req,
178c0b9f4feSDoug Rabson 	    &mc->gmc_cred,
179c0b9f4feSDoug Rabson 	    actual_mechs,
180c0b9f4feSDoug Rabson 	    initiator_time_rec,
181c0b9f4feSDoug Rabson 	    acceptor_time_rec);
182c0b9f4feSDoug Rabson 
183c0b9f4feSDoug Rabson 	if (major_status) {
18433f12199SDoug Rabson 		_gss_mg_error(m, major_status, *minor_status);
18533f12199SDoug Rabson 		release_cred = (gss_cred_id_t) new_cred;
18633f12199SDoug Rabson 		gss_release_cred(&junk, &release_cred);
187c0b9f4feSDoug Rabson 		free(mc);
188c0b9f4feSDoug Rabson 		return (major_status);
189c0b9f4feSDoug Rabson 	}
190c0b9f4feSDoug Rabson 	SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link);
191c0b9f4feSDoug Rabson 	*output_cred_handle = (gss_cred_id_t) new_cred;
192c0b9f4feSDoug Rabson 
193c0b9f4feSDoug Rabson 	return (GSS_S_COMPLETE);
194c0b9f4feSDoug Rabson }
195c0b9f4feSDoug Rabson 
196