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