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