1*0a6a1f1dSLionel Sambuc /* $NetBSD: mcache.c,v 1.1.1.2 2014/04/24 12:45:50 pettai Exp $ */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc * All rights reserved.
7ebfedea0SLionel Sambuc *
8ebfedea0SLionel Sambuc * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
9ebfedea0SLionel Sambuc *
10ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
11ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
12ebfedea0SLionel Sambuc * are met:
13ebfedea0SLionel Sambuc *
14ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
15ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
16ebfedea0SLionel Sambuc *
17ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
18ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
19ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
20ebfedea0SLionel Sambuc *
21ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
22ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
23ebfedea0SLionel Sambuc * without specific prior written permission.
24ebfedea0SLionel Sambuc *
25ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35ebfedea0SLionel Sambuc * SUCH DAMAGE.
36ebfedea0SLionel Sambuc */
37ebfedea0SLionel Sambuc
38ebfedea0SLionel Sambuc #include "krb5_locl.h"
39ebfedea0SLionel Sambuc
40ebfedea0SLionel Sambuc typedef struct krb5_mcache {
41ebfedea0SLionel Sambuc char *name;
42ebfedea0SLionel Sambuc unsigned int refcnt;
43ebfedea0SLionel Sambuc int dead;
44ebfedea0SLionel Sambuc krb5_principal primary_principal;
45ebfedea0SLionel Sambuc struct link {
46ebfedea0SLionel Sambuc krb5_creds cred;
47ebfedea0SLionel Sambuc struct link *next;
48ebfedea0SLionel Sambuc } *creds;
49ebfedea0SLionel Sambuc struct krb5_mcache *next;
50ebfedea0SLionel Sambuc time_t mtime;
51ebfedea0SLionel Sambuc krb5_deltat kdc_offset;
52ebfedea0SLionel Sambuc } krb5_mcache;
53ebfedea0SLionel Sambuc
54ebfedea0SLionel Sambuc static HEIMDAL_MUTEX mcc_mutex = HEIMDAL_MUTEX_INITIALIZER;
55ebfedea0SLionel Sambuc static struct krb5_mcache *mcc_head;
56ebfedea0SLionel Sambuc
57ebfedea0SLionel Sambuc #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
58ebfedea0SLionel Sambuc
59ebfedea0SLionel Sambuc #define MISDEAD(X) ((X)->dead)
60ebfedea0SLionel Sambuc
61ebfedea0SLionel Sambuc static const char* KRB5_CALLCONV
mcc_get_name(krb5_context context,krb5_ccache id)62ebfedea0SLionel Sambuc mcc_get_name(krb5_context context,
63ebfedea0SLionel Sambuc krb5_ccache id)
64ebfedea0SLionel Sambuc {
65ebfedea0SLionel Sambuc return MCACHE(id)->name;
66ebfedea0SLionel Sambuc }
67ebfedea0SLionel Sambuc
68ebfedea0SLionel Sambuc static krb5_mcache * KRB5_CALLCONV
mcc_alloc(const char * name)69ebfedea0SLionel Sambuc mcc_alloc(const char *name)
70ebfedea0SLionel Sambuc {
71ebfedea0SLionel Sambuc krb5_mcache *m, *m_c;
72ebfedea0SLionel Sambuc int ret = 0;
73ebfedea0SLionel Sambuc
74ebfedea0SLionel Sambuc ALLOC(m, 1);
75ebfedea0SLionel Sambuc if(m == NULL)
76ebfedea0SLionel Sambuc return NULL;
77ebfedea0SLionel Sambuc if(name == NULL)
78ebfedea0SLionel Sambuc ret = asprintf(&m->name, "%p", m);
79ebfedea0SLionel Sambuc else
80ebfedea0SLionel Sambuc m->name = strdup(name);
81ebfedea0SLionel Sambuc if(ret < 0 || m->name == NULL) {
82ebfedea0SLionel Sambuc free(m);
83ebfedea0SLionel Sambuc return NULL;
84ebfedea0SLionel Sambuc }
85ebfedea0SLionel Sambuc /* check for dups first */
86ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&mcc_mutex);
87ebfedea0SLionel Sambuc for (m_c = mcc_head; m_c != NULL; m_c = m_c->next)
88ebfedea0SLionel Sambuc if (strcmp(m->name, m_c->name) == 0)
89ebfedea0SLionel Sambuc break;
90ebfedea0SLionel Sambuc if (m_c) {
91ebfedea0SLionel Sambuc free(m->name);
92ebfedea0SLionel Sambuc free(m);
93ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&mcc_mutex);
94ebfedea0SLionel Sambuc return NULL;
95ebfedea0SLionel Sambuc }
96ebfedea0SLionel Sambuc
97ebfedea0SLionel Sambuc m->dead = 0;
98ebfedea0SLionel Sambuc m->refcnt = 1;
99ebfedea0SLionel Sambuc m->primary_principal = NULL;
100ebfedea0SLionel Sambuc m->creds = NULL;
101ebfedea0SLionel Sambuc m->mtime = time(NULL);
102ebfedea0SLionel Sambuc m->kdc_offset = 0;
103ebfedea0SLionel Sambuc m->next = mcc_head;
104ebfedea0SLionel Sambuc mcc_head = m;
105ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&mcc_mutex);
106ebfedea0SLionel Sambuc return m;
107ebfedea0SLionel Sambuc }
108ebfedea0SLionel Sambuc
109ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_resolve(krb5_context context,krb5_ccache * id,const char * res)110ebfedea0SLionel Sambuc mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
111ebfedea0SLionel Sambuc {
112ebfedea0SLionel Sambuc krb5_mcache *m;
113ebfedea0SLionel Sambuc
114ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&mcc_mutex);
115ebfedea0SLionel Sambuc for (m = mcc_head; m != NULL; m = m->next)
116ebfedea0SLionel Sambuc if (strcmp(m->name, res) == 0)
117ebfedea0SLionel Sambuc break;
118ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&mcc_mutex);
119ebfedea0SLionel Sambuc
120ebfedea0SLionel Sambuc if (m != NULL) {
121ebfedea0SLionel Sambuc m->refcnt++;
122ebfedea0SLionel Sambuc (*id)->data.data = m;
123ebfedea0SLionel Sambuc (*id)->data.length = sizeof(*m);
124ebfedea0SLionel Sambuc return 0;
125ebfedea0SLionel Sambuc }
126ebfedea0SLionel Sambuc
127ebfedea0SLionel Sambuc m = mcc_alloc(res);
128ebfedea0SLionel Sambuc if (m == NULL) {
129ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_CC_NOMEM,
130ebfedea0SLionel Sambuc N_("malloc: out of memory", ""));
131ebfedea0SLionel Sambuc return KRB5_CC_NOMEM;
132ebfedea0SLionel Sambuc }
133ebfedea0SLionel Sambuc
134ebfedea0SLionel Sambuc (*id)->data.data = m;
135ebfedea0SLionel Sambuc (*id)->data.length = sizeof(*m);
136ebfedea0SLionel Sambuc
137ebfedea0SLionel Sambuc return 0;
138ebfedea0SLionel Sambuc }
139ebfedea0SLionel Sambuc
140ebfedea0SLionel Sambuc
141ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_gen_new(krb5_context context,krb5_ccache * id)142ebfedea0SLionel Sambuc mcc_gen_new(krb5_context context, krb5_ccache *id)
143ebfedea0SLionel Sambuc {
144ebfedea0SLionel Sambuc krb5_mcache *m;
145ebfedea0SLionel Sambuc
146ebfedea0SLionel Sambuc m = mcc_alloc(NULL);
147ebfedea0SLionel Sambuc
148ebfedea0SLionel Sambuc if (m == NULL) {
149ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_CC_NOMEM,
150ebfedea0SLionel Sambuc N_("malloc: out of memory", ""));
151ebfedea0SLionel Sambuc return KRB5_CC_NOMEM;
152ebfedea0SLionel Sambuc }
153ebfedea0SLionel Sambuc
154ebfedea0SLionel Sambuc (*id)->data.data = m;
155ebfedea0SLionel Sambuc (*id)->data.length = sizeof(*m);
156ebfedea0SLionel Sambuc
157ebfedea0SLionel Sambuc return 0;
158ebfedea0SLionel Sambuc }
159ebfedea0SLionel Sambuc
160ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_initialize(krb5_context context,krb5_ccache id,krb5_principal primary_principal)161ebfedea0SLionel Sambuc mcc_initialize(krb5_context context,
162ebfedea0SLionel Sambuc krb5_ccache id,
163ebfedea0SLionel Sambuc krb5_principal primary_principal)
164ebfedea0SLionel Sambuc {
165ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
166ebfedea0SLionel Sambuc m->dead = 0;
167ebfedea0SLionel Sambuc m->mtime = time(NULL);
168ebfedea0SLionel Sambuc return krb5_copy_principal (context,
169ebfedea0SLionel Sambuc primary_principal,
170ebfedea0SLionel Sambuc &m->primary_principal);
171ebfedea0SLionel Sambuc }
172ebfedea0SLionel Sambuc
173ebfedea0SLionel Sambuc static int
mcc_close_internal(krb5_mcache * m)174ebfedea0SLionel Sambuc mcc_close_internal(krb5_mcache *m)
175ebfedea0SLionel Sambuc {
176ebfedea0SLionel Sambuc if (--m->refcnt != 0)
177ebfedea0SLionel Sambuc return 0;
178ebfedea0SLionel Sambuc
179ebfedea0SLionel Sambuc if (MISDEAD(m)) {
180ebfedea0SLionel Sambuc free (m->name);
181ebfedea0SLionel Sambuc return 1;
182ebfedea0SLionel Sambuc }
183ebfedea0SLionel Sambuc return 0;
184ebfedea0SLionel Sambuc }
185ebfedea0SLionel Sambuc
186ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_close(krb5_context context,krb5_ccache id)187ebfedea0SLionel Sambuc mcc_close(krb5_context context,
188ebfedea0SLionel Sambuc krb5_ccache id)
189ebfedea0SLionel Sambuc {
190ebfedea0SLionel Sambuc if (mcc_close_internal(MCACHE(id)))
191ebfedea0SLionel Sambuc krb5_data_free(&id->data);
192ebfedea0SLionel Sambuc return 0;
193ebfedea0SLionel Sambuc }
194ebfedea0SLionel Sambuc
195ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_destroy(krb5_context context,krb5_ccache id)196ebfedea0SLionel Sambuc mcc_destroy(krb5_context context,
197ebfedea0SLionel Sambuc krb5_ccache id)
198ebfedea0SLionel Sambuc {
199ebfedea0SLionel Sambuc krb5_mcache **n, *m = MCACHE(id);
200ebfedea0SLionel Sambuc struct link *l;
201ebfedea0SLionel Sambuc
202ebfedea0SLionel Sambuc if (m->refcnt == 0)
203ebfedea0SLionel Sambuc krb5_abortx(context, "mcc_destroy: refcnt already 0");
204ebfedea0SLionel Sambuc
205ebfedea0SLionel Sambuc if (!MISDEAD(m)) {
206ebfedea0SLionel Sambuc /* if this is an active mcache, remove it from the linked
207ebfedea0SLionel Sambuc list, and free all data */
208ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&mcc_mutex);
209ebfedea0SLionel Sambuc for(n = &mcc_head; n && *n; n = &(*n)->next) {
210ebfedea0SLionel Sambuc if(m == *n) {
211ebfedea0SLionel Sambuc *n = m->next;
212ebfedea0SLionel Sambuc break;
213ebfedea0SLionel Sambuc }
214ebfedea0SLionel Sambuc }
215ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&mcc_mutex);
216ebfedea0SLionel Sambuc if (m->primary_principal != NULL) {
217ebfedea0SLionel Sambuc krb5_free_principal (context, m->primary_principal);
218ebfedea0SLionel Sambuc m->primary_principal = NULL;
219ebfedea0SLionel Sambuc }
220ebfedea0SLionel Sambuc m->dead = 1;
221ebfedea0SLionel Sambuc
222ebfedea0SLionel Sambuc l = m->creds;
223ebfedea0SLionel Sambuc while (l != NULL) {
224ebfedea0SLionel Sambuc struct link *old;
225ebfedea0SLionel Sambuc
226ebfedea0SLionel Sambuc krb5_free_cred_contents (context, &l->cred);
227ebfedea0SLionel Sambuc old = l;
228ebfedea0SLionel Sambuc l = l->next;
229ebfedea0SLionel Sambuc free (old);
230ebfedea0SLionel Sambuc }
231ebfedea0SLionel Sambuc m->creds = NULL;
232ebfedea0SLionel Sambuc }
233ebfedea0SLionel Sambuc return 0;
234ebfedea0SLionel Sambuc }
235ebfedea0SLionel Sambuc
236ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_store_cred(krb5_context context,krb5_ccache id,krb5_creds * creds)237ebfedea0SLionel Sambuc mcc_store_cred(krb5_context context,
238ebfedea0SLionel Sambuc krb5_ccache id,
239ebfedea0SLionel Sambuc krb5_creds *creds)
240ebfedea0SLionel Sambuc {
241ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
242ebfedea0SLionel Sambuc krb5_error_code ret;
243ebfedea0SLionel Sambuc struct link *l;
244ebfedea0SLionel Sambuc
245ebfedea0SLionel Sambuc if (MISDEAD(m))
246ebfedea0SLionel Sambuc return ENOENT;
247ebfedea0SLionel Sambuc
248ebfedea0SLionel Sambuc l = malloc (sizeof(*l));
249ebfedea0SLionel Sambuc if (l == NULL) {
250ebfedea0SLionel Sambuc krb5_set_error_message(context, KRB5_CC_NOMEM,
251ebfedea0SLionel Sambuc N_("malloc: out of memory", ""));
252ebfedea0SLionel Sambuc return KRB5_CC_NOMEM;
253ebfedea0SLionel Sambuc }
254ebfedea0SLionel Sambuc l->next = m->creds;
255ebfedea0SLionel Sambuc m->creds = l;
256ebfedea0SLionel Sambuc memset (&l->cred, 0, sizeof(l->cred));
257ebfedea0SLionel Sambuc ret = krb5_copy_creds_contents (context, creds, &l->cred);
258ebfedea0SLionel Sambuc if (ret) {
259ebfedea0SLionel Sambuc m->creds = l->next;
260ebfedea0SLionel Sambuc free (l);
261ebfedea0SLionel Sambuc return ret;
262ebfedea0SLionel Sambuc }
263ebfedea0SLionel Sambuc m->mtime = time(NULL);
264ebfedea0SLionel Sambuc return 0;
265ebfedea0SLionel Sambuc }
266ebfedea0SLionel Sambuc
267ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_get_principal(krb5_context context,krb5_ccache id,krb5_principal * principal)268ebfedea0SLionel Sambuc mcc_get_principal(krb5_context context,
269ebfedea0SLionel Sambuc krb5_ccache id,
270ebfedea0SLionel Sambuc krb5_principal *principal)
271ebfedea0SLionel Sambuc {
272ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
273ebfedea0SLionel Sambuc
274ebfedea0SLionel Sambuc if (MISDEAD(m) || m->primary_principal == NULL)
275ebfedea0SLionel Sambuc return ENOENT;
276ebfedea0SLionel Sambuc return krb5_copy_principal (context,
277ebfedea0SLionel Sambuc m->primary_principal,
278ebfedea0SLionel Sambuc principal);
279ebfedea0SLionel Sambuc }
280ebfedea0SLionel Sambuc
281ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_get_first(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)282ebfedea0SLionel Sambuc mcc_get_first (krb5_context context,
283ebfedea0SLionel Sambuc krb5_ccache id,
284ebfedea0SLionel Sambuc krb5_cc_cursor *cursor)
285ebfedea0SLionel Sambuc {
286ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
287ebfedea0SLionel Sambuc
288ebfedea0SLionel Sambuc if (MISDEAD(m))
289ebfedea0SLionel Sambuc return ENOENT;
290ebfedea0SLionel Sambuc
291ebfedea0SLionel Sambuc *cursor = m->creds;
292ebfedea0SLionel Sambuc return 0;
293ebfedea0SLionel Sambuc }
294ebfedea0SLionel Sambuc
295ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_get_next(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor,krb5_creds * creds)296ebfedea0SLionel Sambuc mcc_get_next (krb5_context context,
297ebfedea0SLionel Sambuc krb5_ccache id,
298ebfedea0SLionel Sambuc krb5_cc_cursor *cursor,
299ebfedea0SLionel Sambuc krb5_creds *creds)
300ebfedea0SLionel Sambuc {
301ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
302ebfedea0SLionel Sambuc struct link *l;
303ebfedea0SLionel Sambuc
304ebfedea0SLionel Sambuc if (MISDEAD(m))
305ebfedea0SLionel Sambuc return ENOENT;
306ebfedea0SLionel Sambuc
307ebfedea0SLionel Sambuc l = *cursor;
308ebfedea0SLionel Sambuc if (l != NULL) {
309ebfedea0SLionel Sambuc *cursor = l->next;
310ebfedea0SLionel Sambuc return krb5_copy_creds_contents (context,
311ebfedea0SLionel Sambuc &l->cred,
312ebfedea0SLionel Sambuc creds);
313ebfedea0SLionel Sambuc } else
314ebfedea0SLionel Sambuc return KRB5_CC_END;
315ebfedea0SLionel Sambuc }
316ebfedea0SLionel Sambuc
317ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_end_get(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)318ebfedea0SLionel Sambuc mcc_end_get (krb5_context context,
319ebfedea0SLionel Sambuc krb5_ccache id,
320ebfedea0SLionel Sambuc krb5_cc_cursor *cursor)
321ebfedea0SLionel Sambuc {
322ebfedea0SLionel Sambuc return 0;
323ebfedea0SLionel Sambuc }
324ebfedea0SLionel Sambuc
325ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_remove_cred(krb5_context context,krb5_ccache id,krb5_flags which,krb5_creds * mcreds)326ebfedea0SLionel Sambuc mcc_remove_cred(krb5_context context,
327ebfedea0SLionel Sambuc krb5_ccache id,
328ebfedea0SLionel Sambuc krb5_flags which,
329ebfedea0SLionel Sambuc krb5_creds *mcreds)
330ebfedea0SLionel Sambuc {
331ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
332ebfedea0SLionel Sambuc struct link **q, *p;
333ebfedea0SLionel Sambuc for(q = &m->creds, p = *q; p; p = *q) {
334ebfedea0SLionel Sambuc if(krb5_compare_creds(context, which, mcreds, &p->cred)) {
335ebfedea0SLionel Sambuc *q = p->next;
336ebfedea0SLionel Sambuc krb5_free_cred_contents(context, &p->cred);
337ebfedea0SLionel Sambuc free(p);
338ebfedea0SLionel Sambuc m->mtime = time(NULL);
339ebfedea0SLionel Sambuc } else
340ebfedea0SLionel Sambuc q = &p->next;
341ebfedea0SLionel Sambuc }
342ebfedea0SLionel Sambuc return 0;
343ebfedea0SLionel Sambuc }
344ebfedea0SLionel Sambuc
345ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_set_flags(krb5_context context,krb5_ccache id,krb5_flags flags)346ebfedea0SLionel Sambuc mcc_set_flags(krb5_context context,
347ebfedea0SLionel Sambuc krb5_ccache id,
348ebfedea0SLionel Sambuc krb5_flags flags)
349ebfedea0SLionel Sambuc {
350ebfedea0SLionel Sambuc return 0; /* XXX */
351ebfedea0SLionel Sambuc }
352ebfedea0SLionel Sambuc
353ebfedea0SLionel Sambuc struct mcache_iter {
354ebfedea0SLionel Sambuc krb5_mcache *cache;
355ebfedea0SLionel Sambuc };
356ebfedea0SLionel Sambuc
357ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_get_cache_first(krb5_context context,krb5_cc_cursor * cursor)358ebfedea0SLionel Sambuc mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
359ebfedea0SLionel Sambuc {
360ebfedea0SLionel Sambuc struct mcache_iter *iter;
361ebfedea0SLionel Sambuc
362ebfedea0SLionel Sambuc iter = calloc(1, sizeof(*iter));
363ebfedea0SLionel Sambuc if (iter == NULL) {
364ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM,
365ebfedea0SLionel Sambuc N_("malloc: out of memory", ""));
366ebfedea0SLionel Sambuc return ENOMEM;
367ebfedea0SLionel Sambuc }
368ebfedea0SLionel Sambuc
369ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&mcc_mutex);
370ebfedea0SLionel Sambuc iter->cache = mcc_head;
371ebfedea0SLionel Sambuc if (iter->cache)
372ebfedea0SLionel Sambuc iter->cache->refcnt++;
373ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&mcc_mutex);
374ebfedea0SLionel Sambuc
375ebfedea0SLionel Sambuc *cursor = iter;
376ebfedea0SLionel Sambuc return 0;
377ebfedea0SLionel Sambuc }
378ebfedea0SLionel Sambuc
379ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_get_cache_next(krb5_context context,krb5_cc_cursor cursor,krb5_ccache * id)380ebfedea0SLionel Sambuc mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
381ebfedea0SLionel Sambuc {
382ebfedea0SLionel Sambuc struct mcache_iter *iter = cursor;
383ebfedea0SLionel Sambuc krb5_error_code ret;
384ebfedea0SLionel Sambuc krb5_mcache *m;
385ebfedea0SLionel Sambuc
386ebfedea0SLionel Sambuc if (iter->cache == NULL)
387ebfedea0SLionel Sambuc return KRB5_CC_END;
388ebfedea0SLionel Sambuc
389ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&mcc_mutex);
390ebfedea0SLionel Sambuc m = iter->cache;
391ebfedea0SLionel Sambuc if (m->next)
392ebfedea0SLionel Sambuc m->next->refcnt++;
393ebfedea0SLionel Sambuc iter->cache = m->next;
394ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&mcc_mutex);
395ebfedea0SLionel Sambuc
396ebfedea0SLionel Sambuc ret = _krb5_cc_allocate(context, &krb5_mcc_ops, id);
397ebfedea0SLionel Sambuc if (ret)
398ebfedea0SLionel Sambuc return ret;
399ebfedea0SLionel Sambuc
400ebfedea0SLionel Sambuc (*id)->data.data = m;
401ebfedea0SLionel Sambuc (*id)->data.length = sizeof(*m);
402ebfedea0SLionel Sambuc
403ebfedea0SLionel Sambuc return 0;
404ebfedea0SLionel Sambuc }
405ebfedea0SLionel Sambuc
406ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_end_cache_get(krb5_context context,krb5_cc_cursor cursor)407ebfedea0SLionel Sambuc mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
408ebfedea0SLionel Sambuc {
409ebfedea0SLionel Sambuc struct mcache_iter *iter = cursor;
410ebfedea0SLionel Sambuc
411ebfedea0SLionel Sambuc if (iter->cache)
412ebfedea0SLionel Sambuc mcc_close_internal(iter->cache);
413ebfedea0SLionel Sambuc iter->cache = NULL;
414ebfedea0SLionel Sambuc free(iter);
415ebfedea0SLionel Sambuc return 0;
416ebfedea0SLionel Sambuc }
417ebfedea0SLionel Sambuc
418ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_move(krb5_context context,krb5_ccache from,krb5_ccache to)419ebfedea0SLionel Sambuc mcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
420ebfedea0SLionel Sambuc {
421ebfedea0SLionel Sambuc krb5_mcache *mfrom = MCACHE(from), *mto = MCACHE(to);
422ebfedea0SLionel Sambuc struct link *creds;
423ebfedea0SLionel Sambuc krb5_principal principal;
424ebfedea0SLionel Sambuc krb5_mcache **n;
425ebfedea0SLionel Sambuc
426ebfedea0SLionel Sambuc HEIMDAL_MUTEX_lock(&mcc_mutex);
427ebfedea0SLionel Sambuc
428ebfedea0SLionel Sambuc /* drop the from cache from the linked list to avoid lookups */
429ebfedea0SLionel Sambuc for(n = &mcc_head; n && *n; n = &(*n)->next) {
430ebfedea0SLionel Sambuc if(mfrom == *n) {
431ebfedea0SLionel Sambuc *n = mfrom->next;
432ebfedea0SLionel Sambuc break;
433ebfedea0SLionel Sambuc }
434ebfedea0SLionel Sambuc }
435ebfedea0SLionel Sambuc
436ebfedea0SLionel Sambuc /* swap creds */
437ebfedea0SLionel Sambuc creds = mto->creds;
438ebfedea0SLionel Sambuc mto->creds = mfrom->creds;
439ebfedea0SLionel Sambuc mfrom->creds = creds;
440ebfedea0SLionel Sambuc /* swap principal */
441ebfedea0SLionel Sambuc principal = mto->primary_principal;
442ebfedea0SLionel Sambuc mto->primary_principal = mfrom->primary_principal;
443ebfedea0SLionel Sambuc mfrom->primary_principal = principal;
444ebfedea0SLionel Sambuc
445ebfedea0SLionel Sambuc mto->mtime = mfrom->mtime = time(NULL);
446ebfedea0SLionel Sambuc
447ebfedea0SLionel Sambuc HEIMDAL_MUTEX_unlock(&mcc_mutex);
448ebfedea0SLionel Sambuc mcc_destroy(context, from);
449ebfedea0SLionel Sambuc
450ebfedea0SLionel Sambuc return 0;
451ebfedea0SLionel Sambuc }
452ebfedea0SLionel Sambuc
453ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_default_name(krb5_context context,char ** str)454ebfedea0SLionel Sambuc mcc_default_name(krb5_context context, char **str)
455ebfedea0SLionel Sambuc {
456ebfedea0SLionel Sambuc *str = strdup("MEMORY:");
457ebfedea0SLionel Sambuc if (*str == NULL) {
458ebfedea0SLionel Sambuc krb5_set_error_message(context, ENOMEM,
459ebfedea0SLionel Sambuc N_("malloc: out of memory", ""));
460ebfedea0SLionel Sambuc return ENOMEM;
461ebfedea0SLionel Sambuc }
462ebfedea0SLionel Sambuc return 0;
463ebfedea0SLionel Sambuc }
464ebfedea0SLionel Sambuc
465ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_lastchange(krb5_context context,krb5_ccache id,krb5_timestamp * mtime)466ebfedea0SLionel Sambuc mcc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
467ebfedea0SLionel Sambuc {
468ebfedea0SLionel Sambuc *mtime = MCACHE(id)->mtime;
469ebfedea0SLionel Sambuc return 0;
470ebfedea0SLionel Sambuc }
471ebfedea0SLionel Sambuc
472ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_set_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat kdc_offset)473ebfedea0SLionel Sambuc mcc_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
474ebfedea0SLionel Sambuc {
475ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
476ebfedea0SLionel Sambuc m->kdc_offset = kdc_offset;
477ebfedea0SLionel Sambuc return 0;
478ebfedea0SLionel Sambuc }
479ebfedea0SLionel Sambuc
480ebfedea0SLionel Sambuc static krb5_error_code KRB5_CALLCONV
mcc_get_kdc_offset(krb5_context context,krb5_ccache id,krb5_deltat * kdc_offset)481ebfedea0SLionel Sambuc mcc_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset)
482ebfedea0SLionel Sambuc {
483ebfedea0SLionel Sambuc krb5_mcache *m = MCACHE(id);
484ebfedea0SLionel Sambuc *kdc_offset = m->kdc_offset;
485ebfedea0SLionel Sambuc return 0;
486ebfedea0SLionel Sambuc }
487ebfedea0SLionel Sambuc
488ebfedea0SLionel Sambuc
489ebfedea0SLionel Sambuc /**
490ebfedea0SLionel Sambuc * Variable containing the MEMORY based credential cache implemention.
491ebfedea0SLionel Sambuc *
492ebfedea0SLionel Sambuc * @ingroup krb5_ccache
493ebfedea0SLionel Sambuc */
494ebfedea0SLionel Sambuc
495ebfedea0SLionel Sambuc KRB5_LIB_VARIABLE const krb5_cc_ops krb5_mcc_ops = {
496ebfedea0SLionel Sambuc KRB5_CC_OPS_VERSION,
497ebfedea0SLionel Sambuc "MEMORY",
498ebfedea0SLionel Sambuc mcc_get_name,
499ebfedea0SLionel Sambuc mcc_resolve,
500ebfedea0SLionel Sambuc mcc_gen_new,
501ebfedea0SLionel Sambuc mcc_initialize,
502ebfedea0SLionel Sambuc mcc_destroy,
503ebfedea0SLionel Sambuc mcc_close,
504ebfedea0SLionel Sambuc mcc_store_cred,
505ebfedea0SLionel Sambuc NULL, /* mcc_retrieve */
506ebfedea0SLionel Sambuc mcc_get_principal,
507ebfedea0SLionel Sambuc mcc_get_first,
508ebfedea0SLionel Sambuc mcc_get_next,
509ebfedea0SLionel Sambuc mcc_end_get,
510ebfedea0SLionel Sambuc mcc_remove_cred,
511ebfedea0SLionel Sambuc mcc_set_flags,
512ebfedea0SLionel Sambuc NULL,
513ebfedea0SLionel Sambuc mcc_get_cache_first,
514ebfedea0SLionel Sambuc mcc_get_cache_next,
515ebfedea0SLionel Sambuc mcc_end_cache_get,
516ebfedea0SLionel Sambuc mcc_move,
517ebfedea0SLionel Sambuc mcc_default_name,
518ebfedea0SLionel Sambuc NULL,
519ebfedea0SLionel Sambuc mcc_lastchange,
520ebfedea0SLionel Sambuc mcc_set_kdc_offset,
521ebfedea0SLionel Sambuc mcc_get_kdc_offset
522ebfedea0SLionel Sambuc };
523