Imported Upstream version 1.10.2
[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 val_store_cred_args(
16         OM_uint32 *minor_status,
17         const gss_cred_id_t input_cred_handle,
18         gss_cred_usage_t cred_usage,
19         const gss_OID desired_mech,
20         OM_uint32 overwrite_cred,
21         OM_uint32 default_cred,
22         gss_OID_set *elements_stored,
23         gss_cred_usage_t *cred_usage_stored)
24 {
25
26         /* Initialize outputs. */
27
28         if (minor_status != NULL)
29                 *minor_status = 0;
30
31         if (elements_stored != NULL)
32                 *elements_stored = GSS_C_NULL_OID_SET;
33
34         /* Validate arguments. */
35
36         if (minor_status == NULL)
37                 return (GSS_S_CALL_INACCESSIBLE_WRITE);
38
39         if (input_cred_handle == GSS_C_NO_CREDENTIAL)
40                 return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED);
41
42         if (cred_usage != GSS_C_ACCEPT
43             && cred_usage != GSS_C_INITIATE
44             && cred_usage != GSS_C_BOTH) {
45             if (minor_status) {
46                 *minor_status = EINVAL;
47                 map_errcode(minor_status);
48             }
49             return GSS_S_FAILURE;
50         }
51
52         return (GSS_S_COMPLETE);
53 }
54
55
56 OM_uint32 KRB5_CALLCONV
57 gss_store_cred(minor_status,
58                input_cred_handle,
59                cred_usage,
60                desired_mech,
61                overwrite_cred,
62                default_cred,
63                elements_stored,
64                cred_usage_stored)
65
66 OM_uint32               *minor_status;
67 gss_cred_id_t            input_cred_handle;
68 gss_cred_usage_t         cred_usage;
69 const gss_OID            desired_mech;
70 OM_uint32                overwrite_cred;
71 OM_uint32                default_cred;
72 gss_OID_set             *elements_stored;
73 gss_cred_usage_t        *cred_usage_stored;
74
75 {
76         OM_uint32               major_status = GSS_S_FAILURE;
77         gss_union_cred_t        union_cred;
78         gss_cred_id_t           mech_cred;
79         gss_mechanism           mech;
80         gss_OID                 dmech;
81         int                     i;
82
83         major_status = val_store_cred_args(minor_status,
84                                            input_cred_handle,
85                                            cred_usage,
86                                            desired_mech,
87                                            overwrite_cred,
88                                            default_cred,
89                                            elements_stored,
90                                            cred_usage_stored);
91         if (major_status != GSS_S_COMPLETE)
92                 return (major_status);
93
94         /* Initial value needed below. */
95         major_status = GSS_S_FAILURE;
96
97         if (cred_usage_stored != NULL)
98                 *cred_usage_stored = GSS_C_BOTH; /* there's no GSS_C_NEITHER */
99
100         union_cred = (gss_union_cred_t)input_cred_handle;
101
102         /* desired_mech != GSS_C_NULL_OID -> store one element */
103         if (desired_mech != GSS_C_NULL_OID) {
104                 mech = gssint_get_mechanism(desired_mech);
105                 if (mech == NULL)
106                         return (GSS_S_BAD_MECH);
107
108                 if (mech->gss_store_cred == NULL)
109                         return (major_status);
110
111                 mech_cred = gssint_get_mechanism_cred(union_cred, desired_mech);
112                 if (mech_cred == GSS_C_NO_CREDENTIAL)
113                         return (GSS_S_NO_CRED);
114
115                 major_status = mech->gss_store_cred(
116                                                     minor_status,
117                                                     (gss_cred_id_t)mech_cred,
118                                                     cred_usage,
119                                                     desired_mech,
120                                                     overwrite_cred,
121                                                     default_cred,
122                                                     elements_stored,
123                                                     cred_usage_stored);
124                 if (major_status != GSS_S_COMPLETE)
125                     map_error(minor_status, mech);
126                 return major_status;
127         }
128
129         /* desired_mech == GSS_C_NULL_OID -> store all elements */
130
131         *minor_status = 0;
132
133         for (i = 0; i < union_cred->count; i++) {
134                 /* Get mech and cred element */
135                 dmech = &union_cred->mechs_array[i];
136                 mech = gssint_get_mechanism(dmech);
137                 if (mech == NULL)
138                         continue;
139
140                 if (mech->gss_store_cred == NULL)
141                         continue;
142
143                 mech_cred = gssint_get_mechanism_cred(union_cred, dmech);
144                 if (mech_cred == GSS_C_NO_CREDENTIAL)
145                         continue; /* can't happen, but safe to ignore */
146
147                 major_status = mech->gss_store_cred(
148                                                 minor_status,
149                                                 (gss_cred_id_t)mech_cred,
150                                                 cred_usage,
151                                                 dmech,
152                                                 overwrite_cred,
153                                                 default_cred,
154                                                 NULL,
155                                                 cred_usage_stored);
156                 if (major_status != GSS_S_COMPLETE) {
157                     map_error(minor_status, mech);
158                     continue;
159                 }
160
161                 /* Succeeded for at least one mech */
162
163                 if (elements_stored == NULL)
164                         continue;
165
166                 if (*elements_stored == GSS_C_NULL_OID_SET) {
167                         major_status = gss_create_empty_oid_set(minor_status,
168                                                 elements_stored);
169
170                         if (GSS_ERROR(major_status))
171                                 return (major_status);
172                 }
173
174                 major_status = gss_add_oid_set_member(minor_status, dmech,
175                         elements_stored);
176
177                 /* The caller should clean up elements_stored */
178                 if (GSS_ERROR(major_status))
179                         return (major_status);
180         }
181
182         /*
183          * Success with some mechs may mask failure with others, but
184          * that's what elements_stored is for.
185          */
186         return (major_status);
187 }