(afsrights2nnpfsrights): export
[arla.git] / arlad / cred.c
blob557df6d81c54a6a5063bdd584ad9cbb8fe9d248f
1 /*
2 * Copyright (c) 1995 - 2002, 2005-2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
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
31 * SUCH DAMAGE.
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"
43 RCSID("$Id$");
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.
69 static int
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;
80 static unsigned
81 credhash (void *a)
83 CredCacheEntry *c = (CredCacheEntry*)a;
85 return c->cred + c->type + c->cell;
90 * Create `n' credentials and add them to `freelist'
93 static void
94 create_new_credentials (unsigned n)
96 unsigned i;
97 CredCacheEntry *entries;
99 entries = (CredCacheEntry*)calloc (n, sizeof (CredCacheEntry));
100 if (entries == NULL)
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]);
106 ncredentials += n;
110 * Initialize the cred cache.
113 void
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");
122 ncredentials = 0;
123 create_new_credentials (nentries);
126 static CredCacheEntry *
127 internal_get (long cell, nnpfs_pag_t cred, int type)
129 CredCacheEntry *e;
130 CredCacheEntry key;
132 if (cell == CRED_ROOT_CELL)
133 return NULL;
135 key.cell = cell;
136 key.type = type;
137 key.cred = cred;
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);
145 if (e != NULL) {
146 ++e->refcount;
147 assert(e->cell != CRED_ROOT_CELL);
150 return e;
153 struct list_pag {
154 int (*func)(CredCacheEntry *, void *);
155 void *arg;
158 static Bool
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 *),
170 void *ptr)
172 CredCacheEntry key, *root_e;
173 struct list_pag d;
175 key.cell = CRED_ROOT_CELL;
176 key.type = type;
177 key.cred = cred;
179 root_e = (CredCacheEntry *)hashtabsearch (credhtab, (void *)&key);
180 if (root_e == NULL)
181 return 0;
183 d.func = func;
184 d.arg = ptr;
186 listiter(root_e->pag.list, list_pag_func, &d);
188 return 0;
191 CredCacheEntry *
192 cred_get (long cell, nnpfs_pag_t cred, int type)
194 if (type == CRED_ANY) {
195 CredCacheEntry *e;
196 int i;
198 for (i = CRED_MAX; i > CRED_NONE; --i) {
199 e = internal_get (cell, cred, i);
200 if (e != NULL)
201 return e;
204 return internal_get (cell, cred, CRED_NONE);
205 } else
206 return internal_get (cell, cred, type);
209 void
210 cred_ref(CredCacheEntry *cred)
212 ++cred->refcount;
215 static void
216 recycle_entry (CredCacheEntry *ce)
218 assert(ce->refcount == 0);
220 if (ce->cell != CRED_ROOT_CELL)
221 root_free(ce);
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;
235 void
236 cred_free (CredCacheEntry *ce)
238 if(ce == NULL)
239 return;
240 assert (ce->cell != CRED_ROOT_CELL);
242 --ce->refcount;
243 if (ce->flags.killme && ce->refcount == 0)
244 recycle_entry (ce);
247 static CredCacheEntry *
248 get_free_cred (void)
250 CredCacheEntry *e;
252 e = (CredCacheEntry *)listdelhead (freelist);
253 if (e != NULL)
254 return e;
256 create_new_credentials (CREDFREEINC);
258 e = (CredCacheEntry *)listdelhead (freelist);
259 if (e != NULL)
260 return e;
262 arla_errx (1, ADEBERROR,
263 "credcache: there was no way of getting a cred");
266 static void
267 root_free(CredCacheEntry *e)
269 CredCacheEntry key, *root_e;
271 assert(e->cell != CRED_ROOT_CELL);
273 if (e->pag.li == NULL)
274 return;
276 key.cell = CRED_ROOT_CELL;
277 key.type = e->type;
278 key.cred = e->cred;
280 root_e = (CredCacheEntry *)hashtabsearch (credhtab, (void *)&key);
281 assert(root_e);
283 listdel(root_e->pag.list, e->pag.li);
284 e->pag.li = NULL;
286 if (listemptyp(root_e->pag.list)) {
287 listfree(root_e->pag.list);
288 root_e->pag.list = NULL;
289 recycle_entry(root_e);
293 static void
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;
301 key.type = e->type;
302 key.cred = e->cred;
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;
312 root_e->expire = 0;
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);
326 CredCacheEntry *
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,
329 uid_t uid)
331 void *data;
332 CredCacheEntry *e;
333 CredCacheEntry *old;
335 if (cred_data != NULL) {
336 data = malloc (cred_data_sz);
337 if (data == NULL)
338 return NULL;
339 memcpy (data, cred_data, cred_data_sz);
340 } else
341 data = NULL;
343 e = get_free_cred ();
345 e->cred = cred;
346 e->type = type;
347 e->securityindex = securityindex;
348 e->cell = cell;
349 e->expire = expire;
350 e->cred_data = data;
351 e->uid = uid;
352 e->pag.li = NULL;
354 add_to_root_entry(e);
356 old = (CredCacheEntry *)hashtabsearch (credhtab, (void *)e);
357 if (old != NULL)
358 cred_delete (old);
360 hashtabadd (credhtab, e);
362 ++nactive_credentials;
364 return e;
371 void
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);
379 root_free(ce);
380 } else
381 recycle_entry (ce);
388 void
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);
397 else
398 arla_warnx (ADEBWARN,
399 "Credentials for UID %u in cell unknown %ld have expired",
400 (unsigned)ce->uid, ce->cell);
402 cred_delete (ce);
405 static Bool
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)
412 return FALSE;
414 if (ce->cred == *cred)
415 cred_delete (ce);
416 return FALSE;
419 void
420 cred_remove (nnpfs_pag_t cred)
422 hashtabforeach (credhtab, remove_entry, &cred);
425 static Bool
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);
434 return FALSE;
437 void
438 cred_status (void)
440 arla_log(ADEBVLOG, "%u(%u) credentials",
441 nactive_credentials, ncredentials);
442 hashtabforeach (credhtab, print_cred, NULL);
445 static Bool
446 foreach_cred (void *ptr, void *arg)
448 CredCacheEntry *e = (CredCacheEntry *)ptr;
449 Bool (* func)(CredCacheEntry *e) = (Bool (*)(CredCacheEntry *e)) arg;
451 func(e);
452 return FALSE;
455 void
456 cred_foreach (Bool (* func)(CredCacheEntry *e))
458 hashtabforeach (credhtab, foreach_cred, func);