From: Ken Raeburn Date: Fri, 10 Jun 2005 02:48:13 +0000 (+0000) Subject: * kdb_dbm.c: Unused file deleted X-Git-Tag: ms-bug-test-20060525~238 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=bd8956afa9c2b16ba7a60d6498faa49b4b755474;p=krb5.git * kdb_dbm.c: Unused file deleted git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17235 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/lib/kdb/ChangeLog b/src/lib/kdb/ChangeLog index e69af02a2..99e6b58ca 100644 --- a/src/lib/kdb/ChangeLog +++ b/src/lib/kdb/ChangeLog @@ -1,3 +1,7 @@ +2005-06-09 Ken Raeburn + + * kdb_dbm.c: Unused file deleted. + 2004-07-09 Ken Raeburn * kdb_db2.c (krb5_db2_db_get_principal): Rename local variable diff --git a/src/lib/kdb/kdb_dbm.c b/src/lib/kdb/kdb_dbm.c deleted file mode 100644 index 4769ba9c7..000000000 --- a/src/lib/kdb/kdb_dbm.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* - * lib/kdb/kdb_dbm.c - * - * Copyright 1988,1989,1990,1991 by the Massachusetts Institute of Technology. - * All Rights Reserved. - * - * Export of this software from the United States of America may - * require a specific license from the United States Government. - * It is the responsibility of any person or organization contemplating - * export to obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of M.I.T. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Furthermore if you modify this software you must label - * your software as modified software and not distribute it in such a - * fashion that it might be confused with the original M.I.T. software. - * M.I.T. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - */ - -#if HAVE_UNISTD_H -#include -#endif - -/* Obtain dispatch table definitions from kdb.h */ -#define KDB5_DISPATCH -#include "k5-int.h" -#include "kdb_dbc.h" -#include -#include -#include - -#define OLD_COMPAT_VERSION_1 - -#ifdef OLD_COMPAT_VERSION_1 -#include "kdb_compat.h" -#endif - -#define KRB5_DBM_MAX_RETRY 5 - -#ifdef DEBUG -extern int debug; -extern long krb5_dbm_db_debug; -extern char *progname; -#endif - -static char default_db_name[] = DEFAULT_KDB_FILE; - -static char *gen_dbsuffix - (char *, char * ); -static krb5_error_code krb5_dbm_db_start_update - (krb5_context); -static krb5_error_code krb5_dbm_db_end_update - (krb5_context); - -/* - * This module contains all of the code which directly interfaces to - * the underlying representation of the Kerberos database; this - * implementation uses the Berkeley hash db to store the relations, plus a - * second file as a semaphore to allow the database to be replaced out - * from underneath the KDC server. - */ -static kdb5_dispatch_table kdb5_default_dispatch = { - "Berkeley Hashed Database w/ DBM interface", - ".db", /* Index file name ext */ - (char *) NULL, /* Data file name ext */ - ".ok", /* Lock file name ext */ - dbm_open, /* Open Database */ - dbm_close, /* Close Database */ - dbm_fetch, /* Fetch Key */ - dbm_firstkey, /* Fetch First Key */ - dbm_nextkey, /* Fetch Next Key */ - dbm_delete, /* Delete Key */ - dbm_store, /* Store Key */ - /* - * The following are #ifdef'd because they have the potential to be - * macros rather than functions. - */ - (int (*)()) NULL, /* Get DB index FD num */ - (int (*)()) NULL, /* Get DB data FD num */ -}; - -/* - * These macros dispatch via the dispatch table. - */ -#define KDBM_OPEN(dbc, db, fl, mo) ((*(((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_dbm_open)) \ - (db, fl, mo)) -#define KDBM_CLOSE(dbc, db) ((*(((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_dbm_close))(db)) -#define KDBM_FETCH(dbc, db, key) ((*(((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_dbm_fetch)) \ - (db, key)) -#define KDBM_FIRSTKEY(dbc, db) ((*(((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_dbm_firstkey)) \ - (db)) -#define KDBM_NEXTKEY(dbc, db) ((*(((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_dbm_nextkey)) \ - (db)) -#define KDBM_DELETE(dbc, db, key) ((*(((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_dbm_delete)) \ - (db, key)) -#define KDBM_STORE(dbc, db, key, c, f) ((*(((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_dbm_store)) \ - (db, key, c, f)) -#define KDBM_INDEX_EXT(dbc) (((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_db_index_ext) -#define KDBM_DATA_EXT(dbc) (((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_db_data_ext) -#define KDBM_LOCK_EXT(dbc) (((krb5_db_context *)dbc)-> \ - db_dispatch->kdb5_db_lock_ext) - -/* - * Locking: - * - * There are two distinct locking protocols used. One is designed to - * lock against processes (the admin_server, for one) which make - * incremental changes to the database; the other is designed to lock - * against utilities (kdb5_edit, kpropd, kdb5_convert) which replace the - * entire database in one fell swoop. - * - * The first locking protocol is implemented using flock() in the - * krb_dbl_lock() and krb_dbl_unlock routines. - * - * The second locking protocol is necessary because DBM "files" are - * actually implemented as two separate files, and it is impossible to - * atomically rename two files simultaneously. It assumes that the - * database is replaced only very infrequently in comparison to the time - * needed to do a database read operation. - * - * A third file is used as a "version" semaphore; the modification - * time of this file is the "version number" of the database. - * At the start of a read operation, the reader checks the version - * number; at the end of the read operation, it checks again. If the - * version number changed, or if the semaphore was nonexistant at - * either time, the reader sleeps for a second to let things - * stabilize, and then tries again; if it does not succeed after - * KRB5_DBM_MAX_RETRY attempts, it gives up. - * - * On update, the semaphore file is deleted (if it exists) before any - * update takes place; at the end of the update, it is replaced, with - * a version number strictly greater than the version number which - * existed at the start of the update. - * - * If the system crashes in the middle of an update, the semaphore - * file is not automatically created on reboot; this is a feature, not - * a bug, since the database may be inconsistant. Note that the - * absence of a semaphore file does not prevent another _update_ from - * taking place later. Database replacements take place automatically - * only on slave servers; a crash in the middle of an update will be - * fixed by the next slave propagation. A crash in the middle of an - * update on the master would be somewhat more serious, but this would - * likely be noticed by an administrator, who could fix the problem and - * retry the operation. - */ - -#define free_dbsuffix(name) free(name) - -/* - * Routines to deal with context. - */ -#define k5dbm_inited(c) (c && c->db_context && \ - ((krb5_db_context *) c->db_context)->db_inited) - -/* - * Restore the default context. - */ -static void -k5dbm_clear_context(dbctx) - krb5_db_context * dbctx; -{ - /* - * Free any dynamically allocated memory. File descriptors and locks - * are the caller's problem. - */ - if (dbctx->db_lf_name) - free(dbctx->db_lf_name); - if (dbctx->db_name && (dbctx->db_name != default_db_name)) - free(dbctx->db_name); - /* - * Clear the structure and reset the defaults. - */ - memset((char *) dbctx, 0, sizeof(krb5_db_context)); - dbctx->db_name = default_db_name; - dbctx->db_nb_locks = FALSE; - dbctx->db_dispatch = &kdb5_default_dispatch; -} - -static krb5_error_code -k5dbm_init_context(context) - krb5_context context; -{ - krb5_db_context * db_ctx; - - if (context->db_context == NULL) { - if ((db_ctx = (krb5_db_context *) malloc(sizeof(krb5_db_context)))) { - memset((char *) db_ctx, 0, sizeof(krb5_db_context)); - k5dbm_clear_context((krb5_db_context *)db_ctx); - context->db_context = (void *) db_ctx; - } else - return(ENOMEM); - } - return(0); -} - -/* - * Utility routine: generate name of database file. - */ - -static char * -gen_dbsuffix(db_name, sfx) -char *db_name; -char *sfx; -{ - char *dbsuffix; - - if (sfx == NULL) - return((char *) NULL); - - dbsuffix = malloc (strlen(db_name) + strlen(sfx) + 1); - if (!dbsuffix) - return(0); - (void) strcpy(dbsuffix, db_name); - (void) strcat(dbsuffix, sfx); - return dbsuffix; -} - -/* - * initialization for data base routines. - */ - -krb5_error_code -krb5_dbm_db_init(context) - krb5_context context; -{ - char * filename = NULL; - krb5_db_context * db_ctx; - krb5_error_code retval; - - if (k5dbm_inited(context)) - return 0; - - /* Check for presence of our context, if not present, allocate one. */ - if ((retval = k5dbm_init_context(context))) - return(retval); - - db_ctx = context->db_context; - db_ctx->db_dbm_ctx = NULL; - - if (!(filename = gen_dbsuffix (db_ctx->db_name, KDBM_LOCK_EXT(db_ctx)))) - return ENOMEM; - - /* - * should be opened read/write so that write locking can work with - * POSIX systems - */ - if ((db_ctx->db_lf_file = open(filename, O_RDWR, 0666)) < 0) { - if ((db_ctx->db_lf_file = open(filename, O_RDONLY, 0666)) < 0) { - retval = errno; - goto err_out; - } - } - db_ctx->db_lf_name = filename; - db_ctx->db_inited++; - - if ((retval = krb5_dbm_db_get_age(context, NULL, &db_ctx->db_lf_time))) - goto err_out; - - return 0; - -err_out: - db_ctx->db_dbm_ctx = (DBM *) NULL; - k5dbm_clear_context(db_ctx); - return (retval); -} - -/* - * gracefully shut down database--must be called by ANY program that does - * a krb5_dbm_db_init - */ -krb5_error_code -krb5_dbm_db_fini(context) - krb5_context context; -{ - krb5_error_code retval = 0; - krb5_db_context *db_ctx; - - db_ctx = (krb5_db_context *) context->db_context; - - if (k5dbm_inited(context)) { - if (close(db_ctx->db_lf_file)) - retval = errno; - else - retval = 0; - } - if (db_ctx) { - k5dbm_clear_context(db_ctx); - free (context->db_context); - context->db_context = NULL; - } - return retval; -} - -krb5_error_code -krb5_dbm_db_open_database(context) - krb5_context context; -{ - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - return 0; -} - -krb5_error_code -krb5_dbm_db_close_database(context) - krb5_context context; -{ - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - return 0; -} - -/* - * Set/Get the master key associated with the database - * - * These only exist because the db_context is part of the kcontext - * The should really reference the db_context - */ -krb5_error_code -krb5_dbm_db_set_mkey(context, db_context, key) - krb5_context context; - krb5_db_context * db_context; - krb5_keyblock * key; -{ - krb5_db_context *db_ctx; - - if (!k5dbm_inited(context)) - return(KRB5_KDB_DBNOTINITED); - - db_ctx = context->db_context; - db_ctx->db_master_key = key; - return 0; -} - -krb5_error_code -krb5_dbm_db_get_mkey(context, db_context, key) - krb5_context context; - krb5_db_context * db_context; - krb5_keyblock **key; -{ - krb5_db_context *db_ctx; - - if (!k5dbm_inited(context)) - return(KRB5_KDB_DBNOTINITED); - - db_ctx = context->db_context; - *key = db_ctx->db_master_key; - return 0; - -} - -/* - * Set the "name" of the current database to some alternate value. - * - * Passing a null pointer as "name" will set back to the default. - * If the alternate database doesn't exist, nothing is changed. - * - * XXX rethink this - */ - -krb5_error_code -krb5_dbm_db_set_name(context, name) - krb5_context context; - char *name; -{ - DBM *db; - krb5_db_context *db_ctx; - krb5_error_code kret; - - if (k5dbm_inited(context)) - return KRB5_KDB_DBINITED; - - /* Check for presence of our context, if not present, allocate one. */ - if ((kret = k5dbm_init_context(context))) - return(kret); - - if (name == NULL) - name = default_db_name; - - db_ctx = context->db_context; - if ((db = KDBM_OPEN(db_ctx, name, O_RDONLY, 0)) == NULL) - return errno; - - db_ctx->db_name = strdup(name); - KDBM_CLOSE(db_ctx, db); - return 0; -} - -/* - * Return the last modification time of the database. - * - * Think about using fstat. - */ - -krb5_error_code -krb5_dbm_db_get_age(context, db_name, age) - krb5_context context; - char *db_name; - time_t *age; -{ - krb5_db_context *db_ctx; - struct stat st; - - if (!k5dbm_inited(context)) - return(KRB5_KDB_DBNOTINITED); - db_ctx = (krb5_db_context *) context->db_context; - if (fstat (db_ctx->db_lf_file, &st) < 0) - *age = -1; - else - *age = st.st_mtime; - return 0; -} - -/* - * Remove the semaphore file; indicates that database is currently - * under renovation. - * - * This is only for use when moving the database out from underneath - * the server (for example, during slave updates). - */ - -static krb5_error_code -krb5_dbm_db_start_update(context) - krb5_context context; -{ - return 0; -} - -static krb5_error_code -krb5_dbm_db_end_update(context) - krb5_context context; -{ - krb5_error_code retval; - krb5_db_context *db_ctx = context->db_context; - struct stat st; - time_t now; - struct utimbuf utbuf; - - if (!k5dbm_inited(context)) - return(KRB5_KDB_DBNOTINITED); - - retval = 0; - now = time((time_t *) NULL); - if (fstat(db_ctx->db_lf_file, &st) == 0) { - if (st.st_mtime >= now) { - utbuf.actime = st.st_mtime+1; - utbuf.modtime = st.st_mtime+1; - if (utime(db_ctx->db_lf_name, &utbuf)) - retval = errno; - } - else { - if (utime(db_ctx->db_lf_name, (struct utimbuf *) NULL)) - retval = errno; - } - } - else - retval = errno; - if (!retval) { - if (fstat(db_ctx->db_lf_file, &st) == 0) - db_ctx->db_lf_time = st.st_mtime; - else - retval = errno; - } - return(retval); -} - -krb5_error_code -krb5_dbm_db_lock(context, mode) - krb5_context context; - int mode; -{ - int krb5_lock_mode; - krb5_error_code retval; - time_t mod_time; - krb5_db_context * db_ctx; - DBM * db; - - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - - db_ctx = (krb5_db_context *) context->db_context; - if (db_ctx->db_locks_held && (db_ctx->db_lock_mode >= mode)) { - /* No need to upgrade lock, just return */ - db_ctx->db_locks_held++; - return(0); - } - - if ((mode != KRB5_LOCKMODE_SHARED) && (mode != KRB5_LOCKMODE_EXCLUSIVE)) - return KRB5_KDB_BADLOCKMODE; - - if (db_ctx->db_nb_locks) - krb5_lock_mode = mode | KRB5_LOCKMODE_DONTBLOCK; - else - krb5_lock_mode = mode; - - switch (retval = krb5_lock_file(context,db_ctx->db_lf_file,krb5_lock_mode)){ - case EBADF: - if (mode == KRB5_LOCKMODE_EXCLUSIVE) - return KRB5_KDB_CANTLOCK_DB; - default: - return retval; - case 0: - break; - } - - if ((retval = krb5_dbm_db_get_age(context, NULL, &mod_time))) - goto lock_error; - - if ((db = KDBM_OPEN(db_ctx, db_ctx->db_name, - mode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR, - 0600))) { - db_ctx->db_lf_time = mod_time; - db_ctx->db_dbm_ctx = db; - } else { - retval = errno; - goto lock_error; - } - - db_ctx->db_lock_mode = mode; - db_ctx->db_locks_held++; - return 0; - -lock_error:; - db_ctx->db_lock_mode = 0; - db_ctx->db_locks_held = 0; - (void) krb5_dbm_db_unlock(context); - return retval; -} - -krb5_error_code -krb5_dbm_db_unlock(context) - krb5_context context; -{ - krb5_db_context * db_ctx; - krb5_error_code retval; - - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - - db_ctx = (krb5_db_context *) context->db_context; - if (!db_ctx->db_locks_held) /* lock already unlocked */ - return KRB5_KDB_NOTLOCKED; - - if (--(db_ctx->db_locks_held) == 0) { - KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx); - db_ctx->db_dbm_ctx = NULL; - - retval = krb5_lock_file(context, db_ctx->db_lf_file, - KRB5_LOCKMODE_UNLOCK); - db_ctx->db_lock_mode = 0; - return(retval); - } - return 0; -} - -/* - * Create the database, assuming it's not there. - */ -krb5_error_code -krb5_dbm_db_create(context, db_name) - krb5_context context; - char *db_name; -{ - char *okname; - int fd; - register krb5_error_code retval = 0; - DBM *db; - - if ((retval = k5dbm_init_context(context))) - return(retval); - - db = KDBM_OPEN(context->db_context, db_name, O_RDWR|O_CREAT|O_EXCL, 0600); - if (db == NULL) - retval = errno; - else - KDBM_CLOSE(context->db_context, db); - if (retval == 0) { - okname = gen_dbsuffix(db_name, KDBM_LOCK_EXT(context->db_context)); - if (!okname) - retval = ENOMEM; - else { - fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600); - if (fd < 0) - retval = errno; - else - close(fd); - free_dbsuffix(okname); - } - } - return retval; -} - -/* - * Destroy the database. Zero's out all of the files, just to be sure. - */ -static krb5_error_code -destroy_file_suffix(dbname, suffix) - char *dbname; - char *suffix; -{ - char *filename; - struct stat statb; - int nb,fd,i,j; - char buf[BUFSIZ]; - char zbuf[BUFSIZ]; - int dowrite; - - filename = gen_dbsuffix(dbname, suffix); - if (filename == 0) - return ENOMEM; - if ((fd = open(filename, O_RDWR, 0)) < 0) { - free(filename); - return errno; - } - /* fstat() will probably not fail unless using a remote filesystem - (which is inappropriate for the kerberos database) so this check - is mostly paranoia. */ - if (fstat(fd, &statb) == -1) { - int retval = errno; - free(filename); - return retval; - } - /* - * Stroll through the file, reading in BUFSIZ chunks. If everything - * is zero, then we're done for that block, otherwise, zero the block. - * We would like to just blast through everything, but some DB - * implementations make holey files and writing data to the holes - * causes actual blocks to be allocated which is no good, since - * we're just about to unlink it anyways. - */ - memset(zbuf, 0, BUFSIZ); - i = 0; - while (i < statb.st_size) { - dowrite = 0; - nb = read(fd, buf, BUFSIZ); - if (nb < 0) { - int retval = errno; - free(filename); - return retval; - } - for (j=0; jdb_context) { - tmpcontext = 1; - if ((retval1 = k5dbm_init_context(context))) - return(retval1); - } - retval1 = retval2 = retval3 = 0; - if (KDBM_DATA_EXT(context->db_context)) - retval1 = destroy_file_suffix(dbname, - KDBM_DATA_EXT(context->db_context)); - if (KDBM_INDEX_EXT(context->db_context)) - retval2 = destroy_file_suffix(dbname, - KDBM_INDEX_EXT(context->db_context)); - retval3 = destroy_file_suffix(dbname, - KDBM_LOCK_EXT(context->db_context)); - /* - * This kludgery is needed because it is possible to link - * against BSD DB but use the ndbm interface. The result is - * that the dispatch table thinks the file extensions are - * .dir and .pag, but the database layer uses .db. - */ - if (retval1 == ENOENT && retval2 == ENOENT && - KDBM_INDEX_EXT(context->db_context) && - strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 && - KDBM_DATA_EXT(context->db_context) && - strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) { - retval1 = retval2 = destroy_file_suffix(dbname, ".db"); - } - if (retval1 || retval2 || retval3) - return (retval1 ? retval1 : (retval2 ? retval2 : retval3)); - - if (tmpcontext) { - k5dbm_clear_context((krb5_db_context *) context->db_context); - free(context->db_context); - context->db_context = (void *) NULL; - } - return(0); -} - -/* - * "Atomically" rename the database in a way that locks out read - * access in the middle of the rename. - * - * Not perfect; if we crash in the middle of an update, we don't - * necessarily know to complete the transaction the rename, but... - */ -/* - * Since the rename operation happens outside the init/fini bracket, we - * have to go through the same stuff that we went through up in db_destroy. - */ -krb5_error_code -krb5_dbm_db_rename(context, from, to) - krb5_context context; - char *from; - char *to; -{ - DBM *db; - char *fromdir = 0; - char *todir = 0; - char *frompag = 0; - char *topag = 0; - char *fromok = 0; - char *took = 0; - krb5_error_code retval; - krb5_db_context *s_context, *db_ctx; - - s_context = context->db_context; - context->db_context = (void *) NULL; - if (!(retval = k5dbm_init_context(context))) { - db_ctx = (krb5_db_context *) context->db_context; - - /* - * Create the database if it does not already exist; the - * files must exist because krb5_dbm_db_lock, called below, - * will fail otherwise. - */ - db = KDBM_OPEN(db_ctx, to, O_RDWR|O_CREAT, 0600); - if (db == NULL) { - retval = errno; - goto errout; - } - else - KDBM_CLOSE(db_ctx, db); - - /* - * Set the database to the target, so that other processes sharing - * the target will stop their activity, and notice the new database. - */ - retval = krb5_dbm_db_set_name(context, to); - if (retval) - goto errout; - - db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, - KDBM_LOCK_EXT(db_ctx)); - if (db_ctx->db_lf_name == (char *)NULL) { - retval = ENOMEM; - goto errout; - } - - db_ctx->db_lf_file = open(db_ctx->db_lf_name, O_RDWR|O_CREAT, 0600); - if (db_ctx->db_lf_file < 0) { - retval = errno; - goto errout; - } - - db_ctx->db_inited = 1; - - retval = krb5_dbm_db_get_age(context, NULL, &db_ctx->db_lf_time); - if (retval) - goto errout; - } - else - return(retval); - - if (KDBM_INDEX_EXT(context->db_context)) { - fromdir = gen_dbsuffix (from, KDBM_INDEX_EXT(context->db_context)); - todir = gen_dbsuffix (to, KDBM_INDEX_EXT(context->db_context)); - if (!fromdir || !todir) { - retval = ENOMEM; - goto errout; - } - } - - if (KDBM_DATA_EXT(context->db_context)) { - frompag = gen_dbsuffix (from, KDBM_DATA_EXT(context->db_context)); - topag = gen_dbsuffix (to, KDBM_DATA_EXT(context->db_context)); - if (!frompag || !topag) { - retval = ENOMEM; - goto errout; - } - } - - if (KDBM_LOCK_EXT(context->db_context)) { - fromok = gen_dbsuffix (from, KDBM_LOCK_EXT(context->db_context)); - took = gen_dbsuffix (to, KDBM_LOCK_EXT(context->db_context)); - if (!fromok || !took) { - retval = ENOMEM; - goto errout; - } - } - - if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE))) - goto errout; - - if ((retval = krb5_dbm_db_start_update(context))) - goto errout; - - if (((!fromdir && !todir) || - (fromdir && todir && (rename (fromdir, todir) == 0))) && - ((!frompag && !topag) || - (frompag && topag && (rename (frompag, topag) == 0)))) { - /* We only need to unlink the source lock file */ - if (fromok) - (void) unlink(fromok); - retval = krb5_dbm_db_end_update(context); - } else { - /* - * This kludgery is needed because it is possible to link - * against BSD DB but use the ndbm interface. The result is - * that the dispatch table thinks the file extensions are - * .dir and .pag, but the database layer uses .db. - */ - if (errno == ENOENT && - KDBM_INDEX_EXT(context->db_context) && - strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 && - KDBM_DATA_EXT(context->db_context) && - strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) { - free(fromdir); free(todir); free(frompag); free(topag); - - fromdir = todir = NULL; - frompag = gen_dbsuffix (from, ".db"); - topag = gen_dbsuffix (to, ".db"); - if (!frompag || !topag) { - retval = ENOMEM; - goto errout; - } - if (rename(frompag, topag) == 0) { - /* We only need to unlink the source lock file */ - if (fromok) - (void) unlink(fromok); - retval = krb5_dbm_db_end_update(context); - } else { - retval = errno; - (void) krb5_dbm_db_end_update(context); - } - } else { - retval = errno; - (void) krb5_dbm_db_end_update(context); - } - } - - -errout: - if (fromok) - free_dbsuffix (fromok); - if (took) - free_dbsuffix (took); - if (topag) - free_dbsuffix (topag); - if (frompag) - free_dbsuffix (frompag); - if (todir) - free_dbsuffix (todir); - if (fromdir) - free_dbsuffix (fromdir); - - if (context->db_context) { - if (db_ctx->db_lf_file >= 0) { - krb5_dbm_db_unlock(context); - close(db_ctx->db_lf_file); - } - k5dbm_clear_context((krb5_db_context *) context->db_context); - free (context->db_context); - } - - context->db_context = s_context; - (void) krb5_dbm_db_unlock(context); /* unlock saved context db */ - - return retval; -} - -/* - * look up a principal in the data base. - * returns number of entries found, and whether there were - * more than requested. - */ - -krb5_error_code -krb5_dbm_db_get_principal(context, searchfor, entries, nentries, more) - krb5_context context; -krb5_const_principal searchfor; -krb5_db_entry *entries; /* filled in */ -int *nentries; /* how much room/how many found */ -krb5_boolean *more; /* are there more? */ -{ - krb5_error_code retval; - datum key, contents; - krb5_db_context *db_ctx; - int try; - - *more = FALSE; - *nentries = 0; - - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - - db_ctx = (krb5_db_context *) context->db_context; - for (try = 0; try < KRB5_DBM_MAX_RETRY; try++) { - if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_SHARED))) { - if (db_ctx->db_nb_locks) - return(retval); - sleep(1); - continue; - } - break; - } - if (try == KRB5_DBM_MAX_RETRY) - return KRB5_KDB_DB_INUSE; - - /* XXX deal with wildcard lookups */ - if ((retval = krb5_encode_princ_dbmkey(context, &key, searchfor))) - goto cleanup; - - contents = KDBM_FETCH(db_ctx, db_ctx->db_dbm_ctx, key); - krb5_free_princ_dbmkey(context, &key); - - if (contents.dptr) - if (!(retval = krb5_decode_princ_contents(context, &contents,entries))) - *nentries = 1; - -cleanup: - (void) krb5_dbm_db_unlock(context); /* unlock read lock */ - return retval; -} - -/* - Free stuff returned by krb5_dbm_db_get_principal. - */ -void -krb5_dbm_db_free_principal(context, entries, nentries) - krb5_context context; - krb5_db_entry *entries; - int nentries; -{ - register int i; - for (i = 0; i < nentries; i++) - krb5_dbe_free_contents(context, &entries[i]); - return; -} - -/* - Stores the *"nentries" entry structures pointed to by "entries" in the - database. - - *"nentries" is updated upon return to reflect the number of records - acutally stored; the first *"nstored" records will have been stored in the - database (even if an error occurs). - - */ - -krb5_error_code -krb5_dbm_db_put_principal(context, entries, nentries) - krb5_context context; - krb5_db_entry *entries; - register int *nentries; /* number of entry structs to update */ -{ - int i, n; - datum key, contents; - krb5_error_code retval; - krb5_db_context *db_ctx; - - n = *nentries; - *nentries = 0; - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - - db_ctx = (krb5_db_context *) context->db_context; - if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE))) - return retval; - - if ((retval = krb5_dbm_db_start_update(context))) { - (void)krb5_dbm_db_unlock(context); - return retval; - } - - /* for each one, stuff temps, and do replace/append */ - for (i = 0; i < n; i++) { - if ((retval = krb5_encode_princ_contents(context, &contents, - entries))) - break; - - if ((retval = krb5_encode_princ_dbmkey(context, &key, - entries->princ))) { - krb5_free_princ_contents(context, &contents); - break; - } - if (KDBM_STORE(db_ctx, db_ctx->db_dbm_ctx, key, contents, DBM_REPLACE)) - retval = errno?errno:KRB5_KDB_DB_CORRUPT; - - krb5_free_princ_contents(context, &contents); - krb5_free_princ_dbmkey(context, &key); - if (retval) - break; - entries++; /* bump to next struct */ - } - - (void)krb5_dbm_db_end_update(context); - (void)krb5_dbm_db_unlock(context); /* unlock database */ - *nentries = i; - return(retval); -} - -/* - * delete a principal from the data base. - * returns number of entries removed - */ - -krb5_error_code -krb5_dbm_db_delete_principal(context, searchfor, nentries) - krb5_context context; - krb5_const_principal searchfor; - int * nentries; /* how many found & deleted */ -{ - krb5_error_code retval; - krb5_db_entry entry; - krb5_db_context * db_ctx; - datum key, contents, contents2; - DBM * db; - int i; - - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - - db_ctx = (krb5_db_context *) context->db_context; - if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE))) - return(retval); - - if ((retval = krb5_dbm_db_start_update(context))) { - (void) krb5_dbm_db_unlock(context); /* unlock write lock */ - return(retval); - } - - if ((retval = krb5_encode_princ_dbmkey(context, &key, searchfor))) - goto cleanup; - - db = db_ctx->db_dbm_ctx; - contents = KDBM_FETCH(db_ctx, db, key); - if (contents.dptr == NULL) { - retval = KRB5_KDB_NOENTRY; - *nentries = 0; - } else { - memset((char *)&entry, 0, sizeof(entry)); - if ((retval = krb5_decode_princ_contents(context, &contents, - &entry))) - goto cleankey; - *nentries = 1; - /* Clear encrypted key contents */ - for (i = 0; i < entry.n_key_data; i++) { - if (entry.key_data[i].key_data_length[0]) { - memset((char *)entry.key_data[i].key_data_contents[0], 0, - entry.key_data[i].key_data_length[0]); - } - } - if ((retval = krb5_encode_princ_contents(context, &contents2, - &entry))) - goto cleancontents; - - if (KDBM_STORE(db_ctx, db, key, contents2, DBM_REPLACE)) - retval = errno?errno:KRB5_KDB_DB_CORRUPT; - else { - if (KDBM_DELETE(db_ctx, db, key)) - retval = errno?errno:KRB5_KDB_DB_CORRUPT; - } - krb5_free_princ_contents(context, &contents2); - cleancontents: - krb5_dbe_free_contents(context, &entry); - cleankey: - krb5_free_princ_dbmkey(context, &key); - } - -cleanup: - (void)krb5_dbm_db_end_update(context); - (void) krb5_dbm_db_unlock(context); /* unlock write lock */ - return retval; -} - -krb5_error_code -krb5_dbm_db_iterate (context, func, func_arg) - krb5_context context; - krb5_error_code (*func) (krb5_pointer, krb5_db_entry *); - krb5_pointer func_arg; -{ - datum key, contents; - krb5_db_entry entries; - krb5_error_code retval; - DBM *db; - krb5_db_context *db_ctx; - - if (!k5dbm_inited(context)) - return KRB5_KDB_DBNOTINITED; - - db_ctx = (krb5_db_context *) context->db_context; - if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_SHARED))) - return retval; - - db = db_ctx->db_dbm_ctx; - for (key = KDBM_FIRSTKEY (db_ctx, db); - key.dptr != NULL; key = KDBM_NEXTKEY(db_ctx, db)) { - contents = KDBM_FETCH (db_ctx, db, key); - if ((retval = krb5_decode_princ_contents(context, &contents, - &entries))) - break; - retval = (*func)(func_arg, &entries); - krb5_dbe_free_contents(context, &entries); - if (retval) - break; - } - (void) krb5_dbm_db_unlock(context); - return retval; -} - -krb5_boolean -krb5_dbm_db_set_lockmode(context, mode) - krb5_context context; - krb5_boolean mode; -{ - krb5_boolean old; - krb5_db_context *db_ctx; - - old = mode; - if ((db_ctx = (krb5_db_context *) context->db_context)) { - old = db_ctx->db_nb_locks; - db_ctx->db_nb_locks = mode; - } - return old; -} - -/* - * Set dispatch table. - */ -krb5_error_code -kdb5_db_set_dbops(context, new) - krb5_context context; - kdb5_dispatch_table *new; -{ - krb5_error_code kret; - krb5_db_context *db_ctx; - - kret = KRB5_KDB_DBINITED; - if (!k5dbm_inited(context)) { - if (!(kret = k5dbm_init_context(context))) { - db_ctx = (krb5_db_context *) context->db_context; - db_ctx->db_dispatch = (new) ? new : &kdb5_default_dispatch; - } - } - return(kret); -} - -/* - * Context serialization operations. - */ - -/* - * kdb5_context_size() - Determine size required to serialize. - */ -static krb5_error_code -kdb5_context_size(kcontext, arg, sizep) - krb5_context kcontext; - krb5_pointer arg; - size_t *sizep; -{ - krb5_error_code kret; - size_t required; - krb5_db_context *dbctx; - - /* - * The database context requires at minimum: - * krb5_int32 for KV5M_DB_CONTEXT - * krb5_int32 for db_inited - * krb5_int32 for database lockfile non-blocking flag - * krb5_int32 for database lockfile lock count - * krb5_int32 for database lockfile lock mode - * krb5_int32 for length of database name. - * krb5_int32 for KV5M_DB_CONTEXT - */ - kret = EINVAL; - if ((dbctx = (krb5_db_context *) arg)) { - required = (sizeof(krb5_int32) * 7); - if (dbctx->db_inited && dbctx->db_dispatch && dbctx->db_name) - required += strlen(dbctx->db_name); - kret = 0; - *sizep += required; - } - return(kret); -} - -/* - * kdb5_context_externalize() - Externalize the database context. - */ -static krb5_error_code -kdb5_context_externalize(kcontext, arg, buffer, lenremain) - krb5_context kcontext; - krb5_pointer arg; - krb5_octet **buffer; - size_t *lenremain; -{ - krb5_error_code kret; - krb5_db_context *dbctx; - size_t required; - krb5_octet *bp; - size_t remain; - - required = 0; - bp = *buffer; - remain = *lenremain; - kret = EINVAL; - if ((dbctx = (krb5_db_context *) arg)) { - kret = ENOMEM; - if (!kdb5_context_size(kcontext, arg, &required) && - (required <= remain)) { - /* Write magic number */ - (void) krb5_ser_pack_int32(KV5M_DB_CONTEXT, &bp, &remain); - - /* Write inited flag */ - (void) krb5_ser_pack_int32((krb5_int32) dbctx->db_inited, - &bp, &remain); - - /* Write blocking lock lockmode */ - (void) krb5_ser_pack_int32((krb5_int32) dbctx->db_nb_locks, - &bp, &remain); - - /* Write lock count */ - (void) krb5_ser_pack_int32((krb5_int32) - (dbctx->db_inited) ? - dbctx->db_locks_held : 0, - &bp, &remain); - - /* Write lock mode */ - (void) krb5_ser_pack_int32((krb5_int32) - (dbctx->db_inited) ? - dbctx->db_lock_mode : 0, - &bp, &remain); - - /* Write length of database name */ - (void) krb5_ser_pack_int32((dbctx->db_inited && dbctx->db_name) ? - (krb5_int32) strlen(dbctx->db_name) : 0, - &bp, &remain); - if (dbctx->db_inited && dbctx->db_name) - (void) krb5_ser_pack_bytes((krb5_octet *) dbctx->db_name, - strlen(dbctx->db_name), - &bp, &remain); - - /* Write trailer */ - (void) krb5_ser_pack_int32(KV5M_DB_CONTEXT, &bp, &remain); - kret = 0; - *buffer = bp; - *lenremain = remain; - } - } - return(kret); -} - -/* - * kdb5_context_internalize() - Internalize the database context. - */ -static krb5_error_code -kdb5_context_internalize(kcontext, argp, buffer, lenremain) - krb5_context kcontext; - krb5_pointer *argp; - krb5_octet **buffer; - size_t *lenremain; -{ - krb5_error_code kret; - krb5_context tmpctx; - krb5_db_context *dbctx; - krb5_int32 ibuf; - krb5_octet *bp; - size_t remain; - krb5_int32 iflag; - krb5_int32 nb_lockmode; - krb5_int32 lockcount; - krb5_int32 lockmode; - krb5_int32 dbnamelen; - char *dbname; - - bp = *buffer; - remain = *lenremain; - kret = EINVAL; - dbctx = (krb5_db_context *) NULL; - /* Read our magic number */ - if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) - ibuf = 0; - if (ibuf == KV5M_DB_CONTEXT) { - kret = ENOMEM; - - if (!(kret = krb5_ser_unpack_int32(&iflag, &bp, &remain)) && - !(kret = krb5_ser_unpack_int32(&nb_lockmode, &bp, &remain)) && - !(kret = krb5_ser_unpack_int32(&lockcount, &bp, &remain)) && - !(kret = krb5_ser_unpack_int32(&lockmode, &bp, &remain)) && - !(kret = krb5_ser_unpack_int32(&dbnamelen, &bp, &remain)) && - !(kret = krb5_init_context(&tmpctx))) { - if (iflag) { - dbname = (char *) NULL; - if (dbnamelen && - (dbname = (char *) malloc((size_t) (dbnamelen+1)))) { - kret = krb5_ser_unpack_bytes((krb5_octet *) dbname, - (size_t) dbnamelen, - &bp, &remain); - if (!kret) - dbname[dbnamelen] = '\0'; - } - if (!kret && - (!dbname || !(kret = krb5_db_set_name(tmpctx, dbname))) && - !(kret = krb5_db_init(tmpctx))) { - dbctx = (krb5_db_context *) tmpctx->db_context; - (void) krb5_dbm_db_set_lockmode(tmpctx, 0); - if (lockmode) - kret = krb5_db_lock(tmpctx, lockmode); - if (!kret && lockmode) - dbctx->db_locks_held = lockcount; - (void) krb5_dbm_db_set_lockmode(tmpctx, nb_lockmode); - } - if (dbname) - krb5_xfree(dbname); - } - if (!kret) - kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); - if (kret || (ibuf != KV5M_DB_CONTEXT)) - kret = EINVAL; - - if (kret) { - if (dbctx) - krb5_db_fini(tmpctx); - } - else - tmpctx->db_context = (void *) NULL; - krb5_free_context(tmpctx); - } - } - if (!kret) { - *buffer = bp; - *lenremain = remain; - *argp = (krb5_pointer) dbctx; - } - return(kret); -} - -/* Dispatch entry */ -static const krb5_ser_entry kdb5_context_ser_entry = { - KV5M_DB_CONTEXT, /* Type */ - kdb5_context_size, /* Sizer routine */ - kdb5_context_externalize, /* Externalize routine */ - kdb5_context_internalize /* Externalize routine */ -}; - -/* - * Register serializer. - */ -krb5_error_code -krb5_ser_db_context_init(kcontext) - krb5_context kcontext; -{ - return(krb5_register_serializer(kcontext, &kdb5_context_ser_entry)); -}