1 /* ccapi/server/ccs_cache_collection.c */ 2 /* 3 * Copyright 2006, 2007 Massachusetts Institute of Technology. 4 * All Rights Reserved. 5 * 6 * Export of this software from the United States of America may 7 * require a specific license from the United States Government. 8 * It is the responsibility of any person or organization contemplating 9 * export to obtain such a license before exporting. 10 * 11 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 12 * distribute this software and its documentation for any purpose and 13 * without fee is hereby granted, provided that the above copyright 14 * notice appear in all copies and that both that copyright notice and 15 * this permission notice appear in supporting documentation, and that 16 * the name of M.I.T. not be used in advertising or publicity pertaining 17 * to distribution of the software without specific, written prior 18 * permission. Furthermore if you modify this software you must label 19 * your software as modified software and not distribute it in such a 20 * fashion that it might be confused with the original M.I.T. software. 21 * M.I.T. makes no representations about the suitability of 22 * this software for any purpose. It is provided "as is" without express 23 * or implied warranty. 24 */ 25 26 #include "k5-platform.h" /* pull in asprintf decl/defn */ 27 #include "ccs_common.h" 28 #include "ccs_os_notify.h" 29 30 struct ccs_cache_collection_d { 31 cc_time_t last_changed_time; 32 cc_uint64 next_unique_name; 33 cci_identifier_t identifier; 34 ccs_lock_state_t lock_state; 35 ccs_ccache_list_t ccaches; 36 ccs_callback_array_t change_callbacks; 37 }; 38 39 struct ccs_cache_collection_d ccs_cache_collection_initializer = { 0, 0, NULL, NULL, NULL, NULL }; 40 41 /* ------------------------------------------------------------------------ */ 42 43 cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection) 44 { 45 cc_int32 err = ccNoError; 46 ccs_cache_collection_t cache_collection = NULL; 47 48 if (!out_cache_collection) { err = cci_check_error (ccErrBadParam); } 49 50 if (!err) { 51 cache_collection = malloc (sizeof (*cache_collection)); 52 if (cache_collection) { 53 *cache_collection = ccs_cache_collection_initializer; 54 } else { 55 err = cci_check_error (ccErrNoMem); 56 } 57 } 58 59 if (!err) { 60 err = ccs_server_new_identifier (&cache_collection->identifier); 61 } 62 63 if (!err) { 64 err = ccs_lock_state_new (&cache_collection->lock_state, 65 ccErrInvalidContext, 66 ccErrContextLocked, 67 ccErrContextUnlocked); 68 } 69 70 if (!err) { 71 err = ccs_ccache_list_new (&cache_collection->ccaches); 72 } 73 74 if (!err) { 75 err = ccs_callback_array_new (&cache_collection->change_callbacks); 76 } 77 78 if (!err) { 79 err = ccs_cache_collection_changed (cache_collection); 80 } 81 82 if (!err) { 83 *out_cache_collection = cache_collection; 84 cache_collection = NULL; 85 } 86 87 ccs_cache_collection_release (cache_collection); 88 89 return cci_check_error (err); 90 } 91 92 /* ------------------------------------------------------------------------ */ 93 94 cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection) 95 { 96 cc_int32 err = ccNoError; 97 98 if (!err && io_cache_collection) { 99 cci_identifier_release (io_cache_collection->identifier); 100 ccs_lock_state_release (io_cache_collection->lock_state); 101 ccs_ccache_list_release (io_cache_collection->ccaches); 102 ccs_callback_array_release (io_cache_collection->change_callbacks); 103 free (io_cache_collection); 104 } 105 106 return cci_check_error (err); 107 } 108 109 /* ------------------------------------------------------------------------ */ 110 111 cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection, 112 cci_identifier_t in_identifier, 113 cc_uint32 *out_equal) 114 { 115 cc_int32 err = ccNoError; 116 117 if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } 118 if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } 119 if (!out_equal ) { err = cci_check_error (ccErrBadParam); } 120 121 if (!err) { 122 err = cci_identifier_compare (in_cache_collection->identifier, 123 in_identifier, 124 out_equal); 125 } 126 127 return cci_check_error (err); 128 } 129 130 #ifdef TARGET_OS_MAC 131 #pragma mark - 132 #endif 133 134 /* ------------------------------------------------------------------------ */ 135 136 cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection) 137 { 138 cc_int32 err = ccNoError; 139 k5_ipc_stream reply_data = NULL; 140 141 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 142 143 if (!err) { 144 cc_time_t now = time (NULL); 145 146 if (io_cache_collection->last_changed_time < now) { 147 io_cache_collection->last_changed_time = now; 148 } else { 149 io_cache_collection->last_changed_time++; 150 } 151 } 152 153 if (!err) { 154 err = krb5int_ipc_stream_new (&reply_data); 155 } 156 157 if (!err) { 158 err = krb5int_ipc_stream_write_time (reply_data, io_cache_collection->last_changed_time); 159 } 160 161 if (!err) { 162 /* Loop over callbacks sending messages to them */ 163 cc_uint64 i; 164 cc_uint64 count = ccs_callback_array_count (io_cache_collection->change_callbacks); 165 166 for (i = 0; !err && i < count; i++) { 167 ccs_callback_t callback = ccs_callback_array_object_at_index (io_cache_collection->change_callbacks, i); 168 169 err = ccs_callback_reply_to_client (callback, reply_data); 170 171 if (!err) { 172 cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); 173 err = ccs_callback_array_remove (io_cache_collection->change_callbacks, i); 174 break; 175 } 176 } 177 } 178 179 if (!err) { 180 err = ccs_os_notify_cache_collection_changed (io_cache_collection); 181 } 182 183 krb5int_ipc_stream_release (reply_data); 184 185 return cci_check_error (err); 186 } 187 188 /* ------------------------------------------------------------------------ */ 189 190 static cc_int32 ccs_cache_collection_invalidate_change_callback (ccs_callback_owner_t io_cache_collection, 191 ccs_callback_t in_callback) 192 { 193 cc_int32 err = ccNoError; 194 195 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 196 if (!in_callback ) { err = cci_check_error (ccErrBadParam); } 197 198 if (!err) { 199 /* Remove callback */ 200 ccs_cache_collection_t cache_collection = (ccs_cache_collection_t) io_cache_collection; 201 cc_uint64 i; 202 cc_uint64 count = ccs_callback_array_count (cache_collection->change_callbacks); 203 204 for (i = 0; !err && i < count; i++) { 205 ccs_callback_t callback = ccs_callback_array_object_at_index (cache_collection->change_callbacks, i); 206 207 if (callback == in_callback) { 208 cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); 209 err = ccs_callback_array_remove (cache_collection->change_callbacks, i); 210 break; 211 } 212 } 213 } 214 215 return cci_check_error (err); 216 } 217 218 #ifdef TARGET_OS_MAC 219 #pragma mark - 220 #endif 221 222 /* ------------------------------------------------------------------------ */ 223 224 static cc_int32 ccs_cache_collection_find_ccache_by_name (ccs_cache_collection_t in_cache_collection, 225 const char *in_name, 226 ccs_ccache_t *out_ccache) 227 { 228 cc_int32 err = ccNoError; 229 ccs_ccache_list_iterator_t iterator = NULL; 230 231 if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } 232 if (!in_name ) { err = cci_check_error (ccErrBadParam); } 233 if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } 234 235 if (!err) { 236 err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, 237 CCS_PIPE_NULL, 238 &iterator); 239 } 240 241 while (!err) { 242 ccs_ccache_t ccache = NULL; 243 244 err = ccs_ccache_list_iterator_next (iterator, &ccache); 245 246 if (!err) { 247 cc_uint32 equal = 0; 248 249 err = ccs_ccache_compare_name (ccache, in_name, &equal); 250 251 if (!err && equal) { 252 *out_ccache = ccache; 253 break; 254 } 255 } 256 } 257 if (err == ccIteratorEnd) { err = ccErrCCacheNotFound; } 258 259 if (iterator) { ccs_ccache_list_iterator_release (iterator); } 260 261 return cci_check_error (err); 262 } 263 264 #ifdef TARGET_OS_MAC 265 #pragma mark - 266 #endif 267 268 /* ------------------------------------------------------------------------ */ 269 270 cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection, 271 cci_identifier_t in_identifier, 272 ccs_ccache_t *out_ccache) 273 { 274 cc_int32 err = ccNoError; 275 276 if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } 277 if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } 278 if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } 279 280 if (!err) { 281 err = ccs_ccache_list_find (in_cache_collection->ccaches, 282 in_identifier, out_ccache); 283 } 284 285 return cci_check_error (err); 286 } 287 288 /* ------------------------------------------------------------------------ */ 289 290 cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection, 291 cci_identifier_t in_source_identifier, 292 ccs_ccache_t io_destination_ccache) 293 { 294 cc_int32 err = ccNoError; 295 ccs_ccache_t source_ccache = NULL; 296 297 if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } 298 if (!in_source_identifier ) { err = cci_check_error (ccErrBadParam); } 299 if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } 300 301 if (!err) { 302 err = ccs_cache_collection_find_ccache (io_cache_collection, 303 in_source_identifier, 304 &source_ccache); 305 } 306 307 if (!err) { 308 err = ccs_ccache_swap_contents (source_ccache, 309 io_destination_ccache, 310 io_cache_collection); 311 } 312 313 if (!err) { 314 err = ccs_cache_collection_destroy_ccache (io_cache_collection, 315 in_source_identifier); 316 } 317 318 return cci_check_error (err); 319 } 320 321 /* ------------------------------------------------------------------------ */ 322 323 cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t io_cache_collection, 324 cci_identifier_t in_identifier) 325 { 326 cc_int32 err = ccNoError; 327 ccs_ccache_t ccache = NULL; 328 329 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 330 if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } 331 332 if (!err) { 333 err = ccs_cache_collection_find_ccache (io_cache_collection, 334 in_identifier, 335 &ccache); 336 } 337 338 if (!err) { 339 /* Notify before deletion because after deletion the ccache 340 * will no longer exist (and won't know about its clients) */ 341 err = ccs_ccache_changed (ccache, io_cache_collection); 342 } 343 344 if (!err) { 345 err = ccs_ccache_list_remove (io_cache_collection->ccaches, 346 in_identifier); 347 } 348 349 return cci_check_error (err); 350 } 351 352 #ifdef TARGET_OS_MAC 353 #pragma mark - 354 #endif 355 356 /* ------------------------------------------------------------------------ */ 357 358 cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection, 359 cci_identifier_t in_identifier, 360 ccs_ccache_iterator_t *out_ccache_iterator) 361 { 362 cc_int32 err = ccNoError; 363 364 if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } 365 if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } 366 if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); } 367 368 if (!err) { 369 err = ccs_ccache_list_find_iterator (in_cache_collection->ccaches, 370 in_identifier, 371 out_ccache_iterator); 372 } 373 374 return cci_check_error (err); 375 } 376 377 #ifdef TARGET_OS_MAC 378 #pragma mark - 379 #endif 380 381 /* ------------------------------------------------------------------------ */ 382 383 cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection, 384 cci_identifier_t in_identifier, 385 ccs_ccache_t *out_ccache, 386 ccs_credentials_iterator_t *out_credentials_iterator) 387 { 388 cc_int32 err = ccNoError; 389 ccs_ccache_list_iterator_t iterator = NULL; 390 391 if (!in_cache_collection ) { err = cci_check_error (ccErrBadParam); } 392 if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } 393 if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } 394 395 if (!err) { 396 err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, 397 CCS_PIPE_NULL, 398 &iterator); 399 } 400 401 while (!err) { 402 ccs_ccache_t ccache = NULL; 403 404 err = ccs_ccache_list_iterator_next (iterator, &ccache); 405 406 if (!err) { 407 cc_int32 terr = ccs_ccache_find_credentials_iterator (ccache, 408 in_identifier, 409 out_credentials_iterator); 410 if (!terr) { 411 *out_ccache = ccache; 412 break; 413 } 414 } 415 } 416 if (err == ccIteratorEnd) { err = cci_check_error (ccErrInvalidCredentialsIterator); } 417 418 if (iterator) { ccs_ccache_list_iterator_release (iterator); } 419 420 return cci_check_error (err); 421 } 422 423 #ifdef TARGET_OS_MAC 424 #pragma mark - 425 #endif 426 427 /* ------------------------------------------------------------------------ */ 428 429 static cc_int32 ccs_cache_collection_get_next_unique_ccache_name (ccs_cache_collection_t io_cache_collection, 430 char **out_name) 431 { 432 cc_int32 err = ccNoError; 433 cc_uint64 count = 0; 434 char *name = NULL; 435 436 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 437 if (!out_name ) { err = cci_check_error (ccErrBadParam); } 438 439 if (!err) { 440 err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count); 441 } 442 443 if (!err) { 444 if (count > 0) { 445 while (!err) { 446 int ret = asprintf (&name, "%lld", io_cache_collection->next_unique_name++); 447 if (ret < 0 || !name) { err = cci_check_error (ccErrNoMem); } 448 449 if (!err) { 450 ccs_ccache_t ccache = NULL; /* temporary to hold ccache pointer */ 451 err = ccs_cache_collection_find_ccache_by_name (io_cache_collection, 452 name, &ccache); 453 } 454 455 if (err == ccErrCCacheNotFound) { 456 err = ccNoError; 457 break; /* found a unique one */ 458 } 459 } 460 } else { 461 name = strdup (k_cci_context_initial_ccache_name); 462 if (!name) { err = cci_check_error (ccErrNoMem); } 463 } 464 } 465 466 if (!err) { 467 *out_name = name; 468 name = NULL; 469 } 470 471 free (name); 472 473 return cci_check_error (err); 474 } 475 476 /* ------------------------------------------------------------------------ */ 477 478 static cc_int32 ccs_cache_collection_get_default_ccache (ccs_cache_collection_t in_cache_collection, 479 ccs_ccache_t *out_ccache) 480 { 481 cc_int32 err = ccNoError; 482 cc_uint64 count = 0; 483 484 if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } 485 if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } 486 487 if (!err) { 488 err = ccs_ccache_list_count (in_cache_collection->ccaches, &count); 489 } 490 491 if (!err) { 492 if (count > 0) { 493 /* First ccache is the default */ 494 ccs_ccache_list_iterator_t iterator = NULL; 495 496 err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, 497 CCS_PIPE_NULL, 498 &iterator); 499 500 if (!err) { 501 err = ccs_ccache_list_iterator_next (iterator, out_ccache); 502 } 503 504 ccs_ccache_list_iterator_release (iterator); 505 506 } else { 507 err = cci_check_error (ccErrCCacheNotFound); 508 } 509 } 510 511 return cci_check_error (err); 512 } 513 514 /* ------------------------------------------------------------------------ */ 515 516 cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t io_cache_collection, 517 cci_identifier_t in_identifier) 518 { 519 cc_int32 err = ccNoError; 520 ccs_ccache_t old_default = NULL; 521 ccs_ccache_t new_default = NULL; 522 cc_uint32 equal = 0; 523 524 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 525 if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } 526 527 if (!err) { 528 err = ccs_cache_collection_get_default_ccache (io_cache_collection, 529 &old_default); 530 } 531 532 if (!err) { 533 err = ccs_ccache_compare_identifier (old_default, in_identifier, &equal); 534 } 535 536 537 if (!err && !equal) { 538 err = ccs_ccache_list_push_front (io_cache_collection->ccaches, 539 in_identifier); 540 541 if (!err) { 542 err = ccs_ccache_notify_default_state_changed (old_default, 543 io_cache_collection, 544 0 /* no longer default */); 545 } 546 547 if (!err) { 548 err = ccs_cache_collection_get_default_ccache (io_cache_collection, 549 &new_default); 550 } 551 552 if (!err) { 553 err = ccs_ccache_notify_default_state_changed (new_default, 554 io_cache_collection, 555 1 /* now default */); 556 } 557 558 if (!err) { 559 err = ccs_cache_collection_changed (io_cache_collection); 560 } 561 } 562 563 return cci_check_error (err); 564 } 565 566 #ifdef TARGET_OS_MAC 567 #pragma mark - 568 #pragma mark -- IPC Messages -- 569 #endif 570 571 /* ------------------------------------------------------------------------ */ 572 573 static cc_int32 ccs_cache_collection_sync (ccs_cache_collection_t io_cache_collection, 574 k5_ipc_stream in_request_data, 575 k5_ipc_stream io_reply_data) 576 { 577 cc_int32 err = ccNoError; 578 579 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 580 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 581 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 582 583 if (!err) { 584 err = cci_identifier_write (io_cache_collection->identifier, io_reply_data); 585 } 586 587 return cci_check_error (err); 588 } 589 590 /* ------------------------------------------------------------------------ */ 591 592 static cc_int32 ccs_cache_collection_get_change_time (ccs_cache_collection_t io_cache_collection, 593 k5_ipc_stream in_request_data, 594 k5_ipc_stream io_reply_data) 595 { 596 cc_int32 err = ccNoError; 597 598 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 599 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 600 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 601 602 if (!err) { 603 err = krb5int_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time); 604 } 605 606 return cci_check_error (err); 607 } 608 609 /* ------------------------------------------------------------------------ */ 610 611 static cc_int32 ccs_cache_collection_wait_for_change (ccs_pipe_t in_client_pipe, 612 ccs_pipe_t in_reply_pipe, 613 ccs_cache_collection_t io_cache_collection, 614 k5_ipc_stream in_request_data, 615 k5_ipc_stream io_reply_data, 616 cc_uint32 *out_will_block) 617 { 618 cc_int32 err = ccNoError; 619 cc_time_t last_wait_for_change_time = 0; 620 cc_uint32 will_block = 0; 621 622 if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } 623 if (!ccs_pipe_valid (in_reply_pipe )) { err = cci_check_error (ccErrBadParam); } 624 if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } 625 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 626 if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } 627 628 if (!err) { 629 err = krb5int_ipc_stream_read_time (in_request_data, &last_wait_for_change_time); 630 } 631 632 if (!err) { 633 if (last_wait_for_change_time < io_cache_collection->last_changed_time) { 634 err = krb5int_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time); 635 636 } else { 637 ccs_callback_t callback = NULL; 638 639 err = ccs_callback_new (&callback, 640 ccErrInvalidContext, 641 in_client_pipe, 642 in_reply_pipe, 643 (ccs_callback_owner_t) io_cache_collection, 644 ccs_cache_collection_invalidate_change_callback); 645 646 if (!err) { 647 err = ccs_callback_array_insert (io_cache_collection->change_callbacks, callback, 648 ccs_callback_array_count (io_cache_collection->change_callbacks)); 649 if (!err) { callback = NULL; /* take ownership */ } 650 651 will_block = 1; 652 } 653 654 ccs_callback_release (callback); 655 } 656 } 657 658 if (!err) { 659 *out_will_block = will_block; 660 } 661 662 return cci_check_error (err); 663 } 664 665 /* ------------------------------------------------------------------------ */ 666 667 static cc_int32 ccs_cache_collection_get_default_ccache_name (ccs_cache_collection_t io_cache_collection, 668 k5_ipc_stream in_request_data, 669 k5_ipc_stream io_reply_data) 670 { 671 cc_int32 err = ccNoError; 672 cc_uint64 count = 0; 673 674 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 675 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 676 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 677 678 if (!err) { 679 err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count); 680 } 681 682 if (!err) { 683 if (count > 0) { 684 ccs_ccache_t ccache = NULL; 685 686 err = ccs_cache_collection_get_default_ccache (io_cache_collection, &ccache); 687 688 if (!err) { 689 err = ccs_ccache_write_name (ccache, io_reply_data); 690 } 691 } else { 692 err = krb5int_ipc_stream_write_string (io_reply_data, 693 k_cci_context_initial_ccache_name); 694 } 695 } 696 697 return cci_check_error (err); 698 } 699 700 /* ------------------------------------------------------------------------ */ 701 702 static cc_int32 ccs_cache_collection_open_ccache (ccs_cache_collection_t io_cache_collection, 703 k5_ipc_stream in_request_data, 704 k5_ipc_stream io_reply_data) 705 { 706 cc_int32 err = ccNoError; 707 char *name = NULL; 708 ccs_ccache_t ccache = NULL; 709 710 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 711 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 712 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 713 714 if (!err) { 715 err = krb5int_ipc_stream_read_string (in_request_data, &name); 716 } 717 718 if (!err) { 719 err = ccs_cache_collection_find_ccache_by_name (io_cache_collection, 720 name, &ccache); 721 } 722 723 if (!err) { 724 err = ccs_ccache_write (ccache, io_reply_data); 725 } 726 727 krb5int_ipc_stream_free_string (name); 728 729 return cci_check_error (err); 730 } 731 732 /* ------------------------------------------------------------------------ */ 733 734 static cc_int32 ccs_cache_collection_open_default_ccache (ccs_cache_collection_t io_cache_collection, 735 k5_ipc_stream in_request_data, 736 k5_ipc_stream io_reply_data) 737 { 738 cc_int32 err = ccNoError; 739 ccs_ccache_t ccache = NULL; 740 741 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 742 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 743 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 744 745 if (!err) { 746 err = ccs_cache_collection_get_default_ccache (io_cache_collection, 747 &ccache); 748 } 749 750 if (!err) { 751 err = ccs_ccache_write (ccache, io_reply_data); 752 } 753 754 return cci_check_error (err); 755 } 756 757 /* ------------------------------------------------------------------------ */ 758 759 static cc_int32 ccs_cache_collection_create_ccache (ccs_cache_collection_t io_cache_collection, 760 k5_ipc_stream in_request_data, 761 k5_ipc_stream io_reply_data) 762 { 763 cc_int32 err = ccNoError; 764 char *name = NULL; 765 cc_uint32 cred_vers; 766 char *principal = NULL; 767 ccs_ccache_t ccache = NULL; 768 769 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 770 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 771 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 772 773 if (!err) { 774 err = krb5int_ipc_stream_read_string (in_request_data, &name); 775 } 776 777 if (!err) { 778 err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); 779 } 780 781 if (!err) { 782 err = krb5int_ipc_stream_read_string (in_request_data, &principal); 783 } 784 785 if (!err) { 786 cc_int32 terr = ccs_cache_collection_find_ccache_by_name (io_cache_collection, 787 name, 788 &ccache); 789 790 if (!terr) { 791 err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal); 792 793 } else { 794 err = ccs_ccache_new (&ccache, cred_vers, name, principal, 795 io_cache_collection->ccaches); 796 } 797 } 798 799 if (!err) { 800 err = ccs_ccache_write (ccache, io_reply_data); 801 } 802 803 if (!err) { 804 err = ccs_cache_collection_changed (io_cache_collection); 805 } 806 807 krb5int_ipc_stream_free_string (name); 808 krb5int_ipc_stream_free_string (principal); 809 810 return cci_check_error (err); 811 } 812 813 /* ------------------------------------------------------------------------ */ 814 815 static cc_int32 ccs_cache_collection_create_default_ccache (ccs_cache_collection_t io_cache_collection, 816 k5_ipc_stream in_request_data, 817 k5_ipc_stream io_reply_data) 818 { 819 cc_int32 err = ccNoError; 820 cc_uint32 cred_vers; 821 char *principal = NULL; 822 ccs_ccache_t ccache = NULL; 823 824 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 825 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 826 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 827 828 if (!err) { 829 err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); 830 } 831 832 if (!err) { 833 err = krb5int_ipc_stream_read_string (in_request_data, &principal); 834 } 835 836 if (!err) { 837 err = ccs_cache_collection_get_default_ccache (io_cache_collection, 838 &ccache); 839 840 if (!err) { 841 err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal); 842 843 } else if (err == ccErrCCacheNotFound) { 844 char *name = NULL; 845 846 err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, 847 &name); 848 849 if (!err) { 850 err = ccs_ccache_new (&ccache, cred_vers, name, principal, 851 io_cache_collection->ccaches); 852 } 853 854 free (name); 855 } 856 } 857 858 if (!err) { 859 err = ccs_ccache_write (ccache, io_reply_data); 860 } 861 862 if (!err) { 863 err = ccs_cache_collection_changed (io_cache_collection); 864 } 865 866 krb5int_ipc_stream_free_string (principal); 867 868 return cci_check_error (err); 869 } 870 871 /* ------------------------------------------------------------------------ */ 872 873 static cc_int32 ccs_cache_collection_create_new_ccache (ccs_cache_collection_t io_cache_collection, 874 k5_ipc_stream in_request_data, 875 k5_ipc_stream io_reply_data) 876 { 877 cc_int32 err = ccNoError; 878 cc_uint32 cred_vers; 879 char *principal = NULL; 880 char *name = NULL; 881 ccs_ccache_t ccache = NULL; 882 883 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 884 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 885 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 886 887 if (!err) { 888 err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); 889 } 890 891 if (!err) { 892 err = krb5int_ipc_stream_read_string (in_request_data, &principal); 893 } 894 895 if (!err) { 896 err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, 897 &name); 898 } 899 900 if (!err) { 901 err = ccs_ccache_new (&ccache, cred_vers, name, principal, 902 io_cache_collection->ccaches); 903 } 904 905 if (!err) { 906 err = ccs_ccache_write (ccache, io_reply_data); 907 } 908 909 if (!err) { 910 err = ccs_cache_collection_changed (io_cache_collection); 911 } 912 913 free (name); 914 krb5int_ipc_stream_free_string (principal); 915 916 return cci_check_error (err); 917 } 918 919 /* ------------------------------------------------------------------------ */ 920 921 static cc_int32 ccs_cache_collection_new_ccache_iterator (ccs_cache_collection_t io_cache_collection, 922 ccs_pipe_t in_client_pipe, 923 k5_ipc_stream in_request_data, 924 k5_ipc_stream io_reply_data) 925 { 926 cc_int32 err = ccNoError; 927 ccs_ccache_iterator_t ccache_iterator = NULL; 928 929 if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } 930 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 931 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 932 933 if (!err) { 934 err = ccs_ccache_list_new_iterator (io_cache_collection->ccaches, 935 in_client_pipe, 936 &ccache_iterator); 937 } 938 939 if (!err) { 940 err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data); 941 } 942 943 return cci_check_error (err); 944 } 945 946 /* ------------------------------------------------------------------------ */ 947 948 static cc_int32 ccs_cache_collection_lock (ccs_pipe_t in_client_pipe, 949 ccs_pipe_t in_reply_pipe, 950 ccs_cache_collection_t io_cache_collection, 951 k5_ipc_stream in_request_data, 952 cc_uint32 *out_will_block, 953 k5_ipc_stream io_reply_data) 954 { 955 cc_int32 err = ccNoError; 956 cc_uint32 lock_type; 957 cc_uint32 block; 958 959 if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } 960 if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } 961 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 962 if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } 963 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 964 965 if (!err) { 966 err = krb5int_ipc_stream_read_uint32 (in_request_data, &lock_type); 967 } 968 969 if (!err) { 970 err = krb5int_ipc_stream_read_uint32 (in_request_data, &block); 971 } 972 973 if (!err) { 974 err = ccs_lock_state_add (io_cache_collection->lock_state, 975 in_client_pipe, in_reply_pipe, 976 lock_type, block, out_will_block); 977 } 978 979 return cci_check_error (err); 980 } 981 982 /* ------------------------------------------------------------------------ */ 983 984 static cc_int32 ccs_cache_collection_unlock (ccs_pipe_t in_client_pipe, 985 ccs_cache_collection_t io_cache_collection, 986 k5_ipc_stream in_request_data, 987 k5_ipc_stream io_reply_data) 988 { 989 cc_int32 err = ccNoError; 990 991 if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } 992 if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } 993 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 994 if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } 995 996 if (!err) { 997 err = ccs_lock_state_remove (io_cache_collection->lock_state, 998 in_client_pipe); 999 } 1000 1001 return cci_check_error (err); 1002 } 1003 1004 #ifdef TARGET_OS_MAC 1005 #pragma mark - 1006 #endif 1007 1008 /* ------------------------------------------------------------------------ */ 1009 1010 cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe, 1011 ccs_pipe_t in_reply_pipe, 1012 ccs_cache_collection_t io_cache_collection, 1013 enum cci_msg_id_t in_request_name, 1014 k5_ipc_stream in_request_data, 1015 cc_uint32 *out_will_block, 1016 k5_ipc_stream *out_reply_data) 1017 { 1018 cc_int32 err = ccNoError; 1019 cc_uint32 will_block = 0; 1020 k5_ipc_stream reply_data = NULL; 1021 1022 if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } 1023 if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } 1024 if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } 1025 if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } 1026 if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } 1027 if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } 1028 1029 if (!err) { 1030 err = krb5int_ipc_stream_new (&reply_data); 1031 } 1032 1033 if (!err) { 1034 if (in_request_name == cci_context_unused_release_msg_id) { 1035 /* Old release message. Do nothing. */ 1036 1037 } else if (in_request_name == cci_context_sync_msg_id) { 1038 err = ccs_cache_collection_sync (io_cache_collection, 1039 in_request_data, reply_data); 1040 1041 } else if (in_request_name == cci_context_get_change_time_msg_id) { 1042 err = ccs_cache_collection_get_change_time (io_cache_collection, 1043 in_request_data, reply_data); 1044 1045 } else if (in_request_name == cci_context_wait_for_change_msg_id) { 1046 err = ccs_cache_collection_wait_for_change (in_client_pipe, in_reply_pipe, 1047 io_cache_collection, 1048 in_request_data, reply_data, 1049 &will_block); 1050 1051 } else if (in_request_name == cci_context_get_default_ccache_name_msg_id) { 1052 err = ccs_cache_collection_get_default_ccache_name (io_cache_collection, 1053 in_request_data, reply_data); 1054 1055 } else if (in_request_name == cci_context_open_ccache_msg_id) { 1056 err = ccs_cache_collection_open_ccache (io_cache_collection, 1057 in_request_data, reply_data); 1058 1059 } else if (in_request_name == cci_context_open_default_ccache_msg_id) { 1060 err = ccs_cache_collection_open_default_ccache (io_cache_collection, 1061 in_request_data, reply_data); 1062 1063 } else if (in_request_name == cci_context_create_ccache_msg_id) { 1064 err = ccs_cache_collection_create_ccache (io_cache_collection, 1065 in_request_data, reply_data); 1066 1067 } else if (in_request_name == cci_context_create_default_ccache_msg_id) { 1068 err = ccs_cache_collection_create_default_ccache (io_cache_collection, 1069 in_request_data, reply_data); 1070 1071 } else if (in_request_name == cci_context_create_new_ccache_msg_id) { 1072 err = ccs_cache_collection_create_new_ccache (io_cache_collection, 1073 in_request_data, reply_data); 1074 1075 } else if (in_request_name == cci_context_new_ccache_iterator_msg_id) { 1076 err = ccs_cache_collection_new_ccache_iterator (io_cache_collection, 1077 in_client_pipe, 1078 in_request_data, 1079 reply_data); 1080 1081 } else if (in_request_name == cci_context_lock_msg_id) { 1082 err = ccs_cache_collection_lock (in_client_pipe, in_reply_pipe, 1083 io_cache_collection, 1084 in_request_data, 1085 &will_block, reply_data); 1086 1087 } else if (in_request_name == cci_context_unlock_msg_id) { 1088 err = ccs_cache_collection_unlock (in_client_pipe, io_cache_collection, 1089 in_request_data, reply_data); 1090 1091 } else { 1092 err = ccErrBadInternalMessage; 1093 } 1094 } 1095 1096 if (!err) { 1097 *out_will_block = will_block; 1098 if (!will_block) { 1099 *out_reply_data = reply_data; 1100 reply_data = NULL; /* take ownership */ 1101 } else { 1102 *out_reply_data = NULL; 1103 } 1104 } 1105 1106 krb5int_ipc_stream_release (reply_data); 1107 1108 return cci_check_error (err); 1109 } 1110