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.27 1997/05/02 14:29:09 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.
101 static char *gen_dbsuffix (char *db_name, char *sfx);
104 gen_dbsuffix(char *db_name, char *sfx)
111 asprintf (&dbsuffix, "%s%s", db_name, sfx);
116 decode_princ_key (datum *key, char *name, char *instance);
119 decode_princ_key(datum *key, char *name, char *instance)
121 strncpy(name, key->dptr, ANAME_SZ);
122 strncpy(instance, (char *)key->dptr + ANAME_SZ, INST_SZ);
123 name[ANAME_SZ - 1] = '\0';
124 instance[INST_SZ - 1] = '\0';
128 encode_princ_contents (datum *contents, Principal *principal);
131 encode_princ_contents(datum *contents, Principal *principal)
133 contents->dsize = sizeof(*principal);
134 contents->dptr = (char *) principal;
138 decode_princ_contents (datum *contents, Principal *principal)
140 memcpy(principal, contents->dptr, sizeof(*principal));
144 encode_princ_key (datum *key, char *name, char *instance)
146 static char keystring[ANAME_SZ + INST_SZ];
148 memset(keystring, 0, ANAME_SZ + INST_SZ);
149 strncpy(keystring, name, ANAME_SZ);
150 strncpy(&keystring[ANAME_SZ], instance, INST_SZ);
151 key->dptr = keystring;
152 key->dsize = ANAME_SZ + INST_SZ;
155 static int dblfd = -1; /* db LOCK fd */
156 static int mylock = 0;
157 static int inited = 0;
160 kerb_dbl_init (void);
166 char *filename = gen_dbsuffix (current_db_name, ".ok");
167 if ((dblfd = open(filename, O_RDWR)) < 0) {
168 fprintf(stderr, "kerb_dbl_init: couldn't open %s\n", filename);
180 kerb_dbl_fini (void);
192 kerb_dbl_lock (int mode);
195 kerb_dbl_lock(int mode)
201 if (mylock) { /* Detect lock call when lock already
203 fprintf(stderr, "Kerberos locking error (mylock)\n");
208 case KERB_DBL_EXCLUSIVE:
209 flock_mode = K_LOCK_EX;
211 case KERB_DBL_SHARED:
212 flock_mode = K_LOCK_SH;
215 fprintf(stderr, "invalid lock mode %d\n", mode);
219 flock_mode |= K_LOCK_NB;
221 if (k_flock(dblfd, flock_mode) < 0)
227 static void kerb_dbl_unlock (void);
232 if (!mylock) { /* lock already unlocked */
233 fprintf(stderr, "Kerberos database lock not locked when unlocking.\n");
237 if (k_flock(dblfd, K_LOCK_UN) < 0) {
238 fprintf(stderr, "Kerberos database lock error. (unlocking)\n");
247 kerb_db_set_lockmode (int mode);
250 kerb_db_set_lockmode(int mode)
252 int old = non_blocking;
258 * initialization for data base routines.
272 * gracefully shut down database--must be called by ANY program that does
285 * Set the "name" of the current database to some alternate value.
287 * Passing a null pointer as "name" will set back to the default.
288 * If the alternate database doesn't exist, nothing is changed.
292 kerb_db_set_name (char *name);
295 kerb_db_set_name(char *name)
300 name = default_db_name;
301 db = dbm_open(name, 0, 0);
306 current_db_name = name;
311 * Return the last modification time of the database.
315 kerb_get_db_age (void);
324 okname = gen_dbsuffix(current_db_name, ".ok");
326 if (stat (okname, &st) < 0)
336 * Remove the semaphore file; indicates that database is currently
339 * This is only for use when moving the database out from underneath
340 * the server (for example, during slave updates).
344 kerb_start_update (char *db_name);
347 kerb_start_update(char *db_name)
349 char *okname = gen_dbsuffix(db_name, ".ok");
350 time_t age = kerb_get_db_age();
352 if (unlink(okname) < 0
353 && errno != ENOENT) {
361 kerb_end_update (char *db_name, time_t age);
364 kerb_end_update(char *db_name, time_t age)
368 char *new_okname = gen_dbsuffix(db_name, ".ok#");
369 char *okname = gen_dbsuffix(db_name, ".ok");
371 fd = open (new_okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
377 /* make sure that semaphore is "after" previous value. */
378 if (fstat (fd, &st) == 0
379 && st.st_mtime <= age) {
380 tv.actime = st.st_atime;
383 utime (new_okname, &tv);
387 if (rename (new_okname, okname) < 0)
398 kerb_start_read (void);
403 return kerb_get_db_age();
406 static int kerb_end_read (time_t age);
409 kerb_end_read(time_t age)
411 if (kerb_get_db_age() != age || age == -1) {
418 * Create the database, assuming it's not there.
421 kerb_db_create(char *db_name)
423 char *okname = gen_dbsuffix(db_name, ".ok");
429 db = dbm_open(db_name, O_RDWR|O_CREAT|O_EXCL, 0600);
435 char *dirname = gen_dbsuffix(db_name, ".dir");
436 char *pagname = gen_dbsuffix(db_name, ".pag");
438 fd = open(dirname, O_RDWR|O_CREAT|O_EXCL, 0600);
443 fd = open (pagname, O_RDWR|O_CREAT|O_EXCL, 0600);
449 if (dbminit(db_name) < 0)
453 fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
462 * "Atomically" rename the database in a way that locks out read
463 * access in the middle of the rename.
465 * Not perfect; if we crash in the middle of an update, we don't
466 * necessarily know to complete the transaction the rename, but...
470 kerb_db_rename(char *from, char *to)
473 char *fromdb = gen_dbsuffix (from, ".db");
474 char *todb = gen_dbsuffix (to, ".db");
476 char *fromdir = gen_dbsuffix (from, ".dir");
477 char *todir = gen_dbsuffix (to, ".dir");
478 char *frompag = gen_dbsuffix (from , ".pag");
479 char *topag = gen_dbsuffix (to, ".pag");
481 char *fromok = gen_dbsuffix(from, ".ok");
482 long trans = kerb_start_update(to);
486 if (rename (fromdb, todb) == 0) {
493 if ((rename (fromdir, todir) == 0)
494 && (rename (frompag, topag) == 0)) {
505 return kerb_end_update(to, trans);
511 kerb_db_delete_principal (char *name, char *inst)
522 for(try = 0; try < KERB_DB_MAX_RETRY; try++){
523 if((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
526 db = dbm_open(current_db_name, O_RDWR, 0600);
529 encode_princ_key(&key, name, inst);
530 if(dbm_delete(db, key) == 0)
547 * look up a principal in the data base returns number of principals
548 * found , and whether there were more than requested.
552 kerb_db_get_principal (char *name, char *inst, Principal *principal,
553 unsigned int max, int *more)
558 char testname[ANAME_SZ], testinst[INST_SZ];
564 kerb_db_init(); /* initialize database routines */
566 for (try = 0; try < KERB_DB_MAX_RETRY; try++) {
567 trans = kerb_start_read();
569 if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
572 db = dbm_open(current_db_name, O_RDONLY, 0600);
579 "%s: db_get_principal for %s %s max = %d",
580 progname, name, inst, max);
583 wildp = !strcmp(name, "*");
584 wildi = !strcmp(inst, "*");
586 if (!wildi && !wildp) { /* nothing's wild */
587 encode_princ_key(&key, name, inst);
588 contents = dbm_fetch(db, key);
589 if (contents.dptr == NULL) {
593 decode_princ_contents(&contents, principal);
595 if (kerb_debug & 1) {
596 fprintf(stderr, "\t found %s %s p_n length %d t_n length %d\n",
597 principal->name, principal->instance,
598 strlen(principal->name),
599 strlen(principal->instance));
605 /* process wild cards by looping through entire database */
607 for (key = dbm_firstkey(db); key.dptr != NULL;
608 key = dbm_next(db, key)) {
609 decode_princ_key(&key, testname, testinst);
610 if ((wildp || !strcmp(testname, name)) &&
611 (wildi || !strcmp(testinst, inst))) { /* have a match */
617 contents = dbm_fetch(db, key);
618 decode_princ_contents(&contents, principal);
620 if (kerb_debug & 1) {
622 "\tfound %s %s p_n length %d t_n length %d\n",
623 principal->name, principal->instance,
624 strlen(principal->name),
625 strlen(principal->instance));
628 principal++; /* point to next */
634 kerb_dbl_unlock(); /* unlock read lock */
636 if (kerb_end_read(trans) == 0)
645 /* Use long * rather than DBM * so that the database structure is private */
648 kerb_db_begin_update(void)
652 gettimeofday(×tamp, NULL);
657 if ((code = kerb_dbl_lock(KERB_DBL_EXCLUSIVE)) != 0)
660 return (long *) dbm_open(current_db_name, O_RDWR, 0600);
664 kerb_db_end_update(long *db)
666 dbm_close((DBM *)db);
667 kerb_dbl_unlock(); /* unlock database */
671 kerb_db_update(long *db, Principal *principal, unsigned int max)
679 fprintf(stderr, "%s: kerb_db_put_principal max = %d",
683 /* for each one, stuff temps, and do replace/append */
684 for (i = 0; i < max; i++) {
685 encode_princ_contents(&contents, principal);
686 encode_princ_key(&key, principal->name, principal->instance);
687 dbm_store((DBM *)db, key, contents, DBM_REPLACE);
689 if (kerb_debug & 1) {
690 fprintf(stderr, "\n put %s %s\n",
691 principal->name, principal->instance);
695 principal++; /* bump to next struct */
701 * Update a name in the data base. Returns number of names
702 * successfully updated.
706 kerb_db_put_principal (Principal *principal, unsigned int max);
709 kerb_db_put_principal(Principal *principal,
716 db = kerb_db_begin_update();
720 found = kerb_db_update(db, principal, max);
722 kerb_db_end_update(db);
727 kerb_db_get_stat (DB_stat *s);
730 kerb_db_get_stat(DB_stat *s)
732 gettimeofday(×tamp, NULL);
738 s->t_stamp = timestamp.tv_sec;
744 /* update local copy too */
748 kerb_db_put_stat (DB_stat *s);
751 kerb_db_put_stat(DB_stat *s)
756 delta_stat (DB_stat *a, DB_stat *b, DB_stat *c);
759 delta_stat(DB_stat *a, DB_stat *b, DB_stat *c)
761 /* c = a - b then b = a for the next time */
763 c->cpu = a->cpu - b->cpu;
764 c->elapsed = a->elapsed - b->elapsed;
765 c->dio = a->dio - b->dio;
766 c->pfault = a->pfault - b->pfault;
767 c->t_stamp = a->t_stamp - b->t_stamp;
768 c->n_retrieve = a->n_retrieve - b->n_retrieve;
769 c->n_replace = a->n_replace - b->n_replace;
770 c->n_append = a->n_append - b->n_append;
771 c->n_get_stat = a->n_get_stat - b->n_get_stat;
772 c->n_put_stat = a->n_put_stat - b->n_put_stat;
774 memcpy(b, a, sizeof(DB_stat));
779 * look up a dba in the data base returns number of dbas found , and
780 * whether there were more than requested.
784 kerb_db_get_dba (char *dba_name, char *dba_inst, Dba *dba, unsigned int max, int *more);
787 kerb_db_get_dba(char *dba_name, char *dba_inst, Dba *dba,
790 /* could have wild card */
791 /* could have wild card */
792 /* max number of name structs to return */
793 /* where there more than 'max' tuples? */
800 kerb_db_iterate (k_iter_proc_t func, void *arg)
803 Principal *principal;
807 kerb_db_init(); /* initialize and open the database */
808 if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
811 db = dbm_open(current_db_name, O_RDONLY, 0600);
813 for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_next(db, key)) {
814 contents = dbm_fetch (db, key);
815 /* XXX may not be properly aligned */
816 principal = (Principal *) contents.dptr;
817 if ((code = (*func)(arg, principal)) != 0)