root/source4/heimdal/lib/hdb/db.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. DB_close
  2. DB_destroy
  3. DB_lock
  4. DB_unlock
  5. DB_seq
  6. DB_firstkey
  7. DB_nextkey
  8. DB_rename
  9. DB__get
  10. DB__put
  11. DB__del
  12. DB_open
  13. hdb_db_create

   1 /*
   2  * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include "hdb_locl.h"
  35 
  36 RCSID("$Id$");
  37 
  38 #if HAVE_DB1
  39 
  40 #if defined(HAVE_DB_185_H)
  41 #include <db_185.h>
  42 #elif defined(HAVE_DB_H)
  43 #include <db.h>
  44 #endif
  45 
  46 static krb5_error_code
  47 DB_close(krb5_context context, HDB *db)
     /* [<][>][^][v][top][bottom][index][help] */
  48 {
  49     DB *d = (DB*)db->hdb_db;
  50     (*d->close)(d);
  51     return 0;
  52 }
  53 
  54 static krb5_error_code
  55 DB_destroy(krb5_context context, HDB *db)
     /* [<][>][^][v][top][bottom][index][help] */
  56 {
  57     krb5_error_code ret;
  58 
  59     ret = hdb_clear_master_key (context, db);
  60     free(db->hdb_name);
  61     free(db);
  62     return ret;
  63 }
  64 
  65 static krb5_error_code
  66 DB_lock(krb5_context context, HDB *db, int operation)
     /* [<][>][^][v][top][bottom][index][help] */
  67 {
  68     DB *d = (DB*)db->hdb_db;
  69     int fd = (*d->fd)(d);
  70     if(fd < 0) {
  71         krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB,
  72                                "Can't lock database: %s", db->hdb_name);
  73         return HDB_ERR_CANT_LOCK_DB;
  74     }
  75     return hdb_lock(fd, operation);
  76 }
  77 
  78 static krb5_error_code
  79 DB_unlock(krb5_context context, HDB *db)
     /* [<][>][^][v][top][bottom][index][help] */
  80 {
  81     DB *d = (DB*)db->hdb_db;
  82     int fd = (*d->fd)(d);
  83     if(fd < 0) {
  84         krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB,
  85                                "Can't unlock database: %s", db->hdb_name);
  86         return HDB_ERR_CANT_LOCK_DB;
  87     }
  88     return hdb_unlock(fd);
  89 }
  90 
  91 
  92 static krb5_error_code
  93 DB_seq(krb5_context context, HDB *db,
     /* [<][>][^][v][top][bottom][index][help] */
  94        unsigned flags, hdb_entry_ex *entry, int flag)
  95 {
  96     DB *d = (DB*)db->hdb_db;
  97     DBT key, value;
  98     krb5_data key_data, data;
  99     int code;
 100 
 101     code = db->hdb_lock(context, db, HDB_RLOCK);
 102     if(code == -1) {
 103         krb5_set_error_message(context, HDB_ERR_DB_INUSE, "Database %s in use", db->hdb_name);
 104         return HDB_ERR_DB_INUSE;
 105     }
 106     code = (*d->seq)(d, &key, &value, flag);
 107     db->hdb_unlock(context, db); /* XXX check value */
 108     if(code == -1) {
 109         code = errno;
 110         krb5_set_error_message(context, code, "Database %s seq error: %s",
 111                                db->hdb_name, strerror(code));
 112         return code;
 113     }
 114     if(code == 1) {
 115         krb5_clear_error_message(context);
 116         return HDB_ERR_NOENTRY;
 117     }
 118 
 119     key_data.data = key.data;
 120     key_data.length = key.size;
 121     data.data = value.data;
 122     data.length = value.size;
 123     memset(entry, 0, sizeof(*entry));
 124     if (hdb_value2entry(context, &data, &entry->entry))
 125         return DB_seq(context, db, flags, entry, R_NEXT);
 126     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
 127         code = hdb_unseal_keys (context, db, &entry->entry);
 128         if (code)
 129             hdb_free_entry (context, entry);
 130     }
 131     if (code == 0 && entry->entry.principal == NULL) {
 132         entry->entry.principal = malloc(sizeof(*entry->entry.principal));
 133         if (entry->entry.principal == NULL) {
 134             code = ENOMEM;
 135             krb5_set_error_message(context, code, "malloc: out of memory");
 136             hdb_free_entry (context, entry);
 137         } else {
 138             hdb_key2principal(context, &key_data, entry->entry.principal);
 139         }
 140     }
 141     return code;
 142 }
 143 
 144 
 145 static krb5_error_code
 146 DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148     return DB_seq(context, db, flags, entry, R_FIRST);
 149 }
 150 
 151 
 152 static krb5_error_code
 153 DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155     return DB_seq(context, db, flags, entry, R_NEXT);
 156 }
 157 
 158 static krb5_error_code
 159 DB_rename(krb5_context context, HDB *db, const char *new_name)
     /* [<][>][^][v][top][bottom][index][help] */
 160 {
 161     int ret;
 162     char *old, *new;
 163 
 164     asprintf(&old, "%s.db", db->hdb_name);
 165     asprintf(&new, "%s.db", new_name);
 166     ret = rename(old, new);
 167     free(old);
 168     free(new);
 169     if(ret)
 170         return errno;
 171 
 172     free(db->hdb_name);
 173     db->hdb_name = strdup(new_name);
 174     return 0;
 175 }
 176 
 177 static krb5_error_code
 178 DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
     /* [<][>][^][v][top][bottom][index][help] */
 179 {
 180     DB *d = (DB*)db->hdb_db;
 181     DBT k, v;
 182     int code;
 183 
 184     k.data = key.data;
 185     k.size = key.length;
 186     code = db->hdb_lock(context, db, HDB_RLOCK);
 187     if(code)
 188         return code;
 189     code = (*d->get)(d, &k, &v, 0);
 190     db->hdb_unlock(context, db);
 191     if(code < 0) {
 192         code = errno;
 193         krb5_set_error_message(context, code, "Database %s get error: %s",
 194                                db->hdb_name, strerror(code));
 195         return code;
 196     }
 197     if(code == 1) {
 198         krb5_clear_error_message(context);
 199         return HDB_ERR_NOENTRY;
 200     }
 201 
 202     krb5_data_copy(reply, v.data, v.size);
 203     return 0;
 204 }
 205 
 206 static krb5_error_code
 207 DB__put(krb5_context context, HDB *db, int replace,
     /* [<][>][^][v][top][bottom][index][help] */
 208         krb5_data key, krb5_data value)
 209 {
 210     DB *d = (DB*)db->hdb_db;
 211     DBT k, v;
 212     int code;
 213 
 214     k.data = key.data;
 215     k.size = key.length;
 216     v.data = value.data;
 217     v.size = value.length;
 218     code = db->hdb_lock(context, db, HDB_WLOCK);
 219     if(code)
 220         return code;
 221     code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE);
 222     db->hdb_unlock(context, db);
 223     if(code < 0) {
 224         code = errno;
 225         krb5_set_error_message(context, code, "Database %s put error: %s",
 226                                db->hdb_name, strerror(code));
 227         return code;
 228     }
 229     if(code == 1) {
 230         krb5_clear_error_message(context);
 231         return HDB_ERR_EXISTS;
 232     }
 233     return 0;
 234 }
 235 
 236 static krb5_error_code
 237 DB__del(krb5_context context, HDB *db, krb5_data key)
     /* [<][>][^][v][top][bottom][index][help] */
 238 {
 239     DB *d = (DB*)db->hdb_db;
 240     DBT k;
 241     krb5_error_code code;
 242     k.data = key.data;
 243     k.size = key.length;
 244     code = db->hdb_lock(context, db, HDB_WLOCK);
 245     if(code)
 246         return code;
 247     code = (*d->del)(d, &k, 0);
 248     db->hdb_unlock(context, db);
 249     if(code == 1) {
 250         code = errno;
 251         krb5_set_error_message(context, code, "Database %s put error: %s",
 252                                db->hdb_name, strerror(code));
 253         return code;
 254     }
 255     if(code < 0)
 256         return errno;
 257     return 0;
 258 }
 259 
 260 static krb5_error_code
 261 DB_open(krb5_context context, HDB *db, int flags, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
 262 {
 263     char *fn;
 264     krb5_error_code ret;
 265 
 266     asprintf(&fn, "%s.db", db->hdb_name);
 267     if (fn == NULL) {
 268         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 269         return ENOMEM;
 270     }
 271     db->hdb_db = dbopen(fn, flags, mode, DB_BTREE, NULL);
 272     free(fn);
 273     /* try to open without .db extension */
 274     if(db->hdb_db == NULL && errno == ENOENT)
 275         db->hdb_db = dbopen(db->hdb_name, flags, mode, DB_BTREE, NULL);
 276     if(db->hdb_db == NULL) {
 277         ret = errno;
 278         krb5_set_error_message(context, ret, "dbopen (%s): %s",
 279                               db->hdb_name, strerror(ret));
 280         return ret;
 281     }
 282     if((flags & O_ACCMODE) == O_RDONLY)
 283         ret = hdb_check_db_format(context, db);
 284     else
 285         ret = hdb_init_db(context, db);
 286     if(ret == HDB_ERR_NOENTRY) {
 287         krb5_clear_error_message(context);
 288         return 0;
 289     }
 290     if (ret) {
 291         DB_close(context, db);
 292         krb5_set_error_message(context, ret, "hdb_open: failed %s database %s",
 293                               (flags & O_ACCMODE) == O_RDONLY ?
 294                               "checking format of" : "initialize",
 295                               db->hdb_name);
 296     }
 297     return ret;
 298 }
 299 
 300 krb5_error_code
 301 hdb_db_create(krb5_context context, HDB **db,
     /* [<][>][^][v][top][bottom][index][help] */
 302               const char *filename)
 303 {
 304     *db = calloc(1, sizeof(**db));
 305     if (*db == NULL) {
 306         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 307         return ENOMEM;
 308     }
 309 
 310     (*db)->hdb_db = NULL;
 311     (*db)->hdb_name = strdup(filename);
 312     if ((*db)->hdb_name == NULL) {
 313         free(*db);
 314         *db = NULL;
 315         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 316         return ENOMEM;
 317     }
 318     (*db)->hdb_master_key_set = 0;
 319     (*db)->hdb_openp = 0;
 320     (*db)->hdb_open = DB_open;
 321     (*db)->hdb_close = DB_close;
 322     (*db)->hdb_fetch = _hdb_fetch;
 323     (*db)->hdb_store = _hdb_store;
 324     (*db)->hdb_remove = _hdb_remove;
 325     (*db)->hdb_firstkey = DB_firstkey;
 326     (*db)->hdb_nextkey= DB_nextkey;
 327     (*db)->hdb_lock = DB_lock;
 328     (*db)->hdb_unlock = DB_unlock;
 329     (*db)->hdb_rename = DB_rename;
 330     (*db)->hdb__get = DB__get;
 331     (*db)->hdb__put = DB__put;
 332     (*db)->hdb__del = DB__del;
 333     (*db)->hdb_destroy = DB_destroy;
 334     return 0;
 335 }
 336 
 337 #endif /* HAVE_DB1 */

/* [<][>][^][v][top][bottom][index][help] */