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 typedef struct krb5_mcache
{
40 krb5_principal primary_principal
;
45 struct krb5_mcache
*next
;
49 static HEIMDAL_MUTEX mcc_mutex
= HEIMDAL_MUTEX_INITIALIZER
;
50 static struct krb5_mcache
*mcc_head
;
52 #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
54 #define MISDEAD(X) ((X)->dead)
57 mcc_get_name(krb5_context context
,
60 return MCACHE(id
)->name
;
64 mcc_alloc(const char *name
)
72 asprintf(&m
->name
, "%p", m
);
74 m
->name
= strdup(name
);
79 /* check for dups first */
80 HEIMDAL_MUTEX_lock(&mcc_mutex
);
81 for (m_c
= mcc_head
; m_c
!= NULL
; m_c
= m_c
->next
)
82 if (strcmp(m
->name
, m_c
->name
) == 0)
87 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
93 m
->primary_principal
= NULL
;
95 m
->mtime
= time(NULL
);
98 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
102 static krb5_error_code
103 mcc_resolve(krb5_context context
, krb5_ccache
*id
, const char *res
)
107 HEIMDAL_MUTEX_lock(&mcc_mutex
);
108 for (m
= mcc_head
; m
!= NULL
; m
= m
->next
)
109 if (strcmp(m
->name
, res
) == 0)
111 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
115 (*id
)->data
.data
= m
;
116 (*id
)->data
.length
= sizeof(*m
);
122 krb5_set_error_message(context
, KRB5_CC_NOMEM
,
123 N_("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_message(context
, KRB5_CC_NOMEM
,
143 N_("malloc: out of memory", ""));
144 return KRB5_CC_NOMEM
;
147 (*id
)->data
.data
= m
;
148 (*id
)->data
.length
= sizeof(*m
);
153 static krb5_error_code
154 mcc_initialize(krb5_context context
,
156 krb5_principal primary_principal
)
158 krb5_mcache
*m
= MCACHE(id
);
160 m
->mtime
= time(NULL
);
161 return krb5_copy_principal (context
,
163 &m
->primary_principal
);
167 mcc_close_internal(krb5_mcache
*m
)
169 if (--m
->refcnt
!= 0)
179 static krb5_error_code
180 mcc_close(krb5_context context
,
183 if (mcc_close_internal(MCACHE(id
)))
184 krb5_data_free(&id
->data
);
188 static krb5_error_code
189 mcc_destroy(krb5_context context
,
192 krb5_mcache
**n
, *m
= MCACHE(id
);
196 krb5_abortx(context
, "mcc_destroy: refcnt already 0");
199 /* if this is an active mcache, remove it from the linked
200 list, and free all data */
201 HEIMDAL_MUTEX_lock(&mcc_mutex
);
202 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
208 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
209 if (m
->primary_principal
!= NULL
) {
210 krb5_free_principal (context
, m
->primary_principal
);
211 m
->primary_principal
= NULL
;
219 krb5_free_cred_contents (context
, &l
->cred
);
229 static krb5_error_code
230 mcc_store_cred(krb5_context context
,
234 krb5_mcache
*m
= MCACHE(id
);
241 l
= malloc (sizeof(*l
));
243 krb5_set_error_message(context
, KRB5_CC_NOMEM
,
244 N_("malloc: out of memory", ""));
245 return KRB5_CC_NOMEM
;
249 memset (&l
->cred
, 0, sizeof(l
->cred
));
250 ret
= krb5_copy_creds_contents (context
, creds
, &l
->cred
);
256 m
->mtime
= time(NULL
);
260 static krb5_error_code
261 mcc_get_principal(krb5_context context
,
263 krb5_principal
*principal
)
265 krb5_mcache
*m
= MCACHE(id
);
267 if (MISDEAD(m
) || m
->primary_principal
== NULL
)
269 return krb5_copy_principal (context
,
270 m
->primary_principal
,
274 static krb5_error_code
275 mcc_get_first (krb5_context context
,
277 krb5_cc_cursor
*cursor
)
279 krb5_mcache
*m
= MCACHE(id
);
288 static krb5_error_code
289 mcc_get_next (krb5_context context
,
291 krb5_cc_cursor
*cursor
,
294 krb5_mcache
*m
= MCACHE(id
);
303 return krb5_copy_creds_contents (context
,
310 static krb5_error_code
311 mcc_end_get (krb5_context context
,
313 krb5_cc_cursor
*cursor
)
318 static krb5_error_code
319 mcc_remove_cred(krb5_context context
,
324 krb5_mcache
*m
= MCACHE(id
);
326 for(q
= &m
->creds
, p
= *q
; p
; p
= *q
) {
327 if(krb5_compare_creds(context
, which
, mcreds
, &p
->cred
)) {
329 krb5_free_cred_contents(context
, &p
->cred
);
331 m
->mtime
= time(NULL
);
338 static krb5_error_code
339 mcc_set_flags(krb5_context context
,
350 static krb5_error_code
351 mcc_get_cache_first(krb5_context context
, krb5_cc_cursor
*cursor
)
353 struct mcache_iter
*iter
;
355 iter
= calloc(1, sizeof(*iter
));
357 krb5_set_error_message(context
, ENOMEM
,
358 N_("malloc: out of memory", ""));
362 HEIMDAL_MUTEX_lock(&mcc_mutex
);
363 iter
->cache
= mcc_head
;
365 iter
->cache
->refcnt
++;
366 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
372 static krb5_error_code
373 mcc_get_cache_next(krb5_context context
, krb5_cc_cursor cursor
, krb5_ccache
*id
)
375 struct mcache_iter
*iter
= cursor
;
379 if (iter
->cache
== NULL
)
382 HEIMDAL_MUTEX_lock(&mcc_mutex
);
386 iter
->cache
= m
->next
;
387 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
389 ret
= _krb5_cc_allocate(context
, &krb5_mcc_ops
, id
);
393 (*id
)->data
.data
= m
;
394 (*id
)->data
.length
= sizeof(*m
);
399 static krb5_error_code
400 mcc_end_cache_get(krb5_context context
, krb5_cc_cursor cursor
)
402 struct mcache_iter
*iter
= cursor
;
405 mcc_close_internal(iter
->cache
);
411 static krb5_error_code
412 mcc_move(krb5_context context
, krb5_ccache from
, krb5_ccache to
)
414 krb5_mcache
*mfrom
= MCACHE(from
), *mto
= MCACHE(to
);
416 krb5_principal principal
;
419 HEIMDAL_MUTEX_lock(&mcc_mutex
);
421 /* drop the from cache from the linked list to avoid lookups */
422 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
431 mto
->creds
= mfrom
->creds
;
432 mfrom
->creds
= creds
;
434 principal
= mto
->primary_principal
;
435 mto
->primary_principal
= mfrom
->primary_principal
;
436 mfrom
->primary_principal
= principal
;
438 mto
->mtime
= mfrom
->mtime
= time(NULL
);
440 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
441 mcc_destroy(context
, from
);
446 static krb5_error_code
447 mcc_default_name(krb5_context context
, char **str
)
449 *str
= strdup("MEMORY:");
451 krb5_set_error_message(context
, ENOMEM
,
452 N_("malloc: out of memory", ""));
458 static krb5_error_code
459 mcc_lastchange(krb5_context context
, krb5_ccache id
, krb5_timestamp
*mtime
)
461 *mtime
= MCACHE(id
)->mtime
;
467 * Variable containing the MEMORY based credential cache implemention.
469 * @ingroup krb5_ccache
472 KRB5_LIB_VARIABLE
const krb5_cc_ops krb5_mcc_ops
= {
482 NULL
, /* mcc_retrieve */