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