2 * Copyright (c) 1995 - 2002, 2005 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 recycle_entry (CredCacheEntry
*ce
)
212 assert(ce
->refcount
== 0);
214 if (ce
->cell
!= CRED_ROOT_CELL
)
216 if (!ce
->flags
.killme
)
217 hashtabdel (credhtab
, ce
);
218 if (ce
->cred_data
!= NULL
)
219 free (ce
->cred_data
);
220 memset (ce
, 0, sizeof(*ce
));
221 listaddhead (freelist
, ce
);
222 --nactive_credentials
;
226 cred_free (CredCacheEntry
*ce
)
230 assert (ce
->cell
!= CRED_ROOT_CELL
);
233 if (ce
->flags
.killme
&& ce
->refcount
== 0)
237 static CredCacheEntry
*
242 e
= (CredCacheEntry
*)listdelhead (freelist
);
246 create_new_credentials (CREDFREEINC
);
248 e
= (CredCacheEntry
*)listdelhead (freelist
);
252 arla_errx (1, ADEBERROR
,
253 "credcache: there was no way of getting a cred");
257 root_free(CredCacheEntry
*e
)
259 CredCacheEntry key
, *root_e
;
261 assert(e
->cell
!= CRED_ROOT_CELL
);
263 if (e
->pag
.li
== NULL
)
266 key
.cell
= CRED_ROOT_CELL
;
270 root_e
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)&key
);
273 listdel(root_e
->pag
.list
, e
->pag
.li
);
276 if (listemptyp(root_e
->pag
.list
)) {
277 listfree(root_e
->pag
.list
);
278 root_e
->pag
.list
= NULL
;
279 recycle_entry(root_e
);
284 add_to_root_entry(CredCacheEntry
*e
)
286 CredCacheEntry key
, *root_e
;
288 assert(e
->cell
!= CRED_ROOT_CELL
);
290 key
.cell
= CRED_ROOT_CELL
;
294 root_e
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)&key
);
295 if (root_e
== NULL
) {
296 root_e
= get_free_cred ();
298 root_e
->cell
= CRED_ROOT_CELL
;
299 root_e
->type
= e
->type
;
300 root_e
->cred
= e
->cred
;
301 root_e
->securityindex
= -1;
303 root_e
->cred_data
= NULL
;
304 root_e
->uid
= e
->uid
;
305 root_e
->pag
.list
= listnew();
306 if (root_e
->pag
.list
== NULL
)
307 arla_errx (1, ADEBERROR
, "add_to_root_entry: out of memory");
309 hashtabadd(credhtab
, root_e
);
311 ++nactive_credentials
;
313 e
->pag
.li
= listaddhead (root_e
->pag
.list
, e
);
317 cred_add (nnpfs_pag_t cred
, int type
, int securityindex
, long cell
,
318 time_t expire
, void *cred_data
, size_t cred_data_sz
,
325 if (cred_data
!= NULL
) {
326 data
= malloc (cred_data_sz
);
329 memcpy (data
, cred_data
, cred_data_sz
);
333 e
= get_free_cred ();
337 e
->securityindex
= securityindex
;
344 add_to_root_entry(e
);
346 old
= (CredCacheEntry
*)hashtabsearch (credhtab
, (void *)e
);
350 hashtabadd (credhtab
, e
);
352 ++nactive_credentials
;
362 cred_delete (CredCacheEntry
*ce
)
364 assert(ce
->cell
!= CRED_ROOT_CELL
);
366 if (ce
->refcount
> 0) {
367 ce
->flags
.killme
= 1;
368 hashtabdel (credhtab
, ce
);
379 cred_expire (CredCacheEntry
*ce
)
381 const char *cell_name
= cell_num2name (ce
->cell
);
383 if (cell_name
!= NULL
)
384 arla_warnx (ADEBWARN
,
385 "Credentials for UID %u in cell %s have expired",
386 (unsigned)ce
->uid
, cell_name
);
388 arla_warnx (ADEBWARN
,
389 "Credentials for UID %u in cell unknown %ld have expired",
390 (unsigned)ce
->uid
, ce
->cell
);
396 remove_entry (void *ptr
, void *arg
)
398 CredCacheEntry
*ce
= (CredCacheEntry
*)ptr
;
399 nnpfs_pag_t
*cred
= (nnpfs_pag_t
*)arg
;
401 if (ce
->cell
== CRED_ROOT_CELL
)
404 if (ce
->cred
== *cred
)
410 cred_remove (nnpfs_pag_t cred
)
412 hashtabforeach (credhtab
, remove_entry
, &cred
);
416 print_cred (void *ptr
, void *arg
)
418 CredCacheEntry
*e
= (CredCacheEntry
*)ptr
;
420 arla_log(ADEBVLOG
, "cred = %u, type = %d, securityindex = %d, "
421 "cell = %ld, refcount = %u, killme = %d, uid = %lu",
422 e
->cred
, e
->type
, e
->securityindex
, e
->cell
, e
->refcount
,
423 e
->flags
.killme
, (unsigned long)e
->uid
);
430 arla_log(ADEBVLOG
, "%u(%u) credentials",
431 nactive_credentials
, ncredentials
);
432 hashtabforeach (credhtab
, print_cred
, NULL
);