1b528cefcSMark Murray /* 25e9cd1aeSAssar Westerlund * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "hdb_locl.h" 35b528cefcSMark Murray 365e9cd1aeSAssar Westerlund RCSID("$Id: ndbm.c,v 1.30 2001/01/30 01:24:00 assar Exp $"); 37b528cefcSMark Murray 385e9cd1aeSAssar Westerlund #if defined(HAVE_NDBM_H) || defined(HAVE_GDBM_NDBM_H) 39b528cefcSMark Murray 40b528cefcSMark Murray struct ndbm_db { 41b528cefcSMark Murray DBM *db; 42b528cefcSMark Murray int lock_fd; 43b528cefcSMark Murray }; 44b528cefcSMark Murray 45b528cefcSMark Murray static krb5_error_code 46b528cefcSMark Murray NDBM_destroy(krb5_context context, HDB *db) 47b528cefcSMark Murray { 48b528cefcSMark Murray krb5_error_code ret; 49b528cefcSMark Murray 50b528cefcSMark Murray ret = hdb_clear_master_key (context, db); 51b528cefcSMark Murray free(db->name); 52b528cefcSMark Murray free(db); 53b528cefcSMark Murray return 0; 54b528cefcSMark Murray } 55b528cefcSMark Murray 56b528cefcSMark Murray static krb5_error_code 57b528cefcSMark Murray NDBM_lock(krb5_context context, HDB *db, int operation) 58b528cefcSMark Murray { 59b528cefcSMark Murray struct ndbm_db *d = db->db; 60b528cefcSMark Murray return hdb_lock(d->lock_fd, operation); 61b528cefcSMark Murray } 62b528cefcSMark Murray 63b528cefcSMark Murray static krb5_error_code 64b528cefcSMark Murray NDBM_unlock(krb5_context context, HDB *db) 65b528cefcSMark Murray { 66b528cefcSMark Murray struct ndbm_db *d = db->db; 67b528cefcSMark Murray return hdb_unlock(d->lock_fd); 68b528cefcSMark Murray } 69b528cefcSMark Murray 70b528cefcSMark Murray static krb5_error_code 71b528cefcSMark Murray NDBM_seq(krb5_context context, HDB *db, 72b528cefcSMark Murray unsigned flags, hdb_entry *entry, int first) 73b528cefcSMark Murray 74b528cefcSMark Murray { 75b528cefcSMark Murray struct ndbm_db *d = (struct ndbm_db *)db->db; 76b528cefcSMark Murray datum key, value; 77b528cefcSMark Murray krb5_data key_data, data; 785e9cd1aeSAssar Westerlund krb5_error_code ret = 0; 79b528cefcSMark Murray 80b528cefcSMark Murray if(first) 81b528cefcSMark Murray key = dbm_firstkey(d->db); 82b528cefcSMark Murray else 83b528cefcSMark Murray key = dbm_nextkey(d->db); 84b528cefcSMark Murray if(key.dptr == NULL) 85b528cefcSMark Murray return HDB_ERR_NOENTRY; 86b528cefcSMark Murray key_data.data = key.dptr; 87b528cefcSMark Murray key_data.length = key.dsize; 88b528cefcSMark Murray ret = db->lock(context, db, HDB_RLOCK); 89b528cefcSMark Murray if(ret) return ret; 90b528cefcSMark Murray value = dbm_fetch(d->db, key); 91b528cefcSMark Murray db->unlock(context, db); 92b528cefcSMark Murray data.data = value.dptr; 93b528cefcSMark Murray data.length = value.dsize; 94b528cefcSMark Murray if(hdb_value2entry(context, &data, entry)) 95b528cefcSMark Murray return NDBM_seq(context, db, flags, entry, 0); 965e9cd1aeSAssar Westerlund if (db->master_key_set && (flags & HDB_F_DECRYPT)) { 975e9cd1aeSAssar Westerlund ret = hdb_unseal_keys (context, db, entry); 985e9cd1aeSAssar Westerlund if (ret) 995e9cd1aeSAssar Westerlund hdb_free_entry (context, entry); 1005e9cd1aeSAssar Westerlund } 101b528cefcSMark Murray if (entry->principal == NULL) { 102b528cefcSMark Murray entry->principal = malloc (sizeof(*entry->principal)); 1035e9cd1aeSAssar Westerlund if (entry->principal == NULL) { 1045e9cd1aeSAssar Westerlund ret = ENOMEM; 1055e9cd1aeSAssar Westerlund hdb_free_entry (context, entry); 1065e9cd1aeSAssar Westerlund } else { 107b528cefcSMark Murray hdb_key2principal (context, &key_data, entry->principal); 108b528cefcSMark Murray } 1095e9cd1aeSAssar Westerlund } 1105e9cd1aeSAssar Westerlund return ret; 111b528cefcSMark Murray } 112b528cefcSMark Murray 113b528cefcSMark Murray 114b528cefcSMark Murray static krb5_error_code 115b528cefcSMark Murray NDBM_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) 116b528cefcSMark Murray { 117b528cefcSMark Murray return NDBM_seq(context, db, flags, entry, 1); 118b528cefcSMark Murray } 119b528cefcSMark Murray 120b528cefcSMark Murray 121b528cefcSMark Murray static krb5_error_code 122b528cefcSMark Murray NDBM_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) 123b528cefcSMark Murray { 124b528cefcSMark Murray return NDBM_seq(context, db, flags, entry, 0); 125b528cefcSMark Murray } 126b528cefcSMark Murray 127b528cefcSMark Murray static krb5_error_code 128b528cefcSMark Murray NDBM_rename(krb5_context context, HDB *db, const char *new_name) 129b528cefcSMark Murray { 130b528cefcSMark Murray /* XXX this function will break */ 131b528cefcSMark Murray struct ndbm_db *d = db->db; 132b528cefcSMark Murray 133b528cefcSMark Murray int ret; 134b528cefcSMark Murray char *old_dir, *old_pag, *new_dir, *new_pag; 135b528cefcSMark Murray char *new_lock; 136b528cefcSMark Murray int lock_fd; 137b528cefcSMark Murray 138b528cefcSMark Murray /* lock old and new databases */ 139b528cefcSMark Murray ret = db->lock(context, db, HDB_WLOCK); 140b528cefcSMark Murray if(ret) return ret; 141b528cefcSMark Murray asprintf(&new_lock, "%s.lock", new_name); 142b528cefcSMark Murray lock_fd = open(new_lock, O_RDWR | O_CREAT, 0600); 143b528cefcSMark Murray free(new_lock); 144b528cefcSMark Murray if(lock_fd < 0) { 145b528cefcSMark Murray ret = errno; 146b528cefcSMark Murray db->unlock(context, db); 147b528cefcSMark Murray return ret; 148b528cefcSMark Murray } 149b528cefcSMark Murray ret = hdb_lock(lock_fd, HDB_WLOCK); 150b528cefcSMark Murray if(ret) { 151b528cefcSMark Murray db->unlock(context, db); 152b528cefcSMark Murray close(lock_fd); 153b528cefcSMark Murray return ret; 154b528cefcSMark Murray } 155b528cefcSMark Murray 156b528cefcSMark Murray asprintf(&old_dir, "%s.dir", db->name); 157b528cefcSMark Murray asprintf(&old_pag, "%s.pag", db->name); 158b528cefcSMark Murray asprintf(&new_dir, "%s.dir", new_name); 159b528cefcSMark Murray asprintf(&new_pag, "%s.pag", new_name); 160b528cefcSMark Murray 161b528cefcSMark Murray ret = rename(old_dir, new_dir) || rename(old_pag, new_pag); 162b528cefcSMark Murray free(old_dir); 163b528cefcSMark Murray free(old_pag); 164b528cefcSMark Murray free(new_dir); 165b528cefcSMark Murray free(new_pag); 166b528cefcSMark Murray hdb_unlock(lock_fd); 167b528cefcSMark Murray db->unlock(context, db); 168b528cefcSMark Murray 169b528cefcSMark Murray if(ret) { 170b528cefcSMark Murray close(lock_fd); 171b528cefcSMark Murray return errno; 172b528cefcSMark Murray } 173b528cefcSMark Murray 174b528cefcSMark Murray close(d->lock_fd); 175b528cefcSMark Murray d->lock_fd = lock_fd; 176b528cefcSMark Murray 177b528cefcSMark Murray free(db->name); 178b528cefcSMark Murray db->name = strdup(new_name); 179b528cefcSMark Murray return 0; 180b528cefcSMark Murray } 181b528cefcSMark Murray 182b528cefcSMark Murray static krb5_error_code 183b528cefcSMark Murray NDBM__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply) 184b528cefcSMark Murray { 185b528cefcSMark Murray struct ndbm_db *d = (struct ndbm_db *)db->db; 186b528cefcSMark Murray datum k, v; 187b528cefcSMark Murray int code; 188b528cefcSMark Murray 189b528cefcSMark Murray k.dptr = key.data; 190b528cefcSMark Murray k.dsize = key.length; 191b528cefcSMark Murray code = db->lock(context, db, HDB_RLOCK); 192b528cefcSMark Murray if(code) 193b528cefcSMark Murray return code; 194b528cefcSMark Murray v = dbm_fetch(d->db, k); 195b528cefcSMark Murray db->unlock(context, db); 196b528cefcSMark Murray if(v.dptr == NULL) 197b528cefcSMark Murray return HDB_ERR_NOENTRY; 198b528cefcSMark Murray 199b528cefcSMark Murray krb5_data_copy(reply, v.dptr, v.dsize); 200b528cefcSMark Murray return 0; 201b528cefcSMark Murray } 202b528cefcSMark Murray 203b528cefcSMark Murray static krb5_error_code 204b528cefcSMark Murray NDBM__put(krb5_context context, HDB *db, int replace, 205b528cefcSMark Murray krb5_data key, krb5_data value) 206b528cefcSMark Murray { 207b528cefcSMark Murray struct ndbm_db *d = (struct ndbm_db *)db->db; 208b528cefcSMark Murray datum k, v; 209b528cefcSMark Murray int code; 210b528cefcSMark Murray 211b528cefcSMark Murray k.dptr = key.data; 212b528cefcSMark Murray k.dsize = key.length; 213b528cefcSMark Murray v.dptr = value.data; 214b528cefcSMark Murray v.dsize = value.length; 215b528cefcSMark Murray 216b528cefcSMark Murray code = db->lock(context, db, HDB_WLOCK); 217b528cefcSMark Murray if(code) 218b528cefcSMark Murray return code; 219b528cefcSMark Murray code = dbm_store(d->db, k, v, replace ? DBM_REPLACE : DBM_INSERT); 220b528cefcSMark Murray db->unlock(context, db); 221b528cefcSMark Murray if(code == 1) 222b528cefcSMark Murray return HDB_ERR_EXISTS; 223b528cefcSMark Murray if (code < 0) 224b528cefcSMark Murray return code; 225b528cefcSMark Murray return 0; 226b528cefcSMark Murray } 227b528cefcSMark Murray 228b528cefcSMark Murray static krb5_error_code 229b528cefcSMark Murray NDBM__del(krb5_context context, HDB *db, krb5_data key) 230b528cefcSMark Murray { 231b528cefcSMark Murray struct ndbm_db *d = (struct ndbm_db *)db->db; 232b528cefcSMark Murray datum k; 233b528cefcSMark Murray int code; 234b528cefcSMark Murray krb5_error_code ret; 235b528cefcSMark Murray 236b528cefcSMark Murray k.dptr = key.data; 237b528cefcSMark Murray k.dsize = key.length; 238b528cefcSMark Murray ret = db->lock(context, db, HDB_WLOCK); 239b528cefcSMark Murray if(ret) return ret; 240b528cefcSMark Murray code = dbm_delete(d->db, k); 241b528cefcSMark Murray db->unlock(context, db); 242b528cefcSMark Murray if(code < 0) 243b528cefcSMark Murray return errno; 244b528cefcSMark Murray return 0; 245b528cefcSMark Murray } 246b528cefcSMark Murray 247b528cefcSMark Murray static krb5_error_code 248b528cefcSMark Murray NDBM_open(krb5_context context, HDB *db, int flags, mode_t mode) 249b528cefcSMark Murray { 250b528cefcSMark Murray krb5_error_code ret; 251b528cefcSMark Murray struct ndbm_db *d = malloc(sizeof(*d)); 252b528cefcSMark Murray char *lock_file; 253b528cefcSMark Murray 254b528cefcSMark Murray if(d == NULL) 255b528cefcSMark Murray return ENOMEM; 256b528cefcSMark Murray asprintf(&lock_file, "%s.lock", (char*)db->name); 257b528cefcSMark Murray if(lock_file == NULL) { 258b528cefcSMark Murray free(d); 259b528cefcSMark Murray return ENOMEM; 260b528cefcSMark Murray } 261b528cefcSMark Murray d->db = dbm_open((char*)db->name, flags, mode); 262b528cefcSMark Murray if(d->db == NULL){ 263b528cefcSMark Murray free(d); 264b528cefcSMark Murray free(lock_file); 265b528cefcSMark Murray return errno; 266b528cefcSMark Murray } 267b528cefcSMark Murray d->lock_fd = open(lock_file, O_RDWR | O_CREAT, 0600); 268b528cefcSMark Murray free(lock_file); 269b528cefcSMark Murray if(d->lock_fd < 0){ 270b528cefcSMark Murray dbm_close(d->db); 271b528cefcSMark Murray free(d); 272b528cefcSMark Murray return errno; 273b528cefcSMark Murray } 274b528cefcSMark Murray db->db = d; 275b528cefcSMark Murray if((flags & O_ACCMODE) == O_RDONLY) 276b528cefcSMark Murray ret = hdb_check_db_format(context, db); 277b528cefcSMark Murray else 278b528cefcSMark Murray ret = hdb_init_db(context, db); 279b528cefcSMark Murray if(ret == HDB_ERR_NOENTRY) 280b528cefcSMark Murray return 0; 281b528cefcSMark Murray return ret; 282b528cefcSMark Murray } 283b528cefcSMark Murray 284b528cefcSMark Murray static krb5_error_code 285b528cefcSMark Murray NDBM_close(krb5_context context, HDB *db) 286b528cefcSMark Murray { 287b528cefcSMark Murray struct ndbm_db *d = db->db; 288b528cefcSMark Murray dbm_close(d->db); 289b528cefcSMark Murray close(d->lock_fd); 290b528cefcSMark Murray free(d); 291b528cefcSMark Murray return 0; 292b528cefcSMark Murray } 293b528cefcSMark Murray 294b528cefcSMark Murray krb5_error_code 295b528cefcSMark Murray hdb_ndbm_create(krb5_context context, HDB **db, 296b528cefcSMark Murray const char *filename) 297b528cefcSMark Murray { 298b528cefcSMark Murray *db = malloc(sizeof(**db)); 299b528cefcSMark Murray if (*db == NULL) 300b528cefcSMark Murray return ENOMEM; 301b528cefcSMark Murray 302b528cefcSMark Murray (*db)->db = NULL; 303b528cefcSMark Murray (*db)->name = strdup(filename); 304b528cefcSMark Murray (*db)->master_key_set = 0; 305b528cefcSMark Murray (*db)->openp = 0; 306b528cefcSMark Murray (*db)->open = NDBM_open; 307b528cefcSMark Murray (*db)->close = NDBM_close; 308b528cefcSMark Murray (*db)->fetch = _hdb_fetch; 309b528cefcSMark Murray (*db)->store = _hdb_store; 310b528cefcSMark Murray (*db)->remove = _hdb_remove; 311b528cefcSMark Murray (*db)->firstkey = NDBM_firstkey; 312b528cefcSMark Murray (*db)->nextkey= NDBM_nextkey; 313b528cefcSMark Murray (*db)->lock = NDBM_lock; 314b528cefcSMark Murray (*db)->unlock = NDBM_unlock; 315b528cefcSMark Murray (*db)->rename = NDBM_rename; 316b528cefcSMark Murray (*db)->_get = NDBM__get; 317b528cefcSMark Murray (*db)->_put = NDBM__put; 318b528cefcSMark Murray (*db)->_del = NDBM__del; 319b528cefcSMark Murray (*db)->destroy = NDBM_destroy; 320b528cefcSMark Murray return 0; 321b528cefcSMark Murray } 322b528cefcSMark Murray 323b528cefcSMark Murray #endif 324