2 Copyright (C) 1989 by the Massachusetts Institute of Technology
4 Export of this software from the United States of America is assumed
5 to require a specific license from the United States Government.
6 It is the responsibility of any person or organization contemplating
7 export to obtain such a license before exporting.
9 WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10 distribute this software and its documentation for any purpose and
11 without fee is hereby granted, provided that the above copyright
12 notice appear in all copies and that both that copyright notice and
13 this permission notice appear in supporting documentation, and that
14 the name of M.I.T. not be used in advertising or publicity pertaining
15 to distribution of the software without specific, written prior
16 permission. M.I.T. makes no representations about the suitability of
17 this software for any purpose. It is provided "as is" without express
24 RCSID("$Id: krb_dbm.c,v 1.37 1999/09/16 20:41:49 assar Exp $");
28 #define KERB_DB_MAX_RETRY 5
32 extern long kerb_debug;
33 extern char *progname;
37 static char default_db_name[] = DBM_FILE;
38 static char *current_db_name = default_db_name;
40 static struct timeval timestamp;/* current time of request */
41 static int non_blocking = 0;
44 * This module contains all of the code which directly interfaces to
45 * the underlying representation of the Kerberos database; this
46 * implementation uses a DBM or NDBM indexed "file" (actually
47 * implemented as two separate files) to store the relations, plus a
48 * third file as a semaphore to allow the database to be replaced out
49 * from underneath the KDC server.
55 * There are two distinct locking protocols used. One is designed to
56 * lock against processes (the admin_server, for one) which make
57 * incremental changes to the database; the other is designed to lock
58 * against utilities (kdb_util, kpropd) which replace the entire
59 * database in one fell swoop.
61 * The first locking protocol is implemented using flock() in the
62 * krb_dbl_lock() and krb_dbl_unlock routines.
64 * The second locking protocol is necessary because DBM "files" are
65 * actually implemented as two separate files, and it is impossible to
66 * atomically rename two files simultaneously. It assumes that the
67 * database is replaced only very infrequently in comparison to the time
68 * needed to do a database read operation.
70 * A third file is used as a "version" semaphore; the modification
71 * time of this file is the "version number" of the database.
72 * At the start of a read operation, the reader checks the version
73 * number; at the end of the read operation, it checks again. If the
74 * version number changed, or if the semaphore was nonexistant at
75 * either time, the reader sleeps for a second to let things
76 * stabilize, and then tries again; if it does not succeed after
77 * KERB_DB_MAX_RETRY attempts, it gives up.
79 * On update, the semaphore file is deleted (if it exists) before any
80 * update takes place; at the end of the update, it is replaced, with
81 * a version number strictly greater than the version number which
82 * existed at the start of the update.
84 * If the system crashes in the middle of an update, the semaphore
85 * file is not automatically created on reboot; this is a feature, not
86 * a bug, since the database may be inconsistant. Note that the
87 * absence of a semaphore file does not prevent another _update_ from
88 * taking place later. Database replacements take place automatically
89 * only on slave servers; a crash in the middle of an update will be
90 * fixed by the next slave propagation. A crash in the middle of an
91 * update on the master would be somewhat more serious, but this would
92 * likely be noticed by an administrator, who could fix the problem and
93 * retry the operation.
98 * Utility routine: generate name of database file.
102 gen_dbsuffix(char *db_name, char *sfx)
109 asprintf (&dbsuffix, "%s%s", db_name, sfx);
110 if (dbsuffix == NULL) {
111 fprintf (stderr, "gen_dbsuffix: out of memory\n");
118 decode_princ_key(datum *key, char *name, char *instance)
120 strlcpy (name, key->dptr, ANAME_SZ);
121 strlcpy (instance, (char *)key->dptr + ANAME_SZ, INST_SZ);
125 encode_princ_contents(datum *contents, Principal *principal)
127 contents->dsize = sizeof(*principal);
128 contents->dptr = (char *) principal;
132 decode_princ_contents (datum *contents, Principal *principal)
134 memcpy(principal, contents->dptr, sizeof(*principal));
138 encode_princ_key (datum *key, char *name, char *instance)
140 static char keystring[ANAME_SZ + INST_SZ];
142 memset(keystring, 0, ANAME_SZ + INST_SZ);
143 strncpy(keystring, name, ANAME_SZ);
144 strncpy(&keystring[ANAME_SZ], instance, INST_SZ);
145 key->dptr = keystring;
146 key->dsize = ANAME_SZ + INST_SZ;
149 static int dblfd = -1; /* db LOCK fd */
150 static int mylock = 0;
151 static int inited = 0;
157 char *filename = gen_dbsuffix (current_db_name, ".ok");
158 if ((dblfd = open(filename, O_RDWR)) < 0) {
159 fprintf(stderr, "kerb_dbl_init: couldn't open %s\n", filename);
180 kerb_dbl_lock(int mode)
186 if (mylock) { /* Detect lock call when lock already
188 fprintf(stderr, "Kerberos locking error (mylock)\n");
193 case KERB_DBL_EXCLUSIVE:
194 flock_mode = LOCK_EX;
196 case KERB_DBL_SHARED:
197 flock_mode = LOCK_SH;
200 fprintf(stderr, "invalid lock mode %d\n", mode);
204 flock_mode |= LOCK_NB;
206 if (flock(dblfd, flock_mode) < 0)
213 kerb_dbl_unlock(void)
215 if (!mylock) { /* lock already unlocked */
216 fprintf(stderr, "Kerberos database lock not locked when unlocking.\n");
220 if (flock(dblfd, LOCK_UN) < 0) {
221 fprintf(stderr, "Kerberos database lock error. (unlocking)\n");
230 kerb_db_set_lockmode(int mode)
232 int old = non_blocking;
238 * initialization for data base routines.
249 * gracefully shut down database--must be called by ANY program that does
259 * Set the "name" of the current database to some alternate value.
261 * Passing a null pointer as "name" will set back to the default.
262 * If the alternate database doesn't exist, nothing is changed.
266 kerb_db_set_name(char *name)
271 name = default_db_name;
272 db = dbm_open(name, 0, 0);
277 current_db_name = name;
282 * Return the last modification time of the database.
286 kerb_get_db_age(void)
292 okname = gen_dbsuffix(current_db_name, ".ok");
294 if (stat (okname, &st) < 0)
304 * Remove the semaphore file; indicates that database is currently
307 * This is only for use when moving the database out from underneath
308 * the server (for example, during slave updates).
312 kerb_start_update(char *db_name)
314 char *okname = gen_dbsuffix(db_name, ".ok");
315 time_t age = kerb_get_db_age();
317 if (unlink(okname) < 0
318 && errno != ENOENT) {
326 kerb_end_update(char *db_name, time_t age)
330 char *new_okname = gen_dbsuffix(db_name, ".ok#");
331 char *okname = gen_dbsuffix(db_name, ".ok");
333 fd = open (new_okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
339 /* make sure that semaphore is "after" previous value. */
340 if (fstat (fd, &st) == 0
341 && st.st_mtime <= age) {
342 tv.actime = st.st_atime;
345 utime (new_okname, &tv);
349 if (rename (new_okname, okname) < 0)
360 kerb_start_read(void)
362 return kerb_get_db_age();
366 kerb_end_read(time_t age)
368 if (kerb_get_db_age() != age || age == -1) {
375 * Create the database, assuming it's not there.
378 kerb_db_create(char *db_name)
380 char *okname = gen_dbsuffix(db_name, ".ok");
386 db = dbm_open(db_name, O_RDWR|O_CREAT|O_EXCL, 0600);
392 char *dirname = gen_dbsuffix(db_name, ".dir");
393 char *pagname = gen_dbsuffix(db_name, ".pag");
395 fd = open(dirname, O_RDWR|O_CREAT|O_EXCL, 0600);
400 fd = open (pagname, O_RDWR|O_CREAT|O_EXCL, 0600);
406 if (dbminit(db_name) < 0)
410 fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
419 * "Atomically" rename the database in a way that locks out read
420 * access in the middle of the rename.
422 * Not perfect; if we crash in the middle of an update, we don't
423 * necessarily know to complete the transaction the rename, but...
427 kerb_db_rename(char *from, char *to)
430 char *fromdb = gen_dbsuffix (from, ".db");
431 char *todb = gen_dbsuffix (to, ".db");
433 char *fromdir = gen_dbsuffix (from, ".dir");
434 char *todir = gen_dbsuffix (to, ".dir");
435 char *frompag = gen_dbsuffix (from , ".pag");
436 char *topag = gen_dbsuffix (to, ".pag");
438 char *fromok = gen_dbsuffix(from, ".ok");
439 long trans = kerb_start_update(to);
443 if (rename (fromdb, todb) == 0) {
450 if ((rename (fromdir, todir) == 0)
451 && (rename (frompag, topag) == 0)) {
462 return kerb_end_update(to, trans);
468 kerb_db_delete_principal (char *name, char *inst)
479 for(try = 0; try < KERB_DB_MAX_RETRY; try++){
480 if((code = kerb_dbl_lock(KERB_DBL_EXCLUSIVE)) != 0)
483 db = dbm_open(current_db_name, O_RDWR, 0600);
486 encode_princ_key(&key, name, inst);
487 if(dbm_delete(db, key) == 0)
504 * look up a principal in the data base returns number of principals
505 * found , and whether there were more than requested.
509 kerb_db_get_principal (char *name, char *inst, Principal *principal,
510 unsigned int max, int *more)
515 char testname[ANAME_SZ], testinst[INST_SZ];
521 kerb_db_init(); /* initialize database routines */
523 for (try = 0; try < KERB_DB_MAX_RETRY; try++) {
524 trans = kerb_start_read();
526 if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
529 db = dbm_open(current_db_name, O_RDONLY, 0600);
538 "%s: db_get_principal for %s %s max = %d",
539 progname, name, inst, max);
542 wildp = !strcmp(name, "*");
543 wildi = !strcmp(inst, "*");
545 if (!wildi && !wildp) { /* nothing's wild */
546 encode_princ_key(&key, name, inst);
547 contents = dbm_fetch(db, key);
548 if (contents.dptr == NULL) {
552 decode_princ_contents(&contents, principal);
554 if (kerb_debug & 1) {
555 fprintf(stderr, "\t found %s %s p_n length %d t_n length %d\n",
556 principal->name, principal->instance,
557 strlen(principal->name),
558 strlen(principal->instance));
564 /* process wild cards by looping through entire database */
566 for (key = dbm_firstkey(db); key.dptr != NULL;
567 key = dbm_next(db, key)) {
568 decode_princ_key(&key, testname, testinst);
569 if ((wildp || !strcmp(testname, name)) &&
570 (wildi || !strcmp(testinst, inst))) { /* have a match */
576 contents = dbm_fetch(db, key);
577 decode_princ_contents(&contents, principal);
579 if (kerb_debug & 1) {
581 "\tfound %s %s p_n length %d t_n length %d\n",
582 principal->name, principal->instance,
583 strlen(principal->name),
584 strlen(principal->instance));
587 principal++; /* point to next */
593 kerb_dbl_unlock(); /* unlock read lock */
595 if (kerb_end_read(trans) == 0)
604 /* Use long * rather than DBM * so that the database structure is private */
607 kerb_db_begin_update(void)
611 gettimeofday(×tamp, NULL);
616 if ((code = kerb_dbl_lock(KERB_DBL_EXCLUSIVE)) != 0)
619 return (long *) dbm_open(current_db_name, O_RDWR, 0600);
623 kerb_db_end_update(long *db)
625 dbm_close((DBM *)db);
626 kerb_dbl_unlock(); /* unlock database */
630 kerb_db_update(long *db, Principal *principal, unsigned int max)
638 fprintf(stderr, "%s: kerb_db_put_principal max = %d",
642 /* for each one, stuff temps, and do replace/append */
643 for (i = 0; i < max; i++) {
644 encode_princ_contents(&contents, principal);
645 encode_princ_key(&key, principal->name, principal->instance);
646 if(dbm_store((DBM *)db, key, contents, DBM_REPLACE) < 0)
647 return found; /* XXX some better mechanism to report
648 failure should exist */
650 if (kerb_debug & 1) {
651 fprintf(stderr, "\n put %s %s\n",
652 principal->name, principal->instance);
656 principal++; /* bump to next struct */
662 * Update a name in the data base. Returns number of names
663 * successfully updated.
667 kerb_db_put_principal(Principal *principal,
674 db = kerb_db_begin_update();
678 found = kerb_db_update(db, principal, max);
680 kerb_db_end_update(db);
685 kerb_db_get_stat(DB_stat *s)
687 gettimeofday(×tamp, NULL);
693 s->t_stamp = timestamp.tv_sec;
699 /* update local copy too */
703 kerb_db_put_stat(DB_stat *s)
708 delta_stat(DB_stat *a, DB_stat *b, DB_stat *c)
710 /* c = a - b then b = a for the next time */
712 c->cpu = a->cpu - b->cpu;
713 c->elapsed = a->elapsed - b->elapsed;
714 c->dio = a->dio - b->dio;
715 c->pfault = a->pfault - b->pfault;
716 c->t_stamp = a->t_stamp - b->t_stamp;
717 c->n_retrieve = a->n_retrieve - b->n_retrieve;
718 c->n_replace = a->n_replace - b->n_replace;
719 c->n_append = a->n_append - b->n_append;
720 c->n_get_stat = a->n_get_stat - b->n_get_stat;
721 c->n_put_stat = a->n_put_stat - b->n_put_stat;
723 memcpy(b, a, sizeof(DB_stat));
727 * look up a dba in the data base returns number of dbas found , and
728 * whether there were more than requested.
732 kerb_db_get_dba(char *dba_name, /* could have wild card */
733 char *dba_inst, /* could have wild card */
735 unsigned max, /* max number of name structs to return */
736 int *more) /* where there more than 'max' tuples? */
743 kerb_db_iterate (k_iter_proc_t func, void *arg)
746 Principal *principal;
750 kerb_db_init(); /* initialize and open the database */
751 if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
754 db = dbm_open(current_db_name, O_RDONLY, 0600);
758 for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_next(db, key)) {
759 contents = dbm_fetch (db, key);
760 /* XXX may not be properly aligned */
761 principal = (Principal *) contents.dptr;
762 if ((code = (*func)(arg, principal)) != 0)