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

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

DEFINITIONS

This source file includes following definitions.
  1. NDBM_destroy
  2. NDBM_lock
  3. NDBM_unlock
  4. NDBM_seq
  5. NDBM_firstkey
  6. NDBM_nextkey
  7. NDBM_rename
  8. NDBM__get
  9. NDBM__put
  10. NDBM__del
  11. NDBM_close
  12. NDBM_open
  13. hdb_ndbm_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_NDBM
  39 
  40 #if defined(HAVE_GDBM_NDBM_H)
  41 #include <gdbm/ndbm.h>
  42 #elif defined(HAVE_NDBM_H)
  43 #include <ndbm.h>
  44 #elif defined(HAVE_DBM_H)
  45 #include <dbm.h>
  46 #endif
  47 
  48 struct ndbm_db {
  49     DBM *db;
  50     int lock_fd;
  51 };
  52 
  53 static krb5_error_code
  54 NDBM_destroy(krb5_context context, HDB *db)
     /* [<][>][^][v][top][bottom][index][help] */
  55 {
  56     krb5_error_code ret;
  57 
  58     ret = hdb_clear_master_key (context, db);
  59     free(db->hdb_name);
  60     free(db);
  61     return 0;
  62 }
  63 
  64 static krb5_error_code
  65 NDBM_lock(krb5_context context, HDB *db, int operation)
     /* [<][>][^][v][top][bottom][index][help] */
  66 {
  67     struct ndbm_db *d = db->hdb_db;
  68     return hdb_lock(d->lock_fd, operation);
  69 }
  70 
  71 static krb5_error_code
  72 NDBM_unlock(krb5_context context, HDB *db)
     /* [<][>][^][v][top][bottom][index][help] */
  73 {
  74     struct ndbm_db *d = db->hdb_db;
  75     return hdb_unlock(d->lock_fd);
  76 }
  77 
  78 static krb5_error_code
  79 NDBM_seq(krb5_context context, HDB *db,
     /* [<][>][^][v][top][bottom][index][help] */
  80          unsigned flags, hdb_entry_ex *entry, int first)
  81 
  82 {
  83     struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
  84     datum key, value;
  85     krb5_data key_data, data;
  86     krb5_error_code ret = 0;
  87 
  88     if(first)
  89         key = dbm_firstkey(d->db);
  90     else
  91         key = dbm_nextkey(d->db);
  92     if(key.dptr == NULL)
  93         return HDB_ERR_NOENTRY;
  94     key_data.data = key.dptr;
  95     key_data.length = key.dsize;
  96     ret = db->hdb_lock(context, db, HDB_RLOCK);
  97     if(ret) return ret;
  98     value = dbm_fetch(d->db, key);
  99     db->hdb_unlock(context, db);
 100     data.data = value.dptr;
 101     data.length = value.dsize;
 102     memset(entry, 0, sizeof(*entry));
 103     if(hdb_value2entry(context, &data, &entry->entry))
 104         return NDBM_seq(context, db, flags, entry, 0);
 105     if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
 106         ret = hdb_unseal_keys (context, db, &entry->entry);
 107         if (ret)
 108             hdb_free_entry (context, entry);
 109     }
 110     if (ret == 0 && entry->entry.principal == NULL) {
 111         entry->entry.principal = malloc (sizeof(*entry->entry.principal));
 112         if (entry->entry.principal == NULL) {
 113             hdb_free_entry (context, entry);
 114             ret = ENOMEM;
 115             krb5_set_error_message(context, ret, "malloc: out of memory");
 116         } else {
 117             hdb_key2principal (context, &key_data, entry->entry.principal);
 118         }
 119     }
 120     return ret;
 121 }
 122 
 123 
 124 static krb5_error_code
 125 NDBM_firstkey(krb5_context context, HDB *db,unsigned flags,hdb_entry_ex *entry)
     /* [<][>][^][v][top][bottom][index][help] */
 126 {
 127     return NDBM_seq(context, db, flags, entry, 1);
 128 }
 129 
 130 
 131 static krb5_error_code
 132 NDBM_nextkey(krb5_context context, HDB *db, unsigned flags,hdb_entry_ex *entry)
     /* [<][>][^][v][top][bottom][index][help] */
 133 {
 134     return NDBM_seq(context, db, flags, entry, 0);
 135 }
 136 
 137 static krb5_error_code
 138 NDBM_rename(krb5_context context, HDB *db, const char *new_name)
     /* [<][>][^][v][top][bottom][index][help] */
 139 {
 140     /* XXX this function will break */
 141     struct ndbm_db *d = db->hdb_db;
 142 
 143     int ret;
 144     char *old_dir, *old_pag, *new_dir, *new_pag;
 145     char *new_lock;
 146     int lock_fd;
 147 
 148     /* lock old and new databases */
 149     ret = db->hdb_lock(context, db, HDB_WLOCK);
 150     if(ret)
 151         return ret;
 152     asprintf(&new_lock, "%s.lock", new_name);
 153     if(new_lock == NULL) {
 154         db->hdb_unlock(context, db);
 155         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 156         return ENOMEM;
 157     }
 158     lock_fd = open(new_lock, O_RDWR | O_CREAT, 0600);
 159     if(lock_fd < 0) {
 160         ret = errno;
 161         db->hdb_unlock(context, db);
 162         krb5_set_error_message(context, ret, "open(%s): %s", new_lock,
 163                                strerror(ret));
 164         free(new_lock);
 165         return ret;
 166     }
 167     free(new_lock);
 168     ret = hdb_lock(lock_fd, HDB_WLOCK);
 169     if(ret) {
 170         db->hdb_unlock(context, db);
 171         close(lock_fd);
 172         return ret;
 173     }
 174 
 175     asprintf(&old_dir, "%s.dir", db->hdb_name);
 176     asprintf(&old_pag, "%s.pag", db->hdb_name);
 177     asprintf(&new_dir, "%s.dir", new_name);
 178     asprintf(&new_pag, "%s.pag", new_name);
 179 
 180     ret = rename(old_dir, new_dir) || rename(old_pag, new_pag);
 181     free(old_dir);
 182     free(old_pag);
 183     free(new_dir);
 184     free(new_pag);
 185     hdb_unlock(lock_fd);
 186     db->hdb_unlock(context, db);
 187 
 188     if(ret) {
 189         ret = errno;
 190         close(lock_fd);
 191         krb5_set_error_message(context, ret, "rename: %s", strerror(ret));
 192         return ret;
 193     }
 194 
 195     close(d->lock_fd);
 196     d->lock_fd = lock_fd;
 197 
 198     free(db->hdb_name);
 199     db->hdb_name = strdup(new_name);
 200     return 0;
 201 }
 202 
 203 static krb5_error_code
 204 NDBM__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
     /* [<][>][^][v][top][bottom][index][help] */
 205 {
 206     struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
 207     datum k, v;
 208     int code;
 209 
 210     k.dptr  = key.data;
 211     k.dsize = key.length;
 212     code = db->hdb_lock(context, db, HDB_RLOCK);
 213     if(code)
 214         return code;
 215     v = dbm_fetch(d->db, k);
 216     db->hdb_unlock(context, db);
 217     if(v.dptr == NULL)
 218         return HDB_ERR_NOENTRY;
 219 
 220     krb5_data_copy(reply, v.dptr, v.dsize);
 221     return 0;
 222 }
 223 
 224 static krb5_error_code
 225 NDBM__put(krb5_context context, HDB *db, int replace,
     /* [<][>][^][v][top][bottom][index][help] */
 226         krb5_data key, krb5_data value)
 227 {
 228     struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
 229     datum k, v;
 230     int code;
 231 
 232     k.dptr  = key.data;
 233     k.dsize = key.length;
 234     v.dptr  = value.data;
 235     v.dsize = value.length;
 236 
 237     code = db->hdb_lock(context, db, HDB_WLOCK);
 238     if(code)
 239         return code;
 240     code = dbm_store(d->db, k, v, replace ? DBM_REPLACE : DBM_INSERT);
 241     db->hdb_unlock(context, db);
 242     if(code == 1)
 243         return HDB_ERR_EXISTS;
 244     if (code < 0)
 245         return code;
 246     return 0;
 247 }
 248 
 249 static krb5_error_code
 250 NDBM__del(krb5_context context, HDB *db, krb5_data key)
     /* [<][>][^][v][top][bottom][index][help] */
 251 {
 252     struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
 253     datum k;
 254     int code;
 255     krb5_error_code ret;
 256 
 257     k.dptr = key.data;
 258     k.dsize = key.length;
 259     ret = db->hdb_lock(context, db, HDB_WLOCK);
 260     if(ret) return ret;
 261     code = dbm_delete(d->db, k);
 262     db->hdb_unlock(context, db);
 263     if(code < 0)
 264         return errno;
 265     return 0;
 266 }
 267 
 268 
 269 static krb5_error_code
 270 NDBM_close(krb5_context context, HDB *db)
     /* [<][>][^][v][top][bottom][index][help] */
 271 {
 272     struct ndbm_db *d = db->hdb_db;
 273     dbm_close(d->db);
 274     close(d->lock_fd);
 275     free(d);
 276     return 0;
 277 }
 278 
 279 static krb5_error_code
 280 NDBM_open(krb5_context context, HDB *db, int flags, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
 281 {
 282     krb5_error_code ret;
 283     struct ndbm_db *d = malloc(sizeof(*d));
 284     char *lock_file;
 285 
 286     if(d == NULL) {
 287         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 288         return ENOMEM;
 289     }
 290     asprintf(&lock_file, "%s.lock", (char*)db->hdb_name);
 291     if(lock_file == NULL) {
 292         free(d);
 293         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 294         return ENOMEM;
 295     }
 296     d->db = dbm_open((char*)db->hdb_name, flags, mode);
 297     if(d->db == NULL){
 298         ret = errno;
 299         free(d);
 300         free(lock_file);
 301         krb5_set_error_message(context, ret, "dbm_open(%s): %s", db->hdb_name,
 302                                strerror(ret));
 303         return ret;
 304     }
 305     d->lock_fd = open(lock_file, O_RDWR | O_CREAT, 0600);
 306     if(d->lock_fd < 0){
 307         ret = errno;
 308         dbm_close(d->db);
 309         free(d);
 310         krb5_set_error_message(context, ret, "open(%s): %s", lock_file,
 311                                strerror(ret));
 312         free(lock_file);
 313         return ret;
 314     }
 315     free(lock_file);
 316     db->hdb_db = d;
 317     if((flags & O_ACCMODE) == O_RDONLY)
 318         ret = hdb_check_db_format(context, db);
 319     else
 320         ret = hdb_init_db(context, db);
 321     if(ret == HDB_ERR_NOENTRY)
 322         return 0;
 323     if (ret) {
 324         NDBM_close(context, db);
 325         krb5_set_error_message(context, ret, "hdb_open: failed %s database %s",
 326                                (flags & O_ACCMODE) == O_RDONLY ?
 327                                "checking format of" : "initialize",
 328                                db->hdb_name);
 329     }
 330     return ret;
 331 }
 332 
 333 krb5_error_code
 334 hdb_ndbm_create(krb5_context context, HDB **db,
     /* [<][>][^][v][top][bottom][index][help] */
 335                 const char *filename)
 336 {
 337     *db = calloc(1, sizeof(**db));
 338     if (*db == NULL) {
 339         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 340         return ENOMEM;
 341     }
 342 
 343     (*db)->hdb_db = NULL;
 344     (*db)->hdb_name = strdup(filename);
 345     if ((*db)->hdb_name == NULL) {
 346         free(*db);
 347         *db = NULL;
 348         krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
 349         return ENOMEM;
 350     }
 351     (*db)->hdb_master_key_set = 0;
 352     (*db)->hdb_openp = 0;
 353     (*db)->hdb_open = NDBM_open;
 354     (*db)->hdb_close = NDBM_close;
 355     (*db)->hdb_fetch = _hdb_fetch;
 356     (*db)->hdb_store = _hdb_store;
 357     (*db)->hdb_remove = _hdb_remove;
 358     (*db)->hdb_firstkey = NDBM_firstkey;
 359     (*db)->hdb_nextkey= NDBM_nextkey;
 360     (*db)->hdb_lock = NDBM_lock;
 361     (*db)->hdb_unlock = NDBM_unlock;
 362     (*db)->hdb_rename = NDBM_rename;
 363     (*db)->hdb__get = NDBM__get;
 364     (*db)->hdb__put = NDBM__put;
 365     (*db)->hdb__del = NDBM__del;
 366     (*db)->hdb_destroy = NDBM_destroy;
 367     return 0;
 368 }
 369 
 370 #endif /* HAVE_NDBM */

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