1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 7 /* 8 * lib/krb5/krb/init_ctx.c 9 * 10 * Copyright 1994,1999,2000, 2002, 2003 by the Massachusetts Institute of Technology. 11 * All Rights Reserved. 12 * 13 * Export of this software from the United States of America may 14 * require a specific license from the United States Government. 15 * It is the responsibility of any person or organization contemplating 16 * export to obtain such a license before exporting. 17 * 18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 19 * distribute this software and its documentation for any purpose and 20 * without fee is hereby granted, provided that the above copyright 21 * notice appear in all copies and that both that copyright notice and 22 * this permission notice appear in supporting documentation, and that 23 * the name of M.I.T. not be used in advertising or publicity pertaining 24 * to distribution of the software without specific, written prior 25 * permission. Furthermore if you modify this software you must label 26 * your software as modified software and not distribute it in such a 27 * fashion that it might be confused with the original M.I.T. software. 28 * M.I.T. makes no representations about the suitability of 29 * this software for any purpose. It is provided "as is" without express 30 * or implied warranty. 31 * 32 * krb5_init_contex() 33 */ 34 35 /* 36 * Copyright (C) 1998 by the FundsXpress, INC. 37 * 38 * All rights reserved. 39 * 40 * Export of this software from the United States of America may require 41 * a specific license from the United States Government. It is the 42 * responsibility of any person or organization contemplating export to 43 * obtain such a license before exporting. 44 * 45 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 46 * distribute this software and its documentation for any purpose and 47 * without fee is hereby granted, provided that the above copyright 48 * notice appear in all copies and that both that copyright notice and 49 * this permission notice appear in supporting documentation, and that 50 * the name of FundsXpress. not be used in advertising or publicity pertaining 51 * to distribution of the software without specific, written prior 52 * permission. FundsXpress makes no representations about the suitability of 53 * this software for any purpose. It is provided "as is" without express 54 * or implied warranty. 55 * 56 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 57 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 58 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 59 */ 60 61 #include "k5-int.h" 62 63 /* 64 * Solaris Kerberos: the code related to EF/pkcs11 and fork safety are mods Sun 65 * has made to the MIT code. 66 */ 67 68 #ifndef _KERNEL 69 #include <ctype.h> 70 71 pid_t __krb5_current_pid; /* fork safety: contains the current process ID */ 72 #endif 73 74 #ifndef _KERNEL 75 #include <krb5_libinit.h> 76 #endif 77 78 /* The des-mdX entries are last for now, because it's easy to 79 configure KDCs to issue TGTs with des-mdX keys and then not accept 80 them. This'll be fixed, but for better compatibility, let's prefer 81 des-crc for now. */ 82 #define DEFAULT_ETYPE_LIST \ 83 "aes256-cts-hmac-sha1-96 " \ 84 "aes128-cts-hmac-sha1-96 " \ 85 "des3-hmac-sha1 " \ 86 "arcfour-hmac-md5 " \ 87 "des-cbc-md5 " \ 88 "des-cbc-crc" 89 90 91 /* The only functions that are needed from this file when in kernel are 92 * krb5_init_context and krb5_free_context. 93 * In krb5_init_context we need only os_init_context since we don'it need the 94 * profile info unless we do init/accept in kernel. Currently only mport, 95 * delete , sign/verify, wrap/unwrap routines are ported to the kernel. 96 */ 97 98 #if (defined(_WIN32)) 99 extern krb5_error_code krb5_vercheck(); 100 extern void krb5_win_ccdll_load(krb5_context context); 101 #endif 102 103 static krb5_error_code init_common (krb5_context *, krb5_boolean, krb5_boolean); 104 105 krb5_error_code KRB5_CALLCONV 106 krb5_init_context(krb5_context *context) 107 { 108 109 return init_common (context, FALSE, FALSE); 110 } 111 112 krb5_error_code KRB5_CALLCONV 113 krb5_init_secure_context(krb5_context *context) 114 { 115 116 #if 0 /* Solaris Kerberos */ 117 /* This is to make gcc -Wall happy */ 118 if(0) krb5_brand[0] = krb5_brand[0]; 119 #endif 120 return init_common (context, TRUE, FALSE); 121 } 122 123 #ifndef _KERNEL 124 125 krb5_error_code 126 krb5int_init_context_kdc(krb5_context *context) 127 { 128 return init_common (context, FALSE, TRUE); 129 } 130 131 /* Solaris Kerberos */ 132 krb5_error_code 133 krb5_open_pkcs11_session(CK_SESSION_HANDLE *hSession) 134 { 135 krb5_error_code retval = 0; 136 CK_RV rv; 137 CK_SLOT_ID_PTR slotlist = NULL_PTR; 138 CK_ULONG slotcount; 139 CK_ULONG i; 140 141 /* List of all Slots */ 142 rv = C_GetSlotList(FALSE, NULL_PTR, &slotcount); 143 if (rv != CKR_OK) { 144 KRB5_LOG(KRB5_ERR, "C_GetSlotList failed with 0x%x.", rv); 145 retval = PKCS_ERR; 146 goto cleanup; 147 } 148 149 if (slotcount == 0) { 150 KRB5_LOG0(KRB5_ERR, "No slot is found in PKCS11."); 151 retval = PKCS_ERR; 152 goto cleanup; 153 } 154 155 slotlist = (CK_SLOT_ID_PTR)malloc(slotcount * sizeof(CK_SLOT_ID)); 156 if (slotlist == NULL) { 157 KRB5_LOG0(KRB5_ERR, "malloc failed for slotcount."); 158 retval = PKCS_ERR; 159 goto cleanup; 160 } 161 162 rv = C_GetSlotList(FALSE, slotlist, &slotcount); 163 if (rv != CKR_OK) { 164 KRB5_LOG(KRB5_ERR, "C_GetSlotList failed with 0x%x", rv); 165 retval = PKCS_ERR; 166 goto cleanup; 167 } 168 for (i = 0; i < slotcount; i++) { 169 if (slot_supports_krb5(slotlist + i)) 170 break; 171 } 172 if (i == slotcount){ 173 KRB5_LOG0(KRB5_ERR, "Could not find slot which supports " 174 "Kerberos"); 175 retval = PKCS_ERR; 176 goto cleanup; 177 } 178 rv = C_OpenSession(slotlist[i], CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, 179 hSession); 180 if (rv != CKR_OK) { 181 retval = PKCS_ERR; 182 } 183 cleanup: 184 if (slotlist != NULL) 185 free(slotlist); 186 return(retval); 187 } 188 189 /* 190 * krb5_reinit_ef_handle() 191 * 192 * deal with fork safety issue regarding the krb ctx and the pkcs11 hSession 193 * field. This function is called if it is determined that the krb ctx hSession 194 * is being accessed in a child process after a fork(). This function 195 * re-initilizes the pkcs11 session and returns the session handle. 196 */ 197 CK_SESSION_HANDLE 198 krb5_reinit_ef_handle(krb5_context ctx) 199 { 200 ctx->cryptoki_initialized = FALSE; 201 202 if (krb5_init_ef_handle(ctx) != 0) { 203 /* 204 * krb5_free_ef_handle() not needed here -- we assume that an equivalent 205 * of C_Finalize() was done in the child-side of the fork(), so all EF 206 * resources in this context will be invalid. 207 */ 208 return(CK_INVALID_HANDLE); 209 } 210 211 /* reset the ctx pid since we're in a new process (child) */ 212 ctx->pid = __krb5_current_pid; 213 214 /* If the RC4 handles were initialized, reset them here */ 215 if (ctx->arcfour_ctx.initialized) { 216 krb5_error_code ret; 217 ret = krb5_open_pkcs11_session(&ctx->arcfour_ctx.eSession); 218 if (ret) { 219 ctx->arcfour_ctx.initialized = 0; 220 ctx->arcfour_ctx.eSession = CK_INVALID_HANDLE; 221 C_CloseSession(ctx->hSession); 222 ctx->hSession = CK_INVALID_HANDLE; 223 } 224 ret = krb5_open_pkcs11_session(&ctx->arcfour_ctx.dSession); 225 if (ret) { 226 ctx->arcfour_ctx.initialized = 0; 227 ctx->arcfour_ctx.eSession = CK_INVALID_HANDLE; 228 ctx->arcfour_ctx.dSession = CK_INVALID_HANDLE; 229 C_CloseSession(ctx->hSession); 230 ctx->hSession = CK_INVALID_HANDLE; 231 } 232 } 233 234 /* 235 * It is safe for this function to access ctx->hSession directly. Do 236 * NOT use the krb_ctx_hSession() here. 237 */ 238 return(ctx->hSession); 239 } 240 241 /* 242 * krb5_pthread_atfork_child_handler() sets a global that indicates the current 243 * PID. This is an optimization to keep getpid() from being called a zillion 244 * times. 245 */ 246 void 247 krb5_pthread_atfork_child_handler() 248 { 249 /* 250 * __krb5_current_pid should always be set to current process ID, see the 251 * definition of krb_ctx_hSession() for more info 252 */ 253 __krb5_current_pid = getpid(); 254 } 255 256 /* 257 * krb5_ld_init() contains code that will be executed at load time (via the 258 * ld -zinitarray directive). 259 */ 260 void 261 krb5_ld_init() 262 { 263 /* 264 * fork safety: __krb5_current_pid should always be set to current process 265 * ID, see the definition of krb_ctx_hSession() for more info 266 */ 267 __krb5_current_pid = getpid(); 268 /* 269 * The child handler below will help reduce the number of times getpid() is 270 * called by updating a global PID var. with the current PID whenever a fork 271 * occurrs. 272 */ 273 (void) pthread_atfork(NULL, NULL, krb5_pthread_atfork_child_handler); 274 } 275 #endif /* !_KERNEL */ 276 277 krb5_error_code 278 krb5_init_ef_handle(krb5_context ctx) 279 { 280 krb5_error_code retval = 0; 281 #ifndef _KERNEL 282 CK_RV rv = C_Initialize(NULL_PTR); 283 if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) { 284 KRB5_LOG(KRB5_ERR, "C_Initialize failed with 0x%x.", rv); 285 return (PKCS_ERR); 286 287 } 288 /* 289 * It is safe for this function to access ctx->hSession directly. Do 290 * NOT use the krb_ctx_hSession() here. 291 */ 292 retval = krb5_open_pkcs11_session(&ctx->hSession); 293 if (retval != 0) 294 return (retval); 295 296 ctx->cryptoki_initialized = TRUE; 297 #else /* ! _KERNEL */ 298 ctx->kef_cipher_mt = CRYPTO_MECH_INVALID; 299 ctx->kef_hash_mt = CRYPTO_MECH_INVALID; 300 ctx->kef_cksum_mt = CRYPTO_MECH_INVALID; 301 302 setup_kef_keytypes(); 303 setup_kef_cksumtypes(); 304 305 #endif /* ! _KERNEL */ 306 return(retval); 307 } 308 309 #ifndef _KERNEL 310 krb5_error_code 311 krb5_free_ef_handle(krb5_context ctx) 312 { 313 /* 314 * fork safety: Don't free any PKCS state if we've forked since 315 * allocating the pkcs handles. 316 */ 317 if (ctx->cryptoki_initialized == TRUE && 318 ctx->pid == __krb5_current_pid) { 319 /* 320 * It is safe for this function to access ctx->hSession 321 * directly. Do NOT use the krb_ctx_hSession() here. 322 */ 323 if (ctx->hSession) { 324 C_CloseSession(ctx->hSession); 325 ctx->hSession = 0; 326 } 327 if (ctx->arcfour_ctx.dKey) { 328 C_DestroyObject(ctx->arcfour_ctx.dSession, 329 ctx->arcfour_ctx.dKey); 330 ctx->arcfour_ctx.dKey = 0; 331 } 332 if (ctx->arcfour_ctx.eKey) { 333 C_DestroyObject(ctx->arcfour_ctx.eSession, 334 ctx->arcfour_ctx.eKey); 335 ctx->arcfour_ctx.eKey = 0; 336 } 337 if (ctx->arcfour_ctx.eSession) { 338 C_CloseSession(ctx->arcfour_ctx.eSession); 339 ctx->arcfour_ctx.eSession = 0; 340 } 341 if (ctx->arcfour_ctx.dSession) { 342 C_CloseSession(ctx->arcfour_ctx.dSession); 343 ctx->arcfour_ctx.eSession = 0; 344 } 345 ctx->arcfour_ctx.initialized = 0; 346 347 ctx->cryptoki_initialized = FALSE; 348 } 349 return(0); 350 } 351 #endif /* !_KERNEL */ 352 353 static krb5_error_code 354 init_common (krb5_context *context, krb5_boolean secure, krb5_boolean kdc) 355 { 356 krb5_context ctx = 0; 357 krb5_error_code retval; 358 #ifndef _KERNEL 359 struct { 360 krb5_int32 now, now_usec; 361 long pid; 362 } seed_data; 363 krb5_data seed; 364 int tmp; 365 /* Solaris Kerberos */ 366 #if 0 367 /* Verify some assumptions. If the assumptions hold and the 368 compiler is optimizing, this should result in no code being 369 executed. If we're guessing "unsigned long long" instead 370 of using uint64_t, the possibility does exist that we're 371 wrong. */ 372 { 373 krb5_ui_8 i64; 374 assert(sizeof(i64) == 8); 375 i64 = 0, i64--, i64 >>= 62; 376 assert(i64 == 3); 377 i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1; 378 assert(i64 != 0); 379 i64 <<= 1; 380 assert(i64 == 0); 381 } 382 #endif 383 retval = krb5int_initialize_library(); 384 if (retval) 385 return retval; 386 #endif 387 388 #if (defined(_WIN32)) 389 /* 390 * Load the krbcc32.dll if necessary. We do this here so that 391 * we know to use API: later on during initialization. 392 * The context being NULL is ok. 393 */ 394 krb5_win_ccdll_load(ctx); 395 396 /* 397 * krb5_vercheck() is defined in win_glue.c, and this is 398 * where we handle the timebomb and version server checks. 399 */ 400 retval = krb5_vercheck(); 401 if (retval) 402 return retval; 403 #endif 404 405 *context = 0; 406 407 ctx = MALLOC(sizeof(struct _krb5_context)); 408 if (!ctx) 409 return ENOMEM; 410 (void) memset(ctx, 0, sizeof(struct _krb5_context)); 411 ctx->magic = KV5M_CONTEXT; 412 413 ctx->profile_secure = secure; 414 415 if ((retval = krb5_os_init_context(ctx, kdc))) 416 goto cleanup; 417 418 /* 419 * Initialize the EF handle, its needed before doing 420 * the random seed. 421 */ 422 if ((retval = krb5_init_ef_handle(ctx))) 423 goto cleanup; 424 425 #ifndef _KERNEL 426 427 /* fork safety: set pid to current process ID for later checking */ 428 ctx->pid = __krb5_current_pid; 429 430 /* Set the default encryption types, possible defined in krb5/conf */ 431 if ((retval = krb5_set_default_in_tkt_ktypes(ctx, NULL))) 432 goto cleanup; 433 434 if ((retval = krb5_set_default_tgs_ktypes(ctx, NULL))) 435 goto cleanup; 436 437 if (ctx->tgs_ktype_count != 0) { 438 ctx->conf_tgs_ktypes = MALLOC(ctx->tgs_ktype_count * 439 sizeof(krb5_enctype)); 440 if (ctx->conf_tgs_ktypes == NULL) 441 goto cleanup; 442 443 (void) memcpy(ctx->conf_tgs_ktypes, ctx->tgs_ktypes, 444 sizeof(krb5_enctype) * ctx->tgs_ktype_count); 445 } 446 447 ctx->conf_tgs_ktypes_count = ctx->tgs_ktype_count; 448 449 450 /* initialize the prng (not well, but passable) */ 451 if ((retval = krb5_crypto_us_timeofday(&seed_data.now, &seed_data.now_usec))) 452 goto cleanup; 453 seed_data.pid = getpid (); 454 seed.length = sizeof(seed_data); 455 seed.data = (char *) &seed_data; 456 if ((retval = krb5_c_random_seed(ctx, &seed))) 457 /* 458 * Solaris Kerberos: we use /dev/urandom, which is 459 * automatically seeded, so its OK if this fails. 460 */ 461 retval = 0; 462 463 ctx->default_realm = 0; 464 profile_get_integer(ctx->profile, "libdefaults", "clockskew", 465 0, 5 * 60, &tmp); 466 ctx->clockskew = tmp; 467 468 #if 0 469 /* Default ticket lifetime is currently not supported */ 470 profile_get_integer(ctx->profile, "libdefaults", "tkt_lifetime", 471 0, 10 * 60 * 60, &tmp); 472 ctx->tkt_lifetime = tmp; 473 #endif 474 475 /* DCE 1.1 and below only support CKSUMTYPE_RSA_MD4 (2) */ 476 /* DCE add kdc_req_checksum_type = 2 to krb5.conf */ 477 profile_get_integer(ctx->profile, "libdefaults", 478 "kdc_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, 479 &tmp); 480 ctx->kdc_req_sumtype = tmp; 481 482 profile_get_integer(ctx->profile, "libdefaults", 483 "ap_req_checksum_type", 0, CKSUMTYPE_RSA_MD5, 484 &tmp); 485 ctx->default_ap_req_sumtype = tmp; 486 487 profile_get_integer(ctx->profile, "libdefaults", 488 "safe_checksum_type", 0, 489 CKSUMTYPE_RSA_MD5_DES, &tmp); 490 ctx->default_safe_sumtype = tmp; 491 492 profile_get_integer(ctx->profile, "libdefaults", 493 "kdc_default_options", 0, 494 KDC_OPT_RENEWABLE_OK, &tmp); 495 ctx->kdc_default_options = tmp; 496 #define DEFAULT_KDC_TIMESYNC 1 497 profile_get_integer(ctx->profile, "libdefaults", 498 "kdc_timesync", 0, DEFAULT_KDC_TIMESYNC, 499 &tmp); 500 ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0; 501 502 /* 503 * We use a default file credentials cache of 3. See 504 * lib/krb5/krb/ccache/file/fcc.h for a description of the 505 * credentials cache types. 506 * 507 * Note: DCE 1.0.3a only supports a cache type of 1 508 * DCE 1.1 supports a cache type of 2. 509 */ 510 #define DEFAULT_CCACHE_TYPE 4 511 profile_get_integer(ctx->profile, "libdefaults", "ccache_type", 512 0, DEFAULT_CCACHE_TYPE, &tmp); 513 ctx->fcc_default_format = tmp + 0x0500; 514 ctx->scc_default_format = tmp + 0x0500; 515 ctx->prompt_types = 0; 516 ctx->use_conf_ktypes = 0; 517 518 ctx->udp_pref_limit = -1; 519 520 #endif /* !_KERNEL */ 521 522 *context = ctx; 523 return 0; 524 525 cleanup: 526 krb5_free_context(ctx); 527 return retval; 528 } 529 530 void KRB5_CALLCONV 531 krb5_free_context(krb5_context ctx) 532 { 533 KRB5_LOG0(KRB5_INFO,"krb5_free_context() start"); 534 535 #ifndef _KERNEL 536 krb5_free_ef_handle(ctx); 537 538 if (ctx->conf_tgs_ktypes) { 539 FREE(ctx->conf_tgs_ktypes, sizeof(krb5_enctype) *(ctx->conf_tgs_ktypes_count)); 540 ctx->conf_tgs_ktypes = 0; 541 ctx->conf_tgs_ktypes_count = 0; 542 } 543 544 krb5_clear_error_message(ctx); 545 546 #endif 547 krb5_os_free_context(ctx); 548 549 if (ctx->in_tkt_ktypes) { 550 FREE(ctx->in_tkt_ktypes, sizeof(krb5_enctype) *(ctx->in_tkt_ktype_count+1) ); 551 ctx->in_tkt_ktypes = 0; 552 } 553 554 if (ctx->tgs_ktypes) { 555 FREE(ctx->tgs_ktypes, sizeof(krb5_enctype) *(ctx->tgs_ktype_count+1)); 556 ctx->tgs_ktypes = 0; 557 } 558 559 if (ctx->default_realm) { 560 FREE(ctx->default_realm, strlen(ctx->default_realm) + 1); 561 ctx->default_realm = 0; 562 } 563 564 if (ctx->ser_ctx_count && ctx->ser_ctx) { 565 FREE(ctx->ser_ctx,sizeof(krb5_ser_entry) * (ctx->ser_ctx_count) ); 566 ctx->ser_ctx = 0; 567 ctx->ser_ctx_count = 0; 568 } 569 570 571 ctx->magic = 0; 572 FREE(ctx, sizeof(struct _krb5_context)); 573 } 574 575 #ifndef _KERNEL 576 /* 577 * Set the desired default ktypes, making sure they are valid. 578 */ 579 krb5_error_code 580 krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes) 581 { 582 krb5_enctype * new_ktypes; 583 int i; 584 585 if (ktypes) { 586 for (i = 0; ktypes[i]; i++) { 587 if (!krb5_c_valid_enctype(ktypes[i])) 588 return KRB5_PROG_ETYPE_NOSUPP; 589 } 590 591 /* Now copy the default ktypes into the context pointer */ 592 if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i))) 593 (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i); 594 else 595 return ENOMEM; 596 597 } else { 598 i = 0; 599 new_ktypes = 0; 600 } 601 602 if (context->in_tkt_ktypes) 603 free(context->in_tkt_ktypes); 604 context->in_tkt_ktypes = new_ktypes; 605 context->in_tkt_ktype_count = i; 606 return 0; 607 } 608 609 static krb5_error_code 610 get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profstr, 611 unsigned int ctx_count, krb5_enctype *ctx_list) 612 { 613 krb5_enctype *old_ktypes = NULL; 614 615 if (ctx_count) { 616 /* application-set defaults */ 617 if ((old_ktypes = 618 (krb5_enctype *)malloc(sizeof(krb5_enctype) * 619 (ctx_count + 1)))) { 620 (void) memcpy(old_ktypes, ctx_list, 621 sizeof(krb5_enctype) * ctx_count); 622 old_ktypes[ctx_count] = 0; 623 } else { 624 return ENOMEM; 625 } 626 } else { 627 /* 628 XXX - For now, we only support libdefaults 629 Perhaps this should be extended to allow for per-host / per-realm 630 session key types. 631 */ 632 633 char *retval = NULL; 634 char *sp, *ep; 635 int j, checked_enctypes, count; 636 krb5_error_code code; 637 638 code = profile_get_string(context->profile, "libdefaults", profstr, 639 NULL, DEFAULT_ETYPE_LIST, &retval); 640 if (code) 641 return code; 642 643 if (!retval) /* SUNW14resync - just in case */ 644 return PROF_EINVAL; /* XXX */ 645 646 count = 0; 647 sp = retval; 648 while (*sp) { 649 for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++) 650 ; 651 if (*ep) { 652 *ep++ = '\0'; 653 while (isspace((int) (*ep)) || *ep == ',') 654 *ep++ = '\0'; 655 } 656 count++; 657 sp = ep; 658 } 659 660 if ((old_ktypes = 661 (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) == 662 (krb5_enctype *) NULL) 663 return ENOMEM; 664 665 sp = retval; 666 j = checked_enctypes = 0; 667 /*CONSTCOND*/ 668 while (TRUE) { 669 checked_enctypes++; 670 if (krb5_string_to_enctype(sp, &old_ktypes[j])) 671 old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN; 672 673 /* 674 * If 'null' has been specified as a tkt_enctype in 675 * krb5.conf, we need to assign an ENCTYPE_UNKNOWN 676 * value to the corresponding old_ktypes[j] entry. 677 */ 678 if (old_ktypes[j] == (unsigned int)ENCTYPE_NULL) 679 old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN; 680 681 /* Only include known/valid enctypes in the final list */ 682 if (old_ktypes[j] != ENCTYPE_UNKNOWN) { 683 j++; 684 } 685 /* If we checked all the enctypes, we are done */ 686 if (checked_enctypes == count) { 687 break; 688 } 689 690 /* skip to next token */ 691 while (*sp) sp++; 692 while (! *sp) sp++; 693 } 694 695 old_ktypes[j] = (krb5_enctype) 0; 696 profile_release_string(retval); 697 } 698 699 if (old_ktypes[0] == 0) { 700 free (old_ktypes); 701 *ktypes = 0; 702 return KRB5_CONFIG_ETYPE_NOSUPP; 703 } 704 705 *ktypes = old_ktypes; 706 return 0; 707 } 708 709 krb5_error_code 710 krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes) 711 { 712 return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes", 713 context->in_tkt_ktype_count, 714 context->in_tkt_ktypes)); 715 } 716 717 krb5_error_code KRB5_CALLCONV 718 krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes) 719 { 720 krb5_enctype * new_ktypes; 721 int i; 722 723 if (ktypes) { 724 for (i = 0; ktypes[i]; i++) { 725 if (!krb5_c_valid_enctype(ktypes[i])) 726 return KRB5_PROG_ETYPE_NOSUPP; 727 } 728 729 /* Now copy the default ktypes into the context pointer */ 730 if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i))) 731 (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i); 732 else 733 return ENOMEM; 734 735 } else { 736 i = 0; 737 new_ktypes = (krb5_enctype *)NULL; 738 } 739 740 if (context->tgs_ktypes) 741 krb5_free_ktypes(context, context->tgs_ktypes); 742 context->tgs_ktypes = new_ktypes; 743 context->tgs_ktype_count = i; 744 return 0; 745 } 746 747 krb5_error_code krb5_set_default_tgs_ktypes 748 (krb5_context context, const krb5_enctype *etypes) 749 { 750 return (krb5_set_default_tgs_enctypes (context, etypes)); 751 } 752 753 754 /*ARGSUSED*/ 755 void 756 KRB5_CALLCONV 757 krb5_free_ktypes (krb5_context context, krb5_enctype *val) 758 { 759 free (val); 760 } 761 762 /*ARGSUSED*/ 763 krb5_error_code 764 KRB5_CALLCONV 765 krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes) 766 { 767 if (context->use_conf_ktypes) 768 /* This one is set *only* by reading the config file; it's not 769 set by the application. */ 770 return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes", 771 context->conf_tgs_ktypes_count, 772 context->conf_tgs_ktypes)); 773 else 774 return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes", 775 context->tgs_ktype_count, 776 context->tgs_ktypes)); 777 } 778 779 krb5_error_code 780 krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes) 781 { 782 return(get_profile_etype_list(context, ktypes, "permitted_enctypes", 783 context->tgs_ktype_count, 784 context->tgs_ktypes)); 785 } 786 787 krb5_boolean 788 krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype) 789 { 790 krb5_enctype *list, *ptr; 791 krb5_boolean ret; 792 793 if (krb5_get_permitted_enctypes(context, &list)) 794 return(0); 795 796 797 ret = 0; 798 799 for (ptr = list; *ptr; ptr++) 800 if (*ptr == etype) 801 ret = 1; 802 803 krb5_free_ktypes (context, list); 804 805 return(ret); 806 } 807 808 static krb5_error_code 809 copy_ktypes(krb5_context ctx, 810 unsigned int nktypes, 811 krb5_enctype *oldktypes, 812 krb5_enctype **newktypes) 813 { 814 unsigned int i; 815 816 *newktypes = NULL; 817 if (!nktypes) 818 return 0; 819 820 *newktypes = MALLOC(nktypes * sizeof(krb5_enctype)); 821 if (*newktypes == NULL) 822 return ENOMEM; 823 for (i = 0; i < nktypes; i++) 824 (*newktypes)[i] = oldktypes[i]; 825 return 0; 826 } 827 828 krb5_error_code KRB5_CALLCONV 829 krb5_copy_context(krb5_context ctx, krb5_context *nctx_out) 830 { 831 krb5_error_code ret; 832 krb5_context nctx; 833 834 *nctx_out = NULL; 835 if (ctx == NULL) 836 return EINVAL; /* XXX */ 837 838 nctx = MALLOC(sizeof(*nctx)); 839 if (nctx == NULL) 840 return ENOMEM; 841 842 *nctx = *ctx; 843 844 nctx->in_tkt_ktypes = NULL; 845 nctx->in_tkt_ktype_count = 0; 846 nctx->tgs_ktypes = NULL; 847 nctx->tgs_ktype_count = 0; 848 nctx->default_realm = NULL; 849 nctx->profile = NULL; 850 nctx->db_context = NULL; 851 nctx->ser_ctx_count = 0; 852 nctx->ser_ctx = NULL; 853 nctx->prompt_types = NULL; 854 nctx->os_context->default_ccname = NULL; 855 856 memset(&nctx->preauth_plugins, 0, sizeof(nctx->preauth_plugins)); 857 nctx->preauth_context = NULL; 858 859 memset(&nctx->libkrb5_plugins, 0, sizeof(nctx->libkrb5_plugins)); 860 nctx->vtbl = NULL; 861 nctx->locate_fptrs = NULL; 862 863 memset(&nctx->err, 0, sizeof(nctx->err)); 864 865 ret = copy_ktypes(nctx, ctx->in_tkt_ktype_count, 866 ctx->in_tkt_ktypes, &nctx->in_tkt_ktypes); 867 if (ret) 868 goto errout; 869 nctx->in_tkt_ktype_count = ctx->in_tkt_ktype_count; 870 871 ret = copy_ktypes(nctx, ctx->tgs_ktype_count, 872 ctx->tgs_ktypes, &nctx->in_tkt_ktypes); 873 if (ret) 874 goto errout; 875 nctx->tgs_ktype_count = ctx->tgs_ktype_count; 876 877 if (ctx->os_context->default_ccname != NULL) { 878 nctx->os_context->default_ccname = 879 strdup(ctx->os_context->default_ccname); 880 if (nctx->os_context->default_ccname == NULL) { 881 ret = ENOMEM; 882 goto errout; 883 } 884 } 885 ret = krb5_get_profile(ctx, &nctx->profile); 886 if (ret) 887 goto errout; 888 889 errout: 890 if (ret) { 891 krb5_free_context(nctx); 892 } else { 893 *nctx_out = nctx; 894 } 895 return ret; 896 } 897 #endif /* !KERNEL */ 898 899 900