2 * Copyright (c) 1995 - 2002, 2005-2006 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
35 * Cache of credentials
37 * Each 'cred,type' pair is collected on a list where the head is in
38 * the cell CRED_ROOT_CELL. This is to enable fast iterations over
39 * all creds for a user (indexed on cred,type).
42 #include "arla_local.h"
45 #define CRED_ROOT_CELL (-1)
47 #define CREDCACHESIZE 101
49 #define CREDFREEINC 10
51 /* a hashtable of all credentials */
52 static Hashtab
*credhtab
;
54 /* list of all free entries */
55 static List
*freelist
;
57 /* # of credentials */
58 static unsigned ncredentials
;
60 /* # of active credentials */
61 static unsigned nactive_credentials
;
63 static void root_free(CredCacheEntry
*);
66 * Functions for handling entries into the credentials cache.
70 credcmp (void *a
, void *b
)
72 CredCacheEntry
*c1
= (CredCacheEntry
*)a
;
73 CredCacheEntry
*c2
= (CredCacheEntry
*)b
;
75 return c1
->cred
!= c2
->cred
76 || c1
->type
!= c2
->type
77 || c1
->cell
!= c2
->cell
;
83 CredCacheEntry
*c
= (CredCacheEntry
*)a
;
85 return c
->cred
+ c
->type
+ c
->cell
;
90 * Create `n' credentials and add them to `freelist'
94 create_new_credentials (unsigned n
)
97 CredCacheEntry
*entries
;
99 entries
= (CredCacheEntry
*)calloc (n
, sizeof (CredCacheEntry
));
101 arla_errx (1, ADEBERROR
, "credcache: calloc failed");
102 for (i
= 0; i
< n
; ++i
) {
103 entries
[i
].cred_data
= NULL
;
104 listaddhead (freelist
, &entries
[i
]);
110 * Initialize the cred cache.
114 cred_init (unsigned nentries
)
116 credhtab
= hashtabnew (CREDCACHESIZE
, credcmp
, credhash
);
117 if (credhtab
== NULL
)
118 arla_errx (1, ADEBERROR
, "cred_init: hashtabnew failed");
119 freelist
= listnew ();
120 if (freelist
== NULL
)
121 arla_errx (1, ADEBERROR
, "cred_init: listnew failed");
123 create_new_credentials (nentries
);
126 static CredCacheEntry
*
127 internal_get (long cell
, nnpfs_pag_t cred
, int type
)
132 if (cell
== CRED_ROOT_CELL
)
139 e
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)&key
);
141 if (e
== NULL
&& type
== CRED_NONE
) {
142 e
= cred_add (cred
, type
, 0, cell
, 0, NULL
, 0, 0);
147 assert(e
->cell
!= CRED_ROOT_CELL
);
154 int (*func
)(CredCacheEntry
*, void *);
159 list_pag_func(List
*l
, Listitem
*li
, void *arg
)
161 CredCacheEntry
*e
= listdata(li
);
162 struct list_pag
*d
= arg
;
164 return (d
->func
)(e
, d
->arg
);
168 cred_list_pag(nnpfs_pag_t cred
, int type
,
169 int (*func
)(CredCacheEntry
*, void *),
172 CredCacheEntry key
, *root_e
;
175 key
.cell
= CRED_ROOT_CELL
;
179 root_e
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)&key
);
186 listiter(root_e
->pag
.list
, list_pag_func
, &d
);
192 cred_get (long cell
, nnpfs_pag_t cred
, int type
)
194 if (type
== CRED_ANY
) {
198 for (i
= CRED_MAX
; i
> CRED_NONE
; --i
) {
199 e
= internal_get (cell
, cred
, i
);
204 return internal_get (cell
, cred
, CRED_NONE
);
206 return internal_get (cell
, cred
, type
);
210 cred_ref(CredCacheEntry
*cred
)
216 recycle_entry (CredCacheEntry
*ce
)
218 assert(ce
->refcount
== 0);
220 if (ce
->cell
!= CRED_ROOT_CELL
)
222 if (!ce
->flags
.killme
)
223 hashtabdel (credhtab
, ce
);
224 if (ce
->cred_data
!= NULL
)
225 free (ce
->cred_data
);
226 if (ce
->token_rxgk
) {
227 ydr_free_token_rxgk(ce
->token_rxgk
);
228 free(ce
->token_rxgk
);
230 memset (ce
, 0, sizeof(*ce
));
231 listaddhead (freelist
, ce
);
232 --nactive_credentials
;
236 cred_free (CredCacheEntry
*ce
)
240 assert (ce
->cell
!= CRED_ROOT_CELL
);
243 if (ce
->flags
.killme
&& ce
->refcount
== 0)
247 static CredCacheEntry
*
252 e
= (CredCacheEntry
*)listdelhead (freelist
);
256 create_new_credentials (CREDFREEINC
);
258 e
= (CredCacheEntry
*)listdelhead (freelist
);
262 arla_errx (1, ADEBERROR
,
263 "credcache: there was no way of getting a cred");
267 root_free(CredCacheEntry
*e
)
269 CredCacheEntry key
, *root_e
;
271 assert(e
->cell
!= CRED_ROOT_CELL
);
273 if (e
->pag
.li
== NULL
)
276 key
.cell
= CRED_ROOT_CELL
;
280 root_e
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)&key
);
283 listdel(root_e
->pag
.list
, e
->pag
.li
);
286 if (listemptyp(root_e
->pag
.list
)) {
287 listfree(root_e
->pag
.list
);
288 root_e
->pag
.list
= NULL
;
289 recycle_entry(root_e
);
294 add_to_root_entry(CredCacheEntry
*e
)
296 CredCacheEntry key
, *root_e
;
298 assert(e
->cell
!= CRED_ROOT_CELL
);
300 key
.cell
= CRED_ROOT_CELL
;
304 root_e
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)&key
);
305 if (root_e
== NULL
) {
306 root_e
= get_free_cred ();
308 root_e
->cell
= CRED_ROOT_CELL
;
309 root_e
->type
= e
->type
;
310 root_e
->cred
= e
->cred
;
311 root_e
->securityindex
= -1;
313 root_e
->cred_data
= NULL
;
314 root_e
->uid
= e
->uid
;
315 root_e
->pag
.list
= listnew();
316 if (root_e
->pag
.list
== NULL
)
317 arla_errx (1, ADEBERROR
, "add_to_root_entry: out of memory");
319 hashtabadd(credhtab
, root_e
);
321 ++nactive_credentials
;
323 e
->pag
.li
= listaddhead (root_e
->pag
.list
, e
);
327 cred_add (nnpfs_pag_t cred
, int type
, int securityindex
, long cell
,
328 time_t expire
, void *cred_data
, size_t cred_data_sz
,
335 if (cred_data
!= NULL
) {
336 data
= malloc (cred_data_sz
);
339 memcpy (data
, cred_data
, cred_data_sz
);
343 e
= get_free_cred ();
347 e
->securityindex
= securityindex
;
354 add_to_root_entry(e
);
356 old
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)e
);
360 hashtabadd (credhtab
, e
);
362 ++nactive_credentials
;
372 cred_delete (CredCacheEntry
*ce
)
374 assert(ce
->cell
!= CRED_ROOT_CELL
);
376 if (ce
->refcount
> 0) {
377 ce
->flags
.killme
= 1;
378 hashtabdel (credhtab
, ce
);
389 cred_expire (CredCacheEntry
*ce
)
391 const char *cell_name
= cell_num2name (ce
->cell
);
393 if (cell_name
!= NULL
)
394 arla_warnx (ADEBWARN
,
395 "Credentials for UID %u in cell %s have expired",
396 (unsigned)ce
->uid
, cell_name
);
398 arla_warnx (ADEBWARN
,
399 "Credentials for UID %u in cell unknown %ld have expired",
400 (unsigned)ce
->uid
, ce
->cell
);
406 remove_entry (void *ptr
, void *arg
)
408 CredCacheEntry
*ce
= (CredCacheEntry
*)ptr
;
409 nnpfs_pag_t
*cred
= (nnpfs_pag_t
*)arg
;
411 if (ce
->cell
== CRED_ROOT_CELL
)
414 if (ce
->cred
== *cred
)
420 cred_remove (nnpfs_pag_t cred
)
422 hashtabforeach (credhtab
, remove_entry
, &cred
);
426 print_cred (void *ptr
, void *arg
)
428 CredCacheEntry
*e
= (CredCacheEntry
*)ptr
;
430 arla_log(ADEBVLOG
, "cred = %u, type = %d, securityindex = %d, "
431 "cell = %ld, refcount = %u, killme = %d, uid = %lu",
432 e
->cred
, e
->type
, e
->securityindex
, e
->cell
, e
->refcount
,
433 e
->flags
.killme
, (unsigned long)e
->uid
);
440 arla_log(ADEBVLOG
, "%u(%u) credentials",
441 nactive_credentials
, ncredentials
);
442 hashtabforeach (credhtab
, print_cred
, NULL
);
446 foreach_cred (void *ptr
, void *arg
)
448 CredCacheEntry
*e
= (CredCacheEntry
*)ptr
;
449 Bool (* func
)(CredCacheEntry
*e
) = (Bool (*)(CredCacheEntry
*e
)) arg
;
456 cred_foreach (Bool (* func
)(CredCacheEntry
*e
))
458 hashtabforeach (credhtab
, foreach_cred
, func
);