1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson * All rights reserved.
5c19800e8SDoug Rabson *
6*ae771770SStanislav Sedov * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
7*ae771770SStanislav Sedov *
8c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without
9c19800e8SDoug Rabson * modification, are permitted provided that the following conditions
10c19800e8SDoug Rabson * are met:
11c19800e8SDoug Rabson *
12c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright
13c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer.
14c19800e8SDoug Rabson *
15c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
16c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the
17c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution.
18c19800e8SDoug Rabson *
19c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors
20c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software
21c19800e8SDoug Rabson * without specific prior written permission.
22c19800e8SDoug Rabson *
23c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33c19800e8SDoug Rabson * SUCH DAMAGE.
34c19800e8SDoug Rabson */
35c19800e8SDoug Rabson
36c19800e8SDoug Rabson #include "krb5_locl.h"
37c19800e8SDoug Rabson #include <krb5_ccapi.h>
38c19800e8SDoug Rabson #ifdef HAVE_DLFCN_H
39c19800e8SDoug Rabson #include <dlfcn.h>
40c19800e8SDoug Rabson #endif
41c19800e8SDoug Rabson
42*ae771770SStanislav Sedov #ifndef KCM_IS_API_CACHE
43c19800e8SDoug Rabson
44c19800e8SDoug Rabson static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
45c19800e8SDoug Rabson static cc_initialize_func init_func;
46*ae771770SStanislav Sedov static void (KRB5_CALLCONV *set_target_uid)(uid_t);
47*ae771770SStanislav Sedov static void (KRB5_CALLCONV *clear_target)(void);
48c19800e8SDoug Rabson
49c19800e8SDoug Rabson #ifdef HAVE_DLOPEN
50c19800e8SDoug Rabson static void *cc_handle;
51c19800e8SDoug Rabson #endif
52c19800e8SDoug Rabson
53c19800e8SDoug Rabson typedef struct krb5_acc {
54c19800e8SDoug Rabson char *cache_name;
55c19800e8SDoug Rabson cc_context_t context;
56c19800e8SDoug Rabson cc_ccache_t ccache;
57c19800e8SDoug Rabson } krb5_acc;
58c19800e8SDoug Rabson
59*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV acc_close(krb5_context, krb5_ccache);
60c19800e8SDoug Rabson
61c19800e8SDoug Rabson #define ACACHE(X) ((krb5_acc *)(X)->data.data)
62c19800e8SDoug Rabson
63c19800e8SDoug Rabson static const struct {
64c19800e8SDoug Rabson cc_int32 error;
65c19800e8SDoug Rabson krb5_error_code ret;
66c19800e8SDoug Rabson } cc_errors[] = {
67c19800e8SDoug Rabson { ccErrBadName, KRB5_CC_BADNAME },
68c19800e8SDoug Rabson { ccErrCredentialsNotFound, KRB5_CC_NOTFOUND },
69c19800e8SDoug Rabson { ccErrCCacheNotFound, KRB5_FCC_NOFILE },
70c19800e8SDoug Rabson { ccErrContextNotFound, KRB5_CC_NOTFOUND },
71c19800e8SDoug Rabson { ccIteratorEnd, KRB5_CC_END },
72c19800e8SDoug Rabson { ccErrNoMem, KRB5_CC_NOMEM },
73c19800e8SDoug Rabson { ccErrServerUnavailable, KRB5_CC_NOSUPP },
74*ae771770SStanislav Sedov { ccErrInvalidCCache, KRB5_CC_BADNAME },
75c19800e8SDoug Rabson { ccNoError, 0 }
76c19800e8SDoug Rabson };
77c19800e8SDoug Rabson
78c19800e8SDoug Rabson static krb5_error_code
translate_cc_error(krb5_context context,cc_int32 error)79c19800e8SDoug Rabson translate_cc_error(krb5_context context, cc_int32 error)
80c19800e8SDoug Rabson {
81*ae771770SStanislav Sedov size_t i;
82*ae771770SStanislav Sedov krb5_clear_error_message(context);
83c19800e8SDoug Rabson for(i = 0; i < sizeof(cc_errors)/sizeof(cc_errors[0]); i++)
84c19800e8SDoug Rabson if (cc_errors[i].error == error)
85c19800e8SDoug Rabson return cc_errors[i].ret;
86c19800e8SDoug Rabson return KRB5_FCC_INTERNAL;
87c19800e8SDoug Rabson }
88c19800e8SDoug Rabson
89c19800e8SDoug Rabson static krb5_error_code
init_ccapi(krb5_context context)90c19800e8SDoug Rabson init_ccapi(krb5_context context)
91c19800e8SDoug Rabson {
92*ae771770SStanislav Sedov const char *lib = NULL;
93c19800e8SDoug Rabson
94c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&acc_mutex);
95c19800e8SDoug Rabson if (init_func) {
96c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex);
97*ae771770SStanislav Sedov if (context)
98*ae771770SStanislav Sedov krb5_clear_error_message(context);
99c19800e8SDoug Rabson return 0;
100c19800e8SDoug Rabson }
101c19800e8SDoug Rabson
102*ae771770SStanislav Sedov if (context)
103c19800e8SDoug Rabson lib = krb5_config_get_string(context, NULL,
104c19800e8SDoug Rabson "libdefaults", "ccapi_library",
105c19800e8SDoug Rabson NULL);
106c19800e8SDoug Rabson if (lib == NULL) {
107c19800e8SDoug Rabson #ifdef __APPLE__
108c19800e8SDoug Rabson lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos";
109*ae771770SStanislav Sedov #elif defined(KRB5_USE_PATH_TOKENS) && defined(_WIN32)
110*ae771770SStanislav Sedov lib = "%{LIBDIR}/libkrb5_cc.dll";
111c19800e8SDoug Rabson #else
112c19800e8SDoug Rabson lib = "/usr/lib/libkrb5_cc.so";
113c19800e8SDoug Rabson #endif
114c19800e8SDoug Rabson }
115c19800e8SDoug Rabson
116c19800e8SDoug Rabson #ifdef HAVE_DLOPEN
117c19800e8SDoug Rabson
118c19800e8SDoug Rabson #ifndef RTLD_LAZY
119c19800e8SDoug Rabson #define RTLD_LAZY 0
120c19800e8SDoug Rabson #endif
121*ae771770SStanislav Sedov #ifndef RTLD_LOCAL
122*ae771770SStanislav Sedov #define RTLD_LOCAL 0
123*ae771770SStanislav Sedov #endif
124c19800e8SDoug Rabson
125*ae771770SStanislav Sedov #ifdef KRB5_USE_PATH_TOKENS
126*ae771770SStanislav Sedov {
127*ae771770SStanislav Sedov char * explib = NULL;
128*ae771770SStanislav Sedov if (_krb5_expand_path_tokens(context, lib, &explib) == 0) {
129*ae771770SStanislav Sedov cc_handle = dlopen(explib, RTLD_LAZY|RTLD_LOCAL);
130*ae771770SStanislav Sedov free(explib);
131*ae771770SStanislav Sedov }
132*ae771770SStanislav Sedov }
133*ae771770SStanislav Sedov #else
134*ae771770SStanislav Sedov cc_handle = dlopen(lib, RTLD_LAZY|RTLD_LOCAL);
135*ae771770SStanislav Sedov #endif
136*ae771770SStanislav Sedov
137c19800e8SDoug Rabson if (cc_handle == NULL) {
138c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex);
139*ae771770SStanislav Sedov if (context)
140*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOSUPP,
141*ae771770SStanislav Sedov N_("Failed to load API cache module %s", "file"),
142*ae771770SStanislav Sedov lib);
143c19800e8SDoug Rabson return KRB5_CC_NOSUPP;
144c19800e8SDoug Rabson }
145c19800e8SDoug Rabson
146c19800e8SDoug Rabson init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize");
147*ae771770SStanislav Sedov set_target_uid = (void (KRB5_CALLCONV *)(uid_t))
148*ae771770SStanislav Sedov dlsym(cc_handle, "krb5_ipc_client_set_target_uid");
149*ae771770SStanislav Sedov clear_target = (void (KRB5_CALLCONV *)(void))
150*ae771770SStanislav Sedov dlsym(cc_handle, "krb5_ipc_client_clear_target");
151c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex);
152c19800e8SDoug Rabson if (init_func == NULL) {
153*ae771770SStanislav Sedov if (context)
154*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOSUPP,
155*ae771770SStanislav Sedov N_("Failed to find cc_initialize"
156*ae771770SStanislav Sedov "in %s: %s", "file, error"), lib, dlerror());
157c19800e8SDoug Rabson dlclose(cc_handle);
158c19800e8SDoug Rabson return KRB5_CC_NOSUPP;
159c19800e8SDoug Rabson }
160c19800e8SDoug Rabson
161c19800e8SDoug Rabson return 0;
162c19800e8SDoug Rabson #else
163c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&acc_mutex);
164*ae771770SStanislav Sedov if (context)
165*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOSUPP,
166*ae771770SStanislav Sedov N_("no support for shared object", ""));
167c19800e8SDoug Rabson return KRB5_CC_NOSUPP;
168c19800e8SDoug Rabson #endif
169c19800e8SDoug Rabson }
170c19800e8SDoug Rabson
171*ae771770SStanislav Sedov void
_heim_krb5_ipc_client_set_target_uid(uid_t uid)172*ae771770SStanislav Sedov _heim_krb5_ipc_client_set_target_uid(uid_t uid)
173*ae771770SStanislav Sedov {
174*ae771770SStanislav Sedov init_ccapi(NULL);
175*ae771770SStanislav Sedov if (set_target_uid != NULL)
176*ae771770SStanislav Sedov (*set_target_uid)(uid);
177*ae771770SStanislav Sedov }
178*ae771770SStanislav Sedov
179*ae771770SStanislav Sedov void
_heim_krb5_ipc_client_clear_target(void)180*ae771770SStanislav Sedov _heim_krb5_ipc_client_clear_target(void)
181*ae771770SStanislav Sedov {
182*ae771770SStanislav Sedov init_ccapi(NULL);
183*ae771770SStanislav Sedov if (clear_target != NULL)
184*ae771770SStanislav Sedov (*clear_target)();
185*ae771770SStanislav Sedov }
186*ae771770SStanislav Sedov
187c19800e8SDoug Rabson static krb5_error_code
make_cred_from_ccred(krb5_context context,const cc_credentials_v5_t * incred,krb5_creds * cred)188c19800e8SDoug Rabson make_cred_from_ccred(krb5_context context,
189c19800e8SDoug Rabson const cc_credentials_v5_t *incred,
190c19800e8SDoug Rabson krb5_creds *cred)
191c19800e8SDoug Rabson {
192c19800e8SDoug Rabson krb5_error_code ret;
193*ae771770SStanislav Sedov unsigned int i;
194c19800e8SDoug Rabson
195c19800e8SDoug Rabson memset(cred, 0, sizeof(*cred));
196c19800e8SDoug Rabson
197c19800e8SDoug Rabson ret = krb5_parse_name(context, incred->client, &cred->client);
198c19800e8SDoug Rabson if (ret)
199c19800e8SDoug Rabson goto fail;
200c19800e8SDoug Rabson
201c19800e8SDoug Rabson ret = krb5_parse_name(context, incred->server, &cred->server);
202c19800e8SDoug Rabson if (ret)
203c19800e8SDoug Rabson goto fail;
204c19800e8SDoug Rabson
205c19800e8SDoug Rabson cred->session.keytype = incred->keyblock.type;
206c19800e8SDoug Rabson cred->session.keyvalue.length = incred->keyblock.length;
207c19800e8SDoug Rabson cred->session.keyvalue.data = malloc(incred->keyblock.length);
208c19800e8SDoug Rabson if (cred->session.keyvalue.data == NULL)
209c19800e8SDoug Rabson goto nomem;
210c19800e8SDoug Rabson memcpy(cred->session.keyvalue.data, incred->keyblock.data,
211c19800e8SDoug Rabson incred->keyblock.length);
212c19800e8SDoug Rabson
213c19800e8SDoug Rabson cred->times.authtime = incred->authtime;
214c19800e8SDoug Rabson cred->times.starttime = incred->starttime;
215c19800e8SDoug Rabson cred->times.endtime = incred->endtime;
216c19800e8SDoug Rabson cred->times.renew_till = incred->renew_till;
217c19800e8SDoug Rabson
218c19800e8SDoug Rabson ret = krb5_data_copy(&cred->ticket,
219c19800e8SDoug Rabson incred->ticket.data,
220c19800e8SDoug Rabson incred->ticket.length);
221c19800e8SDoug Rabson if (ret)
222c19800e8SDoug Rabson goto nomem;
223c19800e8SDoug Rabson
224c19800e8SDoug Rabson ret = krb5_data_copy(&cred->second_ticket,
225c19800e8SDoug Rabson incred->second_ticket.data,
226c19800e8SDoug Rabson incred->second_ticket.length);
227c19800e8SDoug Rabson if (ret)
228c19800e8SDoug Rabson goto nomem;
229c19800e8SDoug Rabson
230c19800e8SDoug Rabson cred->authdata.val = NULL;
231c19800e8SDoug Rabson cred->authdata.len = 0;
232c19800e8SDoug Rabson
233c19800e8SDoug Rabson cred->addresses.val = NULL;
234c19800e8SDoug Rabson cred->addresses.len = 0;
235c19800e8SDoug Rabson
236c19800e8SDoug Rabson for (i = 0; incred->authdata && incred->authdata[i]; i++)
237c19800e8SDoug Rabson ;
238c19800e8SDoug Rabson
239c19800e8SDoug Rabson if (i) {
240c19800e8SDoug Rabson cred->authdata.val = calloc(i, sizeof(cred->authdata.val[0]));
241c19800e8SDoug Rabson if (cred->authdata.val == NULL)
242c19800e8SDoug Rabson goto nomem;
243c19800e8SDoug Rabson cred->authdata.len = i;
244c19800e8SDoug Rabson for (i = 0; i < cred->authdata.len; i++) {
245c19800e8SDoug Rabson cred->authdata.val[i].ad_type = incred->authdata[i]->type;
246c19800e8SDoug Rabson ret = krb5_data_copy(&cred->authdata.val[i].ad_data,
247c19800e8SDoug Rabson incred->authdata[i]->data,
248c19800e8SDoug Rabson incred->authdata[i]->length);
249c19800e8SDoug Rabson if (ret)
250c19800e8SDoug Rabson goto nomem;
251c19800e8SDoug Rabson }
252c19800e8SDoug Rabson }
253c19800e8SDoug Rabson
254c19800e8SDoug Rabson for (i = 0; incred->addresses && incred->addresses[i]; i++)
255c19800e8SDoug Rabson ;
256c19800e8SDoug Rabson
257c19800e8SDoug Rabson if (i) {
258c19800e8SDoug Rabson cred->addresses.val = calloc(i, sizeof(cred->addresses.val[0]));
259c19800e8SDoug Rabson if (cred->addresses.val == NULL)
260c19800e8SDoug Rabson goto nomem;
261c19800e8SDoug Rabson cred->addresses.len = i;
262c19800e8SDoug Rabson
263c19800e8SDoug Rabson for (i = 0; i < cred->addresses.len; i++) {
264c19800e8SDoug Rabson cred->addresses.val[i].addr_type = incred->addresses[i]->type;
265c19800e8SDoug Rabson ret = krb5_data_copy(&cred->addresses.val[i].address,
266c19800e8SDoug Rabson incred->addresses[i]->data,
267c19800e8SDoug Rabson incred->addresses[i]->length);
268c19800e8SDoug Rabson if (ret)
269c19800e8SDoug Rabson goto nomem;
270c19800e8SDoug Rabson }
271c19800e8SDoug Rabson }
272c19800e8SDoug Rabson
273c19800e8SDoug Rabson cred->flags.i = 0;
274c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE)
275c19800e8SDoug Rabson cred->flags.b.forwardable = 1;
276c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED)
277c19800e8SDoug Rabson cred->flags.b.forwarded = 1;
278c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE)
279c19800e8SDoug Rabson cred->flags.b.proxiable = 1;
280c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY)
281c19800e8SDoug Rabson cred->flags.b.proxy = 1;
282c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE)
283c19800e8SDoug Rabson cred->flags.b.may_postdate = 1;
284c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED)
285c19800e8SDoug Rabson cred->flags.b.postdated = 1;
286c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID)
287c19800e8SDoug Rabson cred->flags.b.invalid = 1;
288c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE)
289c19800e8SDoug Rabson cred->flags.b.renewable = 1;
290c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL)
291c19800e8SDoug Rabson cred->flags.b.initial = 1;
292c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH)
293c19800e8SDoug Rabson cred->flags.b.pre_authent = 1;
294c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH)
295c19800e8SDoug Rabson cred->flags.b.hw_authent = 1;
296c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED)
297c19800e8SDoug Rabson cred->flags.b.transited_policy_checked = 1;
298c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE)
299c19800e8SDoug Rabson cred->flags.b.ok_as_delegate = 1;
300c19800e8SDoug Rabson if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS)
301c19800e8SDoug Rabson cred->flags.b.anonymous = 1;
302c19800e8SDoug Rabson
303c19800e8SDoug Rabson return 0;
304c19800e8SDoug Rabson
305c19800e8SDoug Rabson nomem:
306c19800e8SDoug Rabson ret = ENOMEM;
307*ae771770SStanislav Sedov krb5_set_error_message(context, ret, N_("malloc: out of memory", "malloc"));
308c19800e8SDoug Rabson
309c19800e8SDoug Rabson fail:
310c19800e8SDoug Rabson krb5_free_cred_contents(context, cred);
311c19800e8SDoug Rabson return ret;
312c19800e8SDoug Rabson }
313c19800e8SDoug Rabson
314c19800e8SDoug Rabson static void
free_ccred(cc_credentials_v5_t * cred)315c19800e8SDoug Rabson free_ccred(cc_credentials_v5_t *cred)
316c19800e8SDoug Rabson {
317c19800e8SDoug Rabson int i;
318c19800e8SDoug Rabson
319c19800e8SDoug Rabson if (cred->addresses) {
320c19800e8SDoug Rabson for (i = 0; cred->addresses[i] != 0; i++) {
321c19800e8SDoug Rabson if (cred->addresses[i]->data)
322c19800e8SDoug Rabson free(cred->addresses[i]->data);
323c19800e8SDoug Rabson free(cred->addresses[i]);
324c19800e8SDoug Rabson }
325c19800e8SDoug Rabson free(cred->addresses);
326c19800e8SDoug Rabson }
327c19800e8SDoug Rabson if (cred->server)
328c19800e8SDoug Rabson free(cred->server);
329c19800e8SDoug Rabson if (cred->client)
330c19800e8SDoug Rabson free(cred->client);
331c19800e8SDoug Rabson memset(cred, 0, sizeof(*cred));
332c19800e8SDoug Rabson }
333c19800e8SDoug Rabson
334c19800e8SDoug Rabson static krb5_error_code
make_ccred_from_cred(krb5_context context,const krb5_creds * incred,cc_credentials_v5_t * cred)335c19800e8SDoug Rabson make_ccred_from_cred(krb5_context context,
336c19800e8SDoug Rabson const krb5_creds *incred,
337c19800e8SDoug Rabson cc_credentials_v5_t *cred)
338c19800e8SDoug Rabson {
339c19800e8SDoug Rabson krb5_error_code ret;
340*ae771770SStanislav Sedov size_t i;
341c19800e8SDoug Rabson
342c19800e8SDoug Rabson memset(cred, 0, sizeof(*cred));
343c19800e8SDoug Rabson
344c19800e8SDoug Rabson ret = krb5_unparse_name(context, incred->client, &cred->client);
345c19800e8SDoug Rabson if (ret)
346c19800e8SDoug Rabson goto fail;
347c19800e8SDoug Rabson
348c19800e8SDoug Rabson ret = krb5_unparse_name(context, incred->server, &cred->server);
349c19800e8SDoug Rabson if (ret)
350c19800e8SDoug Rabson goto fail;
351c19800e8SDoug Rabson
352c19800e8SDoug Rabson cred->keyblock.type = incred->session.keytype;
353c19800e8SDoug Rabson cred->keyblock.length = incred->session.keyvalue.length;
354c19800e8SDoug Rabson cred->keyblock.data = incred->session.keyvalue.data;
355c19800e8SDoug Rabson
356c19800e8SDoug Rabson cred->authtime = incred->times.authtime;
357c19800e8SDoug Rabson cred->starttime = incred->times.starttime;
358c19800e8SDoug Rabson cred->endtime = incred->times.endtime;
359c19800e8SDoug Rabson cred->renew_till = incred->times.renew_till;
360c19800e8SDoug Rabson
361c19800e8SDoug Rabson cred->ticket.length = incred->ticket.length;
362c19800e8SDoug Rabson cred->ticket.data = incred->ticket.data;
363c19800e8SDoug Rabson
364c19800e8SDoug Rabson cred->second_ticket.length = incred->second_ticket.length;
365c19800e8SDoug Rabson cred->second_ticket.data = incred->second_ticket.data;
366c19800e8SDoug Rabson
367c19800e8SDoug Rabson /* XXX this one should also be filled in */
368c19800e8SDoug Rabson cred->authdata = NULL;
369c19800e8SDoug Rabson
370c19800e8SDoug Rabson cred->addresses = calloc(incred->addresses.len + 1,
371c19800e8SDoug Rabson sizeof(cred->addresses[0]));
372c19800e8SDoug Rabson if (cred->addresses == NULL) {
373c19800e8SDoug Rabson
374c19800e8SDoug Rabson ret = ENOMEM;
375c19800e8SDoug Rabson goto fail;
376c19800e8SDoug Rabson }
377c19800e8SDoug Rabson
378c19800e8SDoug Rabson for (i = 0; i < incred->addresses.len; i++) {
379c19800e8SDoug Rabson cc_data *addr;
380c19800e8SDoug Rabson addr = malloc(sizeof(*addr));
381c19800e8SDoug Rabson if (addr == NULL) {
382c19800e8SDoug Rabson ret = ENOMEM;
383c19800e8SDoug Rabson goto fail;
384c19800e8SDoug Rabson }
385c19800e8SDoug Rabson addr->type = incred->addresses.val[i].addr_type;
386c19800e8SDoug Rabson addr->length = incred->addresses.val[i].address.length;
387c19800e8SDoug Rabson addr->data = malloc(addr->length);
388c19800e8SDoug Rabson if (addr->data == NULL) {
389*ae771770SStanislav Sedov free(addr);
390c19800e8SDoug Rabson ret = ENOMEM;
391c19800e8SDoug Rabson goto fail;
392c19800e8SDoug Rabson }
393c19800e8SDoug Rabson memcpy(addr->data, incred->addresses.val[i].address.data,
394c19800e8SDoug Rabson addr->length);
395c19800e8SDoug Rabson cred->addresses[i] = addr;
396c19800e8SDoug Rabson }
397c19800e8SDoug Rabson cred->addresses[i] = NULL;
398c19800e8SDoug Rabson
399c19800e8SDoug Rabson cred->ticket_flags = 0;
400c19800e8SDoug Rabson if (incred->flags.b.forwardable)
401c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE;
402c19800e8SDoug Rabson if (incred->flags.b.forwarded)
403c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED;
404c19800e8SDoug Rabson if (incred->flags.b.proxiable)
405c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE;
406c19800e8SDoug Rabson if (incred->flags.b.proxy)
407c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY;
408c19800e8SDoug Rabson if (incred->flags.b.may_postdate)
409c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE;
410c19800e8SDoug Rabson if (incred->flags.b.postdated)
411c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED;
412c19800e8SDoug Rabson if (incred->flags.b.invalid)
413c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID;
414c19800e8SDoug Rabson if (incred->flags.b.renewable)
415c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE;
416c19800e8SDoug Rabson if (incred->flags.b.initial)
417c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL;
418c19800e8SDoug Rabson if (incred->flags.b.pre_authent)
419c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH;
420c19800e8SDoug Rabson if (incred->flags.b.hw_authent)
421c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH;
422c19800e8SDoug Rabson if (incred->flags.b.transited_policy_checked)
423c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED;
424c19800e8SDoug Rabson if (incred->flags.b.ok_as_delegate)
425c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE;
426c19800e8SDoug Rabson if (incred->flags.b.anonymous)
427c19800e8SDoug Rabson cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS;
428c19800e8SDoug Rabson
429c19800e8SDoug Rabson return 0;
430c19800e8SDoug Rabson
431c19800e8SDoug Rabson fail:
432c19800e8SDoug Rabson free_ccred(cred);
433c19800e8SDoug Rabson
434*ae771770SStanislav Sedov krb5_clear_error_message(context);
435c19800e8SDoug Rabson return ret;
436c19800e8SDoug Rabson }
437c19800e8SDoug Rabson
438*ae771770SStanislav Sedov static cc_int32
get_cc_name(krb5_acc * a)439*ae771770SStanislav Sedov get_cc_name(krb5_acc *a)
440c19800e8SDoug Rabson {
441c19800e8SDoug Rabson cc_string_t name;
442c19800e8SDoug Rabson cc_int32 error;
443c19800e8SDoug Rabson
444*ae771770SStanislav Sedov error = (*a->ccache->func->get_name)(a->ccache, &name);
445c19800e8SDoug Rabson if (error)
446*ae771770SStanislav Sedov return error;
447c19800e8SDoug Rabson
448*ae771770SStanislav Sedov a->cache_name = strdup(name->data);
449c19800e8SDoug Rabson (*name->func->release)(name);
450*ae771770SStanislav Sedov if (a->cache_name == NULL)
451*ae771770SStanislav Sedov return ccErrNoMem;
452*ae771770SStanislav Sedov return ccNoError;
453c19800e8SDoug Rabson }
454c19800e8SDoug Rabson
455c19800e8SDoug Rabson
456*ae771770SStanislav Sedov static const char* KRB5_CALLCONV
acc_get_name(krb5_context context,krb5_ccache id)457c19800e8SDoug Rabson acc_get_name(krb5_context context,
458c19800e8SDoug Rabson krb5_ccache id)
459c19800e8SDoug Rabson {
460c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
461*ae771770SStanislav Sedov int32_t error;
462*ae771770SStanislav Sedov
463*ae771770SStanislav Sedov if (a->cache_name == NULL) {
464*ae771770SStanislav Sedov krb5_error_code ret;
465*ae771770SStanislav Sedov krb5_principal principal;
466c19800e8SDoug Rabson char *name;
467c19800e8SDoug Rabson
468*ae771770SStanislav Sedov ret = _krb5_get_default_principal_local(context, &principal);
469*ae771770SStanislav Sedov if (ret)
470*ae771770SStanislav Sedov return NULL;
471*ae771770SStanislav Sedov
472*ae771770SStanislav Sedov ret = krb5_unparse_name(context, principal, &name);
473*ae771770SStanislav Sedov krb5_free_principal(context, principal);
474*ae771770SStanislav Sedov if (ret)
475*ae771770SStanislav Sedov return NULL;
476*ae771770SStanislav Sedov
477*ae771770SStanislav Sedov error = (*a->context->func->create_new_ccache)(a->context,
478*ae771770SStanislav Sedov cc_credentials_v5,
479*ae771770SStanislav Sedov name,
480*ae771770SStanislav Sedov &a->ccache);
481*ae771770SStanislav Sedov krb5_xfree(name);
482*ae771770SStanislav Sedov if (error)
483*ae771770SStanislav Sedov return NULL;
484*ae771770SStanislav Sedov
485*ae771770SStanislav Sedov error = get_cc_name(a);
486*ae771770SStanislav Sedov if (error)
487c19800e8SDoug Rabson return NULL;
488c19800e8SDoug Rabson }
489*ae771770SStanislav Sedov
490*ae771770SStanislav Sedov return a->cache_name;
491c19800e8SDoug Rabson }
492c19800e8SDoug Rabson
493*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_alloc(krb5_context context,krb5_ccache * id)494c19800e8SDoug Rabson acc_alloc(krb5_context context, krb5_ccache *id)
495c19800e8SDoug Rabson {
496c19800e8SDoug Rabson krb5_error_code ret;
497c19800e8SDoug Rabson cc_int32 error;
498c19800e8SDoug Rabson krb5_acc *a;
499c19800e8SDoug Rabson
500c19800e8SDoug Rabson ret = init_ccapi(context);
501c19800e8SDoug Rabson if (ret)
502c19800e8SDoug Rabson return ret;
503c19800e8SDoug Rabson
504c19800e8SDoug Rabson ret = krb5_data_alloc(&(*id)->data, sizeof(*a));
505c19800e8SDoug Rabson if (ret) {
506*ae771770SStanislav Sedov krb5_clear_error_message(context);
507c19800e8SDoug Rabson return ret;
508c19800e8SDoug Rabson }
509c19800e8SDoug Rabson
510c19800e8SDoug Rabson a = ACACHE(*id);
511c19800e8SDoug Rabson
512c19800e8SDoug Rabson error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL);
513c19800e8SDoug Rabson if (error) {
514c19800e8SDoug Rabson krb5_data_free(&(*id)->data);
515c19800e8SDoug Rabson return translate_cc_error(context, error);
516c19800e8SDoug Rabson }
517c19800e8SDoug Rabson
518c19800e8SDoug Rabson a->cache_name = NULL;
519c19800e8SDoug Rabson
520c19800e8SDoug Rabson return 0;
521c19800e8SDoug Rabson }
522c19800e8SDoug Rabson
523*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_resolve(krb5_context context,krb5_ccache * id,const char * res)524c19800e8SDoug Rabson acc_resolve(krb5_context context, krb5_ccache *id, const char *res)
525c19800e8SDoug Rabson {
526c19800e8SDoug Rabson krb5_error_code ret;
527c19800e8SDoug Rabson cc_int32 error;
528c19800e8SDoug Rabson krb5_acc *a;
529c19800e8SDoug Rabson
530c19800e8SDoug Rabson ret = acc_alloc(context, id);
531c19800e8SDoug Rabson if (ret)
532c19800e8SDoug Rabson return ret;
533c19800e8SDoug Rabson
534c19800e8SDoug Rabson a = ACACHE(*id);
535c19800e8SDoug Rabson
536*ae771770SStanislav Sedov error = (*a->context->func->open_ccache)(a->context, res, &a->ccache);
537*ae771770SStanislav Sedov if (error == ccNoError) {
538*ae771770SStanislav Sedov cc_time_t offset;
539*ae771770SStanislav Sedov error = get_cc_name(a);
540*ae771770SStanislav Sedov if (error != ccNoError) {
541c19800e8SDoug Rabson acc_close(context, *id);
542c19800e8SDoug Rabson *id = NULL;
543*ae771770SStanislav Sedov return translate_cc_error(context, error);
544c19800e8SDoug Rabson }
545*ae771770SStanislav Sedov
546*ae771770SStanislav Sedov error = (*a->ccache->func->get_kdc_time_offset)(a->ccache,
547*ae771770SStanislav Sedov cc_credentials_v5,
548*ae771770SStanislav Sedov &offset);
549*ae771770SStanislav Sedov if (error == 0)
550*ae771770SStanislav Sedov context->kdc_sec_offset = offset;
551*ae771770SStanislav Sedov
552c19800e8SDoug Rabson } else if (error == ccErrCCacheNotFound) {
553c19800e8SDoug Rabson a->ccache = NULL;
554c19800e8SDoug Rabson a->cache_name = NULL;
555c19800e8SDoug Rabson } else {
556c19800e8SDoug Rabson *id = NULL;
557c19800e8SDoug Rabson return translate_cc_error(context, error);
558c19800e8SDoug Rabson }
559c19800e8SDoug Rabson
560c19800e8SDoug Rabson return 0;
561c19800e8SDoug Rabson }
562c19800e8SDoug Rabson
563*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_gen_new(krb5_context context,krb5_ccache * id)564c19800e8SDoug Rabson acc_gen_new(krb5_context context, krb5_ccache *id)
565c19800e8SDoug Rabson {
566c19800e8SDoug Rabson krb5_error_code ret;
567c19800e8SDoug Rabson krb5_acc *a;
568c19800e8SDoug Rabson
569c19800e8SDoug Rabson ret = acc_alloc(context, id);
570c19800e8SDoug Rabson if (ret)
571c19800e8SDoug Rabson return ret;
572c19800e8SDoug Rabson
573c19800e8SDoug Rabson a = ACACHE(*id);
574c19800e8SDoug Rabson
575c19800e8SDoug Rabson a->ccache = NULL;
576c19800e8SDoug Rabson a->cache_name = NULL;
577c19800e8SDoug Rabson
578c19800e8SDoug Rabson return 0;
579c19800e8SDoug Rabson }
580c19800e8SDoug Rabson
581*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_initialize(krb5_context context,krb5_ccache id,krb5_principal primary_principal)582c19800e8SDoug Rabson acc_initialize(krb5_context context,
583c19800e8SDoug Rabson krb5_ccache id,
584c19800e8SDoug Rabson krb5_principal primary_principal)
585c19800e8SDoug Rabson {
586c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
587c19800e8SDoug Rabson krb5_error_code ret;
588c19800e8SDoug Rabson int32_t error;
589c19800e8SDoug Rabson char *name;
590c19800e8SDoug Rabson
591c19800e8SDoug Rabson ret = krb5_unparse_name(context, primary_principal, &name);
592c19800e8SDoug Rabson if (ret)
593c19800e8SDoug Rabson return ret;
594c19800e8SDoug Rabson
595*ae771770SStanislav Sedov if (a->cache_name == NULL) {
596c19800e8SDoug Rabson error = (*a->context->func->create_new_ccache)(a->context,
597c19800e8SDoug Rabson cc_credentials_v5,
598c19800e8SDoug Rabson name,
599c19800e8SDoug Rabson &a->ccache);
600c19800e8SDoug Rabson free(name);
601*ae771770SStanislav Sedov if (error == ccNoError)
602*ae771770SStanislav Sedov error = get_cc_name(a);
603*ae771770SStanislav Sedov } else {
604*ae771770SStanislav Sedov cc_credentials_iterator_t iter;
605*ae771770SStanislav Sedov cc_credentials_t ccred;
606*ae771770SStanislav Sedov
607*ae771770SStanislav Sedov error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
608*ae771770SStanislav Sedov if (error) {
609*ae771770SStanislav Sedov free(name);
610*ae771770SStanislav Sedov return translate_cc_error(context, error);
611*ae771770SStanislav Sedov }
612*ae771770SStanislav Sedov
613*ae771770SStanislav Sedov while (1) {
614*ae771770SStanislav Sedov error = (*iter->func->next)(iter, &ccred);
615*ae771770SStanislav Sedov if (error)
616*ae771770SStanislav Sedov break;
617*ae771770SStanislav Sedov (*a->ccache->func->remove_credentials)(a->ccache, ccred);
618*ae771770SStanislav Sedov (*ccred->func->release)(ccred);
619*ae771770SStanislav Sedov }
620*ae771770SStanislav Sedov (*iter->func->release)(iter);
621*ae771770SStanislav Sedov
622*ae771770SStanislav Sedov error = (*a->ccache->func->set_principal)(a->ccache,
623*ae771770SStanislav Sedov cc_credentials_v5,
624*ae771770SStanislav Sedov name);
625*ae771770SStanislav Sedov }
626*ae771770SStanislav Sedov
627*ae771770SStanislav Sedov if (error == 0 && context->kdc_sec_offset)
628*ae771770SStanislav Sedov error = (*a->ccache->func->set_kdc_time_offset)(a->ccache,
629*ae771770SStanislav Sedov cc_credentials_v5,
630*ae771770SStanislav Sedov context->kdc_sec_offset);
631c19800e8SDoug Rabson
632c19800e8SDoug Rabson return translate_cc_error(context, error);
633c19800e8SDoug Rabson }
634c19800e8SDoug Rabson
635*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_close(krb5_context context,krb5_ccache id)636c19800e8SDoug Rabson acc_close(krb5_context context,
637c19800e8SDoug Rabson krb5_ccache id)
638c19800e8SDoug Rabson {
639c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
640c19800e8SDoug Rabson
641c19800e8SDoug Rabson if (a->ccache) {
642c19800e8SDoug Rabson (*a->ccache->func->release)(a->ccache);
643c19800e8SDoug Rabson a->ccache = NULL;
644c19800e8SDoug Rabson }
645c19800e8SDoug Rabson if (a->cache_name) {
646c19800e8SDoug Rabson free(a->cache_name);
647c19800e8SDoug Rabson a->cache_name = NULL;
648c19800e8SDoug Rabson }
649*ae771770SStanislav Sedov if (a->context) {
650c19800e8SDoug Rabson (*a->context->func->release)(a->context);
651c19800e8SDoug Rabson a->context = NULL;
652*ae771770SStanislav Sedov }
653c19800e8SDoug Rabson krb5_data_free(&id->data);
654c19800e8SDoug Rabson return 0;
655c19800e8SDoug Rabson }
656c19800e8SDoug Rabson
657*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_destroy(krb5_context context,krb5_ccache id)658c19800e8SDoug Rabson acc_destroy(krb5_context context,
659c19800e8SDoug Rabson krb5_ccache id)
660c19800e8SDoug Rabson {
661c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
662c19800e8SDoug Rabson cc_int32 error = 0;
663c19800e8SDoug Rabson
664c19800e8SDoug Rabson if (a->ccache) {
665c19800e8SDoug Rabson error = (*a->ccache->func->destroy)(a->ccache);
666c19800e8SDoug Rabson a->ccache = NULL;
667c19800e8SDoug Rabson }
668c19800e8SDoug Rabson if (a->context) {
669c19800e8SDoug Rabson error = (a->context->func->release)(a->context);
670c19800e8SDoug Rabson a->context = NULL;
671c19800e8SDoug Rabson }
672c19800e8SDoug Rabson return translate_cc_error(context, error);
673c19800e8SDoug Rabson }
674c19800e8SDoug Rabson
675*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_store_cred(krb5_context context,krb5_ccache id,krb5_creds * creds)676c19800e8SDoug Rabson acc_store_cred(krb5_context context,
677c19800e8SDoug Rabson krb5_ccache id,
678c19800e8SDoug Rabson krb5_creds *creds)
679c19800e8SDoug Rabson {
680c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
681c19800e8SDoug Rabson cc_credentials_union cred;
682c19800e8SDoug Rabson cc_credentials_v5_t v5cred;
683c19800e8SDoug Rabson krb5_error_code ret;
684c19800e8SDoug Rabson cc_int32 error;
685c19800e8SDoug Rabson
686c19800e8SDoug Rabson if (a->ccache == NULL) {
687*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOTFOUND,
688*ae771770SStanislav Sedov N_("No API credential found", ""));
689c19800e8SDoug Rabson return KRB5_CC_NOTFOUND;
690c19800e8SDoug Rabson }
691c19800e8SDoug Rabson
692c19800e8SDoug Rabson cred.version = cc_credentials_v5;
693c19800e8SDoug Rabson cred.credentials.credentials_v5 = &v5cred;
694c19800e8SDoug Rabson
695c19800e8SDoug Rabson ret = make_ccred_from_cred(context,
696c19800e8SDoug Rabson creds,
697c19800e8SDoug Rabson &v5cred);
698c19800e8SDoug Rabson if (ret)
699c19800e8SDoug Rabson return ret;
700c19800e8SDoug Rabson
701c19800e8SDoug Rabson error = (*a->ccache->func->store_credentials)(a->ccache, &cred);
702c19800e8SDoug Rabson if (error)
703c19800e8SDoug Rabson ret = translate_cc_error(context, error);
704c19800e8SDoug Rabson
705c19800e8SDoug Rabson free_ccred(&v5cred);
706c19800e8SDoug Rabson
707c19800e8SDoug Rabson return ret;
708c19800e8SDoug Rabson }
709c19800e8SDoug Rabson
710*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_get_principal(krb5_context context,krb5_ccache id,krb5_principal * principal)711c19800e8SDoug Rabson acc_get_principal(krb5_context context,
712c19800e8SDoug Rabson krb5_ccache id,
713c19800e8SDoug Rabson krb5_principal *principal)
714c19800e8SDoug Rabson {
715c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
716c19800e8SDoug Rabson krb5_error_code ret;
717c19800e8SDoug Rabson int32_t error;
718c19800e8SDoug Rabson cc_string_t name;
719c19800e8SDoug Rabson
720c19800e8SDoug Rabson if (a->ccache == NULL) {
721*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOTFOUND,
722*ae771770SStanislav Sedov N_("No API credential found", ""));
723c19800e8SDoug Rabson return KRB5_CC_NOTFOUND;
724c19800e8SDoug Rabson }
725c19800e8SDoug Rabson
726c19800e8SDoug Rabson error = (*a->ccache->func->get_principal)(a->ccache,
727c19800e8SDoug Rabson cc_credentials_v5,
728c19800e8SDoug Rabson &name);
729c19800e8SDoug Rabson if (error)
730c19800e8SDoug Rabson return translate_cc_error(context, error);
731c19800e8SDoug Rabson
732c19800e8SDoug Rabson ret = krb5_parse_name(context, name->data, principal);
733c19800e8SDoug Rabson
734c19800e8SDoug Rabson (*name->func->release)(name);
735c19800e8SDoug Rabson return ret;
736c19800e8SDoug Rabson }
737c19800e8SDoug Rabson
738*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_get_first(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)739c19800e8SDoug Rabson acc_get_first (krb5_context context,
740c19800e8SDoug Rabson krb5_ccache id,
741c19800e8SDoug Rabson krb5_cc_cursor *cursor)
742c19800e8SDoug Rabson {
743c19800e8SDoug Rabson cc_credentials_iterator_t iter;
744c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
745c19800e8SDoug Rabson int32_t error;
746c19800e8SDoug Rabson
747c19800e8SDoug Rabson if (a->ccache == NULL) {
748*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOTFOUND,
749*ae771770SStanislav Sedov N_("No API credential found", ""));
750c19800e8SDoug Rabson return KRB5_CC_NOTFOUND;
751c19800e8SDoug Rabson }
752c19800e8SDoug Rabson
753c19800e8SDoug Rabson error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
754c19800e8SDoug Rabson if (error) {
755*ae771770SStanislav Sedov krb5_clear_error_message(context);
756c19800e8SDoug Rabson return ENOENT;
757c19800e8SDoug Rabson }
758c19800e8SDoug Rabson *cursor = iter;
759c19800e8SDoug Rabson return 0;
760c19800e8SDoug Rabson }
761c19800e8SDoug Rabson
762c19800e8SDoug Rabson
763*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_get_next(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor,krb5_creds * creds)764c19800e8SDoug Rabson acc_get_next (krb5_context context,
765c19800e8SDoug Rabson krb5_ccache id,
766c19800e8SDoug Rabson krb5_cc_cursor *cursor,
767c19800e8SDoug Rabson krb5_creds *creds)
768c19800e8SDoug Rabson {
769c19800e8SDoug Rabson cc_credentials_iterator_t iter = *cursor;
770c19800e8SDoug Rabson cc_credentials_t cred;
771c19800e8SDoug Rabson krb5_error_code ret;
772c19800e8SDoug Rabson int32_t error;
773c19800e8SDoug Rabson
774c19800e8SDoug Rabson while (1) {
775c19800e8SDoug Rabson error = (*iter->func->next)(iter, &cred);
776c19800e8SDoug Rabson if (error)
777c19800e8SDoug Rabson return translate_cc_error(context, error);
778c19800e8SDoug Rabson if (cred->data->version == cc_credentials_v5)
779c19800e8SDoug Rabson break;
780c19800e8SDoug Rabson (*cred->func->release)(cred);
781c19800e8SDoug Rabson }
782c19800e8SDoug Rabson
783c19800e8SDoug Rabson ret = make_cred_from_ccred(context,
784c19800e8SDoug Rabson cred->data->credentials.credentials_v5,
785c19800e8SDoug Rabson creds);
786c19800e8SDoug Rabson (*cred->func->release)(cred);
787c19800e8SDoug Rabson return ret;
788c19800e8SDoug Rabson }
789c19800e8SDoug Rabson
790*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_end_get(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)791c19800e8SDoug Rabson acc_end_get (krb5_context context,
792c19800e8SDoug Rabson krb5_ccache id,
793c19800e8SDoug Rabson krb5_cc_cursor *cursor)
794c19800e8SDoug Rabson {
795c19800e8SDoug Rabson cc_credentials_iterator_t iter = *cursor;
796c19800e8SDoug Rabson (*iter->func->release)(iter);
797c19800e8SDoug Rabson return 0;
798c19800e8SDoug Rabson }
799c19800e8SDoug Rabson
800*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_remove_cred(krb5_context context,krb5_ccache id,krb5_flags which,krb5_creds * cred)801c19800e8SDoug Rabson acc_remove_cred(krb5_context context,
802c19800e8SDoug Rabson krb5_ccache id,
803c19800e8SDoug Rabson krb5_flags which,
804c19800e8SDoug Rabson krb5_creds *cred)
805c19800e8SDoug Rabson {
806c19800e8SDoug Rabson cc_credentials_iterator_t iter;
807c19800e8SDoug Rabson krb5_acc *a = ACACHE(id);
808c19800e8SDoug Rabson cc_credentials_t ccred;
809c19800e8SDoug Rabson krb5_error_code ret;
810c19800e8SDoug Rabson cc_int32 error;
811c19800e8SDoug Rabson char *client, *server;
812c19800e8SDoug Rabson
813c19800e8SDoug Rabson if (a->ccache == NULL) {
814*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOTFOUND,
815*ae771770SStanislav Sedov N_("No API credential found", ""));
816c19800e8SDoug Rabson return KRB5_CC_NOTFOUND;
817c19800e8SDoug Rabson }
818c19800e8SDoug Rabson
819c19800e8SDoug Rabson if (cred->client) {
820c19800e8SDoug Rabson ret = krb5_unparse_name(context, cred->client, &client);
821c19800e8SDoug Rabson if (ret)
822c19800e8SDoug Rabson return ret;
823c19800e8SDoug Rabson } else
824c19800e8SDoug Rabson client = NULL;
825c19800e8SDoug Rabson
826c19800e8SDoug Rabson ret = krb5_unparse_name(context, cred->server, &server);
827c19800e8SDoug Rabson if (ret) {
828c19800e8SDoug Rabson free(client);
829c19800e8SDoug Rabson return ret;
830c19800e8SDoug Rabson }
831c19800e8SDoug Rabson
832c19800e8SDoug Rabson error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
833c19800e8SDoug Rabson if (error) {
834c19800e8SDoug Rabson free(server);
835c19800e8SDoug Rabson free(client);
836c19800e8SDoug Rabson return translate_cc_error(context, error);
837c19800e8SDoug Rabson }
838c19800e8SDoug Rabson
839c19800e8SDoug Rabson ret = KRB5_CC_NOTFOUND;
840c19800e8SDoug Rabson while (1) {
841c19800e8SDoug Rabson cc_credentials_v5_t *v5cred;
842c19800e8SDoug Rabson
843c19800e8SDoug Rabson error = (*iter->func->next)(iter, &ccred);
844c19800e8SDoug Rabson if (error)
845c19800e8SDoug Rabson break;
846c19800e8SDoug Rabson
847c19800e8SDoug Rabson if (ccred->data->version != cc_credentials_v5)
848c19800e8SDoug Rabson goto next;
849c19800e8SDoug Rabson
850c19800e8SDoug Rabson v5cred = ccred->data->credentials.credentials_v5;
851c19800e8SDoug Rabson
852c19800e8SDoug Rabson if (client && strcmp(v5cred->client, client) != 0)
853c19800e8SDoug Rabson goto next;
854c19800e8SDoug Rabson
855c19800e8SDoug Rabson if (strcmp(v5cred->server, server) != 0)
856c19800e8SDoug Rabson goto next;
857c19800e8SDoug Rabson
858c19800e8SDoug Rabson (*a->ccache->func->remove_credentials)(a->ccache, ccred);
859c19800e8SDoug Rabson ret = 0;
860c19800e8SDoug Rabson next:
861c19800e8SDoug Rabson (*ccred->func->release)(ccred);
862c19800e8SDoug Rabson }
863c19800e8SDoug Rabson
864c19800e8SDoug Rabson (*iter->func->release)(iter);
865c19800e8SDoug Rabson
866c19800e8SDoug Rabson if (ret)
867*ae771770SStanislav Sedov krb5_set_error_message(context, ret,
868*ae771770SStanislav Sedov N_("Can't find credential %s in cache",
869*ae771770SStanislav Sedov "principal"), server);
870c19800e8SDoug Rabson free(server);
871c19800e8SDoug Rabson free(client);
872c19800e8SDoug Rabson
873c19800e8SDoug Rabson return ret;
874c19800e8SDoug Rabson }
875c19800e8SDoug Rabson
876*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_set_flags(krb5_context context,krb5_ccache id,krb5_flags flags)877c19800e8SDoug Rabson acc_set_flags(krb5_context context,
878c19800e8SDoug Rabson krb5_ccache id,
879c19800e8SDoug Rabson krb5_flags flags)
880c19800e8SDoug Rabson {
881c19800e8SDoug Rabson return 0;
882c19800e8SDoug Rabson }
883c19800e8SDoug Rabson
884*ae771770SStanislav Sedov static int KRB5_CALLCONV
acc_get_version(krb5_context context,krb5_ccache id)885c19800e8SDoug Rabson acc_get_version(krb5_context context,
886c19800e8SDoug Rabson krb5_ccache id)
887c19800e8SDoug Rabson {
888c19800e8SDoug Rabson return 0;
889c19800e8SDoug Rabson }
890c19800e8SDoug Rabson
891c19800e8SDoug Rabson struct cache_iter {
892c19800e8SDoug Rabson cc_context_t context;
893c19800e8SDoug Rabson cc_ccache_iterator_t iter;
894c19800e8SDoug Rabson };
895c19800e8SDoug Rabson
896*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_get_cache_first(krb5_context context,krb5_cc_cursor * cursor)897c19800e8SDoug Rabson acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
898c19800e8SDoug Rabson {
899c19800e8SDoug Rabson struct cache_iter *iter;
900c19800e8SDoug Rabson krb5_error_code ret;
901c19800e8SDoug Rabson cc_int32 error;
902c19800e8SDoug Rabson
903c19800e8SDoug Rabson ret = init_ccapi(context);
904c19800e8SDoug Rabson if (ret)
905c19800e8SDoug Rabson return ret;
906c19800e8SDoug Rabson
907c19800e8SDoug Rabson iter = calloc(1, sizeof(*iter));
908c19800e8SDoug Rabson if (iter == NULL) {
909*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
910c19800e8SDoug Rabson return ENOMEM;
911c19800e8SDoug Rabson }
912c19800e8SDoug Rabson
913c19800e8SDoug Rabson error = (*init_func)(&iter->context, ccapi_version_3, NULL, NULL);
914c19800e8SDoug Rabson if (error) {
915c19800e8SDoug Rabson free(iter);
916c19800e8SDoug Rabson return translate_cc_error(context, error);
917c19800e8SDoug Rabson }
918c19800e8SDoug Rabson
919c19800e8SDoug Rabson error = (*iter->context->func->new_ccache_iterator)(iter->context,
920c19800e8SDoug Rabson &iter->iter);
921c19800e8SDoug Rabson if (error) {
922c19800e8SDoug Rabson free(iter);
923*ae771770SStanislav Sedov krb5_clear_error_message(context);
924c19800e8SDoug Rabson return ENOENT;
925c19800e8SDoug Rabson }
926c19800e8SDoug Rabson *cursor = iter;
927c19800e8SDoug Rabson return 0;
928c19800e8SDoug Rabson }
929c19800e8SDoug Rabson
930*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_get_cache_next(krb5_context context,krb5_cc_cursor cursor,krb5_ccache * id)931c19800e8SDoug Rabson acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
932c19800e8SDoug Rabson {
933c19800e8SDoug Rabson struct cache_iter *iter = cursor;
934c19800e8SDoug Rabson cc_ccache_t cache;
935c19800e8SDoug Rabson krb5_acc *a;
936c19800e8SDoug Rabson krb5_error_code ret;
937c19800e8SDoug Rabson int32_t error;
938c19800e8SDoug Rabson
939c19800e8SDoug Rabson error = (*iter->iter->func->next)(iter->iter, &cache);
940c19800e8SDoug Rabson if (error)
941c19800e8SDoug Rabson return translate_cc_error(context, error);
942c19800e8SDoug Rabson
943c19800e8SDoug Rabson ret = _krb5_cc_allocate(context, &krb5_acc_ops, id);
944c19800e8SDoug Rabson if (ret) {
945c19800e8SDoug Rabson (*cache->func->release)(cache);
946c19800e8SDoug Rabson return ret;
947c19800e8SDoug Rabson }
948c19800e8SDoug Rabson
949c19800e8SDoug Rabson ret = acc_alloc(context, id);
950c19800e8SDoug Rabson if (ret) {
951c19800e8SDoug Rabson (*cache->func->release)(cache);
952c19800e8SDoug Rabson free(*id);
953c19800e8SDoug Rabson return ret;
954c19800e8SDoug Rabson }
955c19800e8SDoug Rabson
956c19800e8SDoug Rabson a = ACACHE(*id);
957c19800e8SDoug Rabson a->ccache = cache;
958c19800e8SDoug Rabson
959*ae771770SStanislav Sedov error = get_cc_name(a);
960*ae771770SStanislav Sedov if (error) {
961c19800e8SDoug Rabson acc_close(context, *id);
962c19800e8SDoug Rabson *id = NULL;
963*ae771770SStanislav Sedov return translate_cc_error(context, error);
964c19800e8SDoug Rabson }
965c19800e8SDoug Rabson return 0;
966c19800e8SDoug Rabson }
967c19800e8SDoug Rabson
968*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_end_cache_get(krb5_context context,krb5_cc_cursor cursor)969c19800e8SDoug Rabson acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
970c19800e8SDoug Rabson {
971c19800e8SDoug Rabson struct cache_iter *iter = cursor;
972c19800e8SDoug Rabson
973c19800e8SDoug Rabson (*iter->iter->func->release)(iter->iter);
974c19800e8SDoug Rabson iter->iter = NULL;
975c19800e8SDoug Rabson (*iter->context->func->release)(iter->context);
976c19800e8SDoug Rabson iter->context = NULL;
977c19800e8SDoug Rabson free(iter);
978c19800e8SDoug Rabson return 0;
979c19800e8SDoug Rabson }
980c19800e8SDoug Rabson
981*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_move(krb5_context context,krb5_ccache from,krb5_ccache to)982c19800e8SDoug Rabson acc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
983c19800e8SDoug Rabson {
984c19800e8SDoug Rabson krb5_acc *afrom = ACACHE(from);
985c19800e8SDoug Rabson krb5_acc *ato = ACACHE(to);
986c19800e8SDoug Rabson int32_t error;
987c19800e8SDoug Rabson
988c19800e8SDoug Rabson if (ato->ccache == NULL) {
989c19800e8SDoug Rabson cc_string_t name;
990c19800e8SDoug Rabson
991c19800e8SDoug Rabson error = (*afrom->ccache->func->get_principal)(afrom->ccache,
992c19800e8SDoug Rabson cc_credentials_v5,
993c19800e8SDoug Rabson &name);
994c19800e8SDoug Rabson if (error)
995c19800e8SDoug Rabson return translate_cc_error(context, error);
996c19800e8SDoug Rabson
997c19800e8SDoug Rabson error = (*ato->context->func->create_new_ccache)(ato->context,
998c19800e8SDoug Rabson cc_credentials_v5,
999c19800e8SDoug Rabson name->data,
1000c19800e8SDoug Rabson &ato->ccache);
1001c19800e8SDoug Rabson (*name->func->release)(name);
1002c19800e8SDoug Rabson if (error)
1003c19800e8SDoug Rabson return translate_cc_error(context, error);
1004c19800e8SDoug Rabson }
1005c19800e8SDoug Rabson
1006c19800e8SDoug Rabson error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache);
1007*ae771770SStanislav Sedov
1008*ae771770SStanislav Sedov acc_destroy(context, from);
1009*ae771770SStanislav Sedov
1010c19800e8SDoug Rabson return translate_cc_error(context, error);
1011c19800e8SDoug Rabson }
1012c19800e8SDoug Rabson
1013*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_get_default_name(krb5_context context,char ** str)1014*ae771770SStanislav Sedov acc_get_default_name(krb5_context context, char **str)
1015c19800e8SDoug Rabson {
1016c19800e8SDoug Rabson krb5_error_code ret;
1017c19800e8SDoug Rabson cc_context_t cc;
1018c19800e8SDoug Rabson cc_string_t name;
1019c19800e8SDoug Rabson int32_t error;
1020c19800e8SDoug Rabson
1021c19800e8SDoug Rabson ret = init_ccapi(context);
1022c19800e8SDoug Rabson if (ret)
1023c19800e8SDoug Rabson return ret;
1024c19800e8SDoug Rabson
1025c19800e8SDoug Rabson error = (*init_func)(&cc, ccapi_version_3, NULL, NULL);
1026c19800e8SDoug Rabson if (error)
1027c19800e8SDoug Rabson return translate_cc_error(context, error);
1028c19800e8SDoug Rabson
1029c19800e8SDoug Rabson error = (*cc->func->get_default_ccache_name)(cc, &name);
1030c19800e8SDoug Rabson if (error) {
1031c19800e8SDoug Rabson (*cc->func->release)(cc);
1032c19800e8SDoug Rabson return translate_cc_error(context, error);
1033c19800e8SDoug Rabson }
1034c19800e8SDoug Rabson
1035*ae771770SStanislav Sedov error = asprintf(str, "API:%s", name->data);
1036c19800e8SDoug Rabson (*name->func->release)(name);
1037c19800e8SDoug Rabson (*cc->func->release)(cc);
1038c19800e8SDoug Rabson
1039*ae771770SStanislav Sedov if (error < 0 || *str == NULL) {
1040*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1041c19800e8SDoug Rabson return ENOMEM;
1042c19800e8SDoug Rabson }
1043c19800e8SDoug Rabson return 0;
1044c19800e8SDoug Rabson }
1045c19800e8SDoug Rabson
1046*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_set_default(krb5_context context,krb5_ccache id)1047*ae771770SStanislav Sedov acc_set_default(krb5_context context, krb5_ccache id)
1048*ae771770SStanislav Sedov {
1049*ae771770SStanislav Sedov krb5_acc *a = ACACHE(id);
1050*ae771770SStanislav Sedov cc_int32 error;
1051*ae771770SStanislav Sedov
1052*ae771770SStanislav Sedov if (a->ccache == NULL) {
1053*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOTFOUND,
1054*ae771770SStanislav Sedov N_("No API credential found", ""));
1055*ae771770SStanislav Sedov return KRB5_CC_NOTFOUND;
1056*ae771770SStanislav Sedov }
1057*ae771770SStanislav Sedov
1058*ae771770SStanislav Sedov error = (*a->ccache->func->set_default)(a->ccache);
1059*ae771770SStanislav Sedov if (error)
1060*ae771770SStanislav Sedov return translate_cc_error(context, error);
1061*ae771770SStanislav Sedov
1062*ae771770SStanislav Sedov return 0;
1063*ae771770SStanislav Sedov }
1064*ae771770SStanislav Sedov
1065*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
acc_lastchange(krb5_context context,krb5_ccache id,krb5_timestamp * mtime)1066*ae771770SStanislav Sedov acc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
1067*ae771770SStanislav Sedov {
1068*ae771770SStanislav Sedov krb5_acc *a = ACACHE(id);
1069*ae771770SStanislav Sedov cc_int32 error;
1070*ae771770SStanislav Sedov cc_time_t t;
1071*ae771770SStanislav Sedov
1072*ae771770SStanislav Sedov if (a->ccache == NULL) {
1073*ae771770SStanislav Sedov krb5_set_error_message(context, KRB5_CC_NOTFOUND,
1074*ae771770SStanislav Sedov N_("No API credential found", ""));
1075*ae771770SStanislav Sedov return KRB5_CC_NOTFOUND;
1076*ae771770SStanislav Sedov }
1077*ae771770SStanislav Sedov
1078*ae771770SStanislav Sedov error = (*a->ccache->func->get_change_time)(a->ccache, &t);
1079*ae771770SStanislav Sedov if (error)
1080*ae771770SStanislav Sedov return translate_cc_error(context, error);
1081*ae771770SStanislav Sedov
1082*ae771770SStanislav Sedov *mtime = t;
1083*ae771770SStanislav Sedov
1084*ae771770SStanislav Sedov return 0;
1085*ae771770SStanislav Sedov }
1086c19800e8SDoug Rabson
1087c19800e8SDoug Rabson /**
1088c19800e8SDoug Rabson * Variable containing the API based credential cache implemention.
1089c19800e8SDoug Rabson *
1090c19800e8SDoug Rabson * @ingroup krb5_ccache
1091c19800e8SDoug Rabson */
1092c19800e8SDoug Rabson
1093*ae771770SStanislav Sedov KRB5_LIB_VARIABLE const krb5_cc_ops krb5_acc_ops = {
1094*ae771770SStanislav Sedov KRB5_CC_OPS_VERSION,
1095c19800e8SDoug Rabson "API",
1096c19800e8SDoug Rabson acc_get_name,
1097c19800e8SDoug Rabson acc_resolve,
1098c19800e8SDoug Rabson acc_gen_new,
1099c19800e8SDoug Rabson acc_initialize,
1100c19800e8SDoug Rabson acc_destroy,
1101c19800e8SDoug Rabson acc_close,
1102c19800e8SDoug Rabson acc_store_cred,
1103c19800e8SDoug Rabson NULL, /* acc_retrieve */
1104c19800e8SDoug Rabson acc_get_principal,
1105c19800e8SDoug Rabson acc_get_first,
1106c19800e8SDoug Rabson acc_get_next,
1107c19800e8SDoug Rabson acc_end_get,
1108c19800e8SDoug Rabson acc_remove_cred,
1109c19800e8SDoug Rabson acc_set_flags,
1110c19800e8SDoug Rabson acc_get_version,
1111c19800e8SDoug Rabson acc_get_cache_first,
1112c19800e8SDoug Rabson acc_get_cache_next,
1113c19800e8SDoug Rabson acc_end_cache_get,
1114c19800e8SDoug Rabson acc_move,
1115*ae771770SStanislav Sedov acc_get_default_name,
1116*ae771770SStanislav Sedov acc_set_default,
1117*ae771770SStanislav Sedov acc_lastchange,
1118*ae771770SStanislav Sedov NULL,
1119*ae771770SStanislav Sedov NULL,
1120c19800e8SDoug Rabson };
1121*ae771770SStanislav Sedov
1122*ae771770SStanislav Sedov #endif
1123