; - key_versions = getint(&p); /* key data version */ - kvno = getint(&p); - - /* - * An MIT dump file may contain multiple sets of keys with - * different kvnos. Since the Heimdal database can only represent - * one kvno per principal, we only want the highest set. Assume - * that set will be given first, and discard all keys with lower - * kvnos. - */ - if (kvno > high_kvno && high_kvno != -1) - errx(1, "line %d: high kvno keys given after low kvno keys", - lineno); - else if (kvno < high_kvno) { - nexttoken(&p); /* key type */ - nexttoken(&p); /* key length */ - nexttoken(&p); /* key */ - if (key_versions > 1) { - nexttoken(&p); /* salt type */ - nexttoken(&p); /* salt length */ - nexttoken(&p); /* salt */ - } - ent.entry.keys.len--; - continue; - } - ent.entry.kvno = kvno; - high_kvno = kvno; - ALLOC(ent.entry.keys.val[i].mkvno); - *ent.entry.keys.val[i].mkvno = 1; - - /* key version 0 -- actual key */ - ent.entry.keys.val[i].key.keytype = getint(&p); /* key type */ - tmp = getint(&p); /* key length */ - /* the first two bytes of the key is the key length -- - skip it */ - krb5_data_alloc(&ent.entry.keys.val[i].key.keyvalue, tmp - 2); - q = nexttoken(&p); /* key itself */ - hex_to_octet_string(q + 4, &ent.entry.keys.val[i].key.keyvalue); - - if(key_versions > 1) { - /* key version 1 -- optional salt */ - ALLOC(ent.entry.keys.val[i].salt); - ent.entry.keys.val[i].salt->type = getint(&p); /* salt type */ - tmp = getint(&p); /* salt length */ - if(tmp > 0) { - krb5_data_alloc(&ent.entry.keys.val[i].salt->salt, tmp - 2); - q = nexttoken(&p); /* salt itself */ - hex_to_octet_string(q + 4, - &ent.entry.keys.val[i].salt->salt); - } else { - ent.entry.keys.val[i].salt->salt.length = 0; - ent.entry.keys.val[i].salt->salt.data = NULL; - getint(&p); /* -1, if no data. */ - } - fix_salt(pd->context, &ent.entry, i); - } - } - nexttoken(&p); /* extra data */ - v5_prop(pd->context, NULL, &ent, arg); + krb5_storage_truncate(sp, 0); + ret = _hdb_mit_dump2mitdb_entry(pd->context, line, sp); + if (ret) break; + ret = krb5_storage_to_data(sp, &kdb_ent); + if (ret) break; + ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry); + krb5_data_free(&kdb_ent); + if (ret) break; + ret = v5_prop(pd->context, NULL, &ent, arg); + hdb_free_entry(pd->context, &ent); + if (ret) break; } + +out: fclose(f); - return 0; + free(line); + if (sp) + krb5_storage_free(sp); + if (ret && ret == ENOMEM) + errx(1, "out of memory"); + if (ret) + errx(1, "line %d: problem parsing dump line", lineno); + return ret; } + diff --git a/crypto/heimdal/lib/hdb/Makefile.am b/crypto/heimdal/lib/hdb/Makefile.am index b629f56258d2..fd009bd26867 100644 --- a/crypto/heimdal/lib/hdb/Makefile.am +++ b/crypto/heimdal/lib/hdb/Makefile.am @@ -29,6 +29,7 @@ gen_files_hdb = \ asn1_HDB_Ext_Lan_Manager_OWF.x \ asn1_HDB_Ext_Password.x \ asn1_HDB_Ext_Aliases.x \ + asn1_HDB_Ext_KeySet.x \ asn1_HDB_extension.x \ asn1_HDB_extensions.x \ asn1_hdb_entry.x \ diff --git a/crypto/heimdal/lib/hdb/common.c b/crypto/heimdal/lib/hdb/common.c index 2715adf63dca..80482e7a4c1c 100644 --- a/crypto/heimdal/lib/hdb/common.c +++ b/crypto/heimdal/lib/hdb/common.c @@ -105,7 +105,6 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, krb5_principal enterprise_principal = NULL; krb5_data key, value; krb5_error_code ret; - int code; if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { if (principal->name.name_string.len != 1) { @@ -125,43 +124,74 @@ _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, hdb_principal2key(context, principal, &key); if (enterprise_principal) krb5_free_principal(context, enterprise_principal); - code = db->hdb__get(context, db, key, &value); + ret = db->hdb__get(context, db, key, &value); krb5_data_free(&key); - if(code) - return code; - code = hdb_value2entry(context, &value, &entry->entry); - if (code == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) { + if(ret) + return ret; + ret = hdb_value2entry(context, &value, &entry->entry); + if (ret == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) { krb5_data_free(&value); return HDB_ERR_NOENTRY; - } else if (code == ASN1_BAD_ID) { + } else if (ret == ASN1_BAD_ID) { hdb_entry_alias alias; - code = hdb_value2entry_alias(context, &value, &alias); - if (code) { + ret = hdb_value2entry_alias(context, &value, &alias); + if (ret) { krb5_data_free(&value); - return code; + return ret; } hdb_principal2key(context, alias.principal, &key); krb5_data_free(&value); free_hdb_entry_alias(&alias); - code = db->hdb__get(context, db, key, &value); + ret = db->hdb__get(context, db, key, &value); krb5_data_free(&key); - if (code) - return code; - code = hdb_value2entry(context, &value, &entry->entry); - if (code) { + if (ret) + return ret; + ret = hdb_value2entry(context, &value, &entry->entry); + if (ret) { krb5_data_free(&value); - return code; + return ret; } } krb5_data_free(&value); if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { - code = hdb_unseal_keys (context, db, &entry->entry); - if (code) +#ifdef notnow + if ((flags & HDB_F_KVNO_SPECIFIED) == 0 && + (flags & HDB_F_CURRENT_KVNO) == 0) { + + /* + * Decrypt all the old keys too, since we don't know which + * the caller will need. + */ + ret = hdb_unseal_keys_kvno(context, db, 0, &entry->entry); + if (ret) { + hdb_free_entry(context, entry); + return ret; + } + } else if ((flags & HDB_F_KVNO_SPECIFIED) != 0 && + kvno != entry->entry.kvno && + kvno < entry->entry.kvno && + kvno > 0) { + + /* Decrypt the keys we were asked for, if not the current ones */ + ret = hdb_unseal_keys_kvno(context, db, kvno, &entry->entry); + if (ret) { + hdb_free_entry(context, entry); + return ret; + } + } +#endif + + /* Always decrypt the current keys too */ + ret = hdb_unseal_keys(context, db, &entry->entry); + if (ret) { hdb_free_entry(context, entry); + return ret; + } } - return code; + + return ret; } static krb5_error_code diff --git a/crypto/heimdal/lib/hdb/ext.c b/crypto/heimdal/lib/hdb/ext.c index d2a4373b9b38..5f7a19a55e04 100644 --- a/crypto/heimdal/lib/hdb/ext.c +++ b/crypto/heimdal/lib/hdb/ext.c @@ -432,3 +432,34 @@ hdb_entry_get_aliases(const hdb_entry *entry, const HDB_Ext_Aliases **a) return 0; } + +krb5_error_code +hdb_set_last_modified_by(krb5_context context, hdb_entry *entry, + krb5_principal modby, time_t modtime) +{ + krb5_error_code ret; + Event *old_ev; + Event *ev; + + old_ev = entry->modified_by; + + ev = calloc(1, sizeof (*ev)); + if (!ev) + return ENOMEM; + if (modby) + ret = krb5_copy_principal(context, modby, &ev->principal); + else + ret = krb5_parse_name(context, "root/admin", &ev->principal); + if (ret) { + free(ev); + return ret; + } + ev->time = modtime; + if (!ev->time) + time(&ev->time); + + entry->modified_by = ev; + if (old_ev) + free_Event(old_ev); + return 0; +} diff --git a/crypto/heimdal/lib/hdb/hdb-mitdb.c b/crypto/heimdal/lib/hdb/hdb-mitdb.c index 02c575050fe2..1dfe7835cb4d 100644 --- a/crypto/heimdal/lib/hdb/hdb-mitdb.c *** 1800 LINES SKIPPED ***