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"
38 typedef struct krb5_mcache
{
42 krb5_principal primary_principal
;
47 struct krb5_mcache
*next
;
50 static HEIMDAL_MUTEX mcc_mutex
= HEIMDAL_MUTEX_INITIALIZER
;
51 static struct krb5_mcache
*mcc_head
;
53 #define MCACHE(X) ((krb5_mcache *)(X)->data.data)
55 #define MISDEAD(X) ((X)->dead)
58 mcc_get_name(krb5_context context
,
61 return MCACHE(id
)->name
;
65 mcc_alloc(const char *name
)
73 asprintf(&m
->name
, "%p", m
);
75 m
->name
= strdup(name
);
80 /* check for dups first */
81 HEIMDAL_MUTEX_lock(&mcc_mutex
);
82 for (m_c
= mcc_head
; m_c
!= NULL
; m_c
= m_c
->next
)
83 if (strcmp(m
->name
, m_c
->name
) == 0)
88 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
94 m
->primary_principal
= 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_string (context
, "malloc: out of memory");
123 return KRB5_CC_NOMEM
;
126 (*id
)->data
.data
= m
;
127 (*id
)->data
.length
= sizeof(*m
);
133 static krb5_error_code
134 mcc_gen_new(krb5_context context
, krb5_ccache
*id
)
141 krb5_set_error_string (context
, "malloc: out of memory");
142 return KRB5_CC_NOMEM
;
145 (*id
)->data
.data
= m
;
146 (*id
)->data
.length
= sizeof(*m
);
151 static krb5_error_code
152 mcc_initialize(krb5_context context
,
154 krb5_principal primary_principal
)
156 krb5_mcache
*m
= MCACHE(id
);
158 return krb5_copy_principal (context
,
160 &m
->primary_principal
);
164 mcc_close_internal(krb5_mcache
*m
)
166 if (--m
->refcnt
!= 0)
176 static krb5_error_code
177 mcc_close(krb5_context context
,
180 if (mcc_close_internal(MCACHE(id
)))
181 krb5_data_free(&id
->data
);
185 static krb5_error_code
186 mcc_destroy(krb5_context context
,
189 krb5_mcache
**n
, *m
= MCACHE(id
);
193 krb5_abortx(context
, "mcc_destroy: refcnt already 0");
196 /* if this is an active mcache, remove it from the linked
197 list, and free all data */
198 HEIMDAL_MUTEX_lock(&mcc_mutex
);
199 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
205 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
206 if (m
->primary_principal
!= NULL
) {
207 krb5_free_principal (context
, m
->primary_principal
);
208 m
->primary_principal
= NULL
;
216 krb5_free_cred_contents (context
, &l
->cred
);
226 static krb5_error_code
227 mcc_store_cred(krb5_context context
,
231 krb5_mcache
*m
= MCACHE(id
);
238 l
= malloc (sizeof(*l
));
240 krb5_set_error_string (context
, "malloc: out of memory");
241 return KRB5_CC_NOMEM
;
245 memset (&l
->cred
, 0, sizeof(l
->cred
));
246 ret
= krb5_copy_creds_contents (context
, creds
, &l
->cred
);
255 static krb5_error_code
256 mcc_get_principal(krb5_context context
,
258 krb5_principal
*principal
)
260 krb5_mcache
*m
= MCACHE(id
);
262 if (MISDEAD(m
) || m
->primary_principal
== NULL
)
264 return krb5_copy_principal (context
,
265 m
->primary_principal
,
269 static krb5_error_code
270 mcc_get_first (krb5_context context
,
272 krb5_cc_cursor
*cursor
)
274 krb5_mcache
*m
= MCACHE(id
);
283 static krb5_error_code
284 mcc_get_next (krb5_context context
,
286 krb5_cc_cursor
*cursor
,
289 krb5_mcache
*m
= MCACHE(id
);
298 return krb5_copy_creds_contents (context
,
305 static krb5_error_code
306 mcc_end_get (krb5_context context
,
308 krb5_cc_cursor
*cursor
)
313 static krb5_error_code
314 mcc_remove_cred(krb5_context context
,
319 krb5_mcache
*m
= MCACHE(id
);
321 for(q
= &m
->creds
, p
= *q
; p
; p
= *q
) {
322 if(krb5_compare_creds(context
, which
, mcreds
, &p
->cred
)) {
324 krb5_free_cred_contents(context
, &p
->cred
);
332 static krb5_error_code
333 mcc_set_flags(krb5_context context
,
344 static krb5_error_code
345 mcc_get_cache_first(krb5_context context
, krb5_cc_cursor
*cursor
)
347 struct mcache_iter
*iter
;
349 iter
= calloc(1, sizeof(*iter
));
351 krb5_set_error_string(context
, "malloc - out of memory");
355 HEIMDAL_MUTEX_lock(&mcc_mutex
);
356 iter
->cache
= mcc_head
;
358 iter
->cache
->refcnt
++;
359 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
365 static krb5_error_code
366 mcc_get_cache_next(krb5_context context
, krb5_cc_cursor cursor
, krb5_ccache
*id
)
368 struct mcache_iter
*iter
= cursor
;
372 if (iter
->cache
== NULL
)
375 HEIMDAL_MUTEX_lock(&mcc_mutex
);
379 iter
->cache
= m
->next
;
380 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
382 ret
= _krb5_cc_allocate(context
, &krb5_mcc_ops
, id
);
386 (*id
)->data
.data
= m
;
387 (*id
)->data
.length
= sizeof(*m
);
392 static krb5_error_code
393 mcc_end_cache_get(krb5_context context
, krb5_cc_cursor cursor
)
395 struct mcache_iter
*iter
= cursor
;
398 mcc_close_internal(iter
->cache
);
404 static krb5_error_code
405 mcc_move(krb5_context context
, krb5_ccache from
, krb5_ccache to
)
407 krb5_mcache
*mfrom
= MCACHE(from
), *mto
= MCACHE(to
);
409 krb5_principal principal
;
412 HEIMDAL_MUTEX_lock(&mcc_mutex
);
414 /* drop the from cache from the linked list to avoid lookups */
415 for(n
= &mcc_head
; n
&& *n
; n
= &(*n
)->next
) {
424 mto
->creds
= mfrom
->creds
;
425 mfrom
->creds
= creds
;
427 principal
= mto
->primary_principal
;
428 mto
->primary_principal
= mfrom
->primary_principal
;
429 mfrom
->primary_principal
= principal
;
431 HEIMDAL_MUTEX_unlock(&mcc_mutex
);
432 mcc_destroy(context
, from
);
437 static krb5_error_code
438 mcc_default_name(krb5_context context
, char **str
)
440 *str
= strdup("MEMORY:");
442 krb5_set_error_string(context
, "out of memory");
450 * Variable containing the MEMORY based credential cache implemention.
452 * @ingroup krb5_ccache
455 KRB5_LIB_VARIABLE
const krb5_cc_ops krb5_mcc_ops
= {
465 NULL
, /* mcc_retrieve */