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