1 /* 2 * Copyright 2005 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 /* 494 * Solaris Kerberos: simplifying config by hard-coding udp_pref_limit 495 */ 496 ctx->udp_pref_limit = DEFAULT_UDP_PREF_LIMIT; 497 498 #endif /* !_KERNEL */ 499 500 *context = ctx; 501 return 0; 502 503 cleanup: 504 krb5_free_context(ctx); 505 return retval; 506 } 507 508 void KRB5_CALLCONV 509 krb5_free_context(krb5_context ctx) 510 { 511 KRB5_LOG0(KRB5_INFO,"krb5_free_context() start"); 512 513 #ifndef _KERNEL 514 krb5_free_ef_handle(ctx); 515 516 if (ctx->conf_tgs_ktypes) { 517 FREE(ctx->conf_tgs_ktypes, sizeof(krb5_enctype) *(ctx->conf_tgs_ktypes_count)); 518 ctx->conf_tgs_ktypes = 0; 519 ctx->conf_tgs_ktypes_count = 0; 520 } 521 522 #endif 523 krb5_os_free_context(ctx); 524 525 if (ctx->in_tkt_ktypes) { 526 FREE(ctx->in_tkt_ktypes, sizeof(krb5_enctype) *(ctx->in_tkt_ktype_count+1) ); 527 ctx->in_tkt_ktypes = 0; 528 } 529 530 if (ctx->tgs_ktypes) { 531 FREE(ctx->tgs_ktypes, sizeof(krb5_enctype) *(ctx->tgs_ktype_count+1)); 532 ctx->tgs_ktypes = 0; 533 } 534 535 if (ctx->default_realm) { 536 FREE(ctx->default_realm, strlen(ctx->default_realm) + 1); 537 ctx->default_realm = 0; 538 } 539 540 if (ctx->ser_ctx_count && ctx->ser_ctx) { 541 FREE(ctx->ser_ctx,sizeof(krb5_ser_entry) * (ctx->ser_ctx_count) ); 542 ctx->ser_ctx = 0; 543 ctx->ser_ctx_count = 0; 544 } 545 546 ctx->magic = 0; 547 FREE(ctx, sizeof(struct _krb5_context)); 548 549 } 550 551 #ifndef _KERNEL 552 /* 553 * Set the desired default ktypes, making sure they are valid. 554 */ 555 krb5_error_code 556 krb5_set_default_in_tkt_ktypes(krb5_context context, const krb5_enctype *ktypes) 557 { 558 krb5_enctype * new_ktypes; 559 int i; 560 561 if (ktypes) { 562 for (i = 0; ktypes[i]; i++) { 563 if (!krb5_c_valid_enctype(ktypes[i])) 564 return KRB5_PROG_ETYPE_NOSUPP; 565 } 566 567 /* Now copy the default ktypes into the context pointer */ 568 if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i))) 569 (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i); 570 else 571 return ENOMEM; 572 573 } else { 574 i = 0; 575 new_ktypes = 0; 576 } 577 578 if (context->in_tkt_ktypes) 579 free(context->in_tkt_ktypes); 580 context->in_tkt_ktypes = new_ktypes; 581 context->in_tkt_ktype_count = i; 582 return 0; 583 } 584 585 static krb5_error_code 586 get_profile_etype_list(krb5_context context, krb5_enctype **ktypes, char *profstr, 587 int ctx_count, krb5_enctype *ctx_list) 588 { 589 krb5_enctype *old_ktypes = NULL; 590 591 if (ctx_count) { 592 /* application-set defaults */ 593 if ((old_ktypes = 594 (krb5_enctype *)malloc(sizeof(krb5_enctype) * 595 (ctx_count + 1)))) { 596 (void) memcpy(old_ktypes, ctx_list, 597 sizeof(krb5_enctype) * ctx_count); 598 old_ktypes[ctx_count] = 0; 599 } else { 600 return ENOMEM; 601 } 602 } else { 603 /* 604 XXX - For now, we only support libdefaults 605 Perhaps this should be extended to allow for per-host / per-realm 606 session key types. 607 */ 608 609 char *retval = NULL; 610 char *sp, *ep; 611 int j, checked_enctypes, count; 612 krb5_error_code code; 613 614 code = profile_get_string(context->profile, "libdefaults", profstr, 615 NULL, DEFAULT_ETYPE_LIST, &retval); 616 if (code) 617 return code; 618 619 if (!retval) /* SUNW14resync - just in case */ 620 return PROF_EINVAL; /* XXX */ 621 622 count = 0; 623 sp = retval; 624 while (*sp) { 625 for (ep = sp; *ep && (*ep != ',') && !isspace((int) (*ep)); ep++) 626 ; 627 if (*ep) { 628 *ep++ = '\0'; 629 while (isspace((int) (*ep)) || *ep == ',') 630 *ep++ = '\0'; 631 } 632 count++; 633 sp = ep; 634 } 635 636 if ((old_ktypes = 637 (krb5_enctype *)malloc(sizeof(krb5_enctype) * (count + 1))) == 638 (krb5_enctype *) NULL) 639 return ENOMEM; 640 641 sp = retval; 642 j = checked_enctypes = 0; 643 /*CONSTCOND*/ 644 while (TRUE) { 645 checked_enctypes++; 646 if (krb5_string_to_enctype(sp, &old_ktypes[j])) 647 old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN; 648 649 /* 650 * If 'null' has been specified as a tkt_enctype in 651 * krb5.conf, we need to assign an ENCTYPE_UNKNOWN 652 * value to the corresponding old_ktypes[j] entry. 653 */ 654 if (old_ktypes[j] == (unsigned int)ENCTYPE_NULL) 655 old_ktypes[j] = (unsigned int)ENCTYPE_UNKNOWN; 656 657 /* Only include known/valid enctypes in the final list */ 658 if (old_ktypes[j] != ENCTYPE_UNKNOWN) { 659 j++; 660 } 661 /* If we checked all the enctypes, we are done */ 662 if (checked_enctypes == count) { 663 break; 664 } 665 666 /* skip to next token */ 667 while (*sp) sp++; 668 while (!*sp) sp++; 669 } 670 671 old_ktypes[j] = (krb5_enctype) 0; 672 profile_release_string(retval); 673 } 674 675 if (old_ktypes[0] == 0) { 676 free (old_ktypes); 677 *ktypes = 0; 678 return KRB5_CONFIG_ETYPE_NOSUPP; 679 } 680 681 682 683 *ktypes = old_ktypes; 684 return 0; 685 } 686 687 krb5_error_code 688 krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes) 689 { 690 return(get_profile_etype_list(context, ktypes, "default_tkt_enctypes", 691 context->in_tkt_ktype_count, 692 context->in_tkt_ktypes)); 693 } 694 695 krb5_error_code 696 krb5_set_default_tgs_enctypes (krb5_context context, const krb5_enctype *ktypes) 697 { 698 krb5_enctype * new_ktypes; 699 int i; 700 701 if (ktypes) { 702 for (i = 0; ktypes[i]; i++) { 703 if (!valid_enctype(ktypes[i])) 704 return KRB5_PROG_ETYPE_NOSUPP; 705 } 706 707 /* Now copy the default ktypes into the context pointer */ 708 if ((new_ktypes = (krb5_enctype *)malloc(sizeof(krb5_enctype) * i))) 709 (void) memcpy(new_ktypes, ktypes, sizeof(krb5_enctype) * i); 710 else 711 return ENOMEM; 712 713 } else { 714 i = 0; 715 new_ktypes = (krb5_enctype *)NULL; 716 } 717 718 if (context->tgs_ktypes) 719 krb5_free_ktypes(context, context->tgs_ktypes); 720 context->tgs_ktypes = new_ktypes; 721 context->tgs_ktype_count = i; 722 return 0; 723 } 724 725 krb5_error_code krb5_set_default_tgs_ktypes 726 (krb5_context context, const krb5_enctype *etypes) 727 { 728 return (krb5_set_default_tgs_enctypes (context, etypes)); 729 } 730 731 732 733 734 /*ARGSUSED*/ 735 void 736 KRB5_CALLCONV 737 krb5_free_ktypes (krb5_context context, krb5_enctype *val) 738 { 739 free (val); 740 } 741 742 /*ARGSUSED*/ 743 krb5_error_code 744 KRB5_CALLCONV 745 krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, krb5_enctype **ktypes) 746 { 747 if (context->use_conf_ktypes) 748 /* This one is set *only* by reading the config file; it's not 749 set by the application. */ 750 return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes", 751 context->conf_tgs_ktypes_count, 752 context->conf_tgs_ktypes)); 753 else 754 return(get_profile_etype_list(context, ktypes, "default_tgs_enctypes", 755 context->tgs_ktype_count, 756 context->tgs_ktypes)); 757 } 758 759 krb5_error_code 760 krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes) 761 { 762 return(get_profile_etype_list(context, ktypes, "permitted_enctypes", 763 context->tgs_ktype_count, 764 context->tgs_ktypes)); 765 } 766 767 krb5_boolean 768 krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype) 769 { 770 krb5_enctype *list, *ptr; 771 krb5_boolean ret; 772 773 if (krb5_get_permitted_enctypes(context, &list)) 774 return(0); 775 776 777 ret = 0; 778 779 for (ptr = list; *ptr; ptr++) 780 if (*ptr == etype) 781 ret = 1; 782 783 krb5_free_ktypes (context, list); 784 785 return(ret); 786 } 787 #endif /* !KERNEL */ 788