xref: /freebsd/crypto/krb5/src/ccapi/lib/ccapi_v2.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* ccapi/lib/ccapi_v2.c */
2 /*
3  * Copyright 2006 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 "cci_common.h"
27 #include "ccapi_string.h"
28 #include "ccapi_context.h"
29 #include "ccapi_ccache.h"
30 #include "ccapi_ccache_iterator.h"
31 #include "ccapi_credentials.h"
32 #include "ccapi_credentials_iterator.h"
33 #include <CredentialsCache2.h>
34 
35 infoNC infoNC_initializer = { NULL, NULL, CC_CRED_UNKNOWN };
36 
37 /* ------------------------------------------------------------------------ */
38 
cci_remap_version(cc_int32 in_v2_version,cc_uint32 * out_v3_version)39 static cc_int32 cci_remap_version (cc_int32   in_v2_version,
40                                    cc_uint32 *out_v3_version)
41 {
42     cc_result err = ccNoError;
43 
44     if (!out_v3_version) { err = cci_check_error (ccErrBadParam); }
45 
46     if (!err) {
47         if (in_v2_version == CC_CRED_V5) {
48             *out_v3_version = cc_credentials_v5;
49 
50         } else {
51             err = ccErrBadCredentialsVersion;
52         }
53     }
54 
55     return cci_check_error (err);
56 }
57 
58 /* ------------------------------------------------------------------------ */
59 
_cci_remap_error(cc_result in_error,const char * in_function,const char * in_file,int in_line)60 static cc_result _cci_remap_error (cc_result   in_error,
61                                    const char *in_function,
62                                    const char *in_file,
63                                    int         in_line)
64 {
65     _cci_check_error (in_error, in_function, in_file, in_line);
66 
67     if (in_error >= CC_NOERROR && in_error <= CC_ERR_CRED_VERSION) {
68         return in_error;
69     }
70 
71     switch (in_error) {
72         case ccNoError:
73             return CC_NOERROR;
74 
75         case ccIteratorEnd:
76             return CC_END;
77 
78         case ccErrBadParam:
79         case ccErrContextNotFound:
80         case ccErrInvalidContext:
81         case ccErrInvalidCredentials:
82         case ccErrInvalidCCacheIterator:
83         case ccErrInvalidCredentialsIterator:
84         case ccErrInvalidLock:
85         case ccErrBadLockType:
86             return CC_BAD_PARM;
87 
88         case ccErrNoMem:
89             return CC_NOMEM;
90 
91         case ccErrInvalidCCache:
92         case ccErrCCacheNotFound:
93             return CC_NO_EXIST;
94 
95         case ccErrCredentialsNotFound:
96             return CC_NOTFOUND;
97 
98         case ccErrBadName:
99             return CC_BADNAME;
100 
101         case ccErrBadCredentialsVersion:
102             return CC_ERR_CRED_VERSION;
103 
104         case ccErrBadAPIVersion:
105             return CC_BAD_API_VERSION;
106 
107         case ccErrContextLocked:
108         case ccErrContextUnlocked:
109         case ccErrCCacheLocked:
110         case ccErrCCacheUnlocked:
111             return CC_LOCKED;
112 
113         case ccErrServerUnavailable:
114         case ccErrServerInsecure:
115         case ccErrServerCantBecomeUID:
116         case ccErrBadInternalMessage:
117         case ccErrClientNotFound:
118             return CC_IO;
119 
120         case ccErrNotImplemented:
121             return CC_NOT_SUPP;
122 
123         default:
124             cci_debug_printf ("%s(): Unhandled error", __FUNCTION__);
125             return CC_BAD_PARM;
126     }
127 }
128 #define cci_remap_error(err) _cci_remap_error(err, __FUNCTION__, __FILE__, __LINE__)
129 
130 
131 #if TARGET_OS_MAC
132 #pragma mark -
133 #endif
134 
135 /* ------------------------------------------------------------------------ */
136 
cc_shutdown(apiCB ** io_context)137 cc_result cc_shutdown (apiCB **io_context)
138 {
139     cc_result err = ccNoError;
140 
141     if (!io_context) { err = cci_check_error (ccErrBadParam); }
142 
143     if (!err) {
144         err = ccapi_context_release (*io_context);
145     }
146 
147     if (!err) {
148         *io_context = NULL;
149     }
150 
151     return cci_remap_error (err);
152 }
153 
154 /* ------------------------------------------------------------------------ */
155 
cc_get_change_time(apiCB * in_context,cc_time_t * out_change_time)156 cc_result cc_get_change_time (apiCB     *in_context,
157                               cc_time_t *out_change_time)
158 {
159     cc_result err = ccNoError;
160 
161     if (!in_context     ) { err = cci_check_error (ccErrBadParam); }
162     if (!out_change_time) { err = cci_check_error (ccErrBadParam); }
163 
164     if (!err) {
165         err = ccapi_context_get_change_time (in_context, out_change_time);
166     }
167 
168     return cci_remap_error (err);
169 }
170 
171 /* ------------------------------------------------------------------------ */
172 
cc_get_NC_info(apiCB * in_context,infoNC *** out_info)173 cc_result cc_get_NC_info (apiCB    *in_context,
174                           infoNC ***out_info)
175 {
176     cc_result err = CC_NOERROR;
177     infoNC **info = NULL;
178     cc_uint64 count = 0; /* Preflight the size */
179     cc_uint64 i;
180 
181     if (!in_context) { err = cci_check_error (ccErrBadParam); }
182     if (!out_info  ) { err = cci_check_error (ccErrBadParam); }
183 
184     if (!err) {
185         ccache_cit *iterator = NULL;
186 
187         err = cc_seq_fetch_NCs_begin (in_context, &iterator);
188 
189         while (!err) {
190             ccache_p *ccache = NULL;
191 
192             err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator);
193 
194             if (!err) { count++; }
195 
196             if (ccache) { cc_close (in_context, &ccache); }
197         }
198         if (err == CC_END) { err = CC_NOERROR; }
199 
200         if (!err) {
201             err = cc_seq_fetch_NCs_end (in_context, &iterator);
202         }
203     }
204 
205     if (!err) {
206         info = malloc (sizeof (*info) * (count + 1));
207         if (info) {
208             for (i = 0; i < count + 1; i++) { info[i] = NULL; }
209         } else {
210             err = cci_check_error (CC_NOMEM);
211         }
212     }
213 
214     if (!err) {
215         ccache_cit *iterator = NULL;
216 
217         err = cc_seq_fetch_NCs_begin (in_context, &iterator);
218 
219         for (i = 0; !err && i < count; i++) {
220             ccache_p *ccache = NULL;
221 
222             err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator);
223 
224             if (!err) {
225                 info[i] = malloc (sizeof (*info[i]));
226                 if (info[i]) {
227                     *info[i] = infoNC_initializer;
228                 } else {
229                     err = cci_check_error (CC_NOMEM);
230                 }
231             }
232 
233             if (!err) {
234                 err = cc_get_name (in_context, ccache, &info[i]->name);
235             }
236 
237             if (!err) {
238                 err = cc_get_principal (in_context, ccache, &info[i]->principal);
239             }
240 
241             if (!err) {
242                 err = cc_get_cred_version (in_context, ccache, &info[i]->vers);
243             }
244 
245             if (ccache) { cc_close (in_context, &ccache); }
246         }
247 
248         if (!err) {
249             err = cc_seq_fetch_NCs_end (in_context, &iterator);
250         }
251     }
252 
253     if (!err) {
254         *out_info = info;
255         info = NULL;
256     }
257 
258     if (info) { cc_free_NC_info (in_context, &info); }
259 
260     return cci_check_error (err);
261 }
262 
263 #if TARGET_OS_MAC
264 #pragma mark -
265 #endif
266 
267 /* ------------------------------------------------------------------------ */
268 
cc_open(apiCB * in_context,const char * in_name,cc_int32 in_version,cc_uint32 in_flags,ccache_p ** out_ccache)269 cc_int32 cc_open (apiCB       *in_context,
270                   const char  *in_name,
271                   cc_int32     in_version,
272                   cc_uint32    in_flags,
273                   ccache_p   **out_ccache)
274 {
275     cc_result err = ccNoError;
276     cc_ccache_t ccache = NULL;
277     cc_uint32 compat_version;
278     cc_uint32 real_version;
279 
280     if (!in_context) { err = cci_check_error (ccErrBadParam); }
281     if (!in_name   ) { err = cci_check_error (ccErrBadParam); }
282     if (!out_ccache) { err = cci_check_error (ccErrBadParam); }
283 
284     if (!err) {
285         err = cci_remap_version (in_version, &compat_version);
286     }
287 
288     if (!err) {
289         err = ccapi_context_open_ccache (in_context, in_name, &ccache);
290     }
291 
292     /* We must not allow a CCAPI v2 caller to open a v5-only ccache
293      as a v4 ccache and vice versa. Allowing that would break
294      (valid) assumptions made by CCAPI v2 callers. */
295 
296     if (!err) {
297         err = ccapi_ccache_get_credentials_version (ccache, &real_version);
298     }
299 
300     if (!err) {
301         /* check the version and set up the ccache to use it */
302         if (compat_version & real_version) {
303             err = cci_ccache_set_compat_version (ccache, compat_version);
304         } else {
305             err = ccErrBadCredentialsVersion;
306         }
307     }
308 
309     if (!err) {
310         *out_ccache = ccache;
311         ccache = NULL;
312     }
313 
314     if (ccache) { ccapi_ccache_release (ccache); }
315 
316     return cci_remap_error (err);
317 }
318 
319 /* ------------------------------------------------------------------------ */
320 
cc_create(apiCB * in_context,const char * in_name,const char * in_principal,cc_int32 in_version,cc_uint32 in_flags,ccache_p ** out_ccache)321 cc_result cc_create (apiCB       *in_context,
322                      const char  *in_name,
323                      const char  *in_principal,
324                      cc_int32     in_version,
325                      cc_uint32    in_flags,
326                      ccache_p   **out_ccache)
327 {
328     cc_result err = ccNoError;
329     cc_ccache_t	ccache = NULL;
330     cc_uint32 compat_version;
331 
332     if (!in_context) { err = cci_check_error (ccErrBadParam); }
333     if (!in_name   ) { err = cci_check_error (ccErrBadParam); }
334     if (!out_ccache) { err = cci_check_error (ccErrBadParam); }
335 
336     if (!err) {
337         err = cci_remap_version (in_version, &compat_version);
338     }
339 
340     if (!err) {
341         err = ccapi_context_create_ccache (in_context, in_name, compat_version,
342                                            in_principal, &ccache);
343     }
344 
345     if (!err) {
346         err = cci_ccache_set_compat_version (ccache, compat_version);
347     }
348 
349     if (!err) {
350         *out_ccache = ccache;
351         ccache = NULL;
352     }
353 
354     if (ccache) { ccapi_ccache_release (ccache); }
355 
356     return cci_remap_error (err);
357 }
358 
359 /* ------------------------------------------------------------------------ */
360 
cc_close(apiCB * in_context,ccache_p ** io_ccache)361 cc_result cc_close (apiCB     *in_context,
362                     ccache_p **io_ccache)
363 {
364     cc_result err = ccNoError;
365 
366     if (!in_context) { err = cci_check_error (ccErrBadParam); }
367     if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
368 
369     if (!err) {
370         err = ccapi_ccache_release (*io_ccache);
371     }
372 
373     if (!err) {
374         *io_ccache = NULL;
375     }
376 
377     return cci_remap_error (err);
378 }
379 
380 /* ------------------------------------------------------------------------ */
381 
cc_destroy(apiCB * in_context,ccache_p ** io_ccache)382 cc_result cc_destroy (apiCB     *in_context,
383                       ccache_p **io_ccache)
384 {
385     cc_result err = ccNoError;
386 
387     if (!in_context) { err = cci_check_error (ccErrBadParam); }
388     if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
389 
390     if (!err) {
391         err = ccapi_ccache_destroy (*io_ccache);
392     }
393 
394     if (!err) {
395         *io_ccache = NULL;
396     }
397 
398     return cci_remap_error (err);
399 }
400 
401 /* ------------------------------------------------------------------------ */
402 
cc_get_name(apiCB * in_context,ccache_p * in_ccache,char ** out_name)403 cc_result cc_get_name (apiCB     *in_context,
404                        ccache_p  *in_ccache,
405                        char     **out_name)
406 {
407     cc_result err = ccNoError;
408     cc_string_t name = NULL;
409 
410     if (!in_context) { err = cci_check_error (ccErrBadParam); }
411     if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
412     if (!out_name  ) { err = cci_check_error (ccErrBadParam); }
413 
414     if (!err) {
415         err = ccapi_ccache_get_name (in_ccache, &name);
416     }
417 
418     if (!err) {
419         char *string = strdup (name->data);
420         if (string) {
421             *out_name = string;
422         } else {
423             err = cci_check_error (ccErrNoMem);
424         }
425     }
426 
427     if (name) { ccapi_string_release (name); }
428 
429     return cci_remap_error (err);
430 }
431 
432 /* ------------------------------------------------------------------------ */
433 
cc_get_cred_version(apiCB * in_context,ccache_p * in_ccache,cc_int32 * out_version)434 cc_result cc_get_cred_version (apiCB    *in_context,
435                                ccache_p *in_ccache,
436                                cc_int32 *out_version)
437 {
438     cc_result err = ccNoError;
439     cc_uint32 compat_version;
440 
441     if (!in_context ) { err = cci_check_error (ccErrBadParam); }
442     if (!in_ccache  ) { err = cci_check_error (ccErrBadParam); }
443     if (!out_version) { err = cci_check_error (ccErrBadParam); }
444 
445     if (!err) {
446         err = cci_ccache_get_compat_version (in_ccache, &compat_version);
447     }
448 
449     if (!err) {
450         if (compat_version == cc_credentials_v5) {
451             *out_version = CC_CRED_V5;
452 
453         } else {
454             err = ccErrBadCredentialsVersion;
455         }
456     }
457 
458     return cci_remap_error (err);
459 }
460 
461 /* ------------------------------------------------------------------------ */
462 
cc_set_principal(apiCB * in_context,ccache_p * io_ccache,cc_int32 in_version,char * in_principal)463 cc_result cc_set_principal (apiCB    *in_context,
464                             ccache_p *io_ccache,
465                             cc_int32  in_version,
466                             char     *in_principal)
467 {
468     cc_result err = ccNoError;
469     cc_uint32 version;
470     cc_uint32 compat_version;
471 
472     if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
473     if (!io_ccache   ) { err = cci_check_error (ccErrBadParam); }
474     if (!in_principal) { err = cci_check_error (ccErrBadParam); }
475 
476     if (!err) {
477         err = cci_remap_version (in_version, &version);
478     }
479 
480     if (!err) {
481         err = cci_ccache_get_compat_version (io_ccache, &compat_version);
482     }
483 
484     if (!err && version != compat_version) {
485         err = cci_check_error (ccErrBadCredentialsVersion);
486     }
487 
488     if (!err) {
489         err = ccapi_ccache_set_principal (io_ccache, version, in_principal);
490     }
491 
492     return cci_remap_error (err);
493 }
494 
495 /* ------------------------------------------------------------------------ */
496 
cc_get_principal(apiCB * in_context,ccache_p * in_ccache,char ** out_principal)497 cc_result cc_get_principal (apiCB      *in_context,
498                             ccache_p   *in_ccache,
499                             char      **out_principal)
500 {
501     cc_result err = ccNoError;
502     cc_uint32 compat_version;
503     cc_string_t principal = NULL;
504 
505     if (!in_context   ) { err = cci_check_error (ccErrBadParam); }
506     if (!in_ccache    ) { err = cci_check_error (ccErrBadParam); }
507     if (!out_principal) { err = cci_check_error (ccErrBadParam); }
508 
509     if (!err) {
510         err = cci_ccache_get_compat_version (in_ccache, &compat_version);
511     }
512 
513     if (!err) {
514         err = ccapi_ccache_get_principal (in_ccache, compat_version, &principal);
515     }
516 
517     if (!err) {
518         char *string = strdup (principal->data);
519         if (string) {
520             *out_principal = string;
521         } else {
522             err = cci_check_error (ccErrNoMem);
523         }
524     }
525 
526     if (principal) { ccapi_string_release (principal); }
527 
528     return cci_remap_error (err);
529 }
530 
531 /* ------------------------------------------------------------------------ */
532 
cc_store(apiCB * in_context,ccache_p * io_ccache,cred_union in_credentials)533 cc_result cc_store (apiCB      *in_context,
534                     ccache_p   *io_ccache,
535                     cred_union  in_credentials)
536 {
537     cc_result err = ccNoError;
538     cc_credentials_union *creds_union = NULL;
539 
540     if (!in_context) { err = cci_check_error (ccErrBadParam); }
541     if (!io_ccache ) { err = cci_check_error (ccErrBadParam); }
542 
543     if (!err) {
544         err = cci_cred_union_to_credentials_union (&in_credentials,
545                                                    &creds_union);
546     }
547 
548     if (!err) {
549         err = ccapi_ccache_store_credentials (io_ccache, creds_union);
550     }
551 
552     if (creds_union) { cci_credentials_union_release (creds_union); }
553     return cci_remap_error (err);
554 }
555 
556 /* ------------------------------------------------------------------------ */
557 
cc_remove_cred(apiCB * in_context,ccache_p * in_ccache,cred_union in_credentials)558 cc_result cc_remove_cred (apiCB      *in_context,
559                           ccache_p   *in_ccache,
560                           cred_union  in_credentials)
561 {
562     cc_result err = ccNoError;
563     cc_credentials_iterator_t iterator = NULL;
564     cc_uint32 found = 0;
565 
566     if (!in_context) { err = cci_check_error (ccErrBadParam); }
567     if (!in_ccache ) { err = cci_check_error (ccErrBadParam); }
568 
569     if (!err) {
570         err = ccapi_ccache_new_credentials_iterator (in_ccache, &iterator);
571     }
572 
573     while (!err && !found) {
574         cc_credentials_t creds = NULL;
575 
576         err = ccapi_credentials_iterator_next (iterator, &creds);
577 
578         if (!err) {
579             err = cci_cred_union_compare_to_credentials_union (&in_credentials,
580                                                                creds->data,
581                                                                &found);
582         }
583 
584         if (!err && found) {
585             err = ccapi_ccache_remove_credentials (in_ccache, creds);
586         }
587 
588         ccapi_credentials_release (creds);
589     }
590     if (err == ccIteratorEnd) { err = cci_check_error (ccErrCredentialsNotFound); }
591 
592     return cci_remap_error (err);
593 }
594 
595 #if TARGET_OS_MAC
596 #pragma mark -
597 #endif
598 
599 /* ------------------------------------------------------------------------ */
600 
cc_seq_fetch_NCs_begin(apiCB * in_context,ccache_cit ** out_iterator)601 cc_result cc_seq_fetch_NCs_begin (apiCB       *in_context,
602                                   ccache_cit **out_iterator)
603 {
604     cc_result err = ccNoError;
605     cc_ccache_iterator_t iterator = NULL;
606 
607     if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
608     if (!out_iterator) { err = cci_check_error (ccErrBadParam); }
609 
610     if (!err) {
611         err = ccapi_context_new_ccache_iterator (in_context, &iterator);
612     }
613 
614     if (!err) {
615         *out_iterator = (ccache_cit *) iterator;
616         iterator = NULL; /* take ownership */
617     }
618 
619     if (iterator) { ccapi_ccache_iterator_release (iterator); }
620 
621     return cci_remap_error (err);
622 }
623 
624 /* ------------------------------------------------------------------------ */
625 
cc_seq_fetch_NCs_next(apiCB * in_context,ccache_p ** out_ccache,ccache_cit * in_iterator)626 cc_result cc_seq_fetch_NCs_next (apiCB       *in_context,
627                                  ccache_p   **out_ccache,
628                                  ccache_cit  *in_iterator)
629 {
630     cc_result err = ccNoError;
631     cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) in_iterator;
632     cc_ccache_t ccache = NULL;
633     const char *saved_ccache_name;
634 
635     if (!in_context ) { err = cci_check_error (ccErrBadParam); }
636     if (!out_ccache ) { err = cci_check_error (ccErrBadParam); }
637     if (!in_iterator) { err = cci_check_error (ccErrBadParam); }
638 
639     if (!err) {
640         err = cci_ccache_iterator_get_saved_ccache_name (iterator,
641                                                          &saved_ccache_name);
642     }
643 
644     if (!err) {
645         if (saved_ccache_name) {
646             err = ccapi_context_open_ccache (in_context, saved_ccache_name,
647                                              &ccache);
648 
649             if (!err) {
650                 err = cci_ccache_set_compat_version (ccache, cc_credentials_v5);
651             }
652 
653             if (!err) {
654                 err = cci_ccache_iterator_set_saved_ccache_name (iterator, NULL);
655             }
656 
657         } else {
658             cc_uint32 version = 0;
659 
660             err = ccapi_ccache_iterator_next (iterator, &ccache);
661 
662             if (!err) {
663                 err = ccapi_ccache_get_credentials_version (ccache, &version);
664             }
665 
666             if (!err) {
667                 err = cci_ccache_set_compat_version (ccache, version);
668             }
669         }
670     }
671 
672     if (!err) {
673         *out_ccache = ccache;
674         ccache = NULL; /* take ownership */
675     }
676 
677     if (ccache) { ccapi_ccache_release (ccache); }
678 
679     return cci_remap_error (err);
680 }
681 
682 /* ------------------------------------------------------------------------ */
683 
cc_seq_fetch_NCs_end(apiCB * in_context,ccache_cit ** io_iterator)684 cc_result cc_seq_fetch_NCs_end (apiCB       *in_context,
685                                 ccache_cit **io_iterator)
686 {
687     cc_result err = ccNoError;
688     cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) *io_iterator;
689 
690     if (!in_context ) { err = cci_check_error (ccErrBadParam); }
691     if (!io_iterator) { err = cci_check_error (ccErrBadParam); }
692 
693     if (!err) {
694         err = ccapi_ccache_iterator_release (iterator);
695     }
696 
697     if (!err) {
698         *io_iterator = NULL;
699     }
700 
701     return cci_remap_error (err);
702 }
703 
704 #if TARGET_OS_MAC
705 #pragma mark -
706 #endif
707 
708 /* ------------------------------------------------------------------------ */
709 
cc_seq_fetch_creds_begin(apiCB * in_context,const ccache_p * in_ccache,ccache_cit ** out_iterator)710 cc_result cc_seq_fetch_creds_begin (apiCB           *in_context,
711                                     const ccache_p  *in_ccache,
712                                     ccache_cit     **out_iterator)
713 {
714     cc_result err = ccNoError;
715     cc_credentials_iterator_t iterator = NULL;
716     cc_uint32 compat_version;
717 
718     if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
719     if (!in_ccache   ) { err = cci_check_error (ccErrBadParam); }
720     if (!out_iterator) { err = cci_check_error (ccErrBadParam); }
721 
722     if (!err) {
723         err = cci_ccache_get_compat_version ((cc_ccache_t) in_ccache,
724                                              &compat_version);
725     }
726 
727     if (!err) {
728         err = ccapi_ccache_new_credentials_iterator ((cc_ccache_t) in_ccache,
729                                                      &iterator);
730     }
731 
732     if (!err) {
733         err = cci_credentials_iterator_set_compat_version (iterator,
734                                                            compat_version);
735     }
736 
737     if (!err) {
738         *out_iterator = (ccache_cit *) iterator;
739         iterator = NULL; /* take ownership */
740     }
741 
742     if (iterator) { ccapi_credentials_iterator_release (iterator); }
743 
744     return cci_remap_error (err);
745 }
746 
747 /* ------------------------------------------------------------------------ */
748 
cc_seq_fetch_creds_next(apiCB * in_context,cred_union ** out_creds,ccache_cit * in_iterator)749 cc_result cc_seq_fetch_creds_next (apiCB       *in_context,
750                                    cred_union **out_creds,
751                                    ccache_cit  *in_iterator)
752 {
753     cc_result err = ccNoError;
754     cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) in_iterator;
755     cc_uint32 compat_version;
756 
757     if (!in_context ) { err = cci_check_error (ccErrBadParam); }
758     if (!out_creds  ) { err = cci_check_error (ccErrBadParam); }
759     if (!in_iterator) { err = cci_check_error (ccErrBadParam); }
760 
761     if (!err) {
762         err = cci_credentials_iterator_get_compat_version (iterator,
763                                                            &compat_version);
764     }
765 
766     while (!err) {
767         cc_credentials_t credentials = NULL;
768 
769         err = ccapi_credentials_iterator_next (iterator, &credentials);
770 
771         if (!err && (credentials->data->version & compat_version)) {
772             /* got the next credentials for the correct version */
773             err = cci_credentials_union_to_cred_union (credentials->data,
774                                                        out_creds);
775             break;
776         }
777 
778         if (credentials) { ccapi_credentials_release (credentials); }
779     }
780 
781     return cci_remap_error (err);
782 }
783 
784 /* ------------------------------------------------------------------------ */
785 
cc_seq_fetch_creds_end(apiCB * in_context,ccache_cit ** io_iterator)786 cc_result cc_seq_fetch_creds_end (apiCB       *in_context,
787                                   ccache_cit **io_iterator)
788 {
789     cc_result err = ccNoError;
790     cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) *io_iterator;
791 
792     if (!in_context ) { err = cci_check_error (ccErrBadParam); }
793     if (!io_iterator) { err = cci_check_error (ccErrBadParam); }
794 
795     if (!err) {
796         err = ccapi_credentials_iterator_release (iterator);
797     }
798 
799     if (!err) {
800         *io_iterator = NULL;
801     }
802 
803     return cci_remap_error (err);
804 }
805 
806 #if TARGET_OS_MAC
807 #pragma mark -
808 #endif
809 
810 /* ------------------------------------------------------------------------ */
811 
cc_free_principal(apiCB * in_context,char ** io_principal)812 cc_result cc_free_principal (apiCB  *in_context,
813                              char  **io_principal)
814 {
815     cc_result err = ccNoError;
816 
817     if (!in_context  ) { err = cci_check_error (ccErrBadParam); }
818     if (!io_principal) { err = cci_check_error (ccErrBadParam); }
819 
820     if (!err) {
821         free (*io_principal);
822         *io_principal = NULL;
823     }
824 
825     return cci_remap_error (err);
826 }
827 
828 /* ------------------------------------------------------------------------ */
829 
cc_free_name(apiCB * in_context,char ** io_name)830 cc_result cc_free_name (apiCB  *in_context,
831                         char  **io_name)
832 {
833     cc_result err = ccNoError;
834 
835     if (!in_context) { err = cci_check_error (ccErrBadParam); }
836     if (!io_name   ) { err = cci_check_error (ccErrBadParam); }
837 
838     if (!err) {
839         free (*io_name);
840         *io_name = NULL;
841     }
842 
843     return cci_remap_error (err);
844 }
845 
846 /* ------------------------------------------------------------------------ */
847 
cc_free_creds(apiCB * in_context,cred_union ** io_credentials)848 cc_result cc_free_creds (apiCB       *in_context,
849                          cred_union **io_credentials)
850 {
851     cc_result err = ccNoError;
852 
853     if (!in_context    ) { err = cci_check_error (ccErrBadParam); }
854     if (!io_credentials) { err = cci_check_error (ccErrBadParam); }
855 
856     if (!err) {
857         err = cci_cred_union_release (*io_credentials);
858         if (!err) { *io_credentials = NULL; }
859     }
860 
861     return cci_remap_error (err);
862 }
863 
864 /* ------------------------------------------------------------------------ */
865 
cc_free_NC_info(apiCB * in_context,infoNC *** io_info)866 cc_result cc_free_NC_info (apiCB    *in_context,
867                            infoNC ***io_info)
868 {
869     cc_result err = ccNoError;
870 
871     if (!in_context) { err = cci_check_error (ccErrBadParam); }
872     if (!io_info   ) { err = cci_check_error (ccErrBadParam); }
873 
874     if (!err && *io_info) {
875         infoNC **data = *io_info;
876         int i;
877 
878         for (i = 0; data[i] != NULL; i++) {
879             cc_free_principal (in_context, &data[i]->principal);
880             cc_free_name (in_context, &data[i]->name);
881             free (data[i]);
882         }
883         free (data);
884 
885         *io_info = NULL;
886     }
887 
888     return cci_remap_error (err);
889 }
890