xref: /minix3/crypto/external/bsd/heimdal/dist/lib/krb5/mcache.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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