1 /* $NetBSD: mcache.c,v 1.1.1.2 2014/04/24 12:45:50 pettai Exp $ */
4 * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the Institute nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include "krb5_locl.h"
40 typedef struct krb5_mcache
{
44 krb5_principal primary_principal
;
49 struct krb5_mcache
*next
;
51 krb5_deltat kdc_offset
;
54 static HEIMDAL_MUTEX mcc_mutex
= HEIMDAL_MUTEX_INITIALIZER
;
55 static struct krb5_mcache
*mcc_head
;
57 #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
59 #define MISDEAD(X) ((X)->dead)
61 static const char* KRB5_CALLCONV
62 mcc_get_name(krb5_context context
,
65 return MCACHE(id
)->name
;
68 static krb5_mcache
* KRB5_CALLCONV
69 mcc_alloc(const char *name
)
78 ret
= asprintf(&m
->name
, "%p", m
);
80 m
->name
= strdup(name
);
81 if(ret
< 0 || m
->name
== NULL
) {
85 /* check for dups first */
86 HEIMDAL_MUTEX_lock(&mcc_mutex
);
87 for (m_c
= mcc_head
; m_c
!= NULL
; m_c
= m_c
->next
)
88 if (strcmp(m
->name
, m_c
->name
) == 0)
93 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
99 m
->primary_principal
= NULL
;
101 m
->mtime
= time(NULL
);
105 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
109 static krb5_error_code KRB5_CALLCONV
110 mcc_resolve(krb5_context context
, krb5_ccache
*id
, const char *res
)
114 HEIMDAL_MUTEX_lock(&mcc_mutex
);
115 for (m
= mcc_head
; m
!= NULL
; m
= m
->next
)
116 if (strcmp(m
->name
, res
) == 0)
118 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
122 (*id
)->data
.data
= m
;
123 (*id
)->data
.length
= sizeof(*m
);
129 krb5_set_error_message(context
, KRB5_CC_NOMEM
,
130 N_("malloc: out of memory", ""));
131 return KRB5_CC_NOMEM
;
134 (*id
)->data
.data
= m
;
135 (*id
)->data
.length
= sizeof(*m
);
141 static krb5_error_code KRB5_CALLCONV
142 mcc_gen_new(krb5_context context
, krb5_ccache
*id
)
149 krb5_set_error_message(context
, KRB5_CC_NOMEM
,
150 N_("malloc: out of memory", ""));
151 return KRB5_CC_NOMEM
;
154 (*id
)->data
.data
= m
;
155 (*id
)->data
.length
= sizeof(*m
);
160 static krb5_error_code KRB5_CALLCONV
161 mcc_initialize(krb5_context context
,
163 krb5_principal primary_principal
)
165 krb5_mcache
*m
= MCACHE(id
);
167 m
->mtime
= time(NULL
);
168 return krb5_copy_principal (context
,
170 &m
->primary_principal
);
174 mcc_close_internal(krb5_mcache
*m
)
176 if (--m
->refcnt
!= 0)
186 static krb5_error_code KRB5_CALLCONV
187 mcc_close(krb5_context context
,
190 if (mcc_close_internal(MCACHE(id
)))
191 krb5_data_free(&id
->data
);
195 static krb5_error_code KRB5_CALLCONV
196 mcc_destroy(krb5_context context
,
199 krb5_mcache
**n
, *m
= MCACHE(id
);
203 krb5_abortx(context
, "mcc_destroy: refcnt already 0");
206 /* if this is an active mcache, remove it from the linked
207 list, and free all data */
208 HEIMDAL_MUTEX_lock(&mcc_mutex
);
209 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
215 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
216 if (m
->primary_principal
!= NULL
) {
217 krb5_free_principal (context
, m
->primary_principal
);
218 m
->primary_principal
= NULL
;
226 krb5_free_cred_contents (context
, &l
->cred
);
236 static krb5_error_code KRB5_CALLCONV
237 mcc_store_cred(krb5_context context
,
241 krb5_mcache
*m
= MCACHE(id
);
248 l
= malloc (sizeof(*l
));
250 krb5_set_error_message(context
, KRB5_CC_NOMEM
,
251 N_("malloc: out of memory", ""));
252 return KRB5_CC_NOMEM
;
256 memset (&l
->cred
, 0, sizeof(l
->cred
));
257 ret
= krb5_copy_creds_contents (context
, creds
, &l
->cred
);
263 m
->mtime
= time(NULL
);
267 static krb5_error_code KRB5_CALLCONV
268 mcc_get_principal(krb5_context context
,
270 krb5_principal
*principal
)
272 krb5_mcache
*m
= MCACHE(id
);
274 if (MISDEAD(m
) || m
->primary_principal
== NULL
)
276 return krb5_copy_principal (context
,
277 m
->primary_principal
,
281 static krb5_error_code KRB5_CALLCONV
282 mcc_get_first (krb5_context context
,
284 krb5_cc_cursor
*cursor
)
286 krb5_mcache
*m
= MCACHE(id
);
295 static krb5_error_code KRB5_CALLCONV
296 mcc_get_next (krb5_context context
,
298 krb5_cc_cursor
*cursor
,
301 krb5_mcache
*m
= MCACHE(id
);
310 return krb5_copy_creds_contents (context
,
317 static krb5_error_code KRB5_CALLCONV
318 mcc_end_get (krb5_context context
,
320 krb5_cc_cursor
*cursor
)
325 static krb5_error_code KRB5_CALLCONV
326 mcc_remove_cred(krb5_context context
,
331 krb5_mcache
*m
= MCACHE(id
);
333 for(q
= &m
->creds
, p
= *q
; p
; p
= *q
) {
334 if(krb5_compare_creds(context
, which
, mcreds
, &p
->cred
)) {
336 krb5_free_cred_contents(context
, &p
->cred
);
338 m
->mtime
= time(NULL
);
345 static krb5_error_code KRB5_CALLCONV
346 mcc_set_flags(krb5_context context
,
357 static krb5_error_code KRB5_CALLCONV
358 mcc_get_cache_first(krb5_context context
, krb5_cc_cursor
*cursor
)
360 struct mcache_iter
*iter
;
362 iter
= calloc(1, sizeof(*iter
));
364 krb5_set_error_message(context
, ENOMEM
,
365 N_("malloc: out of memory", ""));
369 HEIMDAL_MUTEX_lock(&mcc_mutex
);
370 iter
->cache
= mcc_head
;
372 iter
->cache
->refcnt
++;
373 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
379 static krb5_error_code KRB5_CALLCONV
380 mcc_get_cache_next(krb5_context context
, krb5_cc_cursor cursor
, krb5_ccache
*id
)
382 struct mcache_iter
*iter
= cursor
;
386 if (iter
->cache
== NULL
)
389 HEIMDAL_MUTEX_lock(&mcc_mutex
);
393 iter
->cache
= m
->next
;
394 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
396 ret
= _krb5_cc_allocate(context
, &krb5_mcc_ops
, id
);
400 (*id
)->data
.data
= m
;
401 (*id
)->data
.length
= sizeof(*m
);
406 static krb5_error_code KRB5_CALLCONV
407 mcc_end_cache_get(krb5_context context
, krb5_cc_cursor cursor
)
409 struct mcache_iter
*iter
= cursor
;
412 mcc_close_internal(iter
->cache
);
418 static krb5_error_code KRB5_CALLCONV
419 mcc_move(krb5_context context
, krb5_ccache from
, krb5_ccache to
)
421 krb5_mcache
*mfrom
= MCACHE(from
), *mto
= MCACHE(to
);
423 krb5_principal principal
;
426 HEIMDAL_MUTEX_lock(&mcc_mutex
);
428 /* drop the from cache from the linked list to avoid lookups */
429 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
438 mto
->creds
= mfrom
->creds
;
439 mfrom
->creds
= creds
;
441 principal
= mto
->primary_principal
;
442 mto
->primary_principal
= mfrom
->primary_principal
;
443 mfrom
->primary_principal
= principal
;
445 mto
->mtime
= mfrom
->mtime
= time(NULL
);
447 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
448 mcc_destroy(context
, from
);
453 static krb5_error_code KRB5_CALLCONV
454 mcc_default_name(krb5_context context
, char **str
)
456 *str
= strdup("MEMORY:");
458 krb5_set_error_message(context
, ENOMEM
,
459 N_("malloc: out of memory", ""));
465 static krb5_error_code KRB5_CALLCONV
466 mcc_lastchange(krb5_context context
, krb5_ccache id
, krb5_timestamp
*mtime
)
468 *mtime
= MCACHE(id
)->mtime
;
472 static krb5_error_code KRB5_CALLCONV
473 mcc_set_kdc_offset(krb5_context context
, krb5_ccache id
, krb5_deltat kdc_offset
)
475 krb5_mcache
*m
= MCACHE(id
);
476 m
->kdc_offset
= kdc_offset
;
480 static krb5_error_code KRB5_CALLCONV
481 mcc_get_kdc_offset(krb5_context context
, krb5_ccache id
, krb5_deltat
*kdc_offset
)
483 krb5_mcache
*m
= MCACHE(id
);
484 *kdc_offset
= m
->kdc_offset
;
490 * Variable containing the MEMORY based credential cache implemention.
492 * @ingroup krb5_ccache
495 KRB5_LIB_VARIABLE
const krb5_cc_ops krb5_mcc_ops
= {
505 NULL
, /* mcc_retrieve */