155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2002 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "hdb_locl.h" 3555682Smarkm 3655682Smarkmint 37178825Sdfrhdb_principal2key(krb5_context context, krb5_const_principal p, krb5_data *key) 3855682Smarkm{ 3955682Smarkm Principal new; 40233294Sstas size_t len = 0; 4155682Smarkm int ret; 4255682Smarkm 4355682Smarkm ret = copy_Principal(p, &new); 44233294Sstas if(ret) 45103423Snectar return ret; 4655682Smarkm new.name.name_type = 0; 47103423Snectar 48103423Snectar ASN1_MALLOC_ENCODE(Principal, key->data, key->length, &new, &len, ret); 49178825Sdfr if (ret == 0 && key->length != len) 50178825Sdfr krb5_abortx(context, "internal asn.1 encoder error"); 5155682Smarkm free_Principal(&new); 5255682Smarkm return ret; 5355682Smarkm} 5455682Smarkm 5555682Smarkmint 5655682Smarkmhdb_key2principal(krb5_context context, krb5_data *key, krb5_principal p) 5755682Smarkm{ 5855682Smarkm return decode_Principal(key->data, key->length, p, NULL); 5955682Smarkm} 6055682Smarkm 6155682Smarkmint 62178825Sdfrhdb_entry2value(krb5_context context, const hdb_entry *ent, krb5_data *value) 6355682Smarkm{ 64233294Sstas size_t len = 0; 6555682Smarkm int ret; 66233294Sstas 67103423Snectar ASN1_MALLOC_ENCODE(hdb_entry, value->data, value->length, ent, &len, ret); 68178825Sdfr if (ret == 0 && value->length != len) 69178825Sdfr krb5_abortx(context, "internal asn.1 encoder error"); 70103423Snectar return ret; 7155682Smarkm} 7255682Smarkm 7355682Smarkmint 7455682Smarkmhdb_value2entry(krb5_context context, krb5_data *value, hdb_entry *ent) 7555682Smarkm{ 7655682Smarkm return decode_hdb_entry(value->data, value->length, ent, NULL); 7755682Smarkm} 7855682Smarkm 79178825Sdfrint 80233294Sstashdb_entry_alias2value(krb5_context context, 81178825Sdfr const hdb_entry_alias *alias, 82178825Sdfr krb5_data *value) 83178825Sdfr{ 84233294Sstas size_t len = 0; 85178825Sdfr int ret; 86233294Sstas 87233294Sstas ASN1_MALLOC_ENCODE(hdb_entry_alias, value->data, value->length, 88178825Sdfr alias, &len, ret); 89178825Sdfr if (ret == 0 && value->length != len) 90178825Sdfr krb5_abortx(context, "internal asn.1 encoder error"); 91178825Sdfr return ret; 92178825Sdfr} 93178825Sdfr 94178825Sdfrint 95233294Sstashdb_value2entry_alias(krb5_context context, krb5_data *value, 96178825Sdfr hdb_entry_alias *ent) 97178825Sdfr{ 98178825Sdfr return decode_hdb_entry_alias(value->data, value->length, ent, NULL); 99178825Sdfr} 100178825Sdfr 10155682Smarkmkrb5_error_code 102233294Sstas_hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, 103233294Sstas unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) 10455682Smarkm{ 105233294Sstas krb5_principal enterprise_principal = NULL; 10655682Smarkm krb5_data key, value; 107233294Sstas krb5_error_code ret; 108120945Snectar int code; 10955682Smarkm 110233294Sstas if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { 111233294Sstas if (principal->name.name_string.len != 1) { 112233294Sstas ret = KRB5_PARSE_MALFORMED; 113233294Sstas krb5_set_error_message(context, ret, "malformed principal: " 114233294Sstas "enterprise name with %d name components", 115233294Sstas principal->name.name_string.len); 116233294Sstas return ret; 117233294Sstas } 118233294Sstas ret = krb5_parse_name(context, principal->name.name_string.val[0], 119233294Sstas &enterprise_principal); 120233294Sstas if (ret) 121233294Sstas return ret; 122233294Sstas principal = enterprise_principal; 123233294Sstas } 124233294Sstas 125178825Sdfr hdb_principal2key(context, principal, &key); 126233294Sstas if (enterprise_principal) 127233294Sstas krb5_free_principal(context, enterprise_principal); 128178825Sdfr code = db->hdb__get(context, db, key, &value); 12955682Smarkm krb5_data_free(&key); 13055682Smarkm if(code) 13155682Smarkm return code; 132178825Sdfr code = hdb_value2entry(context, &value, &entry->entry); 133178825Sdfr if (code == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) { 134178825Sdfr krb5_data_free(&value); 135178825Sdfr return HDB_ERR_NOENTRY; 136178825Sdfr } else if (code == ASN1_BAD_ID) { 137178825Sdfr hdb_entry_alias alias; 138178825Sdfr 139178825Sdfr code = hdb_value2entry_alias(context, &value, &alias); 140178825Sdfr if (code) { 141178825Sdfr krb5_data_free(&value); 142178825Sdfr return code; 143178825Sdfr } 144178825Sdfr hdb_principal2key(context, alias.principal, &key); 145178825Sdfr krb5_data_free(&value); 146178825Sdfr free_hdb_entry_alias(&alias); 147178825Sdfr 148178825Sdfr code = db->hdb__get(context, db, key, &value); 149178825Sdfr krb5_data_free(&key); 150178825Sdfr if (code) 151178825Sdfr return code; 152178825Sdfr code = hdb_value2entry(context, &value, &entry->entry); 153178825Sdfr if (code) { 154178825Sdfr krb5_data_free(&value); 155178825Sdfr return code; 156178825Sdfr } 157178825Sdfr } 158120945Snectar krb5_data_free(&value); 159178825Sdfr if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 160178825Sdfr code = hdb_unseal_keys (context, db, &entry->entry); 16172445Sassar if (code) 16272445Sassar hdb_free_entry(context, entry); 16372445Sassar } 16472445Sassar return code; 16555682Smarkm} 16655682Smarkm 167178825Sdfrstatic krb5_error_code 168178825Sdfrhdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key) 169178825Sdfr{ 170178825Sdfr const HDB_Ext_Aliases *aliases; 171178825Sdfr krb5_error_code code; 172178825Sdfr hdb_entry oldentry; 173178825Sdfr krb5_data value; 174233294Sstas size_t i; 175178825Sdfr 176178825Sdfr code = db->hdb__get(context, db, *key, &value); 177178825Sdfr if (code == HDB_ERR_NOENTRY) 178178825Sdfr return 0; 179178825Sdfr else if (code) 180178825Sdfr return code; 181233294Sstas 182178825Sdfr code = hdb_value2entry(context, &value, &oldentry); 183178825Sdfr krb5_data_free(&value); 184178825Sdfr if (code) 185178825Sdfr return code; 186178825Sdfr 187178825Sdfr code = hdb_entry_get_aliases(&oldentry, &aliases); 188178825Sdfr if (code || aliases == NULL) { 189178825Sdfr free_hdb_entry(&oldentry); 190178825Sdfr return code; 191178825Sdfr } 192178825Sdfr for (i = 0; i < aliases->aliases.len; i++) { 193178825Sdfr krb5_data akey; 194178825Sdfr 195178825Sdfr hdb_principal2key(context, &aliases->aliases.val[i], &akey); 196178825Sdfr code = db->hdb__del(context, db, akey); 197178825Sdfr krb5_data_free(&akey); 198178825Sdfr if (code) { 199178825Sdfr free_hdb_entry(&oldentry); 200178825Sdfr return code; 201178825Sdfr } 202178825Sdfr } 203178825Sdfr free_hdb_entry(&oldentry); 204178825Sdfr return 0; 205178825Sdfr} 206178825Sdfr 207178825Sdfrstatic krb5_error_code 208233294Sstashdb_add_aliases(krb5_context context, HDB *db, 209178825Sdfr unsigned flags, hdb_entry_ex *entry) 210178825Sdfr{ 211178825Sdfr const HDB_Ext_Aliases *aliases; 212178825Sdfr krb5_error_code code; 213178825Sdfr krb5_data key, value; 214233294Sstas size_t i; 215233294Sstas 216178825Sdfr code = hdb_entry_get_aliases(&entry->entry, &aliases); 217178825Sdfr if (code || aliases == NULL) 218178825Sdfr return code; 219233294Sstas 220178825Sdfr for (i = 0; i < aliases->aliases.len; i++) { 221178825Sdfr hdb_entry_alias entryalias; 222178825Sdfr entryalias.principal = entry->entry.principal; 223233294Sstas 224178825Sdfr hdb_principal2key(context, &aliases->aliases.val[i], &key); 225178825Sdfr code = hdb_entry_alias2value(context, &entryalias, &value); 226178825Sdfr if (code) { 227178825Sdfr krb5_data_free(&key); 228178825Sdfr return code; 229178825Sdfr } 230178825Sdfr code = db->hdb__put(context, db, flags, key, value); 231178825Sdfr krb5_data_free(&key); 232178825Sdfr krb5_data_free(&value); 233178825Sdfr if (code) 234178825Sdfr return code; 235178825Sdfr } 236178825Sdfr return 0; 237178825Sdfr} 238178825Sdfr 239233294Sstasstatic krb5_error_code 240233294Sstashdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry) 241233294Sstas{ 242233294Sstas const HDB_Ext_Aliases *aliases; 243233294Sstas int code; 244233294Sstas size_t i; 245233294Sstas 246233294Sstas /* check if new aliases already is used */ 247233294Sstas 248233294Sstas code = hdb_entry_get_aliases(&entry->entry, &aliases); 249233294Sstas if (code) 250233294Sstas return code; 251233294Sstas 252233294Sstas for (i = 0; aliases && i < aliases->aliases.len; i++) { 253233294Sstas hdb_entry_alias alias; 254233294Sstas krb5_data akey, value; 255233294Sstas 256233294Sstas hdb_principal2key(context, &aliases->aliases.val[i], &akey); 257233294Sstas code = db->hdb__get(context, db, akey, &value); 258233294Sstas krb5_data_free(&akey); 259233294Sstas if (code == HDB_ERR_NOENTRY) 260233294Sstas continue; 261233294Sstas else if (code) 262233294Sstas return code; 263233294Sstas 264233294Sstas code = hdb_value2entry_alias(context, &value, &alias); 265233294Sstas krb5_data_free(&value); 266233294Sstas 267233294Sstas if (code == ASN1_BAD_ID) 268233294Sstas return HDB_ERR_EXISTS; 269233294Sstas else if (code) 270233294Sstas return code; 271233294Sstas 272233294Sstas code = krb5_principal_compare(context, alias.principal, 273233294Sstas entry->entry.principal); 274233294Sstas free_hdb_entry_alias(&alias); 275233294Sstas if (code == 0) 276233294Sstas return HDB_ERR_EXISTS; 277233294Sstas } 278233294Sstas return 0; 279233294Sstas} 280233294Sstas 28155682Smarkmkrb5_error_code 282178825Sdfr_hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 28355682Smarkm{ 28455682Smarkm krb5_data key, value; 28555682Smarkm int code; 28655682Smarkm 287233294Sstas /* check if new aliases already is used */ 288233294Sstas code = hdb_check_aliases(context, db, entry); 289233294Sstas if (code) 290233294Sstas return code; 291233294Sstas 292178825Sdfr if(entry->entry.generation == NULL) { 29390926Snectar struct timeval t; 294178825Sdfr entry->entry.generation = malloc(sizeof(*entry->entry.generation)); 295178825Sdfr if(entry->entry.generation == NULL) { 296233294Sstas krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 29790926Snectar return ENOMEM; 29890926Snectar } 29990926Snectar gettimeofday(&t, NULL); 300178825Sdfr entry->entry.generation->time = t.tv_sec; 301178825Sdfr entry->entry.generation->usec = t.tv_usec; 302178825Sdfr entry->entry.generation->gen = 0; 30390926Snectar } else 304178825Sdfr entry->entry.generation->gen++; 305233294Sstas 306178825Sdfr code = hdb_seal_keys(context, db, &entry->entry); 307233294Sstas if (code) 30872445Sassar return code; 309178825Sdfr 310233294Sstas hdb_principal2key(context, entry->entry.principal, &key); 311233294Sstas 312178825Sdfr /* remove aliases */ 313178825Sdfr code = hdb_remove_aliases(context, db, &key); 314178825Sdfr if (code) { 315178825Sdfr krb5_data_free(&key); 316178825Sdfr return code; 317178825Sdfr } 318178825Sdfr hdb_entry2value(context, &entry->entry, &value); 319178825Sdfr code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value); 32055682Smarkm krb5_data_free(&value); 32155682Smarkm krb5_data_free(&key); 322178825Sdfr if (code) 323178825Sdfr return code; 324178825Sdfr 325178825Sdfr code = hdb_add_aliases(context, db, flags, entry); 326178825Sdfr 32755682Smarkm return code; 32855682Smarkm} 32955682Smarkm 33055682Smarkmkrb5_error_code 331178825Sdfr_hdb_remove(krb5_context context, HDB *db, krb5_const_principal principal) 33255682Smarkm{ 33355682Smarkm krb5_data key; 33455682Smarkm int code; 33555682Smarkm 336178825Sdfr hdb_principal2key(context, principal, &key); 337178825Sdfr 338178825Sdfr code = hdb_remove_aliases(context, db, &key); 339178825Sdfr if (code) { 340178825Sdfr krb5_data_free(&key); 341178825Sdfr return code; 342178825Sdfr } 343178825Sdfr code = db->hdb__del(context, db, key); 34455682Smarkm krb5_data_free(&key); 34555682Smarkm return code; 34655682Smarkm} 34755682Smarkm 348