1#include <string.h>
2
3#define CCAPI_DEPRECATED
4
5#include "test_ccapi_v2.h"
6#include <limits.h>
7#include <time.h>
8#include "test_ccapi_check.h"
9#include "test_ccapi_util.h"
10
11// ---------------------------------------------------------------------------
12
13static cc_result destroy_all_ccaches_v2(apiCB *context) {
14    cc_result err = CC_NOERROR;
15    infoNC **info = NULL;
16    int i = 0;
17
18    err = cc_get_NC_info(context, &info);
19
20    for (i = 0; !err && info[i]; i++) {
21        ccache_p *ccache = NULL;
22
23        err = cc_open(context, info[i]->name, info[i]->vers, 0, &ccache);
24
25        if (!err) { cc_destroy(context, &ccache); }
26    }
27
28    if (info) { cc_free_NC_info(context, &info); }
29
30    if (err) {
31        log_error("cc_get_NC_info or cc_open failed with %s (%d)", translate_ccapi_error(err), err);
32    }
33
34    return err;
35}
36
37// ---------------------------------------------------------------------------
38// return zero when both unions are considered equal, non-zero when not
39
40static int compare_v5_creds_unions_compat(const cred_union *a, const cred_union *b) {
41    int retval = -1;
42
43    if (a && b && a->cred_type == b->cred_type) {
44        if (a->cred_type == CC_CRED_V5) {
45            if (!strcmp(a->cred.pV5Cred->client, b->cred.pV5Cred->client) &&
46                !strcmp(a->cred.pV5Cred->server, b->cred.pV5Cred->server) &&
47                a->cred.pV5Cred->starttime == b->cred.pV5Cred->starttime) {
48                retval = 0;
49            }
50        } else if (a->cred_type == CC_CRED_V4) {
51            if (!strcmp (a->cred.pV4Cred->principal,
52                         b->cred.pV4Cred->principal) &&
53                !strcmp (a->cred.pV4Cred->principal_instance,
54                         b->cred.pV4Cred->principal_instance) &&
55                !strcmp (a->cred.pV4Cred->service,
56                         b->cred.pV4Cred->service) &&
57                !strcmp (a->cred.pV4Cred->service_instance,
58                         b->cred.pV4Cred->service_instance) &&
59                !strcmp (a->cred.pV4Cred->realm,
60                         b->cred.pV4Cred->realm) &&
61                a->cred.pV4Cred->issue_date == b->cred.pV4Cred->issue_date) {
62                retval = 0;
63            }
64        }
65    }
66
67    return retval;
68}
69
70// ---------------------------------------------------------------------------
71
72static cc_result new_v5_creds_union_compat (cred_union *out_union, const char *realm)
73{
74    cc_result err = CC_NOERROR;
75    cred_union *creds_union = NULL;
76    cc_credentials_v5_compat *v5creds = NULL;
77    static int num_runs = 1;
78    char *client = NULL;
79    char *server = NULL;
80
81    if (!out_union) { err = CC_BAD_PARM; }
82
83    if (!err) {
84        v5creds = malloc (sizeof (*v5creds));
85        if (!v5creds) {
86            err = CC_NOMEM;
87        }
88    }
89
90    if (!err) {
91        asprintf(&client, "client@%s", realm);
92        asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm);
93        if (!client || !server) {
94            err = CC_NOMEM;
95        }
96    }
97
98    if (!err) {
99        v5creds->client = client;
100        v5creds->server = server;
101        v5creds->keyblock.type = 1;
102        v5creds->keyblock.length = 0;
103        v5creds->keyblock.data = NULL;
104        v5creds->authtime = time (NULL);
105        v5creds->starttime = time (NULL);
106        v5creds->endtime = time(NULL) + 1000;
107        v5creds->renew_till = time(NULL) + 10000;
108        v5creds->is_skey = 0;
109        v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL;
110        v5creds->addresses = NULL;
111        v5creds->ticket.type = 0;
112        v5creds->ticket.length = 0;
113        v5creds->ticket.data = NULL;
114        v5creds->second_ticket.type = 0;
115        v5creds->second_ticket.length = 0;
116        v5creds->second_ticket.data = NULL;
117        v5creds->authdata = NULL;
118    }
119
120
121    if (!err) {
122        creds_union = malloc (sizeof (*creds_union));
123        if (creds_union) {
124            creds_union->cred_type = CC_CRED_V5;
125            creds_union->cred.pV5Cred = v5creds;
126        } else {
127            err = CC_NOMEM;
128        }
129    }
130    if (!err) {
131        *out_union = *creds_union;
132        creds_union = NULL;
133    }
134
135    return err;
136}
137
138// ---------------------------------------------------------------------------
139
140static void release_v5_creds_union_compat(cred_union *creds_union) {
141    cc_credentials_v5_compat *v5creds = NULL;
142
143    if (creds_union) {
144        if (creds_union->cred.pV5Cred) {
145            v5creds = creds_union->cred.pV5Cred;
146            if (v5creds->client) { free(v5creds->client); }
147            if (v5creds->server) { free(v5creds->server); }
148            if (v5creds->keyblock.data) { free(v5creds->keyblock.data); }
149            if (v5creds->ticket.data) { free(v5creds->ticket.data); }
150            if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); }
151            free(v5creds);
152        }
153    }
154}
155
156// ---------------------------------------------------------------------------
157
158int check_cc_shutdown(void) {
159    cc_result err = 0;
160    apiCB *context = NULL;
161
162    BEGIN_TEST("cc_shutdown");
163
164    // try with valid context
165    err = check_once_cc_shutdown(&context, CC_NOERROR, NULL);
166
167    // try with NULL
168    err = check_once_cc_shutdown(NULL, CC_BAD_PARM, NULL);
169
170    if (context) { cc_shutdown(&context); }
171
172    END_TEST_AND_RETURN
173}
174
175cc_result check_once_cc_shutdown(apiCB **out_context, cc_result expected_err, const char *description) {
176    cc_result err = 0;
177    apiCB *context = NULL;
178
179    cc_result possible_return_values[2] = {
180        CC_NOERROR,
181        CC_BAD_PARM,
182    };
183
184    BEGIN_CHECK_ONCE(description);
185
186#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
187
188    if (out_context) {
189        err = cc_initialize(out_context, ccapi_version_2, NULL, NULL);
190        if (!err) {
191            context = *out_context;
192        } else {
193            log_error("failure in cc_initialize, unable to perform check");
194            return err;
195        }
196    }
197
198    if (!err) {
199        err = cc_shutdown(&context);
200        // check returned error
201        check_err(err, expected_err, possible_return_values);
202
203    }
204
205    if (out_context) {
206        *out_context = NULL;
207    }
208
209    END_CHECK_ONCE;
210
211    return err;
212}
213
214// ---------------------------------------------------------------------------
215
216int check_cc_get_change_time(void) {
217    cc_result err = 0;
218    apiCB *context = NULL;
219    cc_time_t last_change_time = 0;
220    ccache_p *ccache = NULL;
221    cred_union creds_union;
222
223    BEGIN_TEST("cc_get_change_time");
224
225    /*
226     * Make a context
227     * make sure the change time changes after:
228     * 	a ccache is created
229     * 	a ccache is destroyed
230     * 	a credential is stored
231     * 	a credential is removed
232     * 	a ccache principal is changed
233     * clean up memory
234     */
235
236    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
237    if (!err) {
238
239        // try bad parameters first
240        err = check_once_cc_get_change_time(context, NULL, CC_BAD_PARM, "NULL param, should fail");
241
242        // get_change_time should always give something > 0
243        check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "first-run, should be > 0");
244
245        // create a ccache
246        err = cc_create(context, "TEST_CCACHE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
247        if (err) {
248            log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err);
249            failure_count++;
250        }
251        check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after creating a new ccache");
252
253        if (!err) {
254            // change principal
255            err = cc_set_principal(context, ccache, CC_CRED_V5, "foo@BAR.ORG");
256            if (err) {
257                log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err);
258                failure_count++;
259                err = CC_NOERROR;
260            }
261        }
262        check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after changing a principle");
263
264        new_v5_creds_union_compat(&creds_union, "BAR.ORG");
265
266        // store a credential
267        if (!err) {
268            err = cc_store(context, ccache, creds_union);
269            if (err) {
270                log_error("failed to store a credential - %s (%d)", translate_ccapi_error(err), err);
271                failure_count++;
272                err = CC_NOERROR;
273            }
274        }
275        check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after storing a credential");
276
277        // remove a credential
278        if (!err) {
279            err = cc_remove_cred(context, ccache, creds_union);
280            if (err) {
281                log_error("failed to remove a credential - %s (%d)", translate_ccapi_error(err), err);
282                failure_count++;
283                err = CC_NOERROR;
284            }
285        }
286        check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after removing a credential");
287
288        release_v5_creds_union_compat(&creds_union);
289
290        if (ccache) {
291            // destroy a ccache
292            err = cc_destroy(context, &ccache);
293            check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after destroying a ccache");
294        }
295    }
296
297    if (context) { cc_shutdown(&context); }
298
299    END_TEST_AND_RETURN
300}
301
302// ---------------------------------------------------------------------------
303
304cc_int32 check_once_cc_get_change_time(apiCB *context, cc_time_t *last_time, cc_result expected_err, const char *description) {
305    cc_result err = 0;
306    cc_time_t last_change_time;
307    cc_time_t current_change_time = 0;
308
309    cc_result possible_return_values[3] = {
310        CC_NOERROR,
311        CC_BAD_PARM,
312        CC_NO_EXIST,
313    };
314
315    BEGIN_CHECK_ONCE(description);
316
317#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
318
319    if (last_time != NULL) { // if we were passed NULL, then we're looking to pass a bad param
320        err = cc_get_change_time(context, &current_change_time);
321    } else {
322        err = cc_get_change_time(context, NULL);
323    }
324
325    check_err(err, expected_err, possible_return_values);
326
327    if (!err) {
328        last_change_time = *last_time;
329        check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time);
330        *last_time = current_change_time;
331    }
332
333    END_CHECK_ONCE;
334
335    return err;
336}
337
338// ---------------------------------------------------------------------------
339
340int check_cc_open(void) {
341    cc_result err = 0;
342    apiCB *context = NULL;
343    ccache_p *ccache = NULL;
344    char *name = "TEST_OPEN_CCACHE";
345
346    BEGIN_TEST("cc_open");
347
348    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
349    if (!err) {
350        // create a ccache
351        err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
352        if (err) {
353            log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err);
354            failure_count++;
355        }
356        if (!err) {
357            err = cc_close(context, &ccache);
358            ccache = NULL;
359        }
360
361        // try default ccache
362        if (!err) {
363            err = check_once_cc_open(context, name, CC_CRED_V5, &ccache, CC_NOERROR, NULL);
364        }
365
366        // check version
367        if (!err) {
368            err = check_once_cc_open(context, name, CC_CRED_V4, &ccache, CC_ERR_CRED_VERSION, NULL);
369        }
370        // try bad parameters
371        err = check_once_cc_open(context, NULL, CC_CRED_V5, &ccache, CC_BAD_PARM, NULL);
372        err = check_once_cc_open(context, name, CC_CRED_V5, NULL, CC_BAD_PARM, NULL);
373        err = check_once_cc_open(context, name, CC_CRED_UNKNOWN, &ccache, CC_ERR_CRED_VERSION, NULL);
374     }
375
376    if (context) { cc_shutdown(&context); }
377
378    END_TEST_AND_RETURN
379}
380
381// ---------------------------------------------------------------------------
382
383cc_result check_once_cc_open(apiCB *context, const char *name, cc_int32 version, ccache_p **ccache, cc_result expected_err, const char *description) {
384    cc_result err = 0;
385    char *stored_name = NULL;
386
387    cc_result possible_return_values[5] = {
388        CC_NOERROR,
389        CC_BAD_PARM,
390        CC_NO_EXIST,
391        CC_NOMEM,
392        CC_ERR_CRED_VERSION
393    };
394
395    BEGIN_CHECK_ONCE(description);
396
397#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
398
399    if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param
400        err = cc_open(context, name, version, 0, ccache);
401    } else {
402        err = cc_open(context, name, version, 0, NULL);
403    }
404
405    // check returned error
406    check_err(err, expected_err, possible_return_values);
407
408    if (!err) {
409        check_if(*ccache == NULL, NULL);
410
411        if (!err) {
412            err = cc_get_name(context, *ccache, &stored_name);
413        }
414        if (!err) {
415            check_if(strcmp(stored_name, name), NULL);
416        }
417        if (stored_name) { cc_free_name(context, &stored_name); }
418
419
420        if (ccache && *ccache) {
421            cc_ccache_release(*ccache);
422            *ccache = NULL;
423        }
424    }
425
426    END_CHECK_ONCE;
427
428    return err;
429}
430
431// ---------------------------------------------------------------------------
432
433int check_cc_create(void) {
434    cc_result err = 0;
435    apiCB *context = NULL;
436    ccache_p *ccache = NULL;
437    char *name = "TEST_CC_CREATE";
438
439    BEGIN_TEST("cc_create");
440
441    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
442    if (!err) {
443        if (!err) {
444            err = cc_open(context, name, CC_CRED_V5, 0, &ccache);
445            if (!err) {
446                err = cc_destroy (context, &ccache);
447            } else {
448                err = CC_NOERROR;  /* ccache does not exist */
449            }
450        }
451        // try making a ccache with a unique name (the now destroyed cache's name)
452        if (!err) {
453            err = check_once_cc_create(context, name, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_NOERROR, NULL);
454        }
455
456        // try making a ccache with a non-unique name (the existing cache's name)
457        if (!err) {
458            err = check_once_cc_create(context, name, CC_CRED_V5, "foo/baz@BAR.ORG", &ccache, CC_NOERROR, NULL);
459        }
460
461        // try bad parameters
462        err = check_once_cc_create(context, NULL, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_BAD_PARM, "NULL name");                    // NULL name
463        err = check_once_cc_create(context, "name", CC_CRED_MAX, "foo@BAR.ORG", &ccache, CC_ERR_CRED_VERSION, "invalid creds_vers"); // invalid creds_vers
464        err = check_once_cc_create(context, "name", CC_CRED_V5, NULL, &ccache, CC_BAD_PARM, "NULL principal");                          // NULL principal
465        err = check_once_cc_create(context, "name", CC_CRED_V5, "foo@BAR.ORG", NULL, CC_BAD_PARM, "NULL ccache");                    // NULL ccache
466    }
467
468    if (ccache) { cc_destroy(context, &ccache); }
469    if (context) { cc_shutdown(&context); }
470
471    END_TEST_AND_RETURN
472}
473
474// ---------------------------------------------------------------------------
475
476cc_result check_once_cc_create(apiCB  *context, const char *name, cc_int32 cred_vers, const char *principal, ccache_p **ccache, cc_int32 expected_err, const char *description) {
477    cc_result err = 0;
478    char *stored_name = NULL;
479    char *stored_principal = NULL;
480    cc_int32 stored_creds_vers = 0;
481
482    cc_result possible_return_values[6] = {
483        CC_NOERROR,
484        CC_BADNAME,
485        CC_BAD_PARM,
486        CC_NO_EXIST,
487        CC_NOMEM,
488        CC_ERR_CRED_VERSION,
489    };
490    BEGIN_CHECK_ONCE(description);
491
492#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
493
494    err = cc_create(context, name, principal, cred_vers, 0, ccache);
495
496    // check returned error
497    check_err(err, expected_err, possible_return_values);
498
499    if (!err) {
500        check_if(*ccache == NULL, NULL);
501
502        // make sure all of the ccache's info matches what we gave it
503        // name
504        err = cc_get_name(context, *ccache, &stored_name);
505        if (!err) { check_if(strcmp(stored_name, name), NULL); }
506        if (stored_name) { cc_free_name(context, &stored_name); }
507        // cred_vers
508        err = cc_get_cred_version(context, *ccache, &stored_creds_vers);
509        if (!err) { check_if(stored_creds_vers != cred_vers, NULL); }
510        // principal
511        err = cc_get_principal(context, *ccache, &stored_principal);
512        if (!err) { check_if(strcmp(stored_principal, principal), NULL); }
513        if (stored_principal) { cc_free_principal(context, &stored_principal); }
514
515        if (ccache && *ccache) {
516            cc_destroy(context, ccache);
517            *ccache = NULL;
518        }
519    }
520
521    END_CHECK_ONCE;
522
523    return err;
524}
525
526// ---------------------------------------------------------------------------
527
528int check_cc_close(void) {
529    cc_result err = 0;
530    apiCB *context = NULL;
531    ccache_p *ccache = NULL;
532    char *name = "TEST_CC_CLOSE";
533
534    BEGIN_TEST("cc_close");
535
536    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
537
538    if (!err) {
539        err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
540    }
541
542    if (!err) {
543        check_once_cc_close(context, ccache, CC_NOERROR, NULL);
544        ccache = NULL;
545    }
546
547    if (context) { cc_shutdown(&context); }
548
549    END_TEST_AND_RETURN
550}
551
552// ---------------------------------------------------------------------------
553
554cc_result check_once_cc_close(apiCB *context, ccache_p *ccache, cc_result expected_err, const char *description) {
555    cc_result err = CC_NOERROR;
556
557    cc_result possible_return_values[2] = {
558        CC_NOERROR,
559        CC_BAD_PARM
560    };
561
562    char *name = NULL;
563
564    err = cc_get_name(context, ccache, &name);
565    err = cc_close(context, &ccache);
566    ccache = NULL;
567
568    BEGIN_CHECK_ONCE(description);
569
570#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
571
572    // check returned error
573    check_err(err, expected_err, possible_return_values);
574
575    if (!err && name) { // try opening released ccache to make sure it still exists
576        err = cc_open(context, name, CC_CRED_V5, 0, &ccache);
577    }
578    check_if(err == CC_NO_EXIST, "released ccache was actually destroyed instead");
579    check_if(err != CC_NOERROR, "released ccache cannot be opened");
580
581    if (ccache) { cc_destroy(context, &ccache); }
582    if (name) { cc_free_name(context, &name); }
583
584    END_CHECK_ONCE;
585
586    return err;
587}
588
589// ---------------------------------------------------------------------------
590
591int check_cc_destroy(void) {
592    cc_result err = 0;
593    apiCB *context = NULL;
594    ccache_p *ccache = NULL;
595    char *name = "TEST_CC_DESTROY";
596
597    BEGIN_TEST("cc_destroy");
598
599    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
600
601    if (!err) {
602        err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
603    }
604
605    if (!err) {
606        check_once_cc_destroy(context, ccache, CC_NOERROR, NULL);
607        ccache = NULL;
608    }
609
610    if (context) { cc_shutdown(&context); }
611
612    END_TEST_AND_RETURN
613}
614
615// ---------------------------------------------------------------------------
616
617cc_result check_once_cc_destroy(apiCB *context, ccache_p *ccache, cc_int32 expected_err, const char *description) {
618    cc_result err = CC_NOERROR;
619
620    cc_result possible_return_values[2] = {
621        CC_NOERROR,
622        CC_BAD_PARM,
623    };
624
625    char *name = NULL;
626
627    BEGIN_CHECK_ONCE(description);
628
629#ifdef cc_ccache_destroy
630
631#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
632
633    err = cc_get_name(context, ccache, &name);
634    err = cc_destroy(context, &ccache);
635    ccache = NULL;
636
637    // check returned error
638    check_err(err, expected_err, possible_return_values);
639
640    if (!err && name) { // try opening released ccache to make sure it still exists
641        err = cc_open(context, name, CC_CRED_V5, 0, &ccache);
642    }
643    check_if(err != CC_NO_EXIST, "destroyed ccache was actually released instead");
644
645    if (ccache) { cc_destroy(context, &ccache); }
646    if (name) { cc_free_name(context, &name); }
647
648#endif /* cc_ccache_destroy */
649
650    END_CHECK_ONCE;
651
652    return err;
653}
654
655// ---------------------------------------------------------------------------
656
657int check_cc_get_cred_version(void) {
658    cc_result err = 0;
659    apiCB *context = NULL;
660    ccache_p *ccache = NULL;
661    char *name = "TEST_CC_GET_CRED_VERSION_V5";
662
663    BEGIN_TEST("cc_get_cred_version");
664
665    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
666
667    // try one created with v5 creds
668    if (!err) {
669        err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
670    }
671    if (!err) {
672        check_once_cc_get_cred_version(context, ccache, CC_CRED_V5, CC_NOERROR, "v5 creds");
673    }
674    else {
675        log_error("cc_context_create_new_ccache failed, can't complete test");
676        failure_count++;
677    }
678
679    if (ccache) {
680        cc_destroy(context, &ccache);
681        ccache = NULL;
682    }
683
684    err = CC_NOERROR;
685
686    // try one created with v4 creds
687    if (!err) {
688        err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V4, 0, &ccache);
689    }
690    if (!err) {
691        check_once_cc_get_cred_version(context, ccache, CC_CRED_V4, CC_NOERROR, "v4 creds");
692    }
693    else {
694        log_error("cc_context_create_new_ccache failed, can't complete test");
695        failure_count++;
696    }
697    if (ccache) {
698        cc_destroy(context, &ccache);
699        ccache = NULL;
700    }
701
702    if (context) { cc_shutdown(&context); }
703
704    END_TEST_AND_RETURN
705}
706
707// ---------------------------------------------------------------------------
708
709cc_result check_once_cc_get_cred_version(apiCB *context, ccache_p *ccache, cc_int32 expected_cred_vers, cc_int32 expected_err, const char *description) {
710    cc_result err = CC_NOERROR;
711
712    cc_result possible_return_values[3] = {
713        CC_NOERROR,
714        CC_BAD_PARM,
715        CC_NO_EXIST,
716    };
717
718    cc_int32 stored_cred_vers = 0;
719
720    BEGIN_CHECK_ONCE(description);
721
722#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
723
724    err = cc_get_cred_version(context, ccache, &stored_cred_vers);
725
726    // check returned error
727    check_err(err, expected_err, possible_return_values);
728
729    if (!err) {
730        check_if(stored_cred_vers != expected_cred_vers, NULL);
731    }
732
733    END_CHECK_ONCE;
734
735    return err;
736}
737
738// ---------------------------------------------------------------------------
739
740int check_cc_get_name(void) {
741    cc_result err = 0;
742    apiCB *context = NULL;
743    ccache_p *ccache = NULL;
744
745    BEGIN_TEST("cc_get_name");
746
747    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
748
749    if (!err) {
750        err = destroy_all_ccaches_v2(context);
751    }
752
753    // try with unique ccache (which happens to be default)
754    if (!err) {
755        err = cc_create(context, "0", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
756    }
757    if (!err) {
758        check_once_cc_get_name(context, ccache, "0", CC_NOERROR, "unique ccache (which happens to be default)");
759    }
760    else {
761        log_error("cc_context_create_ccache failed, can't complete test");
762        failure_count++;
763    }
764    if (ccache) {
765        cc_close(context, &ccache);
766        ccache = NULL;
767    }
768
769    // try with unique ccache (which is not default)
770    if (!err) {
771        err = cc_context_create_ccache(context, "1", CC_CRED_V5, "foo@BAR.ORG", &ccache);
772    }
773    if (!err) {
774        check_once_cc_get_name(context, ccache, "1", CC_NOERROR, "unique ccache (which is not default)");
775    }
776    else {
777        log_error("cc_context_create_ccache failed, can't complete test");
778        failure_count++;
779    }
780
781    // try with bad param
782    if (!err) {
783        check_once_cc_get_name(context, ccache, NULL, CC_BAD_PARM, "NULL param");
784    }
785    if (ccache) {
786        cc_close(context, &ccache);
787        ccache = NULL;
788    }
789
790    if (context) {
791        err = destroy_all_ccaches_v2(context);
792        cc_shutdown(&context);
793    }
794
795    END_TEST_AND_RETURN
796}
797
798// ---------------------------------------------------------------------------
799
800cc_int32 check_once_cc_get_name(apiCB *context, ccache_p *ccache, const char *expected_name, cc_int32 expected_err, const char *description) {
801    cc_result err = CC_NOERROR;
802
803    cc_result possible_return_values[4] = {
804        CC_NOERROR,
805        CC_NOMEM,
806        CC_BAD_PARM,
807        CC_NO_EXIST,
808    };
809
810    char *stored_name = NULL;
811
812    BEGIN_CHECK_ONCE(description);
813
814#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
815
816    if (expected_name == NULL) { // we want to try with a NULL param
817        err = cc_get_name(context, ccache, NULL);
818    }
819    else {
820        err = cc_get_name(context, ccache, &stored_name);
821    }
822
823    // check returned error
824    check_err(err, expected_err, possible_return_values);
825
826    if (!err) {
827        check_if(strcmp(stored_name, expected_name), NULL);
828    }
829
830    if (stored_name) { cc_free_name(context, &stored_name); }
831
832    END_CHECK_ONCE;
833
834    return err;
835}
836
837
838// ---------------------------------------------------------------------------
839
840int check_cc_get_principal(void) {
841    cc_result err = 0;
842    apiCB *context = NULL;
843    ccache_p *ccache = NULL;
844    char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5";
845    char *name_v4 = "TEST_CC_GET_PRINCIPAL_V4";
846
847    BEGIN_TEST("cc_get_principal");
848
849    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
850
851    if (!err) {
852        err = destroy_all_ccaches_v2(context);
853    }
854
855    // try with krb5 principal
856    if (!err) {
857        err = cc_create(context, name_v5, "foo/BAR@BAZ.ORG", CC_CRED_V5, 0, &ccache);
858    }
859    if (!err) {
860        check_once_cc_get_principal(context, ccache, "foo/BAR@BAZ.ORG", CC_NOERROR, "trying to get krb5 princ for krb5 ccache");
861    }
862    else {
863        log_error("cc_create failed, can't complete test");
864        failure_count++;
865    }
866    if (ccache) {
867        cc_close(context, &ccache);
868        ccache = NULL;
869    }
870
871    // try with krb4 principal
872    if (!err) {
873        err = cc_create(context, name_v4, "foo.BAR@BAZ.ORG", CC_CRED_V4, 0, &ccache);
874    }
875    if (!err) {
876        check_once_cc_get_principal(context, ccache, "foo.BAR@BAZ.ORG", CC_NOERROR, "trying to get krb4 princ for krb4 ccache");
877    }
878    else {
879        log_error("cc_create failed, can't complete test");
880        failure_count++;
881    }
882
883    // try with bad param
884    if (!err) {
885        check_once_cc_get_principal(context, ccache, NULL, CC_BAD_PARM, "passed null out param");
886    }
887
888    if (ccache) {
889        cc_close(context, &ccache);
890        ccache = NULL;
891    }
892
893    if (context) {
894        err = destroy_all_ccaches_v2(context);
895        cc_shutdown(&context);
896    }
897
898    END_TEST_AND_RETURN
899}
900
901// ---------------------------------------------------------------------------
902
903cc_result check_once_cc_get_principal(apiCB *context,
904                                      ccache_p *ccache,
905                                      const char *expected_principal,
906                                      cc_int32 expected_err,
907                                      const char *description) {
908    cc_result err = CC_NOERROR;
909    char *stored_principal = NULL;
910
911    cc_result possible_return_values[4] = {
912        CC_NOERROR,
913        CC_NOMEM,
914        CC_NO_EXIST,
915        CC_BAD_PARM
916    };
917
918    BEGIN_CHECK_ONCE(description);
919
920#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
921
922    if (expected_principal == NULL) { // we want to try with a NULL param
923        err = cc_get_principal(context, ccache, NULL);
924    }
925    else {
926        err = cc_get_principal(context, ccache, &stored_principal);
927    }
928
929    // check returned error
930    check_err(err, expected_err, possible_return_values);
931
932    if (!err) {
933        check_if(strcmp(stored_principal, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal);
934    }
935
936    if (stored_principal) { cc_free_principal(context, &stored_principal); }
937
938    END_CHECK_ONCE;
939
940    return err;
941}
942
943// ---------------------------------------------------------------------------
944
945int check_cc_set_principal(void) {
946    cc_result err = 0;
947    apiCB *context = NULL;
948    ccache_p *ccache = NULL;
949    char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5";
950    char *name_v4 = "TEST_CC_GET_PRINCIPAL_V4";
951
952    BEGIN_TEST("cc_set_principal");
953
954    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
955
956    if (!err) {
957        err = destroy_all_ccaches_v2(context);
958    }
959
960    // bad params
961    if (!err) {
962        err = cc_create(context, name_v5, "foo@BAZ.ORG", CC_CRED_V5, 0, &ccache);
963    }
964    if (!err) {
965        check_once_cc_set_principal(context, ccache, CC_CRED_MAX, "foo/BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "CC_CRED_MAX (not allowed)");
966        check_once_cc_set_principal(context, ccache, CC_CRED_V5, NULL, CC_BAD_PARM, "NULL principal");
967    }
968    else {
969        log_error("cc_create failed, can't complete test");
970        failure_count++;
971    }
972    if (ccache) {
973        cc_destroy(context, &ccache);
974        ccache = NULL;
975    }
976
977    // empty ccache
978
979    // replace v5 ccache's principal
980    if (!err) {
981        err = cc_create(context, name_v5, "foo@BAZ.ORG", CC_CRED_V5, 0, &ccache);
982     }
983    if (!err) {
984        check_once_cc_set_principal(context, ccache, CC_CRED_V5, "foo/BAZ@BAR.ORG", CC_NOERROR, "replace v5 only ccache's principal (empty ccache)");
985        check_once_cc_set_principal(context, ccache, CC_CRED_V4, "foo.BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "replace v5 principal with v4");
986    }
987    else {
988        log_error("cc_create failed, can't complete test");
989        failure_count++;
990    }
991    if (ccache) {
992        cc_destroy(context, &ccache);
993        ccache = NULL;
994    }
995
996    // replace v4 ccache's principal
997    if (!err) {
998        err = cc_create(context, name_v4, "foo@BAZ.ORG", CC_CRED_V4, 0, &ccache);
999    }
1000    if (!err) {
1001        check_once_cc_set_principal(context, ccache, CC_CRED_V4, "foo.BAZ@BAR.ORG", CC_NOERROR, "replace v4 only ccache's principal (empty ccache)");
1002        check_once_cc_set_principal(context, ccache, CC_CRED_V5, "foo/BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "replace v4 principal with v5");
1003    }
1004    else {
1005        log_error("cc_create failed, can't complete test");
1006        failure_count++;
1007    }
1008    if (ccache) {
1009        cc_destroy(context, &ccache);
1010        ccache = NULL;
1011    }
1012
1013    if (context) {
1014        err = destroy_all_ccaches_v2(context);
1015        cc_shutdown(&context);
1016    }
1017
1018    END_TEST_AND_RETURN
1019}
1020
1021// ---------------------------------------------------------------------------
1022
1023cc_int32 check_once_cc_set_principal(apiCB *context, ccache_p *ccache, cc_int32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) {
1024    cc_result err = CC_NOERROR;
1025    char *stored_principal = NULL;
1026
1027    cc_result possible_return_values[5] = {
1028        CC_NOERROR,
1029        CC_NOMEM,
1030        CC_NO_EXIST,
1031        CC_ERR_CRED_VERSION,
1032        CC_BAD_PARM
1033    };
1034
1035    BEGIN_CHECK_ONCE(description);
1036
1037#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1038
1039    err = cc_set_principal(context, ccache, cred_vers, (char *) in_principal);
1040
1041    // check returned error
1042    check_err(err, expected_err, possible_return_values);
1043
1044    if (!err) {
1045        err = cc_get_principal(context, ccache, &stored_principal);
1046    }
1047
1048    // compare stored with input
1049    if (!err) {
1050        check_if(strcmp(stored_principal, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal);
1051    }
1052
1053    if (stored_principal) { cc_free_principal(context, &stored_principal); }
1054
1055    END_CHECK_ONCE;
1056
1057    return err;
1058}
1059
1060// ---------------------------------------------------------------------------
1061
1062int check_cc_store(void) {
1063    cc_result err = 0;
1064    apiCB *context = NULL;
1065    ccache_p *ccache = NULL;
1066    ccache_p *dup_ccache = NULL;
1067    cred_union creds_union;
1068    char *name = NULL;
1069
1070    BEGIN_TEST("cc_store");
1071
1072    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
1073
1074    if (!err) {
1075        err = destroy_all_ccaches_v2(context);
1076    }
1077
1078    if (!err) {
1079        err = cc_create(context, "TEST_CC_STORE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1080    }
1081
1082    // cred with matching version and realm
1083    if (!err) {
1084        err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
1085
1086        if (!err) {
1087            check_once_cc_store(context, ccache, creds_union, CC_NOERROR, "ok creds");
1088            release_v5_creds_union_compat(&creds_union);
1089        }
1090    }
1091
1092    // invalid creds
1093    if (!err) {
1094        err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
1095
1096        if (!err) {
1097            if (creds_union.cred.pV5Cred->client) {
1098                free(creds_union.cred.pV5Cred->client);
1099                creds_union.cred.pV5Cred->client = NULL;
1100            }
1101            check_once_cc_store(context, ccache, creds_union, CC_BAD_PARM, "invalid creds (NULL client string)");
1102
1103            release_v5_creds_union_compat(&creds_union);
1104        }
1105    }
1106
1107    // bad creds version
1108    if (!err) {
1109        err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
1110
1111        if (!err) {
1112            creds_union.cred_type = CC_CRED_MAX;
1113            check_once_cc_store(context, ccache, creds_union, CC_ERR_CRED_VERSION, "CC_CRED_MAX (invalid) into a ccache with only v5 princ");
1114            creds_union.cred_type = CC_CRED_V4;
1115            check_once_cc_store(context, ccache, creds_union, CC_ERR_CRED_VERSION, "v4 creds into a v5 ccache");
1116            creds_union.cred_type = CC_CRED_V5;
1117
1118            release_v5_creds_union_compat(&creds_union);
1119        }
1120    }
1121
1122    // non-existent ccache
1123    if (ccache) {
1124        err = cc_get_name(context, ccache, &name);
1125        if (!err) {
1126            err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache);
1127        }
1128        if (name) { cc_free_name(context, &name); }
1129        if (dup_ccache) { cc_destroy(context, &dup_ccache); }
1130    }
1131
1132    if (!err) {
1133        err = new_v5_creds_union_compat(&creds_union, "BAR.ORG");
1134
1135        if (!err) {
1136            check_once_cc_store(context, ccache, creds_union, CC_NO_EXIST, "invalid ccache");
1137
1138            release_v5_creds_union_compat(&creds_union);
1139        }
1140    }
1141
1142    if (ccache) { cc_close(context, &ccache); }
1143    if (context) {
1144        destroy_all_ccaches_v2(context);
1145        cc_shutdown(&context);
1146    }
1147
1148    END_TEST_AND_RETURN
1149}
1150
1151// ---------------------------------------------------------------------------
1152
1153cc_result check_once_cc_store(apiCB *context, ccache_p *ccache, const cred_union in_creds, cc_int32 expected_err, const char *description) {
1154    cc_result err = CC_NOERROR;
1155    ccache_cit *iterator = NULL;
1156    int found = 0;
1157
1158    cc_result possible_return_values[5] = {
1159        CC_NOERROR,
1160        CC_BAD_PARM,
1161        CC_ERR_CACHE_FULL,
1162        CC_ERR_CRED_VERSION,
1163        CC_NO_EXIST
1164    };
1165
1166    BEGIN_CHECK_ONCE(description);
1167
1168#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1169
1170    err = cc_store(context, ccache, in_creds);
1171
1172    // check returned error
1173    check_err(err, expected_err, possible_return_values);
1174
1175    // make sure credentials were truly stored
1176    if (!err) {
1177        err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
1178    }
1179    while (!err && !found) {
1180        cred_union *creds = NULL;
1181
1182        err = cc_seq_fetch_creds_next(context, &creds, iterator);
1183        if (!err) {
1184            found = !compare_v5_creds_unions_compat(&in_creds, creds);
1185        }
1186
1187        if (creds) { cc_free_creds(context, &creds); }
1188    }
1189
1190    if (err == CC_END) {
1191        check_if(found, "stored credentials not found in ccache");
1192        err = CC_NOERROR;
1193    }
1194
1195    if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
1196
1197    END_CHECK_ONCE;
1198
1199    return err;
1200}
1201
1202// ---------------------------------------------------------------------------
1203
1204int check_cc_remove_cred(void) {
1205    cc_result err = 0;
1206    apiCB *context = NULL;
1207    ccache_p *ccache = NULL;
1208    cred_union *creds_array[10];
1209    ccache_cit *iterator = NULL;
1210    char *name = NULL;
1211    unsigned int i;
1212
1213    BEGIN_TEST("cc_remove_cred");
1214
1215    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
1216
1217    if (!err) {
1218        err = destroy_all_ccaches_v2(context);
1219    }
1220
1221    if (!err) {
1222        err = cc_create(context, "TEST_CC_REMOVE_CRED", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1223    }
1224
1225    // store 10 creds and retrieve their cc_credentials_t representations
1226    for(i = 0; !err && (i < 10); i++) {
1227        cred_union creds;
1228
1229        new_v5_creds_union_compat(&creds, "BAR.ORG");
1230        err = cc_store(context, ccache, creds);
1231        if (err) {
1232            log_error("failure to store creds_union in remove_creds test");
1233        }
1234        release_v5_creds_union_compat(&creds);
1235    }
1236
1237    if (!err) {
1238        err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
1239    }
1240
1241    for (i = 0; !err && i < 10; i++) {
1242        creds_array[i] = NULL;
1243        err = cc_seq_fetch_creds_next(context, &creds_array[i], iterator);
1244    }
1245    if (err == CC_END) { err = CC_NOERROR; }
1246
1247    // remove 10 valid creds
1248    for (i = 0; !err && (i < 10); i++) {
1249        check_once_cc_remove_cred(context, ccache, *creds_array[i], CC_NOERROR, "10 ok creds");
1250    }
1251
1252    // non-existent creds (remove same one twice)
1253    check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NOTFOUND, "removed same creds twice");
1254
1255    // non-existent ccache
1256    if (ccache) {
1257        ccache_p *dup_ccache = NULL;
1258
1259        err = cc_get_name(context, ccache, &name);
1260
1261        if (!err) {
1262            err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache);
1263        }
1264
1265        if (!err) {
1266            err = cc_destroy(context, &dup_ccache);
1267            check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NO_EXIST, "invalid ccache");
1268        }
1269
1270        if (name) { cc_free_name(context, &name); }
1271    }
1272
1273     for(i = 0; i < 10 && creds_array[i]; i++) {
1274        cc_free_creds(context, &creds_array[i]);
1275    }
1276
1277
1278    if (iterator) { cc_seq_fetch_creds_end(context, &iterator); iterator = NULL; }
1279    if (ccache) { cc_close(context, &ccache); }
1280    if (context) {
1281        destroy_all_ccaches_v2(context);
1282        cc_shutdown(&context);
1283    }
1284
1285    END_TEST_AND_RETURN
1286}
1287
1288// ---------------------------------------------------------------------------
1289
1290cc_result check_once_cc_remove_cred(apiCB *context, ccache_p *ccache, cred_union in_creds, cc_int32 expected_err, const char *description) {
1291    cc_result err = CC_NOERROR;
1292    ccache_cit *iterator = NULL;
1293    int found = 0;
1294
1295    cc_result possible_return_values[5] = {
1296        CC_NOERROR,
1297        CC_BAD_PARM,
1298        CC_ERR_CRED_VERSION,
1299        CC_NOTFOUND,
1300        CC_NO_EXIST
1301    };
1302
1303    BEGIN_CHECK_ONCE(description);
1304
1305#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1306
1307    err = cc_remove_cred(context, ccache, in_creds);
1308
1309    // check returned error
1310    check_err(err, expected_err, possible_return_values);
1311
1312    // make sure credentials were truly stored
1313    if (!err) {
1314        err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
1315    }
1316
1317    while (!err && !found) {
1318        cred_union *creds = NULL;
1319
1320        err = cc_seq_fetch_creds_next(context, &creds, iterator);
1321        if (!err) {
1322            found = !compare_v5_creds_unions_compat(&in_creds, creds);
1323        }
1324
1325        if (creds) { cc_free_creds(context, &creds); }
1326    }
1327
1328    if (err == CC_END) {
1329        check_if(found, "credentials not removed from ccache");
1330        err = CC_NOERROR;
1331    }
1332
1333    if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
1334
1335    END_CHECK_ONCE;
1336
1337    return err;
1338}
1339
1340// ---------------------------------------------------------------------------
1341
1342int check_cc_seq_fetch_NCs_begin(void) {
1343    cc_result err = 0;
1344    apiCB *context = NULL;
1345    ccache_p *ccache = NULL;
1346    ccache_cit *iterator = NULL;
1347
1348    BEGIN_TEST("cc_seq_fetch_NCs_begin");
1349
1350    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
1351    if (!err) {
1352        err = destroy_all_ccaches_v2(context);
1353    }
1354    if (!err) {
1355        // try making when there are no existing ccaches (shouldn't make a difference, but just in case)
1356        check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when there are no existing ccaches");
1357
1358        err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1359    }
1360    if (!err) {
1361        // try making when at least one ccache already exists (just to cover all our bases)
1362        check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when at least one ccache already exists");
1363
1364        // try bad parameters
1365        check_once_cc_seq_fetch_NCs_begin(context, NULL, CC_BAD_PARM, "NULL param"); // NULL iterator
1366    }
1367    // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite
1368
1369    if (ccache ) { cc_close(context, &ccache); }
1370    if (context) { cc_shutdown(&context); }
1371
1372    END_TEST_AND_RETURN
1373}
1374
1375// ---------------------------------------------------------------------------
1376
1377cc_result check_once_cc_seq_fetch_NCs_begin(apiCB *context, ccache_cit **iterator, cc_result expected_err, const char *description) {
1378    cc_result err = CC_NOERROR;
1379
1380    cc_result possible_return_values[4] = {
1381        CC_NOERROR,
1382        CC_BAD_PARM,
1383        CC_NOMEM,
1384        CC_NO_EXIST
1385    };
1386
1387    BEGIN_CHECK_ONCE(description);
1388
1389#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1390
1391     err = cc_seq_fetch_NCs_begin(context, iterator);
1392
1393    // check returned error
1394    check_err(err, expected_err, possible_return_values);
1395
1396    // we'll do a comprehensive test of cc_ccache_iterator related functions later
1397
1398    return err;
1399}
1400
1401// ---------------------------------------------------------------------------
1402
1403int check_cc_seq_fetch_NCs_next(void) {
1404    cc_result err = 0;
1405    apiCB *context = NULL;
1406    ccache_p *ccache = NULL;
1407    ccache_cit *iterator = NULL;
1408    unsigned int i;
1409
1410    BEGIN_TEST("cc_seq_fetch_NCs_next");
1411
1412    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
1413
1414    if (!err) {
1415        err = destroy_all_ccaches_v2(context);
1416    }
1417
1418    // iterate with no ccaches
1419    if (!err) {
1420        err = cc_seq_fetch_NCs_begin(context, &iterator);
1421    }
1422    check_once_cc_seq_fetch_NCs_next(context, iterator, 0, CC_NOERROR, "iterating over an empty collection");
1423    if (iterator) {
1424        cc_seq_fetch_creds_end(context, &iterator);
1425        iterator = NULL;
1426    }
1427
1428    // iterate with one ccache
1429    if (!err) {
1430        destroy_all_ccaches_v2(context);
1431        err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1432    }
1433    if (ccache) {
1434        cc_close(context, &ccache);
1435        ccache = NULL;
1436    }
1437    if (!err) {
1438        err = cc_seq_fetch_NCs_begin(context, &iterator);
1439    }
1440    check_once_cc_seq_fetch_NCs_next(context, iterator, 1, CC_NOERROR, "iterating over a collection of 1 ccache");
1441    if (iterator) {
1442        cc_seq_fetch_creds_end(context, &iterator);
1443        iterator = NULL;
1444    }
1445
1446    // iterate with several ccaches
1447    if (!err) {
1448        destroy_all_ccaches_v2(context);
1449    }
1450    for(i = 0; !err && (i < 1000); i++)
1451    {
1452        char *name = NULL;
1453
1454        if (i%100 == 0) fprintf(stdout, ".");
1455        asprintf (&name, "TEST_CC_SEQ_FETCH_NCS_NEXT_%d", i);
1456        err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1457        if (ccache) {
1458            cc_close(context, &ccache);
1459            ccache = NULL;
1460        }
1461        free (name);
1462    }
1463    if (!err) {
1464        err = cc_seq_fetch_NCs_begin(context, &iterator);
1465    }
1466    check_once_cc_seq_fetch_NCs_next(context, iterator, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache");
1467    if (iterator) {
1468        cc_seq_fetch_creds_end(context, &iterator);
1469        iterator = NULL;
1470    }
1471
1472
1473    if (ccache) { cc_close(context, &ccache); }
1474    if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
1475    if (context) {
1476        destroy_all_ccaches_v2(context);
1477        cc_shutdown(&context);
1478    }
1479
1480    END_TEST_AND_RETURN
1481}
1482
1483// ---------------------------------------------------------------------------
1484
1485cc_result check_once_cc_seq_fetch_NCs_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) {
1486    cc_result err = CC_NOERROR;
1487
1488    cc_result possible_return_values[5] = {
1489        CC_NOERROR,
1490        CC_END,
1491        CC_BAD_PARM,
1492        CC_NOMEM,
1493        CC_NO_EXIST
1494    };
1495#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1496
1497    ccache_p *ccache = NULL;
1498    cc_uint32 actual_count = 0;
1499
1500    BEGIN_CHECK_ONCE(description);
1501
1502    while (!err) {
1503        err = cc_seq_fetch_NCs_next(context, &ccache, iterator);
1504        if (ccache) {
1505            actual_count++;
1506            cc_close(context, &ccache);
1507            ccache = NULL;
1508        }
1509    }
1510    if (err == CC_END) {
1511        err = CC_NOERROR;
1512    }
1513
1514    // check returned error
1515    check_err(err, expected_err, possible_return_values);
1516
1517    check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
1518
1519    END_CHECK_ONCE;
1520
1521    return err;
1522}
1523
1524// ---------------------------------------------------------------------------
1525
1526int check_cc_get_NC_info(void) {
1527    cc_result err = 0;
1528    apiCB *context = NULL;
1529    ccache_p *ccache = NULL;
1530    unsigned int i;
1531
1532    BEGIN_TEST("cc_get_NC_info");
1533
1534    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
1535
1536    if (!err) {
1537        err = destroy_all_ccaches_v2(context);
1538    }
1539
1540    // iterate with no ccaches
1541    check_once_cc_get_NC_info(context, "", "", CC_CRED_MAX, 0, CC_NOERROR, "iterating over an empty collection");
1542
1543    // iterate with one ccache
1544    if (!err) {
1545        destroy_all_ccaches_v2(context);
1546        err = cc_create(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1547    }
1548    if (ccache) {
1549        cc_close(context, &ccache);
1550        ccache = NULL;
1551    }
1552    check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1, CC_NOERROR, "iterating over a collection of 1 ccache");
1553
1554    // iterate with several ccaches
1555    if (!err) {
1556        destroy_all_ccaches_v2(context);
1557    }
1558    for(i = 0; !err && (i < 1000); i++)
1559    {
1560        char *name = NULL;
1561
1562        if (i%100 == 0) fprintf(stdout, ".");
1563        asprintf (&name, "TEST_CC_GET_NC_INFO_%d", i);
1564        err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1565        if (ccache) {
1566            cc_close(context, &ccache);
1567            ccache = NULL;
1568        }
1569        free (name);
1570    }
1571    check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache");
1572
1573    if (ccache) { cc_close(context, &ccache); }
1574    if (context) {
1575        destroy_all_ccaches_v2(context);
1576        cc_shutdown(&context);
1577    }
1578
1579    END_TEST_AND_RETURN
1580}
1581
1582// ---------------------------------------------------------------------------
1583
1584cc_result check_once_cc_get_NC_info(apiCB *context,
1585                                    const char *expected_name_prefix,
1586                                    const char *expected_principal,
1587                                    cc_int32 expected_version,
1588                                    cc_uint32 expected_count,
1589                                    cc_result expected_err,
1590                                    const char *description) {
1591    cc_result err = CC_NOERROR;
1592    infoNC **info = NULL;
1593
1594    cc_result possible_return_values[4] = {
1595        CC_NOERROR,
1596        CC_BAD_PARM,
1597        CC_NOMEM,
1598        CC_NO_EXIST
1599    };
1600#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1601
1602    cc_uint32 actual_count = 0;
1603
1604    BEGIN_CHECK_ONCE(description);
1605
1606    err = cc_get_NC_info(context, &info);
1607
1608    for (actual_count = 0; !err && info[actual_count]; actual_count++) {
1609        check_if(strncmp(info[actual_count]->name, expected_name_prefix, strlen(expected_name_prefix)), "got incorrect ccache name");
1610        check_if(strcmp(info[actual_count]->principal, expected_principal), "got incorrect principal name");
1611        check_if(info[actual_count]->vers != expected_version, "got incorrect cred version");
1612    }
1613
1614    // check returned error
1615    check_err(err, expected_err, possible_return_values);
1616
1617    check_if(actual_count != expected_count, "NC info didn't list all ccaches");
1618
1619    if (info) { cc_free_NC_info (context, &info); }
1620    END_CHECK_ONCE;
1621
1622    return err;
1623}
1624
1625// ---------------------------------------------------------------------------
1626
1627int check_cc_seq_fetch_creds_begin(void) {
1628    cc_result err = 0;
1629    apiCB *context = NULL;
1630    ccache_p *ccache = NULL;
1631    ccache_p *dup_ccache = NULL;
1632    ccache_cit *creds_iterator = NULL;
1633    char *name = NULL;
1634
1635    BEGIN_TEST("cc_seq_fetch_creds_begin");
1636
1637    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
1638
1639    if (!err) {
1640        err = destroy_all_ccaches_v2(context);
1641    }
1642
1643    if (!err) {
1644        err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1645    }
1646
1647    // valid params
1648    if (!err) {
1649        check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NOERROR, "valid params");
1650    }
1651    if (creds_iterator) {
1652        cc_seq_fetch_creds_end(context, &creds_iterator);
1653        creds_iterator = NULL;
1654    }
1655
1656    // NULL out param
1657    if (!err) {
1658        check_once_cc_seq_fetch_creds_begin(context, ccache, NULL, CC_BAD_PARM, "NULL out iterator param");
1659    }
1660    if (creds_iterator) {
1661        cc_seq_fetch_creds_end(context, &creds_iterator);
1662        creds_iterator = NULL;
1663    }
1664
1665    // non-existent ccache
1666    if (ccache) {
1667        err = cc_get_name(context, ccache, &name);
1668        if (!err) {
1669            err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache);
1670        }
1671        if (name) { cc_free_name(context, &name); }
1672        if (dup_ccache) { cc_destroy(context, &dup_ccache); }
1673    }
1674
1675    if (!err) {
1676        check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NO_EXIST, "invalid ccache");
1677    }
1678
1679    if (creds_iterator) {
1680        cc_seq_fetch_creds_end(context, &creds_iterator);
1681        creds_iterator = NULL;
1682    }
1683    if (ccache) { cc_close(context, &ccache); }
1684    if (context) {
1685        destroy_all_ccaches_v2(context);
1686        cc_shutdown(&context);
1687    }
1688
1689    END_TEST_AND_RETURN
1690}
1691
1692// ---------------------------------------------------------------------------
1693
1694cc_result check_once_cc_seq_fetch_creds_begin(apiCB *context, ccache_p *ccache, ccache_cit **iterator, cc_result expected_err, const char *description) {
1695    cc_result err = CC_NOERROR;
1696
1697    cc_result possible_return_values[5] = {
1698        CC_NOERROR,
1699        CC_BAD_PARM,
1700        CC_NOMEM,
1701        CC_NO_EXIST
1702    };
1703
1704    BEGIN_CHECK_ONCE(description);
1705
1706#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1707
1708    err = cc_seq_fetch_creds_begin(context, ccache, iterator);
1709
1710    // check returned error
1711    check_err(err, expected_err, possible_return_values);
1712
1713    END_CHECK_ONCE;
1714
1715    return err;
1716}
1717
1718// ---------------------------------------------------------------------------
1719
1720int check_cc_seq_fetch_creds_next(void) {
1721    cc_result err = 0;
1722    apiCB *context = NULL;
1723    ccache_p *ccache = NULL;
1724    cred_union creds_union;
1725    ccache_cit *iterator = NULL;
1726    unsigned int i;
1727
1728    BEGIN_TEST("cc_seq_fetch_creds_next");
1729
1730    err = cc_initialize(&context, ccapi_version_2, NULL, NULL);
1731
1732    if (!err) {
1733        err = destroy_all_ccaches_v2(context);
1734    }
1735
1736    // iterate with no creds
1737    if (!err) {
1738        err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1739    }
1740    if (!err) {
1741        err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
1742    }
1743    check_once_cc_seq_fetch_creds_next(context, iterator, 0, CC_NOERROR, "iterating over an empty ccache");
1744    if (iterator) {
1745        cc_seq_fetch_creds_end(context, &iterator);
1746        iterator = NULL;
1747    }
1748    if (ccache) {
1749        cc_close(context, &ccache);
1750        ccache = NULL;
1751    }
1752
1753    // iterate with one cred
1754    if (!err) {
1755        destroy_all_ccaches_v2(context);
1756        err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1757    }
1758    if (!err) {
1759        new_v5_creds_union_compat(&creds_union, "BAR.ORG");
1760        err = cc_store(context, ccache, creds_union);
1761        release_v5_creds_union_compat(&creds_union);
1762    }
1763    if (!err) {
1764        err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
1765    }
1766    check_once_cc_seq_fetch_creds_next(context, iterator, 1, CC_NOERROR, "iterating over a ccache with 1 cred");
1767    if (iterator) {
1768        cc_seq_fetch_creds_end(context, &iterator);
1769        iterator = NULL;
1770    }
1771    if (ccache) {
1772        cc_close(context, &ccache);
1773        ccache = NULL;
1774    }
1775
1776    // iterate with several creds
1777    if (!err) {
1778        destroy_all_ccaches_v2(context);
1779        err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache);
1780    }
1781    for(i = 0; !err && (i < 1000); i++) {
1782        if (i%100 == 0) fprintf(stdout, ".");
1783        new_v5_creds_union_compat(&creds_union, "BAR.ORG");
1784        err = cc_store(context, ccache, creds_union);
1785        release_v5_creds_union_compat(&creds_union);
1786    }
1787    if (!err) {
1788        err = cc_seq_fetch_creds_begin(context, ccache, &iterator);
1789    }
1790    check_once_cc_seq_fetch_creds_next(context, iterator, 1000, CC_NOERROR, "iterating over a ccache with 1000 creds");
1791
1792    if (ccache) { cc_close(context, &ccache); }
1793    if (iterator) { cc_seq_fetch_creds_end(context, &iterator); }
1794    if (context) {
1795        destroy_all_ccaches_v2(context);
1796        cc_shutdown(&context);
1797    }
1798
1799    END_TEST_AND_RETURN
1800}
1801
1802// ---------------------------------------------------------------------------
1803
1804cc_result check_once_cc_seq_fetch_creds_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) {
1805    cc_result   err             = CC_NOERROR;
1806    cred_union *creds           = NULL;
1807    cc_uint32   actual_count    = 0;
1808
1809    cc_result possible_return_values[5] = {
1810        CC_NOERROR,
1811        CC_END,
1812        CC_BAD_PARM,
1813        CC_NOMEM,
1814        CC_NO_EXIST,
1815    };
1816
1817    BEGIN_CHECK_ONCE(description);
1818
1819#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0])
1820
1821    while (!err) {
1822        err = cc_seq_fetch_creds_next(context, &creds, iterator);
1823        if (creds) {
1824            actual_count++;
1825            cc_free_creds(context, &creds);
1826            creds = NULL;
1827        }
1828    }
1829    if (err == CC_END) {
1830        err = CC_NOERROR;
1831    }
1832
1833    // check returned error
1834    check_err(err, expected_err, possible_return_values);
1835
1836    check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches");
1837
1838    END_CHECK_ONCE;
1839
1840    return err;
1841}
1842
1843