xref: /illumos-gate/usr/src/lib/libgss/g_store_cred.c (revision 6a634c9d)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  *  glue routine for gss_store_cred
27  */
28 
29 #include <mechglueP.h>
30 #include "gssapiP_generic.h"
31 #include <errno.h>
32 
33 static OM_uint32
val_store_cred_args(OM_uint32 * minor_status,const gss_cred_id_t input_cred_handle,gss_cred_usage_t cred_usage,const gss_OID desired_mech,OM_uint32 overwrite_cred,OM_uint32 default_cred,gss_OID_set * elements_stored,gss_cred_usage_t * cred_usage_stored)34 val_store_cred_args(
35         OM_uint32 *minor_status,
36         const gss_cred_id_t input_cred_handle,
37         gss_cred_usage_t cred_usage,
38 	/*LINTED*/
39         const gss_OID desired_mech,
40 	/*LINTED*/
41         OM_uint32 overwrite_cred,
42 	/*LINTED*/
43         OM_uint32 default_cred,
44         gss_OID_set *elements_stored,
45 	/*LINTED*/
46         gss_cred_usage_t *cred_usage_stored)
47 {
48 
49         /* Initialize outputs. */
50 
51         if (minor_status != NULL)
52                 *minor_status = 0;
53 
54         if (elements_stored != NULL)
55                 *elements_stored = GSS_C_NULL_OID_SET;
56 
57        /* Validate arguments. */
58 
59         if (minor_status == NULL)
60                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
61 
62         if (input_cred_handle == GSS_C_NO_CREDENTIAL)
63                 return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED);
64 
65 	if (cred_usage != GSS_C_ACCEPT
66 	    && cred_usage != GSS_C_INITIATE
67 	    && cred_usage != GSS_C_BOTH) {
68 		if (minor_status) {
69 			*minor_status = EINVAL;
70 			map_errcode(minor_status);
71 		}
72 		return GSS_S_FAILURE;
73 	}
74 
75 	return (GSS_S_COMPLETE);
76 }
77 
gss_store_cred(minor_status,input_cred_handle,cred_usage,desired_mech,overwrite_cred,default_cred,elements_stored,cred_usage_stored)78 OM_uint32 gss_store_cred(minor_status,
79 			input_cred_handle,
80 			cred_usage,
81 			desired_mech,
82 			overwrite_cred,
83 			default_cred,
84 			elements_stored,
85 			cred_usage_stored)
86 
87 OM_uint32		*minor_status;
88 const gss_cred_id_t	 input_cred_handle;
89 gss_cred_usage_t	 cred_usage;
90 const gss_OID		 desired_mech;
91 OM_uint32		 overwrite_cred;
92 OM_uint32		 default_cred;
93 gss_OID_set		*elements_stored;
94 gss_cred_usage_t	*cred_usage_stored;
95 
96 {
97 	OM_uint32		major_status = GSS_S_FAILURE;
98 	gss_union_cred_t	union_cred;
99 	gss_cred_id_t		mech_cred;
100 	gss_mechanism		mech;
101 	gss_OID			dmech;
102 	int			i;
103 
104         major_status = val_store_cred_args(minor_status,
105                                            input_cred_handle,
106                                            cred_usage,
107                                            desired_mech,
108                                            overwrite_cred,
109                                            default_cred,
110                                            elements_stored,
111                                            cred_usage_stored);
112 	if (major_status != GSS_S_COMPLETE)
113 		return (major_status);
114 
115 	/* Initial value needed below. */
116 		major_status = GSS_S_FAILURE;
117 
118 	if (cred_usage_stored != NULL)
119 		*cred_usage_stored = GSS_C_BOTH; /* there's no GSS_C_NEITHER */
120 
121 	union_cred = (gss_union_cred_t)input_cred_handle;
122 
123 	/* desired_mech != GSS_C_NULL_OID -> store one element */
124 	if (desired_mech != GSS_C_NULL_OID) {
125 		mech = __gss_get_mechanism(desired_mech);
126 		if (mech == NULL)
127 			return (GSS_S_BAD_MECH);
128 
129 		if (mech->gss_store_cred == NULL)
130 			return (major_status);
131 
132 		mech_cred = __gss_get_mechanism_cred(union_cred, desired_mech);
133 		if (mech_cred == GSS_C_NO_CREDENTIAL)
134 			return (GSS_S_NO_CRED);
135 
136 		major_status = mech->gss_store_cred(mech->context,
137 						minor_status,
138 						(gss_cred_id_t)mech_cred,
139 						cred_usage,
140 						desired_mech,
141 						overwrite_cred,
142 						default_cred,
143 						elements_stored,
144 						    cred_usage_stored);
145 		if (major_status != GSS_S_COMPLETE)
146 			map_error(minor_status, mech);
147 		return major_status;
148 	}
149 
150 	/* desired_mech == GSS_C_NULL_OID -> store all elements */
151 
152 	*minor_status = 0;
153 
154 	for (i = 0; i < union_cred->count; i++) {
155 		/* Get mech and cred element */
156 		dmech = &union_cred->mechs_array[i];
157 		mech = __gss_get_mechanism(dmech);
158 		if (mech == NULL)
159 			continue;
160 
161 		if (mech->gss_store_cred == NULL)
162 			continue;
163 
164 		mech_cred = __gss_get_mechanism_cred(union_cred, dmech);
165 		if (mech_cred == GSS_C_NO_CREDENTIAL)
166 			continue; /* can't happen, but safe to ignore */
167 
168 		major_status = mech->gss_store_cred(mech->context,
169 						minor_status,
170 						(gss_cred_id_t)mech_cred,
171 						cred_usage,
172 						dmech,
173 						overwrite_cred,
174 						default_cred,
175 						NULL,
176 						cred_usage_stored);
177 		if (major_status != GSS_S_COMPLETE) {
178 			map_error(minor_status, mech);
179 			continue;
180 		}
181 
182 		/* Succeeded for at least one mech */
183 
184 		if (elements_stored == NULL)
185 			continue;
186 
187 		if (*elements_stored == GSS_C_NULL_OID_SET) {
188 			major_status = gss_create_empty_oid_set(minor_status,
189 						elements_stored);
190 
191 			if (GSS_ERROR(major_status))
192 				return (major_status);
193 		}
194 
195 		major_status = gss_add_oid_set_member(minor_status, dmech,
196 			elements_stored);
197 
198 		/* The caller should clean up elements_stored */
199 		if (GSS_ERROR(major_status))
200 			return (major_status);
201 	}
202 
203 	/*
204 	 * Success with some mechs may mask failure with others, but
205 	 * that's what elements_stored is for.
206 	 */
207 	return (major_status);
208 }
209