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
ccs_cache_collection_new(ccs_cache_collection_t * out_cache_collection)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
ccs_cache_collection_release(ccs_cache_collection_t io_cache_collection)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
ccs_cache_collection_compare_identifier(ccs_cache_collection_t in_cache_collection,cci_identifier_t in_identifier,cc_uint32 * out_equal)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
ccs_cache_collection_changed(ccs_cache_collection_t io_cache_collection)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
ccs_cache_collection_invalidate_change_callback(ccs_callback_owner_t io_cache_collection,ccs_callback_t in_callback)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
ccs_cache_collection_find_ccache_by_name(ccs_cache_collection_t in_cache_collection,const char * in_name,ccs_ccache_t * out_ccache)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
ccs_cache_collection_find_ccache(ccs_cache_collection_t in_cache_collection,cci_identifier_t in_identifier,ccs_ccache_t * out_ccache)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
ccs_ccache_collection_move_ccache(ccs_cache_collection_t io_cache_collection,cci_identifier_t in_source_identifier,ccs_ccache_t io_destination_ccache)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
ccs_cache_collection_destroy_ccache(ccs_cache_collection_t io_cache_collection,cci_identifier_t in_identifier)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
ccs_cache_collection_find_ccache_iterator(ccs_cache_collection_t in_cache_collection,cci_identifier_t in_identifier,ccs_ccache_iterator_t * out_ccache_iterator)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
ccs_cache_collection_find_credentials_iterator(ccs_cache_collection_t in_cache_collection,cci_identifier_t in_identifier,ccs_ccache_t * out_ccache,ccs_credentials_iterator_t * out_credentials_iterator)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
ccs_cache_collection_get_next_unique_ccache_name(ccs_cache_collection_t io_cache_collection,char ** out_name)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
ccs_cache_collection_get_default_ccache(ccs_cache_collection_t in_cache_collection,ccs_ccache_t * out_ccache)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
ccs_cache_collection_set_default_ccache(ccs_cache_collection_t io_cache_collection,cci_identifier_t in_identifier)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
ccs_cache_collection_sync(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_get_change_time(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_wait_for_change(ccs_pipe_t in_client_pipe,ccs_pipe_t in_reply_pipe,ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data,cc_uint32 * out_will_block)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
ccs_cache_collection_get_default_ccache_name(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_open_ccache(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_open_default_ccache(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_create_ccache(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_create_default_ccache(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_create_new_ccache(ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_new_ccache_iterator(ccs_cache_collection_t io_cache_collection,ccs_pipe_t in_client_pipe,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_lock(ccs_pipe_t in_client_pipe,ccs_pipe_t in_reply_pipe,ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,cc_uint32 * out_will_block,k5_ipc_stream io_reply_data)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
ccs_cache_collection_unlock(ccs_pipe_t in_client_pipe,ccs_cache_collection_t io_cache_collection,k5_ipc_stream in_request_data,k5_ipc_stream io_reply_data)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
ccs_cache_collection_handle_message(ccs_pipe_t in_client_pipe,ccs_pipe_t in_reply_pipe,ccs_cache_collection_t io_cache_collection,enum cci_msg_id_t in_request_name,k5_ipc_stream in_request_data,cc_uint32 * out_will_block,k5_ipc_stream * out_reply_data)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