summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/hdb
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-07-25 18:51:53 +0200
committerStefan Metzmacher <metze@samba.org>2011-07-26 02:16:08 +0200
commit5a8635bca1b6d60a5b81c602eb4f0b7fd8902d7b (patch)
treea9a73cdf05ce487a174c9ef7ab334007348e7248 /source4/heimdal/lib/hdb
parentf1a59f9d6f45987acd0304ee58e4488333faad18 (diff)
downloadsamba-5a8635bca1b6d60a5b81c602eb4f0b7fd8902d7b.tar.gz
samba-5a8635bca1b6d60a5b81c602eb4f0b7fd8902d7b.tar.bz2
samba-5a8635bca1b6d60a5b81c602eb4f0b7fd8902d7b.zip
s4:heimdal: import lorikeet-heimdal-201107241840 (commit 0fdf11fa3cdb47df9f5393ebf36d9f5742243036)
Diffstat (limited to 'source4/heimdal/lib/hdb')
-rw-r--r--source4/heimdal/lib/hdb/db.c22
-rw-r--r--source4/heimdal/lib/hdb/ext.c64
-rw-r--r--source4/heimdal/lib/hdb/hdb.asn125
-rw-r--r--source4/heimdal/lib/hdb/hdb.c5
-rw-r--r--source4/heimdal/lib/hdb/hdb.h8
-rw-r--r--source4/heimdal/lib/hdb/hdb_err.et1
-rw-r--r--source4/heimdal/lib/hdb/hdb_locl.h3
-rw-r--r--source4/heimdal/lib/hdb/keys.c143
-rw-r--r--source4/heimdal/lib/hdb/mkey.c150
-rw-r--r--source4/heimdal/lib/hdb/version-script.map24
10 files changed, 409 insertions, 36 deletions
diff --git a/source4/heimdal/lib/hdb/db.c b/source4/heimdal/lib/hdb/db.c
index 69940edf89..2ed054a631 100644
--- a/source4/heimdal/lib/hdb/db.c
+++ b/source4/heimdal/lib/hdb/db.c
@@ -65,12 +65,24 @@ DB_lock(krb5_context context, HDB *db, int operation)
{
DB *d = (DB*)db->hdb_db;
int fd = (*d->fd)(d);
+ krb5_error_code ret;
+
+ if (db->lock_count > 0) {
+ db->lock_count++;
+ if (db->lock_type == HDB_WLOCK || db->lock_type == operation)
+ return 0;
+ }
+
if(fd < 0) {
krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB,
"Can't lock database: %s", db->hdb_name);
return HDB_ERR_CANT_LOCK_DB;
}
- return hdb_lock(fd, operation);
+ ret = hdb_lock(fd, operation);
+ if (ret)
+ return ret;
+ db->lock_count++;
+ return 0;
}
static krb5_error_code
@@ -78,6 +90,14 @@ DB_unlock(krb5_context context, HDB *db)
{
DB *d = (DB*)db->hdb_db;
int fd = (*d->fd)(d);
+
+ if (db->lock_count > 1) {
+ db->lock_count--;
+ return 0;
+ }
+ heim_assert(db->lock_count == 1, "HDB lock/unlock sequence does not match");
+ db->lock_count--;
+
if(fd < 0) {
krb5_set_error_message(context, HDB_ERR_CANT_LOCK_DB,
"Can't unlock database: %s", db->hdb_name);
diff --git a/source4/heimdal/lib/hdb/ext.c b/source4/heimdal/lib/hdb/ext.c
index d2a4373b9b..f4f1715240 100644
--- a/source4/heimdal/lib/hdb/ext.c
+++ b/source4/heimdal/lib/hdb/ext.c
@@ -432,3 +432,67 @@ hdb_entry_get_aliases(const hdb_entry *entry, const HDB_Ext_Aliases **a)
return 0;
}
+
+unsigned int
+hdb_entry_get_kvno_diff_clnt(const hdb_entry *entry)
+{
+ const HDB_extension *ext;
+
+ ext = hdb_find_extension(entry,
+ choice_HDB_extension_data_hist_kvno_diff_clnt);
+ if (ext)
+ return ext->data.u.hist_kvno_diff_clnt;
+ return 1;
+}
+
+krb5_error_code
+hdb_entry_set_kvno_diff_clnt(krb5_context context, hdb_entry *entry,
+ unsigned int diff)
+{
+ HDB_extension ext;
+
+ if (diff > 16384)
+ return EINVAL;
+ ext.data.element = choice_HDB_extension_data_hist_kvno_diff_clnt;
+ ext.data.u.hist_kvno_diff_clnt = diff;
+ return hdb_replace_extension(context, entry, &ext);
+}
+
+krb5_error_code
+hdb_entry_clear_kvno_diff_clnt(krb5_context context, hdb_entry *entry)
+{
+ return hdb_clear_extension(context, entry,
+ choice_HDB_extension_data_hist_kvno_diff_clnt);
+}
+
+unsigned int
+hdb_entry_get_kvno_diff_svc(const hdb_entry *entry)
+{
+ const HDB_extension *ext;
+
+ ext = hdb_find_extension(entry,
+ choice_HDB_extension_data_hist_kvno_diff_svc);
+ if (ext)
+ return ext->data.u.hist_kvno_diff_svc;
+ return 1024; /* max_life effectively provides a better default */
+}
+
+krb5_error_code
+hdb_entry_set_kvno_diff_svc(krb5_context context, hdb_entry *entry,
+ unsigned int diff)
+{
+ HDB_extension ext;
+
+ if (diff > 16384)
+ return EINVAL;
+ ext.data.element = choice_HDB_extension_data_hist_kvno_diff_svc;
+ ext.data.u.hist_kvno_diff_svc = diff;
+ return hdb_replace_extension(context, entry, &ext);
+}
+
+krb5_error_code
+hdb_entry_clear_kvno_diff_svc(krb5_context context, hdb_entry *entry)
+{
+ return hdb_clear_extension(context, entry,
+ choice_HDB_extension_data_hist_kvno_diff_svc);
+}
diff --git a/source4/heimdal/lib/hdb/hdb.asn1 b/source4/heimdal/lib/hdb/hdb.asn1
index a72851c9f2..0594b313b7 100644
--- a/source4/heimdal/lib/hdb/hdb.asn1
+++ b/source4/heimdal/lib/hdb/hdb.asn1
@@ -46,8 +46,9 @@ HDBFlags ::= BIT STRING {
trusted-for-delegation(14), -- Trusted to print forwardabled tickets
allow-kerberos4(15), -- Allow Kerberos 4 requests
allow-digest(16), -- Allow digest requests
- locked-out(17) -- Account is locked out,
+ locked-out(17), -- Account is locked out,
-- authentication will be denied
+ do-not-store(31) -- Not to be modified and stored in HDB
}
GENERATION ::= SEQUENCE {
@@ -87,6 +88,17 @@ HDB-Ext-Aliases ::= SEQUENCE {
aliases[1] SEQUENCE OF Principal -- all names, inc primary
}
+Keys ::= SEQUENCE OF Key
+
+hdb_keyset ::= SEQUENCE {
+ kvno[0] INTEGER (0..4294967295),
+ keys[1] Keys,
+ set-time[2] KerberosTime OPTIONAL, -- time this keyset was created/set
+ ...
+}
+
+HDB-Ext-KeySet ::= SEQUENCE OF hdb_keyset
+
HDB-extension ::= SEQUENCE {
mandatory[0] BOOLEAN, -- kdc MUST understand this extension,
@@ -102,6 +114,10 @@ HDB-extension ::= SEQUENCE {
aliases[6] HDB-Ext-Aliases,
last-pw-change[7] KerberosTime,
pkinit-cert[8] HDB-Ext-PKINIT-cert,
+ hist-keys[9] HDB-Ext-KeySet,
+ hist-kvno-diff-clnt[10] INTEGER (0..4294967295),
+ hist-kvno-diff-svc[11] INTEGER (0..4294967295),
+ policy[12] UTF8String,
...
},
...
@@ -109,16 +125,11 @@ 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
-- for compatibility with libkrb5
kvno[1] INTEGER (0..4294967295),
- keys[2] SEQUENCE OF Key,
+ keys[2] Keys,
created-by[3] Event,
modified-by[4] Event OPTIONAL,
valid-start[5] KerberosTime OPTIONAL,
diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c
index ca05cc4a17..5dc5a0957e 100644
--- a/source4/heimdal/lib/hdb/hdb.c
+++ b/source4/heimdal/lib/hdb/hdb.c
@@ -168,13 +168,14 @@ hdb_unlock(int fd)
void
hdb_free_entry(krb5_context context, hdb_entry_ex *ent)
{
+ Key *k;
size_t i;
if (ent->free_entry)
(*ent->free_entry)(context, ent);
- for(i = 0; i < ent->entry.keys.len; ++i) {
- Key *k = &ent->entry.keys.val[i];
+ for(i = 0; i < ent->entry.keys.len; i++) {
+ k = &ent->entry.keys.val[i];
memset (k->key.keyvalue.data, 0, k->key.keyvalue.length);
}
diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h
index 469ec82ec0..75d18770f0 100644
--- a/source4/heimdal/lib/hdb/hdb.h
+++ b/source4/heimdal/lib/hdb/hdb.h
@@ -57,6 +57,12 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
#define HDB_F_CANON 32 /* want canonicalition */
#define HDB_F_ADMIN_DATA 64 /* want data that kdc don't use */
#define HDB_F_KVNO_SPECIFIED 128 /* we want a particular KVNO */
+#define HDB_F_CURRENT_KVNO 256 /* we want the current KVNO */
+#define HDB_F_LIVE_CLNT_KVNOS 512 /* we want all live keys for pre-auth */
+#define HDB_F_LIVE_SVC_KVNOS 1024 /* we want all live keys for tix */
+#define HDB_F_ALL_KVNOS 2048 /* we want all the keys, live or not */
+#define HDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */
+#define HDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */
/* hdb_capability_flags */
#define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1
@@ -102,6 +108,8 @@ typedef struct HDB{
hdb_master_key hdb_master_key;
int hdb_openp;
int hdb_capability_flags;
+ int lock_count;
+ int lock_type;
/**
* Open (or create) the a Kerberos database.
*
diff --git a/source4/heimdal/lib/hdb/hdb_err.et b/source4/heimdal/lib/hdb/hdb_err.et
index 2cad4daba4..0bdcb385f6 100644
--- a/source4/heimdal/lib/hdb/hdb_err.et
+++ b/source4/heimdal/lib/hdb/hdb_err.et
@@ -26,5 +26,6 @@ error_code NO_MKEY, "No correct master key"
error_code MANDATORY_OPTION, "Entry contains unknown mandatory extension"
error_code NO_WRITE_SUPPORT, "HDB backend doesn't contain write support"
error_code NOT_FOUND_HERE, "The secret for this entry is not replicated to this database"
+error_code MISUSE, "Incorrect use of the API"
end
diff --git a/source4/heimdal/lib/hdb/hdb_locl.h b/source4/heimdal/lib/hdb/hdb_locl.h
index e896b58025..c210b98b84 100644
--- a/source4/heimdal/lib/hdb/hdb_locl.h
+++ b/source4/heimdal/lib/hdb/hdb_locl.h
@@ -36,6 +36,9 @@
#ifndef __HDB_LOCL_H__
#define __HDB_LOCL_H__
+#include <assert.h>
+#include <heimbase.h>
+
#include <config.h>
#include <stdio.h>
diff --git a/source4/heimdal/lib/hdb/keys.c b/source4/heimdal/lib/hdb/keys.c
index 3d0b9d7c1b..0bc3392fb6 100644
--- a/source4/heimdal/lib/hdb/keys.c
+++ b/source4/heimdal/lib/hdb/keys.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997 - 2001, 2003 - 2004 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2011 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -39,9 +39,9 @@
*/
void
-hdb_free_keys (krb5_context context, int len, Key *keys)
+hdb_free_keys(krb5_context context, int len, Key *keys)
{
- int i;
+ size_t i;
for (i = 0; i < len; i++) {
free(keys[i].mkvno);
@@ -68,15 +68,15 @@ hdb_free_keys (krb5_context context, int len, Key *keys)
*/
static const krb5_enctype des_etypes[] = {
- ETYPE_DES_CBC_MD5,
- ETYPE_DES_CBC_MD4,
- ETYPE_DES_CBC_CRC
+ KRB5_ENCTYPE_DES_CBC_MD5,
+ KRB5_ENCTYPE_DES_CBC_MD4,
+ KRB5_ENCTYPE_DES_CBC_CRC
};
static const krb5_enctype all_etypes[] = {
- ETYPE_AES256_CTS_HMAC_SHA1_96,
- ETYPE_ARCFOUR_HMAC_MD5,
- ETYPE_DES3_CBC_SHA1
+ KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+ KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
+ KRB5_ENCTYPE_DES3_CBC_SHA1
};
static krb5_error_code
@@ -114,7 +114,7 @@ parse_key_set(krb5_context context, const char *key,
enctypes = des_etypes;
num_enctypes = sizeof(des_etypes)/sizeof(des_etypes[0]);
} else if(strcmp(buf[i], "des3") == 0) {
- e = ETYPE_DES3_CBC_SHA1;
+ e = KRB5_ENCTYPE_DES3_CBC_SHA1;
enctypes = &e;
num_enctypes = 1;
} else {
@@ -196,6 +196,68 @@ parse_key_set(krb5_context context, const char *key,
return 0;
}
+
+/**
+ * This function adds an HDB entry's current keyset to the entry's key
+ * history. The current keyset is left alone; the caller is responsible
+ * for freeing it.
+ *
+ * @param context Context
+ * @param entry HDB entry
+ */
+krb5_error_code
+hdb_add_current_keys_to_history(krb5_context context, hdb_entry *entry)
+{
+ krb5_boolean replace = FALSE;
+ krb5_error_code ret;
+ HDB_extension *ext;
+ hdb_keyset newkey;
+ time_t newtime;
+
+
+ ext = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys);
+ if (ext == NULL) {
+ replace = TRUE;
+ ext = calloc(1, sizeof (*ext));
+ if (ext == NULL)
+ return krb5_enomem(context);
+
+ ext->data.element = choice_HDB_extension_data_hist_keys;
+ }
+
+ /*
+ * Copy in newest old keyset
+ */
+
+ ret = hdb_entry_get_pw_change_time(entry, &newtime);
+ if (ret)
+ goto out;
+
+ memset(&newkey, 0, sizeof(newkey));
+ newkey.keys = entry->keys;
+ newkey.kvno = entry->kvno;
+ newkey.set_time = &newtime;
+
+ ret = add_HDB_Ext_KeySet(&ext->data.u.hist_keys, &newkey);
+ if (ret)
+ goto out;
+
+ if (replace) {
+ /* hdb_replace_extension() deep-copies ext; what a waste */
+ ret = hdb_replace_extension(context, entry, ext);
+ if (ret)
+ goto out;
+ }
+
+ out:
+ if (replace && ext) {
+ free_HDB_extension(ext);
+ free(ext);
+ }
+ return ret;
+}
+
+
static krb5_error_code
add_enctype_to_key_set(Key **key_set, size_t *nkeyset,
krb5_enctype enctype, krb5_salt *salt)
@@ -243,6 +305,50 @@ add_enctype_to_key_set(Key **key_set, size_t *nkeyset,
}
+static
+krb5_error_code
+ks_tuple2str(krb5_context context, int n_ks_tuple,
+ krb5_key_salt_tuple *ks_tuple, char ***ks_tuple_strs)
+{
+ size_t i;
+ char **ksnames;
+ char *ename, *sname;
+ krb5_error_code rc = KRB5_PROG_ETYPE_NOSUPP;
+
+ *ks_tuple_strs = NULL;
+ if (n_ks_tuple < 1)
+ return 0;
+
+ if ((ksnames = calloc(n_ks_tuple, sizeof (*ksnames))) == NULL)
+ return (errno);
+
+ for (i = 0; i < n_ks_tuple; i++) {
+ if (krb5_enctype_to_string(context, ks_tuple[i].ks_enctype, &ename))
+ goto out;
+ if (krb5_salttype_to_string(context, ks_tuple[i].ks_enctype,
+ ks_tuple[i].ks_salttype, &sname))
+ goto out;
+
+ if (asprintf(&ksnames[i], "%s:%s", ename, sname) == -1) {
+ rc = errno;
+ free(ename);
+ free(sname);
+ goto out;
+ }
+ free(ename);
+ free(sname);
+ }
+
+ *ks_tuple_strs = ksnames;
+ rc = 0;
+
+out:
+ for (i = 0; i < n_ks_tuple; i++)
+ free(ksnames[i]);
+ free(ksnames);
+ return (rc);
+}
+
/*
* Generate the `key_set' from the [kadmin]default_keys statement. If
* `no_salt' is set, salt is not important (and will not be set) since
@@ -251,12 +357,15 @@ add_enctype_to_key_set(Key **key_set, size_t *nkeyset,
krb5_error_code
hdb_generate_key_set(krb5_context context, krb5_principal principal,
+ int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
Key **ret_key_set, size_t *nkeyset, int no_salt)
{
- char **ktypes, **kp;
+ char **ktypes = NULL;
+ char **kp;
krb5_error_code ret;
Key *k, *key_set;
size_t i, j;
+ char **ks_tuple_strs;
static const char *default_keytypes[] = {
"aes256-cts-hmac-sha1-96:pw-salt",
"des3-cbc-sha1:pw-salt",
@@ -264,16 +373,18 @@ hdb_generate_key_set(krb5_context context, krb5_principal principal,
NULL
};
- ktypes = krb5_config_get_strings(context, NULL, "kadmin",
- "default_keys", NULL);
+ if ((ret = ks_tuple2str(context, n_ks_tuple, ks_tuple, &ks_tuple_strs)))
+ return ret;
+
+ if (ks_tuple_strs == NULL)
+ ktypes = krb5_config_get_strings(context, NULL, "kadmin",
+ "default_keys", NULL);
if (ktypes == NULL)
ktypes = (char **)(intptr_t)default_keytypes;
*ret_key_set = key_set = NULL;
*nkeyset = 0;
- ret = 0;
-
for(kp = ktypes; kp && *kp; kp++) {
const char *p;
krb5_salt salt;
@@ -366,7 +477,7 @@ hdb_generate_key_set_password(krb5_context context,
krb5_error_code ret;
size_t i;
- ret = hdb_generate_key_set(context, principal,
+ ret = hdb_generate_key_set(context, principal, 0, NULL,
keys, num_keys, 0);
if (ret)
return ret;
diff --git a/source4/heimdal/lib/hdb/mkey.c b/source4/heimdal/lib/hdb/mkey.c
index 9a13d55a51..6dcfc02942 100644
--- a/source4/heimdal/lib/hdb/mkey.c
+++ b/source4/heimdal/lib/hdb/mkey.c
@@ -228,7 +228,7 @@ read_master_encryptionkey(krb5_context context, const char *filename,
should cover all cases, but will break if someone has hacked
this code to really use des-cbc-md5 -- but then that's not my
problem. */
- if(key.keytype == KEYTYPE_DES || key.keytype == ETYPE_DES_CBC_MD5)
+ if(key.keytype == ETYPE_DES_CBC_CRC || key.keytype == ETYPE_DES_CBC_MD5)
key.keytype = ETYPE_DES_CFB64_NONE;
ret = hdb_process_master_key(context, 0, &key, 0, mkey);
@@ -480,6 +480,131 @@ hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent)
}
krb5_error_code
+hdb_unseal_keys_kvno(krb5_context context, HDB *db, krb5_kvno kvno,
+ unsigned flags, hdb_entry *ent)
+{
+ krb5_error_code ret = HDB_ERR_NOENTRY;
+ HDB_extension *ext;
+ HDB_Ext_KeySet *hist_keys;
+ Key *tmp_val;
+ time_t tmp_set_time;
+ unsigned int tmp_len;
+ unsigned int kvno_diff = 0;
+ krb5_kvno tmp_kvno;
+ size_t i, k;
+ int exclude_dead = 0;
+ KerberosTime now = 0;
+ time_t *set_time;
+
+ if (kvno == 0)
+ ret = 0;
+
+ if ((flags & HDB_F_LIVE_CLNT_KVNOS) || (flags & HDB_F_LIVE_SVC_KVNOS)) {
+ exclude_dead = 1;
+ now = time(NULL);
+ if (HDB_F_LIVE_CLNT_KVNOS)
+ kvno_diff = hdb_entry_get_kvno_diff_clnt(ent);
+ else
+ kvno_diff = hdb_entry_get_kvno_diff_svc(ent);
+ }
+
+ ext = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys);
+ if (ext == NULL)
+ return ret;
+
+ /* For swapping; see below */
+ tmp_len = ent->keys.len;
+ tmp_val = ent->keys.val;
+ tmp_kvno = ent->kvno;
+ (void) hdb_entry_get_pw_change_time(ent, &tmp_set_time);
+
+ hist_keys = &ext->data.u.hist_keys;
+
+ for (i = 0; i < hist_keys->len; i++) {
+ if (kvno != 0 && hist_keys->val[i].kvno != kvno)
+ continue;
+
+ if (exclude_dead &&
+ ((ent->max_life != NULL &&
+ hist_keys->val[i].set_time != NULL &&
+ (*hist_keys->val[i].set_time) < (now - (*ent->max_life))) ||
+ (hist_keys->val[i].kvno < kvno &&
+ (kvno - hist_keys->val[i].kvno) > kvno_diff)))
+ /*
+ * The KDC may want to to check for this keyset's set_time
+ * is within the TGS principal's max_life, say. But we stop
+ * here.
+ */
+ continue;
+
+ /* Either the keys we want, or all the keys */
+ for (k = 0; k < hist_keys->val[i].keys.len; k++) {
+ ret = hdb_unseal_key_mkey(context,
+ &hist_keys->val[i].keys.val[k],
+ db->hdb_master_key);
+ /*
+ * If kvno == 0 we might not want to bail here! E.g., if we
+ * no longer have the right master key, so just ignore this.
+ *
+ * We could filter out keys that we can't decrypt here
+ * because of HDB_ERR_NO_MKEY. However, it seems safest to
+ * filter them out only where necessary, say, in kadm5.
+ */
+ if (ret && kvno != 0)
+ return ret;
+ if (ret && ret != HDB_ERR_NO_MKEY)
+ return (ret);
+ }
+
+ if (kvno == 0)
+ continue;
+
+ /*
+ * What follows is a bit of a hack.
+ *
+ * This is the keyset we're being asked for, but it's not the
+ * current keyset. So we add the current keyset to the history,
+ * leave the one we were asked for in the history, and pretend
+ * the one we were asked for is also the current keyset.
+ *
+ * This is a bit of a defensive hack in case an entry fetched
+ * this way ever gets modified then stored: if the keyset is not
+ * changed we can detect this and put things back, else we won't
+ * drop any keysets from history by accident.
+ *
+ * Note too that we only ever get called with a non-zero kvno
+ * either in the KDC or in cases where we aren't changing the
+ * HDB entry anyways, which is why this is just a defensive
+ * hack. We also don't fetch specific kvnos in the dump case,
+ * so there's no danger that we'll dump this entry and load it
+ * again, repeatedly causing the history to grow boundelessly.
+ */
+ set_time = malloc(sizeof (*set_time));
+ if (set_time == NULL)
+ return ENOMEM;
+
+ /* Swap key sets */
+ ent->kvno = hist_keys->val[i].kvno;
+ ent->keys.val = hist_keys->val[i].keys.val;
+ ent->keys.len = hist_keys->val[i].keys.len;
+ if (hist_keys->val[i].set_time != NULL)
+ /* Sloppy, but the callers we expect won't care */
+ (void) hdb_entry_set_pw_change_time(context, ent,
+ *hist_keys->val[i].set_time);
+ hist_keys->val[i].kvno = tmp_kvno;
+ hist_keys->val[i].keys.val = tmp_val;
+ hist_keys->val[i].keys.len = tmp_len;
+ if (hist_keys->val[i].set_time != NULL)
+ /* Sloppy, but the callers we expect won't care */
+ *hist_keys->val[i].set_time = tmp_set_time;
+
+ return 0;
+ }
+
+ return (ret);
+}
+
+krb5_error_code
hdb_unseal_key(krb5_context context, HDB *db, Key *k)
{
if (db->hdb_master_key_set == 0)
@@ -526,14 +651,31 @@ hdb_seal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
krb5_error_code
hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
{
- size_t i;
- for(i = 0; i < ent->keys.len; i++){
- krb5_error_code ret;
+ HDB_extension *ext;
+ HDB_Ext_KeySet *hist_keys;
+ size_t i, k;
+ krb5_error_code ret;
+ for(i = 0; i < ent->keys.len; i++){
ret = hdb_seal_key_mkey(context, &ent->keys.val[i], mkey);
if (ret)
return ret;
}
+
+ ext = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys);
+ if (ext == NULL)
+ return 0;
+ hist_keys = &ext->data.u.hist_keys;
+
+ for (i = 0; i < hist_keys->len; i++) {
+ for (k = 0; k < hist_keys->val[i].keys.len; k++) {
+ ret = hdb_seal_key_mkey(context, &hist_keys->val[i].keys.val[k],
+ mkey);
+ if (ret)
+ return ret;
+ }
+ }
+
return 0;
}
diff --git a/source4/heimdal/lib/hdb/version-script.map b/source4/heimdal/lib/hdb/version-script.map
index 50a36cec0a..f80fb78a65 100644
--- a/source4/heimdal/lib/hdb/version-script.map
+++ b/source4/heimdal/lib/hdb/version-script.map
@@ -4,6 +4,7 @@ HEIMDAL_HDB_1.0 {
global:
encode_hdb_keyset;
hdb_add_master_key;
+ hdb_add_current_keys_to_history;
hdb_check_db_format;
hdb_clear_extension;
hdb_clear_master_key;
@@ -74,33 +75,44 @@ HEIMDAL_HDB_1.0 {
hdb_kt_ops;
# some random bits needed for libkadm
- HDBFlags2int;
+ add_HDB_Ext_KeySet;
+ add_Keys;
asn1_HDBFlags_units;
copy_Event;
copy_HDB_extensions;
copy_Key;
+ copy_Keys;
copy_Salt;
decode_HDB_Ext_Aliases;
- decode_HDB_Ext_PKINIT_acl;
decode_HDB_extension;
+ decode_HDB_Ext_PKINIT_acl;
decode_Key;
+ decode_Keys;
encode_HDB_Ext_Aliases;
- encode_HDB_Ext_PKINIT_acl;
encode_HDB_extension;
+ encode_HDB_Ext_PKINIT_acl;
encode_Key;
+ encode_Keys;
free_Event;
+ free_hdb_entry;
free_HDB_Ext_Aliases;
- free_HDB_Ext_PKINIT_acl;
free_HDB_extension;
free_HDB_extensions;
+ free_HDB_Ext_PKINIT_acl;
+ free_hdb_keyset;
free_Key;
+ free_Keys;
free_Salt;
- free_hdb_entry;
+ HDBFlags2int;
int2HDBFlags;
length_HDB_Ext_Aliases;
- length_HDB_Ext_PKINIT_acl;
length_HDB_extension;
+ length_HDB_Ext_PKINIT_acl;
length_Key;
+ length_Keys;
+ remove_Keys;
+ add_Keys;
+ add_HDB_Ext_Keyset;
local:
*;