diff --git a/lib/hdb/Makefile.am b/lib/hdb/Makefile.am new file mode 100644 index 000000000..4a8f0e55b --- /dev/null +++ b/lib/hdb/Makefile.am @@ -0,0 +1,9 @@ +# $Id$ + +AUTOMAKE_OPTIONS = no-dependencies + +INCLUDES = -I$(top_builddir)/include -I$(top_builddir) + +lib_LIBRARIES = libhdb.a + +libhdb_a_SOURCES = hdb.c db.c ndbm.c diff --git a/lib/hdb/db.c b/lib/hdb/db.c new file mode 100644 index 000000000..9686de176 --- /dev/null +++ b/lib/hdb/db.c @@ -0,0 +1,148 @@ +#include "hdb_locl.h" + +RCSID("$Id$"); + +#ifdef HAVE_DB_H + +krb5_error_code +DB_close(krb5_context context, HDB *db) +{ + DB *d = (DB*)db->db; + d->close(d); + free(db); + return 0; +} + +static krb5_error_code +DB_fetch(krb5_context context, HDB *db, hdb_entry *entry) +{ + DB *d = (DB*)db->db; + DBT key, value; + krb5_data data; + int err; + + hdb_principal2key(context, entry->principal, &data); + + key.data = data.data; + key.size = data.length; + err = d->get(d, &key, &value, 0); + krb5_data_free(&data); + if(err < 0) + return errno; + if(err == 1) + return KRB5_HDB_NOENTRY; + + data.data = value.data; + data.length = value.size; + + hdb_value2entry(context, &data, entry); + krb5_data_free(&data); + return 0; +} + +static krb5_error_code +DB_store(krb5_context context, HDB *db, hdb_entry *entry) +{ + DB *d = (DB*)db->db; + krb5_data data; + int err; + DBT key, value; + hdb_principal2key(context, entry->principal, &data); + key.data = data.data; + key.size = data.length; + hdb_entry2value(context, entry, &data); + value.data = data.data; + value.size = data.length; + err = d->put(d, &key, &value, 0); + free(key.data); + free(value.data); + if(err == -1) + return errno; + return 0; +} + +static krb5_error_code +DB_delete(krb5_context context, HDB *db, hdb_entry *entry) +{ + DB *d = (DB*)db->db; + DBT key; + krb5_data data; + int err; + + hdb_principal2key(context, entry->principal, &data); + + key.data = data.data; + key.size = data.length; + err = d->del(d, &key, 0); + krb5_data_free(&data); + if(err < 0) + return errno; + if(err == 1) + return KRB5_HDB_NOENTRY; + return 0; +} + +static krb5_error_code +DB_seq(krb5_context context, HDB *db, hdb_entry *entry, int flag) + +{ + DB *d = (DB*)db->db; + DBT key, value; + krb5_data data; + int err; + + err = d->seq(d, &key, &value, flag); + if(err == -1) + return errno; + if(err == 1) + return KRB5_HDB_NOENTRY; + + data.data = key.data; + data.length = key.size; + hdb_key2principal(context, &data, &entry->principal); + krb5_data_free(&data); + data.data = value.data; + data.length = value.size; + hdb_value2entry(context, &data, entry); + krb5_data_free(&data); + return 0; +} + + +static krb5_error_code +DB_firstkey(krb5_context context, HDB *db, hdb_entry *entry) +{ + return DB_seq(context, db, entry, R_FIRST); +} + + +static krb5_error_code +DB_nextkey(krb5_context context, HDB *db, hdb_entry *entry) +{ + return DB_seq(context, db, entry, R_NEXT); +} + +krb5_error_code +hdb_db_open(krb5_context context, HDB **db, + const char *filename, int flags, mode_t mode) +{ + DB *d; + char *fn = malloc(strlen(filename) + 4); + sprintf(fn, "%s.db", filename); + d = dbopen(fn, flags, mode, DB_BTREE, NULL); + free(fn); + if(d == NULL) + return errno; + *db = malloc(sizeof(**db)); + (*db)->db = d; + (*db)->close = DB_close; + (*db)->fetch = DB_fetch; + (*db)->store = DB_store; + (*db)->delete = DB_delete; + (*db)->firstkey = DB_firstkey; + (*db)->nextkey= DB_nextkey; + return 0; +} + + +#endif diff --git a/lib/hdb/hdb.c b/lib/hdb/hdb.c new file mode 100644 index 000000000..8e1f6cc3e --- /dev/null +++ b/lib/hdb/hdb.c @@ -0,0 +1,76 @@ +#include "hdb_locl.h" + +RCSID("$Id$"); + +void +hdb_principal2key(krb5_context context, krb5_principal p, krb5_data *key) +{ + krb5_storage *sp; + krb5_principal new; + krb5_copy_principal(context, p, &new); + new->type = 0; + sp = krb5_storage_emem(); + krb5_store_principal(sp, p); + krb5_storage_to_data(sp, key); + krb5_storage_free(sp); + krb5_free_principal(new); +} + +void +hdb_key2principal(krb5_context context, krb5_data *key, krb5_principal *p) +{ + krb5_storage *sp; + int32_t tmp; + sp = krb5_storage_from_mem(key->data, key->length); + krb5_ret_principal(sp, p); + krb5_storage_free(sp); +} + +void +hdb_entry2value(krb5_context context, hdb_entry *ent, krb5_data *value) +{ + krb5_storage *sp; + sp = krb5_storage_emem(); + krb5_store_keyblock(sp, ent->keyblock); + krb5_store_int32(sp, ent->kvno); + krb5_store_int32(sp, ent->max_life); + krb5_store_int32(sp, ent->max_renew); + krb5_storage_to_data(sp, value); + krb5_storage_free(sp); +} + +void +hdb_value2entry(krb5_context context, krb5_data *value, hdb_entry *ent) +{ + krb5_storage *sp; + int32_t tmp; + sp = krb5_storage_from_mem(value->data, value->length); + krb5_ret_keyblock(sp, &ent->keyblock); + krb5_ret_int32(sp, &tmp); + ent->kvno = tmp; + krb5_ret_int32(sp, &tmp); + ent->max_life = tmp; + krb5_ret_int32(sp, &tmp); + ent->max_renew = tmp; + krb5_storage_free(sp); +} + + +#ifdef HAVE_DB_H + +#endif + + +krb5_error_code +hdb_open(krb5_context context, HDB **db, + const char *filename, int flags, mode_t mode) +{ + if(filename == NULL) + filename = HDB_DEFAULT_DB; +#ifdef HAVE_DB_H + return hdb_db_open(context,db, filename, flags, mode); +#elif HAVE_NDBM_H + return hdb_ndbm_open(context,db, filename, flags, mode); +#endif + return 17; +} diff --git a/lib/hdb/hdb.h b/lib/hdb/hdb.h new file mode 100644 index 000000000..437d888bd --- /dev/null +++ b/lib/hdb/hdb.h @@ -0,0 +1,33 @@ +/* $Id$ */ + +#ifndef __HDB_H__ +#define __HDB_H__ + +#include + +typedef struct hdb_entry{ + krb5_principal principal; + krb5_keyblock keyblock; + int kvno; + time_t max_life; + time_t max_renew; +}hdb_entry; + +typedef struct HDB{ + void *db; + + krb5_error_code (*close)(krb5_context, struct HDB*); + krb5_error_code (*fetch)(krb5_context, struct HDB*, hdb_entry*); + krb5_error_code (*store)(krb5_context, struct HDB*, hdb_entry*); + krb5_error_code (*delete)(krb5_context, struct HDB*, hdb_entry*); + krb5_error_code (*firstkey)(krb5_context, struct HDB*, hdb_entry*); + krb5_error_code (*nextkey)(krb5_context, struct HDB*, hdb_entry*); +}HDB; + +krb5_error_code hdb_db_open(krb5_context, HDB**, const char*, int, mode_t); +krb5_error_code hdb_ndbm_open(krb5_context, HDB**, const char*, int, mode_t); +krb5_error_code hdb_open(krb5_context, HDB**, const char*, int, mode_t); + +#define HDB_DEFAULT_DB "heimdal" + +#endif /* __HDB_H__ */ diff --git a/lib/hdb/hdb_locl.h b/lib/hdb/hdb_locl.h new file mode 100644 index 000000000..5b62ab5e7 --- /dev/null +++ b/lib/hdb/hdb_locl.h @@ -0,0 +1,29 @@ +/* $Id$ */ + +#ifndef __HDB_LOCL_H__ +#define __HDB_LOCL_H__ + +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef HAVE_DB_H +#include +#endif + +#ifdef HAVE_NDBM_H +#include +#endif + +void hdb_principal2key(krb5_context, krb5_principal, krb5_data*); +void hdb_key2principal(krb5_context, krb5_data*, krb5_principal*); +void hdb_entry2value(krb5_context, hdb_entry*, krb5_data*); +void hdb_value2entry(krb5_context, krb5_data*, hdb_entry*); + +#endif /* __HDB_LOCL_H__ */ diff --git a/lib/hdb/ndbm.c b/lib/hdb/ndbm.c new file mode 100644 index 000000000..14bb4d02b --- /dev/null +++ b/lib/hdb/ndbm.c @@ -0,0 +1,143 @@ +#include "hdb_locl.h" + +RCSID("$Id$"); + +#ifdef HAVE_NDBM_H + +krb5_error_code +NDBM_close(krb5_context context, HDB *db) +{ + DBM *d = (DB*)db->db; + dbm_close(d); + free(db); + return 0; +} + +static krb5_error_code +NDBM_fetch(krb5_context context, HDB *db, hdb_entry *entry) +{ + DBM *d = (DBM*)db->db; + datum key, value; + krb5_data data; + int err; + + hdb_principal2key(context, entry->principal, &data); + + key.dptr = data.data; + key.dsize = data.length; + value = dbm_fetch(d, key); + krb5_data_free(&data); + if(value.dptr == NULL) + return errno; + + data.data = value.dptr; + data.length = value.dsize; + + hdb_value2entry(context, &data, entry); + krb5_data_free(&data); + return 0; +} + +static krb5_error_code +NDBM_store(krb5_context context, HDB *db, hdb_entry *entry) +{ + DBM *d = (DBM*)db->db; + krb5_data data; + int err; + datum key, value; + hdb_principal2key(context, entry->principal, &data); + key.dptr = data.data; + key.dsize = data.length; + hdb_entry2value(context, entry, &data); + value.dptr = data.data; + value.dsize = data.length; + err = dbm_store(d, key, value, DBM_REPLACE); + free(key.dptr); + free(value.dptr); + if(err < 0) + return errno; + return 0; +} + +static krb5_error_code +NDBM_delete(krb5_context context, HDB *db, hdb_entry *entry) +{ + DBM *d = (DBM*)db->db; + datum key; + krb5_data data; + int err; + + hdb_principal2key(context, entry->principal, &data); + + key.dptr = data.data; + key.dsize = data.length; + err = dbm_delete(d, key); + krb5_data_free(&data); + if(err < 0) + return errno; + return 0; +} + +static krb5_error_code +NDBM_seq(krb5_context context, HDB *db, hdb_entry *entry, int first) + +{ + DBM *d = (DBM*)db->db; + datum key, value; + krb5_data data; + + if(first) + key = dbm_firstkey(d); + else + key = dbm_nextkey(d); + if(key.dptr == NULL) + return KRB5_HDB_NOENTRY; + data.data = key.dptr; + data.length = key.dsize; + hdb_key2principal(context, &data, &entry->principal); + value = dbm_fetch(d, key); + krb5_data_free(&data); + data.data = value.dptr; + data.length = value.dsize; + hdb_value2entry(context, &data, entry); + krb5_data_free(&data); + return 0; +} + + +static krb5_error_code +NDBM_firstkey(krb5_context context, HDB *db, hdb_entry *entry) +{ + return NDBM_seq(context, db, entry, 1); +} + + +static krb5_error_code +NDBM_nextkey(krb5_context context, HDB *db, hdb_entry *entry) +{ + return DB_seq(context, db, entry, 0); +} + +krb5_error_code +hdb_ndbm_open(krb5_context context, HDB **db, + const char *filename, int flags, mode_t mode) +{ + DBM *d; + char *fn = malloc(strlen(filename) + 4); + sprintf(fn, "%s.db", filename); + d = dbm_open(fn, flags, mode); + free(fn); + if(d == NULL) + return errno; + *db = malloc(sizeof(**db)); + (*db)->db = d; + (*db)->close = NDBM_close; + (*db)->fetch = NDBM_fetch; + (*db)->store = NDBM_store; + (*db)->delete = NDBM_delete; + (*db)->firstkey = NDBM_firstkey; + (*db)->nextkey= NDBM_nextkey; + return 0; +} + +#endif