1 /* $NetBSD: common.c,v 1.1.1.2 2014/04/24 12:45:28 pettai Exp $ */ 2 3 /* 4 * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hdb_locl.h" 37 38 int 39 hdb_principal2key(krb5_context context, krb5_const_principal p, krb5_data *key) 40 { 41 Principal new; 42 size_t len = 0; 43 int ret; 44 45 ret = copy_Principal(p, &new); 46 if(ret) 47 return ret; 48 new.name.name_type = 0; 49 50 ASN1_MALLOC_ENCODE(Principal, key->data, key->length, &new, &len, ret); 51 if (ret == 0 && key->length != len) 52 krb5_abortx(context, "internal asn.1 encoder error"); 53 free_Principal(&new); 54 return ret; 55 } 56 57 int 58 hdb_key2principal(krb5_context context, krb5_data *key, krb5_principal p) 59 { 60 return decode_Principal(key->data, key->length, p, NULL); 61 } 62 63 int 64 hdb_entry2value(krb5_context context, const hdb_entry *ent, krb5_data *value) 65 { 66 size_t len = 0; 67 int ret; 68 69 ASN1_MALLOC_ENCODE(hdb_entry, value->data, value->length, ent, &len, ret); 70 if (ret == 0 && value->length != len) 71 krb5_abortx(context, "internal asn.1 encoder error"); 72 return ret; 73 } 74 75 int 76 hdb_value2entry(krb5_context context, krb5_data *value, hdb_entry *ent) 77 { 78 return decode_hdb_entry(value->data, value->length, ent, NULL); 79 } 80 81 int 82 hdb_entry_alias2value(krb5_context context, 83 const hdb_entry_alias *alias, 84 krb5_data *value) 85 { 86 size_t len = 0; 87 int ret; 88 89 ASN1_MALLOC_ENCODE(hdb_entry_alias, value->data, value->length, 90 alias, &len, ret); 91 if (ret == 0 && value->length != len) 92 krb5_abortx(context, "internal asn.1 encoder error"); 93 return ret; 94 } 95 96 int 97 hdb_value2entry_alias(krb5_context context, krb5_data *value, 98 hdb_entry_alias *ent) 99 { 100 return decode_hdb_entry_alias(value->data, value->length, ent, NULL); 101 } 102 103 krb5_error_code 104 _hdb_fetch_kvno(krb5_context context, HDB *db, krb5_const_principal principal, 105 unsigned flags, krb5_kvno kvno, hdb_entry_ex *entry) 106 { 107 krb5_principal enterprise_principal = NULL; 108 krb5_data key, value; 109 krb5_error_code ret; 110 int code; 111 112 if (principal->name.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { 113 if (principal->name.name_string.len != 1) { 114 ret = KRB5_PARSE_MALFORMED; 115 krb5_set_error_message(context, ret, "malformed principal: " 116 "enterprise name with %d name components", 117 principal->name.name_string.len); 118 return ret; 119 } 120 ret = krb5_parse_name(context, principal->name.name_string.val[0], 121 &enterprise_principal); 122 if (ret) 123 return ret; 124 principal = enterprise_principal; 125 } 126 127 hdb_principal2key(context, principal, &key); 128 if (enterprise_principal) 129 krb5_free_principal(context, enterprise_principal); 130 code = db->hdb__get(context, db, key, &value); 131 krb5_data_free(&key); 132 if(code) 133 return code; 134 code = hdb_value2entry(context, &value, &entry->entry); 135 if (code == ASN1_BAD_ID && (flags & HDB_F_CANON) == 0) { 136 krb5_data_free(&value); 137 return HDB_ERR_NOENTRY; 138 } else if (code == ASN1_BAD_ID) { 139 hdb_entry_alias alias; 140 141 code = hdb_value2entry_alias(context, &value, &alias); 142 if (code) { 143 krb5_data_free(&value); 144 return code; 145 } 146 hdb_principal2key(context, alias.principal, &key); 147 krb5_data_free(&value); 148 free_hdb_entry_alias(&alias); 149 150 code = db->hdb__get(context, db, key, &value); 151 krb5_data_free(&key); 152 if (code) 153 return code; 154 code = hdb_value2entry(context, &value, &entry->entry); 155 if (code) { 156 krb5_data_free(&value); 157 return code; 158 } 159 } 160 krb5_data_free(&value); 161 if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 162 code = hdb_unseal_keys (context, db, &entry->entry); 163 if (code) 164 hdb_free_entry(context, entry); 165 } 166 return code; 167 } 168 169 static krb5_error_code 170 hdb_remove_aliases(krb5_context context, HDB *db, krb5_data *key) 171 { 172 const HDB_Ext_Aliases *aliases; 173 krb5_error_code code; 174 hdb_entry oldentry; 175 krb5_data value; 176 size_t i; 177 178 code = db->hdb__get(context, db, *key, &value); 179 if (code == HDB_ERR_NOENTRY) 180 return 0; 181 else if (code) 182 return code; 183 184 code = hdb_value2entry(context, &value, &oldentry); 185 krb5_data_free(&value); 186 if (code) 187 return code; 188 189 code = hdb_entry_get_aliases(&oldentry, &aliases); 190 if (code || aliases == NULL) { 191 free_hdb_entry(&oldentry); 192 return code; 193 } 194 for (i = 0; i < aliases->aliases.len; i++) { 195 krb5_data akey; 196 197 hdb_principal2key(context, &aliases->aliases.val[i], &akey); 198 code = db->hdb__del(context, db, akey); 199 krb5_data_free(&akey); 200 if (code) { 201 free_hdb_entry(&oldentry); 202 return code; 203 } 204 } 205 free_hdb_entry(&oldentry); 206 return 0; 207 } 208 209 static krb5_error_code 210 hdb_add_aliases(krb5_context context, HDB *db, 211 unsigned flags, hdb_entry_ex *entry) 212 { 213 const HDB_Ext_Aliases *aliases; 214 krb5_error_code code; 215 krb5_data key, value; 216 size_t i; 217 218 code = hdb_entry_get_aliases(&entry->entry, &aliases); 219 if (code || aliases == NULL) 220 return code; 221 222 for (i = 0; i < aliases->aliases.len; i++) { 223 hdb_entry_alias entryalias; 224 entryalias.principal = entry->entry.principal; 225 226 hdb_principal2key(context, &aliases->aliases.val[i], &key); 227 code = hdb_entry_alias2value(context, &entryalias, &value); 228 if (code) { 229 krb5_data_free(&key); 230 return code; 231 } 232 code = db->hdb__put(context, db, flags, key, value); 233 krb5_data_free(&key); 234 krb5_data_free(&value); 235 if (code) 236 return code; 237 } 238 return 0; 239 } 240 241 static krb5_error_code 242 hdb_check_aliases(krb5_context context, HDB *db, hdb_entry_ex *entry) 243 { 244 const HDB_Ext_Aliases *aliases; 245 int code; 246 size_t i; 247 248 /* check if new aliases already is used */ 249 250 code = hdb_entry_get_aliases(&entry->entry, &aliases); 251 if (code) 252 return code; 253 254 for (i = 0; aliases && i < aliases->aliases.len; i++) { 255 hdb_entry_alias alias; 256 krb5_data akey, value; 257 258 hdb_principal2key(context, &aliases->aliases.val[i], &akey); 259 code = db->hdb__get(context, db, akey, &value); 260 krb5_data_free(&akey); 261 if (code == HDB_ERR_NOENTRY) 262 continue; 263 else if (code) 264 return code; 265 266 code = hdb_value2entry_alias(context, &value, &alias); 267 krb5_data_free(&value); 268 269 if (code == ASN1_BAD_ID) 270 return HDB_ERR_EXISTS; 271 else if (code) 272 return code; 273 274 code = krb5_principal_compare(context, alias.principal, 275 entry->entry.principal); 276 free_hdb_entry_alias(&alias); 277 if (code == 0) 278 return HDB_ERR_EXISTS; 279 } 280 return 0; 281 } 282 283 krb5_error_code 284 _hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry_ex *entry) 285 { 286 krb5_data key, value; 287 int code; 288 289 /* check if new aliases already is used */ 290 code = hdb_check_aliases(context, db, entry); 291 if (code) 292 return code; 293 294 if(entry->entry.generation == NULL) { 295 struct timeval t; 296 entry->entry.generation = malloc(sizeof(*entry->entry.generation)); 297 if(entry->entry.generation == NULL) { 298 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 299 return ENOMEM; 300 } 301 gettimeofday(&t, NULL); 302 entry->entry.generation->time = t.tv_sec; 303 entry->entry.generation->usec = t.tv_usec; 304 entry->entry.generation->gen = 0; 305 } else 306 entry->entry.generation->gen++; 307 308 code = hdb_seal_keys(context, db, &entry->entry); 309 if (code) 310 return code; 311 312 hdb_principal2key(context, entry->entry.principal, &key); 313 314 /* remove aliases */ 315 code = hdb_remove_aliases(context, db, &key); 316 if (code) { 317 krb5_data_free(&key); 318 return code; 319 } 320 hdb_entry2value(context, &entry->entry, &value); 321 code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value); 322 krb5_data_free(&value); 323 krb5_data_free(&key); 324 if (code) 325 return code; 326 327 code = hdb_add_aliases(context, db, flags, entry); 328 329 return code; 330 } 331 332 krb5_error_code 333 _hdb_remove(krb5_context context, HDB *db, krb5_const_principal principal) 334 { 335 krb5_data key; 336 int code; 337 338 hdb_principal2key(context, principal, &key); 339 340 code = hdb_remove_aliases(context, db, &key); 341 if (code) { 342 krb5_data_free(&key); 343 return code; 344 } 345 code = db->hdb__del(context, db, key); 346 krb5_data_free(&key); 347 return code; 348 } 349 350