db.c revision 90926
1139823Simp/* 244165Sjulian * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 344165Sjulian * (Royal Institute of Technology, Stockholm, Sweden). 444165Sjulian * All rights reserved. 544165Sjulian * 644165Sjulian * Redistribution and use in source and binary forms, with or without 744165Sjulian * modification, are permitted provided that the following conditions 844165Sjulian * are met: 944165Sjulian * 1044165Sjulian * 1. Redistributions of source code must retain the above copyright 1144165Sjulian * notice, this list of conditions and the following disclaimer. 1244165Sjulian * 1344165Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1444165Sjulian * notice, this list of conditions and the following disclaimer in the 1544165Sjulian * documentation and/or other materials provided with the distribution. 1644165Sjulian * 1744165Sjulian * 3. Neither the name of the Institute nor the names of its contributors 1844165Sjulian * may be used to endorse or promote products derived from this software 1944165Sjulian * without specific prior written permission. 2044165Sjulian * 2144165Sjulian * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2244165Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2344165Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2444165Sjulian * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2544165Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2644165Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2744165Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2844165Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2944165Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3044165Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3144165Sjulian * SUCH DAMAGE. 3244165Sjulian */ 3350477Speter 3444165Sjulian#include "hdb_locl.h" 3544165Sjulian 3644165SjulianRCSID("$Id: db.c,v 1.30 2001/08/09 08:41:48 assar Exp $"); 3744165Sjulian 3844165Sjulian#if HAVE_DB1 3944165Sjulian 4044165Sjulian#if defined(HAVE_DB_185_H) 4144165Sjulian#include <db_185.h> 4244165Sjulian#elif defined(HAVE_DB_H) 4344165Sjulian#include <db.h> 4474408Smdodd#endif 4574408Smdodd 4644165Sjulianstatic krb5_error_code 4744165SjulianDB_close(krb5_context context, HDB *db) 4844165Sjulian{ 49112271Smdodd DB *d = (DB*)db->db; 50112271Smdodd d->close(d); 5144165Sjulian return 0; 52112271Smdodd} 5344165Sjulian 5444165Sjulianstatic krb5_error_code 5544165SjulianDB_destroy(krb5_context context, HDB *db) 5644165Sjulian{ 57184710Sbz krb5_error_code ret; 58112271Smdodd 5944165Sjulian ret = hdb_clear_master_key (context, db); 6044165Sjulian free(db->name); 61186119Sqingli free(db); 6244165Sjulian return ret; 63184710Sbz} 64112271Smdodd 65112271Smdoddstatic krb5_error_code 66112271SmdoddDB_lock(krb5_context context, HDB *db, int operation) 6744165Sjulian{ 6844165Sjulian DB *d = (DB*)db->db; 6974408Smdodd int fd = (*d->fd)(d); 7044165Sjulian if(fd < 0) 7144165Sjulian return HDB_ERR_CANT_LOCK_DB; 7244165Sjulian return hdb_lock(fd, operation); 7344165Sjulian} 7474408Smdodd 7574408Smdoddstatic krb5_error_code 7674408SmdoddDB_unlock(krb5_context context, HDB *db) 7744165Sjulian{ 7874408Smdodd DB *d = (DB*)db->db; 7974408Smdodd int fd = (*d->fd)(d); 8074408Smdodd if(fd < 0) 8174408Smdodd return HDB_ERR_CANT_LOCK_DB; 8274408Smdodd return hdb_unlock(fd); 83163606Srwatson} 84163606Srwatson 85126907Srwatson 86112277Smdoddstatic krb5_error_code 87112277SmdoddDB_seq(krb5_context context, HDB *db, 88112273Smdodd unsigned flags, hdb_entry *entry, int flag) 89112294Smdodd{ 90112273Smdodd DB *d = (DB*)db->db; 91112276Smdodd DBT key, value; 9274408Smdodd krb5_data key_data, data; 93112297Smdodd int code; 94112297Smdodd 95112297Smdodd code = db->lock(context, db, HDB_RLOCK); 9644165Sjulian if(code == -1) 97152296Sru return HDB_ERR_DB_INUSE; 9844165Sjulian code = d->seq(d, &key, &value, flag); 99112296Smdodd db->unlock(context, db); /* XXX check value */ 100111774Smdodd if(code == -1) 10144165Sjulian return errno; 102112296Smdodd if(code == 1) 103112296Smdodd return HDB_ERR_NOENTRY; 10444165Sjulian 10558313Slile key_data.data = key.data; 10658313Slile key_data.length = key.size; 107112297Smdodd data.data = value.data; 108112297Smdodd data.length = value.size; 109112297Smdodd if (hdb_value2entry(context, &data, entry)) 110112297Smdodd return DB_seq(context, db, flags, entry, R_NEXT); 111112297Smdodd if (db->master_key_set && (flags & HDB_F_DECRYPT)) { 112112297Smdodd code = hdb_unseal_keys (context, db, entry); 113112297Smdodd if (code) 114112297Smdodd hdb_free_entry (context, entry); 11544165Sjulian } 11658313Slile if (code == 0 && entry->principal == NULL) { 11744165Sjulian entry->principal = malloc(sizeof(*entry->principal)); 11844165Sjulian if (entry->principal == NULL) { 11944165Sjulian krb5_set_error_string(context, "malloc: out of memory"); 120152315Sru code = ENOMEM; 121152315Sru hdb_free_entry (context, entry); 122112297Smdodd } else { 123112272Smdodd hdb_key2principal(context, &key_data, entry->principal); 124112272Smdodd } 125112272Smdodd } 126152296Sru return code; 127112297Smdodd} 128112297Smdodd 129112297Smdodd 130112297Smdoddstatic krb5_error_code 131112297SmdoddDB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) 13244165Sjulian{ 13344165Sjulian return DB_seq(context, db, flags, entry, R_FIRST); 13474408Smdodd} 13574408Smdodd 13674408Smdodd 13774408Smdoddstatic krb5_error_code 13874408SmdoddDB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry) 13974408Smdodd{ 14074408Smdodd return DB_seq(context, db, flags, entry, R_NEXT); 14174408Smdodd} 142112274Smdodd 14374408Smdoddstatic krb5_error_code 14474408SmdoddDB_rename(krb5_context context, HDB *db, const char *new_name) 145112274Smdodd{ 14674408Smdodd int ret; 147112274Smdodd char *old, *new; 148112274Smdodd 14974408Smdodd asprintf(&old, "%s.db", db->name); 15074408Smdodd asprintf(&new, "%s.db", new_name); 15144165Sjulian ret = rename(old, new); 152194581Srdivacky free(old); 15344165Sjulian free(new); 154112274Smdodd if(ret) 155112274Smdodd return errno; 156112274Smdodd 15744165Sjulian free(db->name); 158112274Smdodd db->name = strdup(new_name); 159112274Smdodd return 0; 160112274Smdodd} 161112274Smdodd 16244165Sjulianstatic krb5_error_code 16344165SjulianDB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply) 16444165Sjulian{ 16544165Sjulian DB *d = (DB*)db->db; 16644165Sjulian DBT k, v; 16744165Sjulian int code; 16844165Sjulian 16944165Sjulian k.data = key.data; 17084931Sfjoe k.size = key.length; 17144165Sjulian code = db->lock(context, db, HDB_RLOCK); 17274408Smdodd if(code) 17374408Smdodd return code; 17474408Smdodd code = d->get(d, &k, &v, 0); 17574408Smdodd db->unlock(context, db); 17674408Smdodd if(code < 0) 177120048Smdodd return errno; 178120048Smdodd if(code == 1) 17974408Smdodd return HDB_ERR_NOENTRY; 180120048Smdodd 18174408Smdodd krb5_data_copy(reply, v.data, v.size); 182120048Smdodd return 0; 183120048Smdodd} 184152315Sru 185120048Smdoddstatic krb5_error_code 186120048SmdoddDB__put(krb5_context context, HDB *db, int replace, 187152315Sru krb5_data key, krb5_data value) 188120048Smdodd{ 189120048Smdodd DB *d = (DB*)db->db; 190120048Smdodd DBT k, v; 191120048Smdodd int code; 192120048Smdodd 193120048Smdodd k.data = key.data; 194120048Smdodd k.size = key.length; 195120048Smdodd v.data = value.data; 19674408Smdodd v.size = value.length; 19744165Sjulian code = db->lock(context, db, HDB_WLOCK); 19844165Sjulian if(code) 19944165Sjulian return code; 20044165Sjulian code = d->put(d, &k, &v, replace ? 0 : R_NOOVERWRITE); 20144165Sjulian db->unlock(context, db); 20244165Sjulian if(code < 0) 203120047Smdodd return errno; 20444165Sjulian if(code == 1) 20544165Sjulian return HDB_ERR_EXISTS; 20644165Sjulian return 0; 207152315Sru} 20844165Sjulian 20944165Sjulianstatic krb5_error_code 21044165SjulianDB__del(krb5_context context, HDB *db, krb5_data key) 21144165Sjulian{ 21244165Sjulian DB *d = (DB*)db->db; 21344165Sjulian DBT k; 21444165Sjulian krb5_error_code code; 21544165Sjulian k.data = key.data; 21658313Slile k.size = key.length; 21744165Sjulian code = db->lock(context, db, HDB_WLOCK); 21844165Sjulian if(code) 21944165Sjulian return code; 22044165Sjulian code = d->del(d, &k, 0); 22144165Sjulian db->unlock(context, db); 222112274Smdodd if(code == 1) 223112274Smdodd return HDB_ERR_NOENTRY; 224112274Smdodd if(code < 0) 22544165Sjulian return errno; 226112274Smdodd return 0; 22744165Sjulian} 22844165Sjulian 22944165Sjulianstatic krb5_error_code 23044165SjulianDB_open(krb5_context context, HDB *db, int flags, mode_t mode) 23144165Sjulian{ 23244165Sjulian char *fn; 23344165Sjulian krb5_error_code ret; 234249925Sglebius 235249925Sglebius asprintf(&fn, "%s.db", db->name); 23644165Sjulian if (fn == NULL) { 23774408Smdodd krb5_set_error_string(context, "malloc: out of memory"); 23887914Sjlemon return ENOMEM; 23987914Sjlemon } 24074408Smdodd db->db = dbopen(fn, flags, mode, DB_BTREE, NULL); 24144627Sjulian free(fn); 24274408Smdodd /* try to open without .db extension */ 243193891Sbz if(db->db == NULL && errno == ENOENT) 244193891Sbz db->db = dbopen(db->name, flags, mode, DB_BTREE, NULL); 245186119Sqingli if(db->db == NULL) { 246193891Sbz ret = errno; 24744165Sjulian krb5_set_error_string(context, "dbopen (%s): %s", 248191148Skmacy db->name, strerror(ret)); 249191148Skmacy return ret; 250191148Skmacy } 251112285Smdodd if((flags & O_ACCMODE) == O_RDONLY) 252172930Srwatson ret = hdb_check_db_format(context, db); 253112285Smdodd else 254112285Smdodd ret = hdb_init_db(context, db); 255112285Smdodd if(ret == HDB_ERR_NOENTRY) { 256112285Smdodd krb5_clear_error_string(context); 257112308Smdodd return 0; 258112308Smdodd } 259148887Srwatson return ret; 260148887Srwatson} 26144165Sjulian 26274408Smdoddkrb5_error_code 26374408Smdoddhdb_db_create(krb5_context context, HDB **db, 264128636Sluigi const char *filename) 265128636Sluigi{ 26644627Sjulian *db = malloc(sizeof(**db)); 267186119Sqingli if (*db == NULL) { 268102291Sarchie krb5_set_error_string(context, "malloc: out of memory"); 26996184Skbyanc return ENOMEM; 27044627Sjulian } 27144627Sjulian 27258313Slile (*db)->db = NULL; 27358313Slile (*db)->name = strdup(filename); 274152315Sru if ((*db)->name == NULL) { 275112278Smdodd krb5_set_error_string(context, "malloc: out of memory"); 27644627Sjulian free(*db); 27758313Slile *db = NULL; 27844627Sjulian return ENOMEM; 27996184Skbyanc } 28074408Smdodd (*db)->master_key_set = 0; 28196184Skbyanc (*db)->openp = 0; 28296184Skbyanc (*db)->open = DB_open; 28344627Sjulian (*db)->close = DB_close; 28444627Sjulian (*db)->fetch = _hdb_fetch; 28544627Sjulian (*db)->store = _hdb_store; 28644165Sjulian (*db)->remove = _hdb_remove; 28744165Sjulian (*db)->firstkey = DB_firstkey; 28844165Sjulian (*db)->nextkey= DB_nextkey; 289186119Sqingli (*db)->lock = DB_lock; 290128636Sluigi (*db)->unlock = DB_unlock; 291128636Sluigi (*db)->rename = DB_rename; 29274408Smdodd (*db)->_get = DB__get; 29374408Smdodd (*db)->_put = DB__put; 294126951Smdodd (*db)->_del = DB__del; 295126951Smdodd (*db)->destroy = DB_destroy; 296126951Smdodd return 0; 297126951Smdodd} 298126951Smdodd 299126951Smdodd#endif /* HAVE_DB1 */ 300126951Smdodd