/src/krb5/src/lib/gssapi/krb5/store_cred.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
2 | | /* lib/gssapi/krb5/store_cred.c */ |
3 | | /* |
4 | | * Copyright 2009 by the Massachusetts Institute of Technology. |
5 | | * All Rights Reserved. |
6 | | * |
7 | | * Export of this software from the United States of America may |
8 | | * require a specific license from the United States Government. |
9 | | * It is the responsibility of any person or organization contemplating |
10 | | * export to obtain such a license before exporting. |
11 | | * |
12 | | * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and |
13 | | * distribute this software and its documentation for any purpose and |
14 | | * without fee is hereby granted, provided that the above copyright |
15 | | * notice appear in all copies and that both that copyright notice and |
16 | | * this permission notice appear in supporting documentation, and that |
17 | | * the name of M.I.T. not be used in advertising or publicity pertaining |
18 | | * to distribution of the software without specific, written prior |
19 | | * permission. Furthermore if you modify this software you must label |
20 | | * your software as modified software and not distribute it in such a |
21 | | * fashion that it might be confused with the original M.I.T. software. |
22 | | * M.I.T. makes no representations about the suitability of |
23 | | * this software for any purpose. It is provided "as is" without express |
24 | | * or implied warranty. |
25 | | */ |
26 | | |
27 | | #include "k5-int.h" |
28 | | #include "gssapiP_krb5.h" |
29 | | |
30 | | static OM_uint32 |
31 | | copy_initiator_creds(OM_uint32 *minor_status, |
32 | | gss_cred_id_t input_cred_handle, |
33 | | const gss_OID desired_mech, |
34 | | OM_uint32 overwrite_cred, |
35 | | OM_uint32 default_cred, |
36 | | gss_const_key_value_set_t cred_store) |
37 | 0 | { |
38 | 0 | OM_uint32 major_status; |
39 | 0 | krb5_error_code ret; |
40 | 0 | krb5_gss_cred_id_t kcred = NULL; |
41 | 0 | krb5_context context = NULL; |
42 | 0 | krb5_ccache cache = NULL, defcache = NULL, mcc = NULL; |
43 | 0 | krb5_principal princ = NULL; |
44 | 0 | krb5_boolean switch_to_cache = FALSE; |
45 | 0 | const char *ccache_name, *deftype; |
46 | |
|
47 | 0 | *minor_status = 0; |
48 | |
|
49 | 0 | ret = krb5_gss_init_context(&context); |
50 | 0 | if (ret) |
51 | 0 | goto kerr_cleanup; |
52 | | |
53 | 0 | major_status = krb5_gss_validate_cred_1(minor_status, |
54 | 0 | input_cred_handle, |
55 | 0 | context); |
56 | 0 | if (GSS_ERROR(major_status)) |
57 | 0 | goto cleanup; |
58 | | |
59 | 0 | kcred = (krb5_gss_cred_id_t)input_cred_handle; |
60 | |
|
61 | 0 | if (kcred->ccache == NULL) { |
62 | 0 | *minor_status = KG_CCACHE_NOMATCH; |
63 | 0 | major_status = GSS_S_DEFECTIVE_CREDENTIAL; |
64 | 0 | goto cleanup; |
65 | 0 | } |
66 | | |
67 | 0 | major_status = kg_value_from_cred_store(cred_store, |
68 | 0 | KRB5_CS_CCACHE_URN, &ccache_name); |
69 | 0 | if (GSS_ERROR(major_status)) |
70 | 0 | goto cleanup; |
71 | | |
72 | 0 | if (ccache_name != NULL) { |
73 | 0 | ret = krb5_cc_set_default_name(context, ccache_name); |
74 | 0 | if (ret) |
75 | 0 | goto kerr_cleanup; |
76 | 0 | } else { |
77 | 0 | major_status = kg_sync_ccache_name(context, minor_status); |
78 | 0 | if (major_status != GSS_S_COMPLETE) |
79 | 0 | goto cleanup; |
80 | 0 | } |
81 | | |
82 | | /* Resolve the default ccache and get its type. */ |
83 | 0 | ret = krb5_cc_default(context, &defcache); |
84 | 0 | if (ret) |
85 | 0 | goto kerr_cleanup; |
86 | 0 | deftype = krb5_cc_get_type(context, defcache); |
87 | |
|
88 | 0 | if (krb5_cc_support_switch(context, deftype)) { |
89 | | /* Use an existing or new cache within the collection. */ |
90 | 0 | ret = krb5_cc_cache_match(context, kcred->name->princ, &cache); |
91 | 0 | if (!ret && !overwrite_cred) { |
92 | 0 | major_status = GSS_S_DUPLICATE_ELEMENT; |
93 | 0 | goto cleanup; |
94 | 0 | } |
95 | 0 | if (ret == KRB5_CC_NOTFOUND) |
96 | 0 | ret = krb5_cc_new_unique(context, deftype, NULL, &cache); |
97 | 0 | if (ret) |
98 | 0 | goto kerr_cleanup; |
99 | 0 | switch_to_cache = default_cred; |
100 | 0 | } else { |
101 | | /* Use the default cache. */ |
102 | 0 | cache = defcache; |
103 | 0 | defcache = NULL; |
104 | 0 | ret = krb5_cc_get_principal(context, cache, &princ); |
105 | 0 | krb5_free_principal(context, princ); |
106 | 0 | if (!ret && !overwrite_cred) { |
107 | 0 | major_status = GSS_S_DUPLICATE_ELEMENT; |
108 | 0 | goto cleanup; |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | 0 | ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc); |
113 | 0 | if (ret) |
114 | 0 | goto kerr_cleanup; |
115 | 0 | ret = krb5_cc_initialize(context, mcc, kcred->name->princ); |
116 | 0 | if (ret) |
117 | 0 | goto kerr_cleanup; |
118 | 0 | ret = krb5_cc_copy_creds(context, kcred->ccache, mcc); |
119 | 0 | if (ret) |
120 | 0 | goto kerr_cleanup; |
121 | 0 | ret = krb5_cc_move(context, mcc, cache); |
122 | 0 | if (ret) |
123 | 0 | goto kerr_cleanup; |
124 | 0 | mcc = NULL; |
125 | |
|
126 | 0 | if (switch_to_cache) { |
127 | 0 | ret = krb5_cc_switch(context, cache); |
128 | 0 | if (ret) |
129 | 0 | goto kerr_cleanup; |
130 | 0 | } |
131 | | |
132 | 0 | *minor_status = 0; |
133 | 0 | major_status = GSS_S_COMPLETE; |
134 | |
|
135 | 0 | cleanup: |
136 | 0 | if (kcred != NULL) |
137 | 0 | k5_mutex_unlock(&kcred->lock); |
138 | 0 | if (defcache != NULL) |
139 | 0 | krb5_cc_close(context, defcache); |
140 | 0 | if (cache != NULL) |
141 | 0 | krb5_cc_close(context, cache); |
142 | 0 | if (mcc != NULL) |
143 | 0 | krb5_cc_destroy(context, mcc); |
144 | 0 | krb5_free_context(context); |
145 | |
|
146 | 0 | return major_status; |
147 | | |
148 | 0 | kerr_cleanup: |
149 | 0 | *minor_status = ret; |
150 | 0 | major_status = GSS_S_FAILURE; |
151 | 0 | goto cleanup; |
152 | 0 | } |
153 | | |
154 | | OM_uint32 KRB5_CALLCONV |
155 | | krb5_gss_store_cred(OM_uint32 *minor_status, |
156 | | gss_cred_id_t input_cred_handle, |
157 | | gss_cred_usage_t cred_usage, |
158 | | const gss_OID desired_mech, |
159 | | OM_uint32 overwrite_cred, |
160 | | OM_uint32 default_cred, |
161 | | gss_OID_set *elements_stored, |
162 | | gss_cred_usage_t *cred_usage_stored) |
163 | 0 | { |
164 | 0 | return krb5_gss_store_cred_into(minor_status, input_cred_handle, |
165 | 0 | cred_usage, desired_mech, |
166 | 0 | overwrite_cred, default_cred, |
167 | 0 | GSS_C_NO_CRED_STORE, |
168 | 0 | elements_stored, cred_usage_stored); |
169 | 0 | } |
170 | | |
171 | | OM_uint32 KRB5_CALLCONV |
172 | | krb5_gss_store_cred_into(OM_uint32 *minor_status, |
173 | | gss_cred_id_t input_cred_handle, |
174 | | gss_cred_usage_t cred_usage, |
175 | | const gss_OID desired_mech, |
176 | | OM_uint32 overwrite_cred, |
177 | | OM_uint32 default_cred, |
178 | | gss_const_key_value_set_t cred_store, |
179 | | gss_OID_set *elements_stored, |
180 | | gss_cred_usage_t *cred_usage_stored) |
181 | 0 | { |
182 | 0 | OM_uint32 major_status; |
183 | 0 | gss_cred_usage_t actual_usage; |
184 | 0 | OM_uint32 lifetime; |
185 | |
|
186 | 0 | if (input_cred_handle == GSS_C_NO_CREDENTIAL) |
187 | 0 | return GSS_S_NO_CRED; |
188 | | |
189 | 0 | major_status = GSS_S_FAILURE; |
190 | |
|
191 | 0 | if (cred_usage == GSS_C_ACCEPT) { |
192 | 0 | *minor_status = G_STORE_ACCEPTOR_CRED_NOSUPP; |
193 | 0 | return GSS_S_FAILURE; |
194 | 0 | } else if (cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { |
195 | 0 | *minor_status = G_BAD_USAGE; |
196 | 0 | return GSS_S_FAILURE; |
197 | 0 | } |
198 | | |
199 | 0 | major_status = krb5_gss_inquire_cred(minor_status, input_cred_handle, |
200 | 0 | NULL, &lifetime, |
201 | 0 | &actual_usage, elements_stored); |
202 | 0 | if (GSS_ERROR(major_status)) |
203 | 0 | return major_status; |
204 | | |
205 | 0 | if (lifetime == 0) |
206 | 0 | return GSS_S_CREDENTIALS_EXPIRED; |
207 | | |
208 | 0 | if (actual_usage != GSS_C_INITIATE && actual_usage != GSS_C_BOTH) { |
209 | 0 | *minor_status = G_STORE_ACCEPTOR_CRED_NOSUPP; |
210 | 0 | return GSS_S_FAILURE; |
211 | 0 | } |
212 | | |
213 | 0 | major_status = copy_initiator_creds(minor_status, input_cred_handle, |
214 | 0 | desired_mech, overwrite_cred, |
215 | 0 | default_cred, cred_store); |
216 | 0 | if (GSS_ERROR(major_status)) |
217 | 0 | return major_status; |
218 | | |
219 | 0 | if (cred_usage_stored != NULL) |
220 | 0 | *cred_usage_stored = GSS_C_INITIATE; |
221 | |
|
222 | 0 | return GSS_S_COMPLETE; |
223 | 0 | } |