Imported Upstream version 1.15.1
[platform/upstream/krb5.git] / src / lib / gssapi / mechglue / g_store_cred.c
1 /*
2  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5
6 /* #pragma ident        "@(#)g_store_cred.c     1.2     04/04/05 SMI" */
7
8 /*
9  *  glue routine for gss_store_cred
10  */
11
12 #include <mglueP.h>
13
14 static OM_uint32
15 store_cred_fallback(
16         OM_uint32 *minor_status,
17         gss_mechanism mech,
18         gss_cred_id_t mech_cred,
19         gss_cred_usage_t cred_usage,
20         gss_OID desired_mech,
21         OM_uint32 overwrite_cred,
22         OM_uint32 default_cred,
23         gss_const_key_value_set_t cred_store,
24         gss_OID_set *elements_stored,
25         gss_cred_usage_t *cred_usage_stored)
26 {
27         gss_OID public_mech = gssint_get_public_oid(desired_mech);
28
29         if (mech->gss_store_cred_into != NULL) {
30                 return mech->gss_store_cred_into(minor_status, mech_cred,
31                                                  cred_usage, public_mech,
32                                                  overwrite_cred, default_cred,
33                                                  cred_store, elements_stored,
34                                                  cred_usage_stored);
35         } else if (cred_store == GSS_C_NO_CRED_STORE) {
36                 return mech->gss_store_cred(minor_status, mech_cred,
37                                             cred_usage, public_mech,
38                                             overwrite_cred, default_cred,
39                                             elements_stored,
40                                             cred_usage_stored);
41         } else {
42                 return GSS_S_UNAVAILABLE;
43         }
44 }
45
46 static OM_uint32
47 val_store_cred_args(
48         OM_uint32 *minor_status,
49         const gss_cred_id_t input_cred_handle,
50         gss_cred_usage_t cred_usage,
51         const gss_OID desired_mech,
52         OM_uint32 overwrite_cred,
53         OM_uint32 default_cred,
54         gss_const_key_value_set_t cred_store,
55         gss_OID_set *elements_stored,
56         gss_cred_usage_t *cred_usage_stored)
57 {
58
59         /* Initialize outputs. */
60
61         if (minor_status != NULL)
62                 *minor_status = 0;
63
64         if (elements_stored != NULL)
65                 *elements_stored = GSS_C_NULL_OID_SET;
66
67         /* Validate arguments. */
68
69         if (minor_status == NULL)
70                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
71
72         if (input_cred_handle == GSS_C_NO_CREDENTIAL)
73                 return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED);
74
75         if (cred_usage != GSS_C_ACCEPT
76             && cred_usage != GSS_C_INITIATE
77             && cred_usage != GSS_C_BOTH) {
78             if (minor_status) {
79                 *minor_status = EINVAL;
80                 map_errcode(minor_status);
81             }
82             return GSS_S_FAILURE;
83         }
84
85         if (cred_store != NULL && cred_store->count == 0) {
86                 *minor_status = EINVAL;
87                 map_errcode(minor_status);
88                 return GSS_S_FAILURE;
89         }
90
91         return (GSS_S_COMPLETE);
92 }
93
94
95 OM_uint32 KRB5_CALLCONV
96 gss_store_cred(minor_status,
97                input_cred_handle,
98                cred_usage,
99                desired_mech,
100                overwrite_cred,
101                default_cred,
102                elements_stored,
103                cred_usage_stored)
104
105 OM_uint32               *minor_status;
106 gss_cred_id_t            input_cred_handle;
107 gss_cred_usage_t         cred_usage;
108 const gss_OID            desired_mech;
109 OM_uint32                overwrite_cred;
110 OM_uint32                default_cred;
111 gss_OID_set             *elements_stored;
112 gss_cred_usage_t        *cred_usage_stored;
113
114 {
115         return gss_store_cred_into(minor_status, input_cred_handle, cred_usage,
116                                    desired_mech, overwrite_cred, default_cred,
117                                    GSS_C_NO_CRED_STORE, elements_stored,
118                                    cred_usage_stored);
119 }
120
121 OM_uint32 KRB5_CALLCONV
122 gss_store_cred_into(minor_status,
123                     input_cred_handle,
124                     cred_usage,
125                     desired_mech,
126                     overwrite_cred,
127                     default_cred,
128                     cred_store,
129                     elements_stored,
130                     cred_usage_stored)
131
132 OM_uint32                        *minor_status;
133 gss_cred_id_t                    input_cred_handle;
134 gss_cred_usage_t                 cred_usage;
135 gss_OID                          desired_mech;
136 OM_uint32                        overwrite_cred;
137 OM_uint32                        default_cred;
138 gss_const_key_value_set_t        cred_store;
139 gss_OID_set                      *elements_stored;
140 gss_cred_usage_t                 *cred_usage_stored;
141
142 {
143         OM_uint32               major_status = GSS_S_FAILURE;
144         gss_union_cred_t        union_cred;
145         gss_cred_id_t           mech_cred;
146         gss_mechanism           mech;
147         gss_OID                 dmech;
148         gss_OID                 selected_mech;
149         int                     i;
150
151         major_status = val_store_cred_args(minor_status,
152                                            input_cred_handle,
153                                            cred_usage,
154                                            desired_mech,
155                                            overwrite_cred,
156                                            default_cred,
157                                            cred_store,
158                                            elements_stored,
159                                            cred_usage_stored);
160         if (major_status != GSS_S_COMPLETE)
161                 return (major_status);
162
163         /* Initial value needed below. */
164         major_status = GSS_S_FAILURE;
165
166         if (cred_usage_stored != NULL)
167                 *cred_usage_stored = GSS_C_BOTH; /* there's no GSS_C_NEITHER */
168
169         union_cred = (gss_union_cred_t)input_cred_handle;
170
171         /* desired_mech != GSS_C_NULL_OID -> store one element */
172         if (desired_mech != GSS_C_NULL_OID) {
173                 major_status = gssint_select_mech_type(minor_status,
174                                                        desired_mech,
175                                                        &selected_mech);
176                 if (major_status != GSS_S_COMPLETE)
177                         return (major_status);
178
179                 mech = gssint_get_mechanism(selected_mech);
180                 if (mech == NULL)
181                         return (GSS_S_BAD_MECH);
182
183                 if (mech->gss_store_cred_into == NULL &&
184                     cred_store != GSS_C_NO_CRED_STORE)
185                         return (major_status);
186
187                 if (mech->gss_store_cred == NULL &&
188                     mech->gss_store_cred_into == NULL)
189                         return (major_status);
190
191                 mech_cred = gssint_get_mechanism_cred(union_cred, selected_mech);
192                 if (mech_cred == GSS_C_NO_CREDENTIAL)
193                         return (GSS_S_NO_CRED);
194
195                 major_status = store_cred_fallback(minor_status, mech,
196                                                    mech_cred, cred_usage,
197                                                    selected_mech,
198                                                    overwrite_cred,
199                                                    default_cred, cred_store,
200                                                    elements_stored,
201                                                    cred_usage_stored);
202                 if (major_status != GSS_S_COMPLETE)
203                     map_error(minor_status, mech);
204                 return major_status;
205         }
206
207         /* desired_mech == GSS_C_NULL_OID -> store all elements */
208
209         *minor_status = 0;
210
211         for (i = 0; i < union_cred->count; i++) {
212                 /* Get mech and cred element */
213                 dmech = &union_cred->mechs_array[i];
214                 mech = gssint_get_mechanism(dmech);
215                 if (mech == NULL)
216                         continue;
217
218                 if (mech->gss_store_cred_into == NULL &&
219                     cred_store != GSS_C_NO_CRED_STORE)
220                         continue;
221
222                 if (mech->gss_store_cred == NULL &&
223                     mech->gss_store_cred_into == NULL)
224                         continue;
225
226                 mech_cred = gssint_get_mechanism_cred(union_cred, dmech);
227                 if (mech_cred == GSS_C_NO_CREDENTIAL)
228                         continue; /* can't happen, but safe to ignore */
229
230                 major_status = store_cred_fallback(minor_status, mech,
231                                                    mech_cred, cred_usage,
232                                                    dmech, overwrite_cred,
233                                                    default_cred, cred_store,
234                                                    NULL, cred_usage_stored);
235                 if (major_status != GSS_S_COMPLETE) {
236                     map_error(minor_status, mech);
237                     continue;
238                 }
239
240                 /* Succeeded for at least one mech */
241
242                 if (elements_stored == NULL)
243                         continue;
244
245                 if (*elements_stored == GSS_C_NULL_OID_SET) {
246                         major_status = gss_create_empty_oid_set(minor_status,
247                                                 elements_stored);
248
249                         if (GSS_ERROR(major_status))
250                                 return (major_status);
251                 }
252
253                 major_status = gss_add_oid_set_member(minor_status, dmech,
254                         elements_stored);
255
256                 /* The caller should clean up elements_stored */
257                 if (GSS_ERROR(major_status))
258                         return (major_status);
259         }
260
261         /*
262          * Success with some mechs may mask failure with others, but
263          * that's what elements_stored is for.
264          */
265         return (major_status);
266 }