1 2 /* 3 * Copyright (c) 1997 - 2001, 2003 - 2004 Kungliga Tekniska Högskolan 4 * (Royal Institute of Technology, Stockholm, Sweden). 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of the Institute nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "hdb_locl.h" 36 37 /* 38 * free all the memory used by (len, keys) 39 */ 40 41 void 42 hdb_free_keys(krb5_context context, int len, Key *keys) 43 { 44 int i; 45 46 for (i = 0; i < len; i++) { 47 free(keys[i].mkvno); 48 keys[i].mkvno = NULL; 49 if (keys[i].salt != NULL) { 50 free_Salt(keys[i].salt); 51 free(keys[i].salt); 52 keys[i].salt = NULL; 53 } 54 krb5_free_keyblock_contents(context, &keys[i].key); 55 } 56 free (keys); 57 } 58 59 void 60 hdb_free_keysets(krb5_context context, int len, hdb_keyset *keysets) 61 { 62 int i; 63 64 for (i = 0; i < len; i++) { 65 hdb_free_keys(context, keysets[i].keys.len, keysets[i].keys.val); 66 keysets[i].keys.val = NULL; 67 keysets[i].keys.len = 0; 68 } 69 free (keysets); 70 } 71 72 /* 73 * for each entry in `default_keys' try to parse it as a sequence 74 * of etype:salttype:salt, syntax of this if something like: 75 * [(des|des3|etype):](pw-salt|afs3)[:string], if etype is omitted it 76 * means all etypes, and if string is omitted is means the default 77 * string (for that principal). Additional special values: 78 * v5 == pw-salt, and 79 * v4 == des:pw-salt: 80 * afs or afs3 == des:afs3-salt 81 */ 82 83 static const krb5_enctype des_etypes[] = { 84 ETYPE_DES_CBC_MD5, 85 ETYPE_DES_CBC_MD4, 86 ETYPE_DES_CBC_CRC 87 }; 88 89 static const krb5_enctype all_etypes[] = { 90 ETYPE_AES256_CTS_HMAC_SHA1_96, 91 ETYPE_ARCFOUR_HMAC_MD5, 92 ETYPE_DES3_CBC_SHA1 93 }; 94 95 static krb5_error_code 96 parse_key_set(krb5_context context, const char *key, 97 krb5_enctype **ret_enctypes, size_t *ret_num_enctypes, 98 krb5_salt *salt, krb5_principal principal) 99 { 100 const char *p; 101 char buf[3][256]; 102 int num_buf = 0; 103 int i, num_enctypes = 0; 104 krb5_enctype e; 105 const krb5_enctype *enctypes = NULL; 106 krb5_error_code ret; 107 108 p = key; 109 110 *ret_enctypes = NULL; 111 *ret_num_enctypes = 0; 112 113 /* split p in a list of :-separated strings */ 114 for(num_buf = 0; num_buf < 3; num_buf++) 115 if(strsep_copy(&p, ":", buf[num_buf], sizeof(buf[num_buf])) == -1) 116 break; 117 118 salt->saltvalue.data = NULL; 119 salt->saltvalue.length = 0; 120 121 for(i = 0; i < num_buf; i++) { 122 if(enctypes == NULL && num_buf > 1) { 123 /* this might be a etype specifier */ 124 /* XXX there should be a string_to_etypes handling 125 special cases like `des' and `all' */ 126 if(strcmp(buf[i], "des") == 0) { 127 enctypes = des_etypes; 128 num_enctypes = sizeof(des_etypes)/sizeof(des_etypes[0]); 129 } else if(strcmp(buf[i], "des3") == 0) { 130 e = ETYPE_DES3_CBC_SHA1; 131 enctypes = &e; 132 num_enctypes = 1; 133 } else { 134 ret = krb5_string_to_enctype(context, buf[i], &e); 135 if (ret == 0) { 136 enctypes = &e; 137 num_enctypes = 1; 138 } else 139 return ret; 140 } 141 continue; 142 } 143 if(salt->salttype == 0) { 144 /* interpret string as a salt specifier, if no etype 145 is set, this sets default values */ 146 /* XXX should perhaps use string_to_salttype, but that 147 interface sucks */ 148 if(strcmp(buf[i], "pw-salt") == 0) { 149 if(enctypes == NULL) { 150 enctypes = all_etypes; 151 num_enctypes = sizeof(all_etypes)/sizeof(all_etypes[0]); 152 } 153 salt->salttype = KRB5_PW_SALT; 154 } else if(strcmp(buf[i], "afs3-salt") == 0) { 155 if(enctypes == NULL) { 156 enctypes = des_etypes; 157 num_enctypes = sizeof(des_etypes)/sizeof(des_etypes[0]); 158 } 159 salt->salttype = KRB5_AFS3_SALT; 160 } 161 continue; 162 } 163 164 { 165 /* if there is a final string, use it as the string to 166 salt with, this is mostly useful with null salt for 167 v4 compat, and a cell name for afs compat */ 168 salt->saltvalue.data = strdup(buf[i]); 169 if (salt->saltvalue.data == NULL) { 170 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 171 return ENOMEM; 172 } 173 salt->saltvalue.length = strlen(buf[i]); 174 } 175 } 176 177 if(enctypes == NULL || salt->salttype == 0) { 178 krb5_set_error_message(context, EINVAL, "bad value for default_keys `%s'", key); 179 return EINVAL; 180 } 181 182 /* if no salt was specified make up default salt */ 183 if(salt->saltvalue.data == NULL) { 184 if(salt->salttype == KRB5_PW_SALT) 185 ret = krb5_get_pw_salt(context, principal, salt); 186 else if(salt->salttype == KRB5_AFS3_SALT) { 187 krb5_const_realm realm = krb5_principal_get_realm(context, principal); 188 salt->saltvalue.data = strdup(realm); 189 if(salt->saltvalue.data == NULL) { 190 krb5_set_error_message(context, ENOMEM, 191 "out of memory while " 192 "parsing salt specifiers"); 193 return ENOMEM; 194 } 195 strlwr(salt->saltvalue.data); 196 salt->saltvalue.length = strlen(realm); 197 } 198 } 199 200 *ret_enctypes = malloc(sizeof(enctypes[0]) * num_enctypes); 201 if (*ret_enctypes == NULL) { 202 krb5_free_salt(context, *salt); 203 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 204 return ENOMEM; 205 } 206 memcpy(*ret_enctypes, enctypes, sizeof(enctypes[0]) * num_enctypes); 207 *ret_num_enctypes = num_enctypes; 208 209 return 0; 210 } 211 212 213 krb5_error_code 214 hdb_add_current_keys_to_history(krb5_context context, hdb_entry *entry) 215 { 216 krb5_error_code ret; 217 HDB_extension *ext; 218 HDB_Ext_KeySet *hist_keys; 219 hdb_keyset *tmp_keysets; 220 int add = 0; 221 222 ext = hdb_find_extension(entry, choice_HDB_extension_data_hist_keys); 223 if (ext != NULL) { 224 hist_keys = &ext->data.u.hist_keys; 225 tmp_keysets = realloc(hist_keys->val, 226 sizeof (*hist_keys->val) * (hist_keys->len + 1)); 227 if (tmp_keysets == NULL) 228 return ENOMEM; 229 hist_keys->val = tmp_keysets; 230 memmove(&hist_keys->val[1], hist_keys->val, 231 sizeof (*hist_keys->val) * hist_keys->len++); 232 } else { 233 add = 1; 234 ext = calloc(1, sizeof (*ext)); 235 if (ext == NULL) 236 return ENOMEM; 237 ext->data.element = choice_HDB_extension_data_hist_keys; 238 hist_keys = &ext->data.u.hist_keys; 239 hist_keys->val = calloc(1, sizeof (*hist_keys->val)); 240 if (hist_keys->val == NULL) { 241 free(hist_keys); 242 return ENOMEM; 243 } 244 hist_keys->len = 1; 245 } 246 247 hist_keys->val[0].keys.val = entry->keys.val; 248 hist_keys->val[0].keys.len = entry->keys.len; 249 hist_keys->val[0].kvno = entry->kvno; 250 hist_keys->val[0].replace_time = time(NULL); 251 252 if (add) { 253 ret = hdb_replace_extension(context, entry, ext); 254 if (ret) { 255 free_HDB_extension(ext); 256 return ret; 257 } 258 } 259 260 /* hdb_replace_extension() copies ext, so we have to free it */ 261 free_HDB_extension(ext); 262 return 0; 263 } 264 265 266 static krb5_error_code 267 add_enctype_to_key_set(Key **key_set, size_t *nkeyset, 268 krb5_enctype enctype, krb5_salt *salt) 269 { 270 krb5_error_code ret; 271 Key key, *tmp; 272 273 memset(&key, 0, sizeof(key)); 274 275 tmp = realloc(*key_set, (*nkeyset + 1) * sizeof((*key_set)[0])); 276 if (tmp == NULL) 277 return ENOMEM; 278 279 *key_set = tmp; 280 281 key.key.keytype = enctype; 282 key.key.keyvalue.length = 0; 283 key.key.keyvalue.data = NULL; 284 285 if (salt) { 286 key.salt = calloc(1, sizeof(*key.salt)); 287 if (key.salt == NULL) { 288 free_Key(&key); 289 return ENOMEM; 290 } 291 292 key.salt->type = salt->salttype; 293 krb5_data_zero (&key.salt->salt); 294 295 ret = krb5_data_copy(&key.salt->salt, 296 salt->saltvalue.data, 297 salt->saltvalue.length); 298 if (ret) { 299 free_Key(&key); 300 return ret; 301 } 302 } else 303 key.salt = NULL; 304 305 (*key_set)[*nkeyset] = key; 306 307 *nkeyset += 1; 308 309 return 0; 310 } 311 312 313 /* 314 * Generate the `key_set' from the [kadmin]default_keys statement. If 315 * `no_salt' is set, salt is not important (and will not be set) since 316 * it's random keys that is going to be created. 317 */ 318 319 krb5_error_code 320 hdb_generate_key_set(krb5_context context, krb5_principal principal, 321 Key **ret_key_set, size_t *nkeyset, int no_salt) 322 { 323 char **ktypes, **kp; 324 krb5_error_code ret; 325 Key *k, *key_set; 326 size_t i, j; 327 static const char *default_keytypes[] = { 328 "aes256-cts-hmac-sha1-96:pw-salt", 329 "des3-cbc-sha1:pw-salt", 330 "arcfour-hmac-md5:pw-salt", 331 NULL 332 }; 333 334 ktypes = krb5_config_get_strings(context, NULL, "kadmin", 335 "default_keys", NULL); 336 if (ktypes == NULL) 337 ktypes = (char **)(intptr_t)default_keytypes; 338 339 *ret_key_set = key_set = NULL; 340 *nkeyset = 0; 341 342 ret = 0; 343 344 for(kp = ktypes; kp && *kp; kp++) { 345 const char *p; 346 krb5_salt salt; 347 krb5_enctype *enctypes; 348 size_t num_enctypes; 349 350 p = *kp; 351 /* check alias */ 352 if(strcmp(p, "v5") == 0) 353 p = "pw-salt"; 354 else if(strcmp(p, "v4") == 0) 355 p = "des:pw-salt:"; 356 else if(strcmp(p, "afs") == 0 || strcmp(p, "afs3") == 0) 357 p = "des:afs3-salt"; 358 else if (strcmp(p, "arcfour-hmac-md5") == 0) 359 p = "arcfour-hmac-md5:pw-salt"; 360 361 memset(&salt, 0, sizeof(salt)); 362 363 ret = parse_key_set(context, p, 364 &enctypes, &num_enctypes, &salt, principal); 365 if (ret) { 366 krb5_warn(context, ret, "bad value for default_keys `%s'", *kp); 367 ret = 0; 368 continue; 369 } 370 371 for (i = 0; i < num_enctypes; i++) { 372 /* find duplicates */ 373 for (j = 0; j < *nkeyset; j++) { 374 375 k = &key_set[j]; 376 377 if (k->key.keytype == enctypes[i]) { 378 if (no_salt) 379 break; 380 if (k->salt == NULL && salt.salttype == KRB5_PW_SALT) 381 break; 382 if (k->salt->type == salt.salttype && 383 k->salt->salt.length == salt.saltvalue.length && 384 memcmp(k->salt->salt.data, salt.saltvalue.data, 385 salt.saltvalue.length) == 0) 386 break; 387 } 388 } 389 /* not a duplicate, lets add it */ 390 if (j == *nkeyset) { 391 ret = add_enctype_to_key_set(&key_set, nkeyset, enctypes[i], 392 no_salt ? NULL : &salt); 393 if (ret) { 394 free(enctypes); 395 krb5_free_salt(context, salt); 396 goto out; 397 } 398 } 399 } 400 free(enctypes); 401 krb5_free_salt(context, salt); 402 } 403 404 *ret_key_set = key_set; 405 406 out: 407 if (ktypes != (char **)(intptr_t)default_keytypes) 408 krb5_config_free_strings(ktypes); 409 410 if (ret) { 411 krb5_warn(context, ret, 412 "failed to parse the [kadmin]default_keys values"); 413 414 for (i = 0; i < *nkeyset; i++) 415 free_Key(&key_set[i]); 416 free(key_set); 417 } else if (*nkeyset == 0) { 418 krb5_warnx(context, 419 "failed to parse any of the [kadmin]default_keys values"); 420 ret = EINVAL; /* XXX */ 421 } 422 423 return ret; 424 } 425 426 427 krb5_error_code 428 hdb_generate_key_set_password(krb5_context context, 429 krb5_principal principal, 430 const char *password, 431 Key **keys, size_t *num_keys) 432 { 433 krb5_error_code ret; 434 size_t i; 435 436 ret = hdb_generate_key_set(context, principal, 437 keys, num_keys, 0); 438 if (ret) 439 return ret; 440 441 for (i = 0; i < (*num_keys); i++) { 442 krb5_salt salt; 443 444 salt.salttype = (*keys)[i].salt->type; 445 salt.saltvalue.length = (*keys)[i].salt->salt.length; 446 salt.saltvalue.data = (*keys)[i].salt->salt.data; 447 448 ret = krb5_string_to_key_salt (context, 449 (*keys)[i].key.keytype, 450 password, 451 salt, 452 &(*keys)[i].key); 453 454 if(ret) 455 break; 456 } 457 458 if(ret) { 459 hdb_free_keys (context, *num_keys, *keys); 460 return ret; 461 } 462 return ret; 463 } 464