2 * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include "krb5_locl.h"
36 __RCSID("$Heimdal: mcache.c 22107 2007-12-03 17:22:51Z lha $"
39 typedef struct krb5_mcache
{
43 krb5_principal primary_principal
;
48 struct krb5_mcache
*next
;
51 static HEIMDAL_MUTEX mcc_mutex
= HEIMDAL_MUTEX_INITIALIZER
;
52 static struct krb5_mcache
*mcc_head
;
54 #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
56 #define MISDEAD(X) ((X)->dead)
59 mcc_get_name(krb5_context context
,
62 return MCACHE(id
)->name
;
66 mcc_alloc(const char *name
)
74 asprintf(&m
->name
, "%p", m
);
76 m
->name
= strdup(name
);
81 /* check for dups first */
82 HEIMDAL_MUTEX_lock(&mcc_mutex
);
83 for (m_c
= mcc_head
; m_c
!= NULL
; m_c
= m_c
->next
)
84 if (strcmp(m
->name
, m_c
->name
) == 0)
89 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
95 m
->primary_principal
= NULL
;
99 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
103 static krb5_error_code
104 mcc_resolve(krb5_context context
, krb5_ccache
*id
, const char *res
)
108 HEIMDAL_MUTEX_lock(&mcc_mutex
);
109 for (m
= mcc_head
; m
!= NULL
; m
= m
->next
)
110 if (strcmp(m
->name
, res
) == 0)
112 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
116 (*id
)->data
.data
= m
;
117 (*id
)->data
.length
= sizeof(*m
);
123 krb5_set_error_string (context
, "malloc: out of memory");
124 return KRB5_CC_NOMEM
;
127 (*id
)->data
.data
= m
;
128 (*id
)->data
.length
= sizeof(*m
);
134 static krb5_error_code
135 mcc_gen_new(krb5_context context
, krb5_ccache
*id
)
142 krb5_set_error_string (context
, "malloc: out of memory");
143 return KRB5_CC_NOMEM
;
146 (*id
)->data
.data
= m
;
147 (*id
)->data
.length
= sizeof(*m
);
152 static krb5_error_code
153 mcc_initialize(krb5_context context
,
155 krb5_principal primary_principal
)
157 krb5_mcache
*m
= MCACHE(id
);
159 return krb5_copy_principal (context
,
161 &m
->primary_principal
);
165 mcc_close_internal(krb5_mcache
*m
)
167 if (--m
->refcnt
!= 0)
177 static krb5_error_code
178 mcc_close(krb5_context context
,
181 if (mcc_close_internal(MCACHE(id
)))
182 krb5_data_free(&id
->data
);
186 static krb5_error_code
187 mcc_destroy(krb5_context context
,
190 krb5_mcache
**n
, *m
= MCACHE(id
);
194 krb5_abortx(context
, "mcc_destroy: refcnt already 0");
197 /* if this is an active mcache, remove it from the linked
198 list, and free all data */
199 HEIMDAL_MUTEX_lock(&mcc_mutex
);
200 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
206 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
207 if (m
->primary_principal
!= NULL
) {
208 krb5_free_principal (context
, m
->primary_principal
);
209 m
->primary_principal
= NULL
;
217 krb5_free_cred_contents (context
, &l
->cred
);
227 static krb5_error_code
228 mcc_store_cred(krb5_context context
,
232 krb5_mcache
*m
= MCACHE(id
);
239 l
= malloc (sizeof(*l
));
241 krb5_set_error_string (context
, "malloc: out of memory");
242 return KRB5_CC_NOMEM
;
246 memset (&l
->cred
, 0, sizeof(l
->cred
));
247 ret
= krb5_copy_creds_contents (context
, creds
, &l
->cred
);
256 static krb5_error_code
257 mcc_get_principal(krb5_context context
,
259 krb5_principal
*principal
)
261 krb5_mcache
*m
= MCACHE(id
);
263 if (MISDEAD(m
) || m
->primary_principal
== NULL
)
265 return krb5_copy_principal (context
,
266 m
->primary_principal
,
270 static krb5_error_code
271 mcc_get_first (krb5_context context
,
273 krb5_cc_cursor
*cursor
)
275 krb5_mcache
*m
= MCACHE(id
);
284 static krb5_error_code
285 mcc_get_next (krb5_context context
,
287 krb5_cc_cursor
*cursor
,
290 krb5_mcache
*m
= MCACHE(id
);
299 return krb5_copy_creds_contents (context
,
306 static krb5_error_code
307 mcc_end_get (krb5_context context
,
309 krb5_cc_cursor
*cursor
)
314 static krb5_error_code
315 mcc_remove_cred(krb5_context context
,
320 krb5_mcache
*m
= MCACHE(id
);
322 for(q
= &m
->creds
, p
= *q
; p
; p
= *q
) {
323 if(krb5_compare_creds(context
, which
, mcreds
, &p
->cred
)) {
325 krb5_free_cred_contents(context
, &p
->cred
);
333 static krb5_error_code
334 mcc_set_flags(krb5_context context
,
345 static krb5_error_code
346 mcc_get_cache_first(krb5_context context
, krb5_cc_cursor
*cursor
)
348 struct mcache_iter
*iter
;
350 iter
= calloc(1, sizeof(*iter
));
352 krb5_set_error_string(context
, "malloc - out of memory");
356 HEIMDAL_MUTEX_lock(&mcc_mutex
);
357 iter
->cache
= mcc_head
;
359 iter
->cache
->refcnt
++;
360 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
366 static krb5_error_code
367 mcc_get_cache_next(krb5_context context
, krb5_cc_cursor cursor
, krb5_ccache
*id
)
369 struct mcache_iter
*iter
= cursor
;
373 if (iter
->cache
== NULL
)
376 HEIMDAL_MUTEX_lock(&mcc_mutex
);
380 iter
->cache
= m
->next
;
381 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
383 ret
= _krb5_cc_allocate(context
, &krb5_mcc_ops
, id
);
387 (*id
)->data
.data
= m
;
388 (*id
)->data
.length
= sizeof(*m
);
393 static krb5_error_code
394 mcc_end_cache_get(krb5_context context
, krb5_cc_cursor cursor
)
396 struct mcache_iter
*iter
= cursor
;
399 mcc_close_internal(iter
->cache
);
405 static krb5_error_code
406 mcc_move(krb5_context context
, krb5_ccache from
, krb5_ccache to
)
408 krb5_mcache
*mfrom
= MCACHE(from
), *mto
= MCACHE(to
);
410 krb5_principal principal
;
413 HEIMDAL_MUTEX_lock(&mcc_mutex
);
415 /* drop the from cache from the linked list to avoid lookups */
416 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
425 mto
->creds
= mfrom
->creds
;
426 mfrom
->creds
= creds
;
428 principal
= mto
->primary_principal
;
429 mto
->primary_principal
= mfrom
->primary_principal
;
430 mfrom
->primary_principal
= principal
;
432 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
433 mcc_destroy(context
, from
);
438 static krb5_error_code
439 mcc_default_name(krb5_context context
, char **str
)
441 *str
= strdup("MEMORY:");
443 krb5_set_error_string(context
, "out of memory");
451 * Variable containing the MEMORY based credential cache implemention.
453 * @ingroup krb5_ccache
456 const krb5_cc_ops krb5_mcc_ops
= {
465 NULL
, /* mcc_retrieve */