From 9b261c008a395a323e0516f4cd3f3134aa050577 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 8 Jun 2009 19:06:16 +1000 Subject: s4:heimdal: import lorikeet-heimdal-200906080040 (commit 904d0124b46eed7a8ad6e5b73e892ff34b6865ba) Also including the supporting changes required to pass make test A number of heimdal functions and constants have changed since we last imported a tree (for the better, but inconvenient for us). Andrew Bartlett --- source4/heimdal/lib/hdb/dbinfo.c | 6 +- source4/heimdal/lib/hdb/ext.c | 14 ++++ source4/heimdal/lib/hdb/hdb.asn1 | 12 ++- source4/heimdal/lib/hdb/hdb.c | 55 ++++++++++---- source4/heimdal/lib/hdb/hdb.h | 157 ++++++++++++++++++++++++++------------- source4/heimdal/lib/hdb/keys.c | 13 ++-- source4/heimdal/lib/hdb/keytab.c | 7 +- source4/heimdal/lib/hdb/mkey.c | 29 ++++---- source4/heimdal/lib/hdb/ndbm.c | 4 +- 9 files changed, 203 insertions(+), 94 deletions(-) (limited to 'source4/heimdal/lib/hdb') diff --git a/source4/heimdal/lib/hdb/dbinfo.c b/source4/heimdal/lib/hdb/dbinfo.c index 2121577bb1..7e2961c614 100644 --- a/source4/heimdal/lib/hdb/dbinfo.c +++ b/source4/heimdal/lib/hdb/dbinfo.c @@ -228,10 +228,12 @@ hdb_free_dbinfo(krb5_context context, struct hdb_dbinfo **dbp) for(di = *dbp; di != NULL; di = ndi) { ndi = di->next; + free (di->label); free (di->realm); free (di->dbname); - if (di->mkey_file) - free (di->mkey_file); + free (di->mkey_file); + free (di->acl_file); + free (di->log_file); free(di); } *dbp = NULL; diff --git a/source4/heimdal/lib/hdb/ext.c b/source4/heimdal/lib/hdb/ext.c index f792b85c09..9053fd6633 100644 --- a/source4/heimdal/lib/hdb/ext.c +++ b/source4/heimdal/lib/hdb/ext.c @@ -234,6 +234,20 @@ hdb_entry_get_pkinit_hash(const hdb_entry *entry, const HDB_Ext_PKINIT_hash **a) return 0; } +krb5_error_code +hdb_entry_get_pkinit_cert(const hdb_entry *entry, const HDB_Ext_PKINIT_cert **a) +{ + const HDB_extension *ext; + + ext = hdb_find_extension(entry, choice_HDB_extension_data_pkinit_cert); + if (ext) + *a = &ext->data.u.pkinit_cert; + else + *a = NULL; + + return 0; +} + krb5_error_code hdb_entry_get_pw_change_time(const hdb_entry *entry, time_t *t) { diff --git a/source4/heimdal/lib/hdb/hdb.asn1 b/source4/heimdal/lib/hdb/hdb.asn1 index 5cddf8f1d0..c2abd4af73 100644 --- a/source4/heimdal/lib/hdb/hdb.asn1 +++ b/source4/heimdal/lib/hdb/hdb.asn1 @@ -13,7 +13,8 @@ hdb-afs3-salt INTEGER ::= 10 Salt ::= SEQUENCE { type[0] INTEGER (0..4294967295), - salt[1] OCTET STRING + salt[1] OCTET STRING, + opaque[2] OCTET STRING OPTIONAL } Key ::= SEQUENCE { @@ -64,6 +65,10 @@ HDB-Ext-PKINIT-hash ::= SEQUENCE OF SEQUENCE { digest[1] OCTET STRING } +HDB-Ext-PKINIT-cert ::= SEQUENCE OF SEQUENCE { + cert[0] OCTET STRING +} + HDB-Ext-Constrained-delegation-acl ::= SEQUENCE OF Principal -- hdb-ext-referrals ::= PA-SERVER-REFERRAL-DATA @@ -94,6 +99,7 @@ HDB-extension ::= SEQUENCE { password[5] HDB-Ext-Password, aliases[6] HDB-Ext-Aliases, last-pw-change[7] KerberosTime, + pkinit-cert[8] HDB-Ext-PKINIT-cert, ... }, ... @@ -101,6 +107,10 @@ HDB-extension ::= SEQUENCE { HDB-extensions ::= SEQUENCE OF HDB-extension +hdb_keyset ::= SEQUENCE { + kvno[1] INTEGER (0..4294967295), + keys[0] SEQUENCE OF Key +} hdb_entry ::= SEQUENCE { principal[0] Principal OPTIONAL, -- this is optional only diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c index ad2c35a43a..e55b0bed03 100644 --- a/source4/heimdal/lib/hdb/hdb.c +++ b/source4/heimdal/lib/hdb/hdb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,11 +31,6 @@ * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "krb5.h" #include "krb5_locl.h" #include "hdb_locl.h" RCSID("$Id$"); @@ -44,24 +39,49 @@ RCSID("$Id$"); #include #endif +/*! @mainpage Heimdal database backend library + * + * @section intro Introduction + * + * Heimdal libhdb library provides the backend support for Heimdal kdc + * and kadmind. Its here where plugins for diffrent database engines + * can be pluged in and extend support for here Heimdal get the + * principal and policy data from. + * + * Example of Heimdal backend are: + * - Berkeley DB 1.85 + * - Berkeley DB 3.0 + * - Berkeley DB 4.0 + * - New Berkeley DB + * - LDAP + * + * + * The project web page: http://www.h5l.org/ + * + */ + + + static struct hdb_method methods[] = { #if HAVE_DB1 || HAVE_DB3 - {HDB_INTERFACE_VERSION, "db:", hdb_db_create}, + { HDB_INTERFACE_VERSION, "db:", hdb_db_create}, #endif #if HAVE_NDBM - {HDB_INTERFACE_VERSION, "ndbm:", hdb_ndbm_create}, + { HDB_INTERFACE_VERSION, "ndbm:", hdb_ndbm_create}, #endif #if defined(OPENLDAP) && !defined(OPENLDAP_MODULE) - {HDB_INTERFACE_VERSION, "ldap:", hdb_ldap_create}, - {HDB_INTERFACE_VERSION, "ldapi:", hdb_ldapi_create}, + { HDB_INTERFACE_VERSION, "ldap:", hdb_ldap_create}, + { HDB_INTERFACE_VERSION, "ldapi:", hdb_ldapi_create}, #endif {0, NULL, NULL} }; #if HAVE_DB1 || HAVE_DB3 -static struct hdb_method dbmetod = {"", hdb_db_create }; +static struct hdb_method dbmetod = + { HDB_INTERFACE_VERSION, "", hdb_db_create }; #elif defined(HAVE_NDBM) -static struct hdb_method dbmetod = {"", hdb_ndbm_create }; +static struct hdb_method dbmetod = + { HDB_INTERFACE_VERSION, "", hdb_ndbm_create }; #endif @@ -265,9 +285,10 @@ find_dynamic_method (krb5_context context, len = p - filename; *rest = filename + len + 1; - prefix = strndup(filename, len); + prefix = malloc(len + 1); if (prefix == NULL) krb5_errx(context, 1, "out of memory"); + strlcpy(prefix, filename, len + 1); if (asprintf(&path, LIBDIR "/hdb_%s.so", prefix) == -1) krb5_errx(context, 1, "out of memory"); @@ -390,6 +411,14 @@ hdb_list_builtin(krb5_context context, char **list) return 0; } +/** + * Create a handle for a Kerberos database + * + * Create a handle for a Kerberos database backend specified by a + * filename. Doesn't create a file if its doesn't exists, you have to + * use O_CREAT to tell the backend to create the file. + */ + krb5_error_code hdb_create(krb5_context context, HDB **db, const char *filename) { diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index 53b1defc96..ce219153b3 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -66,65 +66,122 @@ typedef struct hdb_entry_ex { } hdb_entry_ex; +/** + * HDB backend function pointer structure + * + * The HDB structure is what the KDC and kadmind framework uses to + * query the backend database when talking about principals. + */ + typedef struct HDB{ void *hdb_db; - void *hdb_dbc; + void *hdb_dbc; /** don't use, only for DB3 */ char *hdb_name; int hdb_master_key_set; hdb_master_key hdb_master_key; int hdb_openp; - krb5_error_code (*hdb_open)(krb5_context, - struct HDB*, - int, - mode_t); - krb5_error_code (*hdb_close)(krb5_context, - struct HDB*); - void (*hdb_free)(krb5_context, - struct HDB*, - hdb_entry_ex*); - krb5_error_code (*hdb_fetch)(krb5_context, - struct HDB*, - krb5_const_principal, - unsigned, - hdb_entry_ex*); - krb5_error_code (*hdb_store)(krb5_context, - struct HDB*, - unsigned, + /** + * Open (or create) the a Kerberos database. + * + * Open (or create) the a Kerberos database that was resolved with + * hdb_create(). The third and fourth flag to the function are the + * same as open(), thus passing O_CREAT will create the data base + * if it doesn't exists. + * + * Then done the caller should call hdb_close(), and to release + * all resources hdb_destroy(). + */ + krb5_error_code (*hdb_open)(krb5_context, struct HDB*, int, mode_t); + /** + * Close the database for transaction + * + * Closes the database for further transactions, wont release any + * permanant resources. the database can be ->hdb_open-ed again. + */ + krb5_error_code (*hdb_close)(krb5_context, struct HDB*); + /** + * Free an entry after use. + */ + void (*hdb_free)(krb5_context, struct HDB*, hdb_entry_ex*); + /** + * Fetch an entry from the backend + * + * Fetch an entry from the backend, flags are what type of entry + * should be fetch: client, server, krbtgt. + */ + krb5_error_code (*hdb_fetch)(krb5_context, struct HDB*, + krb5_const_principal, unsigned, hdb_entry_ex*); - krb5_error_code (*hdb_remove)(krb5_context, - struct HDB*, + /** + * Store an entry to database + */ + krb5_error_code (*hdb_store)(krb5_context, struct HDB*, + unsigned, hdb_entry_ex*); + /** + * Remove an entry from the database. + */ + krb5_error_code (*hdb_remove)(krb5_context, struct HDB*, krb5_const_principal); - krb5_error_code (*hdb_firstkey)(krb5_context, - struct HDB*, - unsigned, - hdb_entry_ex*); - krb5_error_code (*hdb_nextkey)(krb5_context, - struct HDB*, - unsigned, - hdb_entry_ex*); - krb5_error_code (*hdb_lock)(krb5_context, - struct HDB*, - int operation); - krb5_error_code (*hdb_unlock)(krb5_context, - struct HDB*); - krb5_error_code (*hdb_rename)(krb5_context, - struct HDB*, - const char*); - krb5_error_code (*hdb__get)(krb5_context, - struct HDB*, - krb5_data, - krb5_data*); - krb5_error_code (*hdb__put)(krb5_context, - struct HDB*, - int, - krb5_data, - krb5_data); - krb5_error_code (*hdb__del)(krb5_context, - struct HDB*, - krb5_data); - krb5_error_code (*hdb_destroy)(krb5_context, - struct HDB*); + /** + * As part of iteration, fetch one entry + */ + krb5_error_code (*hdb_firstkey)(krb5_context, struct HDB*, + unsigned, hdb_entry_ex*); + /** + * As part of iteration, fetch next entry + */ + krb5_error_code (*hdb_nextkey)(krb5_context, struct HDB*, + unsigned, hdb_entry_ex*); + /** + * Lock database + * + * A lock can only be held by one consumers. Transaction can still + * happen on the database while the lock is held, so the entry is + * only useful for syncroning creation of the database and renaming of the database. + */ + krb5_error_code (*hdb_lock)(krb5_context, struct HDB*, int); + /** + * Unlock database + */ + krb5_error_code (*hdb_unlock)(krb5_context, struct HDB*); + /** + * Rename the data base. + */ + krb5_error_code (*hdb_rename)(krb5_context, struct HDB*, const char*); + /** + * Get an hdb_entry from a classical DB backend + * + * If the database is a classical DB (ie BDB, NDBM, GDBM, etc) + * backend, this function will take a principal key (krb5_data) + * and return all data related to principal in the return + * krb5_data. The returned encoded entry is of type hdb_entry or + * hdb_entry_alias. + */ + krb5_error_code (*hdb__get)(krb5_context, struct HDB*, + krb5_data, krb5_data*); + /** + * Store an hdb_entry from a classical DB backend + * + * Same discussion as in @ref HDB::hdb__get + */ + krb5_error_code (*hdb__put)(krb5_context, struct HDB*, int, + krb5_data, krb5_data); + /** + * Delete and hdb_entry from a classical DB backend + * + * Same discussion as in @ref HDB::hdb__get + */ + krb5_error_code (*hdb__del)(krb5_context, struct HDB*, krb5_data); + /** + * Destroy the handle to the database. + * + * Destroy the handle to the database, deallocate all memory and + * related resources. Does not remove any permanent data. Its the + * logical reverse of hdb_create() function that is the entry + * point for the module. + */ + krb5_error_code (*hdb_destroy)(krb5_context, struct HDB*); }HDB; #define HDB_INTERFACE_VERSION 4 diff --git a/source4/heimdal/lib/hdb/keys.c b/source4/heimdal/lib/hdb/keys.c index b9f294e2eb..50fe7d7fda 100644 --- a/source4/heimdal/lib/hdb/keys.c +++ b/source4/heimdal/lib/hdb/keys.c @@ -1,3 +1,4 @@ + /* * Copyright (c) 1997 - 2001, 2003 - 2004 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). @@ -172,8 +173,8 @@ parse_key_set(krb5_context context, const char *key, if(salt->salttype == KRB5_PW_SALT) ret = krb5_get_pw_salt(context, principal, salt); else if(salt->salttype == KRB5_AFS3_SALT) { - krb5_realm *realm = krb5_princ_realm(context, principal); - salt->saltvalue.data = strdup(*realm); + krb5_const_realm realm = krb5_principal_get_realm(context, principal); + salt->saltvalue.data = strdup(realm); if(salt->saltvalue.data == NULL) { krb5_set_error_message(context, ENOMEM, "out of memory while " @@ -181,7 +182,7 @@ parse_key_set(krb5_context context, const char *key, return ENOMEM; } strlwr(salt->saltvalue.data); - salt->saltvalue.length = strlen(*realm); + salt->saltvalue.length = strlen(realm); } } @@ -217,7 +218,7 @@ add_enctype_to_key_set(Key **key_set, size_t *nkeyset, key.key.keyvalue.data = NULL; if (salt) { - key.salt = malloc(sizeof(*key.salt)); + key.salt = calloc(1, sizeof(*key.salt)); if (key.salt == NULL) { free_Key(&key); return ENOMEM; @@ -259,7 +260,6 @@ hdb_generate_key_set(krb5_context context, krb5_principal principal, Key *k, *key_set; int i, j; char *default_keytypes[] = { - "des:pw-salt", "aes256-cts-hmac-sha1-96:pw-salt", "des3-cbc-sha1:pw-salt", "arcfour-hmac-md5:pw-salt", @@ -271,9 +271,6 @@ hdb_generate_key_set(krb5_context context, krb5_principal principal, if (ktypes == NULL) ktypes = default_keytypes; - if (ktypes == NULL) - abort(); - *ret_key_set = key_set = NULL; *nkeyset = 0; diff --git a/source4/heimdal/lib/hdb/keytab.c b/source4/heimdal/lib/hdb/keytab.c index a890ba62cd..97989a9764 100644 --- a/source4/heimdal/lib/hdb/keytab.c +++ b/source4/heimdal/lib/hdb/keytab.c @@ -59,7 +59,7 @@ hdb_resolve(krb5_context context, const char *name, krb5_keytab id) return ENOMEM; } db = name; - mkey = strrchr(name, ':'); + mkey = strchr(name, ':'); if(mkey == NULL || mkey[1] == '\0') { if(*name == '\0') d->dbname = NULL; @@ -147,7 +147,7 @@ find_db (krb5_context context, const krb5_config_binding *top_bind = NULL; const krb5_config_binding *default_binding = NULL; const krb5_config_binding *db; - krb5_realm *prealm = krb5_princ_realm(context, rk_UNCONST(principal)); + krb5_const_realm realm = krb5_principal_get_realm(context, principal); *dbname = *mkey = NULL; @@ -169,7 +169,7 @@ find_db (krb5_context context, krb5_warnx(context, "WARNING: using the first encountered"); } else default_binding = db; - } else if (strcmp (*prealm, p) == 0) { + } else if (strcmp (realm, p) == 0) { set_config (context, db, dbname, mkey); break; } @@ -263,6 +263,7 @@ krb5_kt_ops hdb_kt_ops = { hdb_resolve, hdb_get_name, hdb_close, + NULL, /* destroy */ hdb_get_entry, NULL, /* start_seq_get */ NULL, /* next_entry */ diff --git a/source4/heimdal/lib/hdb/mkey.c b/source4/heimdal/lib/hdb/mkey.c index ce1aa9aff1..1520c4f7e9 100644 --- a/source4/heimdal/lib/hdb/mkey.c +++ b/source4/heimdal/lib/hdb/mkey.c @@ -169,23 +169,24 @@ read_master_mit(krb5_context context, const char *filename, return errno; } krb5_storage_set_flags(sp, KRB5_STORAGE_HOST_BYTEORDER); -#if 0 /* could possibly use ret_keyblock here, but do it with more checks for now */ - ret = krb5_ret_keyblock(sp, &key); -#else - ret = krb5_ret_int16(sp, &enctype); - if((htons(enctype) & 0xff00) == 0x3000) { - ret = HEIM_ERR_BAD_MKEY; - krb5_set_error_message(context, ret, "unknown keytype in %s: %#x, expected %#x", - filename, htons(enctype), 0x3000); - goto out; + { + ret = krb5_ret_int16(sp, &enctype); + if (ret) + goto out; + if((htons(enctype) & 0xff00) == 0x3000) { + ret = HEIM_ERR_BAD_MKEY; + krb5_set_error_message(context, ret, "unknown keytype in %s: " + "%#x, expected %#x", + filename, htons(enctype), 0x3000); + goto out; + } + key.keytype = enctype; + ret = krb5_ret_data(sp, &key.keyvalue); + if(ret) + goto out; } - key.keytype = enctype; - ret = krb5_ret_data(sp, &key.keyvalue); - if(ret) - goto out; -#endif ret = hdb_process_master_key(context, 0, &key, 0, mkey); krb5_free_keyblock_contents(context, &key); out: diff --git a/source4/heimdal/lib/hdb/ndbm.c b/source4/heimdal/lib/hdb/ndbm.c index e71125c61f..1e9df81652 100644 --- a/source4/heimdal/lib/hdb/ndbm.c +++ b/source4/heimdal/lib/hdb/ndbm.c @@ -53,9 +53,7 @@ struct ndbm_db { static krb5_error_code NDBM_destroy(krb5_context context, HDB *db) { - krb5_error_code ret; - - ret = hdb_clear_master_key (context, db); + hdb_clear_master_key (context, db); free(db->hdb_name); free(db); return 0; -- cgit