1/* 2 * $Header$ 3 * 4 * Copyright 2006 Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27#include <Security/Authorization.h> 28#include <CoreFoundation/CoreFoundation.h> 29 30#include <string.h> 31#include <syslog.h> 32#include <stdlib.h> 33#include <errno.h> 34#include <time.h> 35#include <pthread.h> 36#include <stdio.h> 37 38#include <dispatch/dispatch.h> 39 40#include "heim.h" 41#include "mit-KerberosLogin.h" 42#include "mit-CredentialsCache.h" 43 44struct KLLoginOptions { 45 krb5_get_init_creds_opt *opt; 46 char *service; 47}; 48 49/* 50 * Deprecated Error codes 51 */ 52enum { 53 /* Carbon Dialog errors */ 54 klDialogDoesNotExistErr = 19676, 55 klDialogAlreadyExistsErr, 56 klNotInForegroundErr, 57 klNoAppearanceErr, 58 klFatalDialogErr, 59 klCarbonUnavailableErr 60}; 61 62krb5_get_init_creds_opt *__KLLoginOptionsGetKerberos5Options (KLLoginOptions ioOptions); 63KLTime __KLLoginOptionsGetStartTime (KLLoginOptions ioOptions); 64char *__KLLoginOptionsGetServiceName (KLLoginOptions ioOptions); 65 66#define CHECK_VERSION(_vers) ((_vers) != kerberosVersion_V5 && (_vers) != kerberosVersion_All) 67 68 69KLStatus 70KLAcquireTickets (KLPrincipal inPrincipal, 71 KLPrincipal *outPrincipal, 72 char **outCredCacheName) 73{ 74 LOG_ENTRY(); 75 return KLAcquireInitialTickets (inPrincipal, 76 NULL, 77 outPrincipal, 78 outCredCacheName); 79} 80 81 82KLStatus 83KLAcquireNewTickets (KLPrincipal inPrincipal, 84 KLPrincipal *outPrincipal, 85 char **outCredCacheName) 86{ 87 LOG_ENTRY(); 88 return KLAcquireNewInitialTickets (inPrincipal, 89 NULL, 90 outPrincipal, 91 outCredCacheName); 92} 93 94 95KLStatus 96KLAcquireTicketsWithPassword (KLPrincipal inPrincipal, 97 KLLoginOptions inLoginOptions, 98 const char *inPassword, 99 char **outCredCacheName) 100{ 101 LOG_ENTRY(); 102 return KLAcquireInitialTicketsWithPassword (inPrincipal, 103 inLoginOptions, 104 inPassword, 105 outCredCacheName); 106} 107 108 109KLStatus 110KLAcquireNewTicketsWithPassword (KLPrincipal inPrincipal, 111 KLLoginOptions inLoginOptions, 112 const char *inPassword, 113 char **outCredCacheName) 114{ 115 LOG_ENTRY(); 116 return KLAcquireNewInitialTicketsWithPassword (inPrincipal, 117 inLoginOptions, 118 inPassword, 119 outCredCacheName); 120} 121 122 123KLStatus 124KLSetApplicationOptions (const void *inAppOptions) 125{ 126 return klNoErr; 127} 128 129 130KLStatus 131KLGetApplicationOptions (void *outAppOptions) 132{ 133 return klDialogDoesNotExistErr; 134} 135 136#define kCoreAuthPanelKerberosRight "com.apple.KerberosAgent" 137#define kCoreAuthPanelKerberosPrincipal "principal" 138#define kCoreAuthPanelKerberosOptions "kerberosOptions" 139 140static OSStatus 141acquireticket_ui(KLPrincipal inPrincipal, 142 KLLoginOptions inLoginOptions, 143 KLPrincipal *outPrincipal, 144 char **outCredCacheName) 145{ 146 AuthorizationRef auth; 147 OSStatus ret; 148 char *princ = NULL; 149 CFDataRef d = NULL; 150 151 LOG_ENTRY(); 152 153 if (outPrincipal) 154 *outPrincipal = NULL; 155 if (outCredCacheName) 156 *outCredCacheName = NULL; 157 158 if (inPrincipal) { 159 ret = heim_krb5_unparse_name(milcontext, inPrincipal, &princ); 160 if (ret) 161 return ret; 162 } 163 164 165 ret = AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &auth); 166 if (ret) { 167 free(princ); 168 return ret; 169 } 170 171 AuthorizationItem rightItems[1] = { kCoreAuthPanelKerberosRight, 0, NULL, 0 }; 172 AuthorizationRights rights = { sizeof(rightItems[0])/sizeof(rightItems) , rightItems }; 173 AuthorizationItem envItems[3]; 174 AuthorizationEnvironment env = { 0 , envItems }; 175 AuthorizationFlags authFlags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; 176 177 if (princ) { 178 envItems[env.count].name = kCoreAuthPanelKerberosPrincipal; 179 envItems[env.count].valueLength = strlen(princ); 180 envItems[env.count].value = princ; 181 envItems[env.count].flags = 0; 182 env.count++; 183 } 184 185 if (inLoginOptions && inLoginOptions->opt) { 186 CFMutableDictionaryRef dict; 187 188 dict = CFDictionaryCreateMutable(NULL, 1, 189 &kCFTypeDictionaryKeyCallBacks, 190 &kCFTypeDictionaryValueCallBacks); 191 if (dict == NULL) 192 goto out; 193 194 if (inLoginOptions->opt->renew_life) { 195 CFStringRef t; 196 t = CFStringCreateWithFormat(NULL, 0, CFSTR("%ld"),(long)inLoginOptions->opt->renew_life); 197 CFDictionarySetValue(dict, CFSTR("renewTime"), t); 198 CFRelease(t); 199 } 200 201 d = CFPropertyListCreateData(NULL, dict, kCFPropertyListBinaryFormat_v1_0, 202 0, NULL); 203 CFRelease(dict); 204 205 envItems[env.count].name = kCoreAuthPanelKerberosOptions; 206 envItems[env.count].valueLength = CFDataGetLength(d); 207 envItems[env.count].value = (void *)CFDataGetBytePtr(d); 208 envItems[env.count].flags = 0; 209 env.count++; 210 } 211 212 ret = AuthorizationCopyRights(auth, &rights, &env, authFlags, NULL); 213 214 if (ret == 0 && outPrincipal) { 215 AuthorizationItemSet *info; 216 UInt32 i; 217 ret = AuthorizationCopyInfo(auth, NULL, &info); 218 if (ret) 219 goto out; 220 for(i = 0; i < info->count; i++) { 221 if (strcmp(info->items[i].name, "out-principal") == 0) { 222 char *str; 223 asprintf(&str, "%.*s", (int)info->items[i].valueLength, (char *)info->items[i].value); 224 heim_krb5_parse_name(milcontext, str, outPrincipal); 225 } else if (strcmp(info->items[i].name, "out-cache-name") == 0) { 226 asprintf(outCredCacheName, "%.*s", (int)info->items[i].valueLength, (char *)info->items[i].value); 227 } 228 } 229 AuthorizationFreeItemSet(info); 230 if (*outPrincipal == NULL) 231 ret = EINVAL; 232 } 233out: 234 if (d) 235 CFRelease(d); 236 AuthorizationFree(auth, kAuthorizationFlagDestroyRights); 237 free(princ); 238 return ret; 239} 240 241KLStatus 242KLAcquireInitialTickets(KLPrincipal inPrincipal, 243 KLLoginOptions inLoginOptions, 244 KLPrincipal *outPrincipal, 245 char **outCredCacheName) 246{ 247 KLBoolean ValidTickets; 248 KLStatus ret; 249 250 LOG_ENTRY(); 251 252 ret = KLCacheHasValidTickets(inPrincipal, 253 kerberosVersion_V5, 254 &ValidTickets, 255 outPrincipal, 256 outCredCacheName); 257 if (ret || !ValidTickets) 258 ret = acquireticket_ui(inPrincipal, inLoginOptions, outPrincipal, outCredCacheName); 259 260 return ret; 261} 262 263 264KLStatus 265KLAcquireNewInitialTickets (KLPrincipal inPrincipal, 266 KLLoginOptions inLoginOptions, 267 KLPrincipal *outPrincipal, 268 char **outCredCacheName) 269{ 270 LOG_ENTRY(); 271 272 return acquireticket_ui(inPrincipal, inLoginOptions, outPrincipal, outCredCacheName); 273} 274 275 276KLStatus 277KLDestroyTickets(KLPrincipal inPrincipal) 278{ 279 krb5_context context = mshim_ctx(); 280 krb5_error_code ret; 281 krb5_ccache id; 282 283 ret = heim_krb5_cc_cache_match(context, inPrincipal, &id); 284 if (ret) 285 return ret; 286 287 return krb5_cc_destroy((mit_krb5_context)context, (mit_krb5_ccache)id); 288} 289 290 291KLStatus KLChangePassword (KLPrincipal inPrincipal) 292{ 293 LOG_UNIMPLEMENTED(); 294 return EINVAL; 295} 296 297 298KLStatus 299KLAcquireInitialTicketsWithPassword(KLPrincipal inPrincipal, 300 KLLoginOptions inLoginOptions, 301 const char *inPassword, 302 char **outCredCacheName) 303{ 304 KLStatus ret; 305 KLBoolean ValidTickets; 306 307 ret = KLCacheHasValidTickets(inPrincipal, 308 kerberosVersion_V5, 309 &ValidTickets, 310 NULL, 311 outCredCacheName); 312 if (ret == 0) { 313 if (ValidTickets) 314 return klNoErr; /* done */ 315 /* get credential */ 316 if (outCredCacheName) 317 free(*outCredCacheName); 318 } 319 return KLAcquireNewInitialTicketsWithPassword(inPrincipal, 320 inLoginOptions, 321 inPassword, 322 outCredCacheName); 323} 324 325KLStatus 326KLAcquireNewInitialTicketsWithPassword(KLPrincipal inPrincipal, 327 KLLoginOptions inLoginOptions, 328 const char *inPassword, 329 char **outCredCacheName) 330{ 331 krb5_context context = mshim_ctx(); 332 krb5_error_code ret; 333 krb5_ccache cache; 334 krb5_creds creds; 335 char *service = NULL; 336 krb5_get_init_creds_opt *opt = NULL; 337 338 LOG_ENTRY(); 339 340 if (inLoginOptions) { 341 service = inLoginOptions->service; 342 opt = inLoginOptions->opt; 343 } 344 345 ret = heim_krb5_get_init_creds_password(context, &creds, 346 inPrincipal, inPassword, 347 NULL, NULL, 0, 348 service, 349 opt); 350 if (ret) 351 return ret; 352 353 ret = heim_krb5_cc_cache_match(context, inPrincipal, &cache); 354 if (ret) 355 ret = heim_krb5_cc_new_unique(context, NULL, NULL, &cache); 356 if (ret) 357 goto out; 358 359 ret = heim_krb5_cc_initialize(context, cache, creds.client); 360 if(ret) 361 goto out; 362 363 ret = heim_krb5_cc_store_cred(context, cache, &creds); 364 if (ret) 365 goto out; 366 367 if (outCredCacheName) 368 *outCredCacheName = strdup(heim_krb5_cc_get_name(context, cache)); 369 370 out: 371 if (cache) { 372 if (ret) 373 krb5_cc_destroy((mit_krb5_context)context, (mit_krb5_ccache)cache); 374 else 375 heim_krb5_cc_close(context, cache); 376 } 377 heim_krb5_free_cred_contents(context, &creds); 378 379 return ret; 380} 381 382 383KLStatus KLAcquireNewInitialTicketCredentialsWithPassword (KLPrincipal inPrincipal, 384 KLLoginOptions inLoginOptions, 385 const char *inPassword, 386 void *inV5Context, 387 KLBoolean *outGotV4Credentials, 388 KLBoolean *outGotV5Credentials, 389 void *outV4Credentials, 390 void *outV5Credentials) 391{ 392 LOG_UNIMPLEMENTED(); 393 return EINVAL; 394} 395 396 397KLStatus KLStoreNewInitialTicketCredentials (KLPrincipal inPrincipal, 398 void *inV5Context, 399 void *inV4Credentials, 400 void *inV5Credentials, 401 char **outCredCacheName) 402{ 403 LOG_UNIMPLEMENTED(); 404 return EINVAL; 405} 406 407 408KLStatus KLVerifyInitialTickets (KLPrincipal inPrincipal, 409 KLBoolean inFailIfNoHostKey, 410 char **outCredCacheName) 411{ 412 LOG_UNIMPLEMENTED(); 413 return klNoErr; 414} 415 416 417KLStatus KLVerifyInitialTicketCredentials (void *inV4Credentials, 418 void *inV5Credentials, 419 KLBoolean inFailIfNoHostKey) 420{ 421 LOG_UNIMPLEMENTED(); 422 return klNoErr; 423} 424 425 426KLStatus KLAcquireNewInitialTicketsWithKeytab (KLPrincipal inPrincipal, 427 KLLoginOptions inLoginOptions, 428 const char *inKeytabName, 429 char **outCredCacheName) 430{ 431 LOG_UNIMPLEMENTED(); 432 return EINVAL; 433} 434 435 436KLStatus 437KLRenewInitialTickets(KLPrincipal inPrincipal, 438 KLLoginOptions inLoginOptions, 439 KLPrincipal *outPrincipal, 440 char **outCredCacheName) 441{ 442 krb5_context context = mshim_ctx(); 443 krb5_error_code ret; 444 krb5_creds in, *cred = NULL; 445 krb5_ccache id; 446 krb5_kdc_flags flags; 447 krb5_const_realm realm; 448 krb5_principal principal = NULL; 449 450 memset(&in, 0, sizeof(in)); 451 452 LOG_ENTRY(); 453 454 if (outPrincipal) 455 *outPrincipal = NULL; 456 if (outCredCacheName) 457 *outCredCacheName = NULL; 458 459 if (inPrincipal) { 460 principal = inPrincipal; 461 } else { 462 ret = heim_krb5_get_default_principal(context, &principal); 463 if (ret) 464 return ret; 465 } 466 467 ret = heim_krb5_cc_cache_match(context, principal, &id); 468 if (ret) { 469 if (inPrincipal == NULL) 470 heim_krb5_free_principal(context, principal); 471 return ret; 472 } 473 474 in.client = principal; 475 476 realm = heim_krb5_principal_get_realm(context, in.client); 477 478 if (inLoginOptions && inLoginOptions->service) 479 ret = heim_krb5_make_principal(context, &in.server, realm, inLoginOptions->service, NULL); 480 else 481 ret = heim_krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME, realm, NULL); 482 if (ret) { 483 if (inPrincipal == NULL) 484 heim_krb5_free_principal(context, principal); 485 heim_krb5_cc_close(context, id); 486 return ret; 487 } 488 489 flags.i = 0; 490 if (inLoginOptions) 491 flags.i = inLoginOptions->opt->flags; 492 493 /* Pull out renewable from previous ticket */ 494 ret = heim_krb5_get_credentials(context, KRB5_GC_CACHED, id, &in, &cred); 495 if (inPrincipal == NULL) 496 heim_krb5_free_principal(context, principal); 497 if (ret == 0 && cred) { 498 flags.b.renewable = cred->flags.b.renewable; 499 heim_krb5_free_creds (context, cred); 500 cred = NULL; 501 } 502 503 flags.b.renew = 1; 504 505 ret = heim_krb5_get_kdc_cred(context, id, flags, NULL, NULL, &in, &cred); 506 heim_krb5_free_principal(context, in.server); 507 if (ret) 508 goto out; 509 ret = heim_krb5_cc_initialize(context, id, in.client); 510 if (ret) 511 goto out; 512 ret = heim_krb5_cc_store_cred(context, id, cred); 513 514 out: 515 if (cred) 516 heim_krb5_free_creds (context, cred); 517 heim_krb5_cc_close(context, id); 518 519 return ret; 520} 521 522 523KLStatus KLValidateInitialTickets (KLPrincipal inPrincipal, 524 KLLoginOptions inLoginOptions, 525 char **outCredCacheName) 526{ 527 LOG_UNIMPLEMENTED(); 528 return klNoErr; 529} 530 531static krb5_timestamp g_cc_change_time = 0; 532static KLTime g_kl_change_time = 0; 533static pthread_mutex_t g_change_time_mutex = PTHREAD_MUTEX_INITIALIZER; 534 535 536KLStatus 537KLLastChangedTime(KLTime *outLastChangedTime) 538{ 539 krb5_timestamp ccChangeTime; 540 KLStatus ret; 541 542 LOG_ENTRY(); 543 544 if (outLastChangedTime == NULL) 545 return klParameterErr; 546 547 ret = heim_krb5_cccol_last_change_time(milcontext, "API", &ccChangeTime); 548 if (ret) 549 return ret; 550 551 pthread_mutex_lock(&g_change_time_mutex); 552 553 if (g_kl_change_time == 0) 554 g_kl_change_time = ccChangeTime; 555 556 if (ccChangeTime > g_cc_change_time) { 557 558 if (ccChangeTime > g_kl_change_time) 559 g_kl_change_time = ccChangeTime; 560 else 561 g_kl_change_time++; 562 563 g_cc_change_time = ccChangeTime; 564 } 565 566 *outLastChangedTime = g_kl_change_time; 567 568 pthread_mutex_unlock (&g_change_time_mutex); 569 570 return klNoErr; 571} 572 573 574static krb5_error_code 575fetch_creds(KLPrincipal inPrincipal, krb5_creds **ocreds, 576 char **outCredCacheName) 577{ 578 krb5_context context = mshim_ctx(); 579 krb5_principal princ = NULL; 580 krb5_creds in_creds; 581 krb5_const_realm realm; 582 krb5_error_code ret; 583 krb5_ccache id = NULL; 584 585 LOG_ENTRY(); 586 587 memset(&in_creds, 0, sizeof(in_creds)); 588 589 if (inPrincipal) { 590 ret = heim_krb5_cc_cache_match(context, inPrincipal, &id); 591 } else { 592 ret = heim_krb5_cc_default(context, &id); 593 if (ret == 0) 594 ret = heim_krb5_cc_get_principal(context, id, &princ); 595 inPrincipal = princ; 596 } 597 if (ret) 598 goto out; 599 600 realm = heim_krb5_principal_get_realm(context, inPrincipal); 601 ret = heim_krb5_make_principal(context, &in_creds.server, realm, KRB5_TGS_NAME, realm, NULL); 602 if (ret) 603 goto out; 604 605 in_creds.client = inPrincipal; 606 607 ret = heim_krb5_get_credentials(context, KRB5_GC_CACHED, id, 608 &in_creds, ocreds); 609 heim_krb5_free_principal(context, in_creds.server); 610 611 if (outCredCacheName) 612 *outCredCacheName = strdup(heim_krb5_cc_get_name(context, id)); 613 614 out: 615 if (id) 616 heim_krb5_cc_close(context, id); 617 if (princ) 618 heim_krb5_free_principal(context, princ); 619 620 return LOG_FAILURE(ret, "fetch_creds"); 621} 622 623 624KLStatus KLCacheHasValidTickets (KLPrincipal inPrincipal, 625 KLKerberosVersion inKerberosVersion, 626 KLBoolean *outFoundValidTickets, 627 KLPrincipal *outPrincipal, 628 char **outCredCacheName) 629{ 630 krb5_error_code ret; 631 krb5_creds *ocreds = NULL; 632 633 LOG_ENTRY(); 634 635 if (outPrincipal) 636 *outPrincipal = NULL; 637 638 if (CHECK_VERSION(inKerberosVersion)) 639 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 640 641 ret = fetch_creds(inPrincipal, &ocreds, outCredCacheName); 642 643 if (ret == 0) { 644 time_t t = time(NULL); 645 /* consinder tickets that are slightly too young as valid 646 * since might just have fetched them */ 647 *outFoundValidTickets = 648 (ocreds->times.starttime - 10 < t) 649 && (t < ocreds->times.endtime); 650 651 if (outPrincipal) 652 (void)heim_krb5_copy_principal(milcontext, ocreds->client, outPrincipal); 653 heim_krb5_free_creds(milcontext, ocreds); 654 } else { 655 LOG_FAILURE(ret, "fetch tickets failed"); 656 ret = 0; 657 *outFoundValidTickets = 0; 658 } 659 660 661 return LOG_FAILURE(ret, "KLCacheHasValidTickets"); 662} 663 664 665KLStatus KLTicketStartTime (KLPrincipal inPrincipal, 666 KLKerberosVersion inKerberosVersion, 667 KLTime *outStartTime) 668{ 669 krb5_creds *creds; 670 krb5_error_code ret; 671 672 LOG_ENTRY(); 673 674 if (CHECK_VERSION(inKerberosVersion)) 675 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 676 677 ret = fetch_creds(inPrincipal, &creds, NULL); 678 if (ret) 679 return LOG_FAILURE(ret, "fetch tickets failed"); 680 681 *outStartTime = creds->times.starttime; 682 683 heim_krb5_free_creds(milcontext, creds); 684 return klNoErr; 685} 686 687 688KLStatus KLTicketExpirationTime (KLPrincipal inPrincipal, 689 KLKerberosVersion inKerberosVersion, 690 KLTime *outExpirationTime) 691{ 692 krb5_error_code ret; 693 krb5_creds *creds; 694 695 LOG_ENTRY(); 696 697 if (CHECK_VERSION(inKerberosVersion)) 698 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 699 700 ret = fetch_creds(inPrincipal, &creds, NULL); 701 if (ret) 702 return LOG_FAILURE(ret, "fetch tickets failed"); 703 704 *outExpirationTime = creds->times.endtime; 705 706 heim_krb5_free_creds(milcontext, creds); 707 return klNoErr; 708} 709 710 711KLStatus 712KLSetSystemDefaultCache (KLPrincipal inPrincipal) 713{ 714 krb5_context context = mshim_ctx(); 715 krb5_error_code ret; 716 krb5_ccache id; 717 718 LOG_ENTRY(); 719 720 ret = heim_krb5_cc_cache_match(context, inPrincipal, &id); 721 if (ret) 722 return LOG_FAILURE(ret, "ccache match"); 723 ret = heim_krb5_cc_switch(context, id); 724 heim_krb5_cc_close(context, id); 725 if (ret) 726 return LOG_FAILURE(ret, "cc switch"); 727 return klNoErr; 728} 729 730 731KLStatus KLHandleError (KLStatus inError, 732 KLDialogIdentifier inDialogIdentifier, 733 KLBoolean inShowAlert) 734{ 735 LOG_UNIMPLEMENTED(); 736 return klNoErr; 737} 738 739 740KLStatus KLGetErrorString (KLStatus inError, 741 char **outErrorString) 742{ 743 const char *msg; 744 LOG_ENTRY(); 745 746 msg = heim_krb5_get_error_message(milcontext, (krb5_error_code)inError); 747 if (msg) { 748 *outErrorString = strdup(msg); 749 krb5_free_error_message((mit_krb5_context)milcontext, msg); 750 } else 751 asprintf(outErrorString, "unknown error: %d\n", (int)inError); 752 if (*outErrorString == NULL) 753 return klMemFullErr; 754 return klNoErr; 755} 756 757 758KLStatus KLCancelAllDialogs (void) 759{ 760 return klNoErr; 761} 762 763 764/* Kerberos change password dialog low level functions */ 765 766KLStatus KLChangePasswordWithPasswords (KLPrincipal inPrincipal, 767 const char *inOldPassword, 768 const char *inNewPassword, 769 KLBoolean *outRejected, 770 char **outRejectionError, 771 char **outRejectionDescription) 772{ 773 LOG_UNIMPLEMENTED(); 774 return EINVAL; 775} 776 777 778/* Application Configuration functions */ 779 780KLStatus KLSetIdleCallback (const KLIdleCallback inCallback, 781 const KLRefCon inRefCon) 782{ 783 return klNoErr; 784} 785 786 787KLStatus KLGetIdleCallback (KLIdleCallback* inCallback, 788 KLRefCon* inRefCon) 789{ 790 return klNoErr; 791} 792 793 794/* Library configuration functions */ 795/* Deprecated options which we now ignore */ 796enum { 797 loginOption_ShowOptions = 'sopt', 798 loginOption_RememberShowOptions = 'ropt', 799 loginOption_LongTicketLifetimeDisplay = 'hms ', 800 loginOption_RememberPassword = 'pass' 801}; 802 803 804 805KLStatus KLGetDefaultLoginOption (const KLDefaultLoginOption inOption, 806 void *ioBuffer, 807 KLSize *ioBufferSize) 808{ 809 LOG_UNIMPLEMENTED(); 810 return EINVAL; 811} 812 813 814KLStatus KLSetDefaultLoginOption (const KLDefaultLoginOption inOption, 815 const void *inBuffer, 816 const KLSize inBufferSize) 817{ 818 LOG_UNIMPLEMENTED(); 819 return EINVAL; 820} 821 822 823/* Realm configuration functions */ 824 825KLStatus KLFindKerberosRealmByName (const char *inRealmName, 826 KLIndex *outIndex) 827{ 828 KLStatus ret; 829 char *realm = NULL; 830 831 ret = KLGetKerberosDefaultRealmByName (&realm); 832 if (ret == klNoErr) { 833 if (!strcmp (inRealmName, realm)) { 834 *outIndex = 0; 835 } else { 836 ret = klRealmDoesNotExistErr; 837 } 838 free(realm); 839 } 840 841 842 return ret; 843} 844 845 846KLStatus KLGetKerberosRealm (KLIndex inIndex, 847 char **outRealmName) 848{ 849 return KLGetKerberosDefaultRealmByName (outRealmName); 850} 851 852 853KLStatus KLSetKerberosRealm (KLIndex inIndex, 854 const char *inRealmName) 855{ 856 return klNoErr; 857} 858 859 860KLStatus KLRemoveKerberosRealm (KLIndex inIndex) 861{ 862 return klNoErr; 863} 864 865 866KLStatus KLInsertKerberosRealm (KLIndex inInsertBeforeIndex, 867 const char *inRealmName) 868{ 869 return klNoErr; 870} 871 872 873KLStatus KLRemoveAllKerberosRealms (void) 874{ 875 return klNoErr; 876} 877 878 879KLSize KLCountKerberosRealms (void) 880{ 881 return 1; 882} 883 884 885KLStatus KLGetKerberosDefaultRealm(KLIndex *outIndex) 886{ 887 if(outIndex) 888 *outIndex = 0; 889 890 return klNoErr; 891} 892 893 894KLStatus KLGetKerberosDefaultRealmByName (char **outRealmName) 895{ 896 LOG_ENTRY(); 897 898 return krb5_get_default_realm((mit_krb5_context)milcontext, outRealmName); 899} 900 901 902KLStatus KLSetKerberosDefaultRealm (KLIndex inIndex) 903{ 904 return klNoErr; 905} 906 907 908KLStatus KLSetKerberosDefaultRealmByName (const char *inRealm) 909{ 910 return klNoErr; 911} 912 913 914/* KLPrincipal functions */ 915 916KLStatus 917KLCreatePrincipalFromTriplet (const char *inName, 918 const char *inInstance, 919 const char *inRealm, 920 KLPrincipal *outPrincipal) 921{ 922 return heim_krb5_make_principal(milcontext, outPrincipal, inRealm, inName, inInstance, NULL); 923} 924 925 926KLStatus 927KLCreatePrincipalFromString (const char *inFullPrincipal, 928 KLKerberosVersion inKerberosVersion, 929 KLPrincipal *outPrincipal) 930{ 931 LOG_ENTRY(); 932 933 if (CHECK_VERSION(inKerberosVersion)) 934 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 935 936 if (inFullPrincipal == NULL) 937 return klParameterErr; 938 return heim_krb5_parse_name(milcontext, inFullPrincipal, outPrincipal); 939} 940 941 942KLStatus KLCreatePrincipalFromKerberos5Principal (void *inKerberos5Principal, 943 KLPrincipal *outPrincipal) 944{ 945 if (inKerberos5Principal == NULL) 946 return klParameterErr; 947 return heim_krb5_copy_principal(milcontext, inKerberos5Principal, outPrincipal); 948} 949 950 951KLStatus KLCreatePrincipalFromPrincipal (KLPrincipal inPrincipal, 952 KLPrincipal *outPrincipal) 953{ 954 if (inPrincipal == NULL) 955 return klParameterErr; 956 return heim_krb5_copy_principal(milcontext, inPrincipal, outPrincipal); 957} 958 959 960KLStatus 961KLGetTripletFromPrincipal(KLPrincipal inPrincipal, 962 char **outName, 963 char **outInstance, 964 char **outRealm) 965{ 966 LOG_ENTRY(); 967 968 if (outName) 969 *outName = NULL; 970 if (outInstance) 971 *outInstance = NULL; 972 if (outRealm) 973 *outRealm = NULL; 974 975 if (inPrincipal == NULL) 976 return klParameterErr; 977 978 switch (inPrincipal->name.name_string.len) { 979 case 2: 980 if (outInstance) 981 *outInstance = strdup(inPrincipal->name.name_string.val[1]); 982 case 1: 983 if (outName) 984 *outName = strdup(inPrincipal->name.name_string.val[0]); 985 break; 986 default: 987 return klInvalidOptionErr; 988 } 989 if (outRealm) 990 *outRealm = strdup(inPrincipal->realm); 991 992 return klNoErr; 993} 994 995KLStatus 996KLGetStringFromPrincipal (KLPrincipal inPrincipal, 997 KLKerberosVersion inKerberosVersion, 998 char **outFullPrincipal) 999{ 1000 LOG_ENTRY(); 1001 if (inPrincipal == NULL) 1002 return klParameterErr; 1003 if (CHECK_VERSION(inKerberosVersion)) 1004 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 1005 return heim_krb5_unparse_name(milcontext, inPrincipal, outFullPrincipal); 1006} 1007 1008 1009KLStatus 1010KLGetDisplayStringFromPrincipal (KLPrincipal inPrincipal, 1011 KLKerberosVersion inKerberosVersion, 1012 char **outFullPrincipal) 1013{ 1014 LOG_ENTRY(); 1015 if (inPrincipal == NULL) 1016 return klParameterErr; 1017 if (CHECK_VERSION(inKerberosVersion)) 1018 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 1019 return heim_krb5_unparse_name(milcontext, inPrincipal, outFullPrincipal); 1020} 1021 1022 1023KLStatus 1024KLComparePrincipal (KLPrincipal inFirstPrincipal, 1025 KLPrincipal inSecondPrincipal, 1026 KLBoolean *outAreEquivalent) 1027{ 1028 LOG_ENTRY(); 1029 if (inFirstPrincipal == NULL || inSecondPrincipal == NULL) 1030 return klParameterErr; 1031 *outAreEquivalent = heim_krb5_principal_compare(milcontext, inFirstPrincipal, inSecondPrincipal); 1032 return klNoErr; 1033} 1034 1035 1036KLStatus 1037KLDisposePrincipal (KLPrincipal inPrincipal) 1038{ 1039 LOG_ENTRY(); 1040 if (inPrincipal == NULL) 1041 return klNoErr; 1042 heim_krb5_free_principal(milcontext, inPrincipal); 1043 return klNoErr; 1044} 1045 1046 1047/* KLLoginOptions functions */ 1048 1049KLStatus 1050KLCreateLoginOptions (KLLoginOptions *outOptions) 1051{ 1052 struct KLLoginOptions *opt; 1053 krb5_error_code ret; 1054 1055 *outOptions = NULL; 1056 1057 LOG_ENTRY(); 1058 1059 opt = calloc(1, sizeof(*opt)); 1060 1061 ret = heim_krb5_get_init_creds_opt_alloc(milcontext, &opt->opt); 1062 if (ret) { 1063 free(opt); 1064 return ret; /* XXX */ 1065 } 1066 *outOptions = opt; 1067 return klNoErr; 1068} 1069 1070 1071KLStatus KLLoginOptionsSetTicketLifetime (KLLoginOptions ioOptions, 1072 KLLifetime inTicketLifetime) 1073{ 1074 LOG_ENTRY(); 1075 heim_krb5_get_init_creds_opt_set_tkt_life(ioOptions->opt, inTicketLifetime); 1076 return klNoErr; 1077} 1078 1079 1080KLStatus KLLoginOptionsSetForwardable (KLLoginOptions ioOptions, 1081 KLBoolean inForwardable) 1082{ 1083 LOG_ENTRY(); 1084 heim_krb5_get_init_creds_opt_set_forwardable(ioOptions->opt, inForwardable); 1085 return klNoErr; 1086} 1087 1088 1089KLStatus KLLoginOptionsSetProxiable (KLLoginOptions ioOptions, 1090 KLBoolean inProxiable) 1091{ 1092 LOG_ENTRY(); 1093 heim_krb5_get_init_creds_opt_set_proxiable(ioOptions->opt, inProxiable); 1094 return klNoErr; 1095} 1096 1097 1098KLStatus KLLoginOptionsSetRenewableLifetime (KLLoginOptions ioOptions, 1099 KLLifetime inRenewableLifetime) 1100{ 1101 LOG_ENTRY(); 1102 heim_krb5_get_init_creds_opt_set_renew_life(ioOptions->opt, inRenewableLifetime); 1103 return klNoErr; 1104} 1105 1106 1107KLStatus 1108KLLoginOptionsSetAddressless (KLLoginOptions ioOptions, 1109 KLBoolean inAddressless) 1110{ 1111 LOG_ENTRY(); 1112 return klNoErr; 1113} 1114 1115 1116KLStatus 1117KLLoginOptionsSetTicketStartTime (KLLoginOptions ioOptions, 1118 KLTime inStartTime) 1119{ 1120 LOG_ENTRY(); 1121 return klNoErr; 1122} 1123 1124 1125KLStatus 1126KLLoginOptionsSetServiceName(KLLoginOptions ioOptions, 1127 const char *inServiceName) 1128{ 1129 LOG_ENTRY(); 1130 if (ioOptions->service) 1131 free(ioOptions->service); 1132 ioOptions->service = strdup(inServiceName); 1133 return klNoErr; 1134} 1135 1136 1137KLStatus KLDisposeLoginOptions(KLLoginOptions ioOptions) 1138{ 1139 LOG_ENTRY(); 1140 heim_krb5_get_init_creds_opt_free(milcontext, ioOptions->opt); 1141 if (ioOptions->service) 1142 free(ioOptions->service); 1143 free(ioOptions); 1144 return klNoErr; 1145} 1146 1147 1148KLStatus KLDisposeString (char *inStringToDispose) 1149{ 1150 free(inStringToDispose); 1151 return klNoErr; 1152} 1153 1154KLStatus __KLSetApplicationPrompter(int inPrompter) 1155{ 1156 /* Deprecated */ 1157 return klNoErr; 1158} 1159 1160KLStatus __KLSetHomeDirectoryAccess (KLBoolean inAllowHomeDirectoryAccess) 1161{ 1162 return heim_krb5_set_home_dir_access(NULL, inAllowHomeDirectoryAccess); 1163} 1164 1165 1166KLBoolean __KLAllowHomeDirectoryAccess (void) 1167{ 1168 return 1; 1169} 1170 1171 1172KLStatus __KLSetAutomaticPrompting (KLBoolean inAllowAutomaticPrompting) 1173{ 1174 return klNoErr; 1175} 1176 1177 1178KLBoolean __KLAllowAutomaticPrompting (void) 1179{ 1180 return 0; 1181} 1182 1183 1184KLStatus __KLSetPromptMechanism (int inPromptMechanism) 1185{ 1186 return klNoErr; 1187} 1188 1189 1190int __KLPromptMechanism (void) 1191{ 1192 return klPromptMechanism_None; 1193} 1194 1195 1196KLBoolean __KLAllowRememberPassword (void) 1197{ 1198 return klNoErr; 1199} 1200 1201 1202KLStatus __KLCreatePrincipalFromTriplet (const char *inName, 1203 const char *inInstance, 1204 const char *inRealm, 1205 KLKerberosVersion inKerberosVersion, 1206 KLPrincipal *outPrincipal) 1207{ 1208 LOG_UNIMPLEMENTED(); 1209 if (CHECK_VERSION(inKerberosVersion)) 1210 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 1211 return EINVAL; 1212} 1213 1214 1215KLStatus __KLGetTripletFromPrincipal (KLPrincipal inPrincipal, 1216 KLKerberosVersion inKerberosVersion, 1217 char **outName, 1218 char **outInstance, 1219 char **outRealm) 1220{ 1221 LOG_UNIMPLEMENTED(); 1222 if (CHECK_VERSION(inKerberosVersion)) 1223 return LOG_FAILURE(klInvalidVersionErr, "wrong version"); 1224 return EINVAL; 1225} 1226 1227 1228KLStatus __KLCreatePrincipalFromKerberos5Principal (krb5_principal inPrincipal, 1229 KLPrincipal *outPrincipal) 1230{ 1231 return KLCreatePrincipalFromKerberos5Principal (inPrincipal, outPrincipal); 1232} 1233 1234 1235KLStatus __KLGetKerberos5PrincipalFromPrincipal (KLPrincipal inPrincipal, 1236 krb5_context inContext, 1237 krb5_principal *outKrb5Principal) 1238{ 1239 LOG_UNIMPLEMENTED(); 1240 return EINVAL; 1241} 1242 1243 1244KLBoolean __KLPrincipalIsTicketGrantingService (KLPrincipal inPrincipal) 1245{ 1246 LOG_UNIMPLEMENTED(); 1247 return klNoErr; 1248} 1249 1250 1251KLStatus __KLGetKeychainPasswordForPrincipal (KLPrincipal inPrincipal, 1252 char **outPassword) 1253{ 1254 LOG_UNIMPLEMENTED(); 1255 return EINVAL; 1256} 1257 1258 1259 1260KLStatus __KLPrincipalSetKeychainPassword (KLPrincipal inPrincipal, 1261 const char *inPassword) 1262{ 1263 return klNoErr; 1264} 1265 1266 1267KLStatus __KLRemoveKeychainPasswordForPrincipal (KLPrincipal inPrincipal) 1268{ 1269 return klNoErr; 1270} 1271 1272krb5_get_init_creds_opt * 1273__KLLoginOptionsGetKerberos5Options (KLLoginOptions ioOptions) 1274{ 1275 return NULL; 1276} 1277 1278KLTime __KLLoginOptionsGetStartTime (KLLoginOptions ioOptions) 1279{ 1280 return klNoErr; 1281} 1282 1283char *__KLLoginOptionsGetServiceName (KLLoginOptions ioOptions) 1284{ 1285 return NULL; 1286} 1287