Home | History | Annotate | Line # | Download | only in krb5
test_cc.c revision 1.1.1.1.4.1
      1 /*	$NetBSD: test_cc.c,v 1.1.1.1.4.1 2014/05/22 13:21:28 yamt Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2003 - 2007 Kungliga Tekniska Hgskolan
      5  * (Royal Institute of Technology, Stockholm, Sweden).
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  *
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * 3. Neither the name of KTH nor the names of its contributors may be
     20  *    used to endorse or promote products derived from this software without
     21  *    specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     24  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
     27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     30  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     31  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     32  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     33  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
     34 
     35 #include "krb5_locl.h"
     36 #include <krb5/getarg.h>
     37 #include <err.h>
     38 
     39 static int debug_flag	= 0;
     40 static int version_flag = 0;
     41 static int help_flag	= 0;
     42 
     43 #ifdef KRB5_USE_PATH_TOKENS
     44 #define TEST_CC_NAME "%{TEMP}/krb5-cc-test-foo"
     45 #else
     46 #define TEST_CC_NAME "/tmp/krb5-cc-test-foo"
     47 #endif
     48 
     49 static void
     50 test_default_name(krb5_context context)
     51 {
     52     krb5_error_code ret;
     53     const char *p, *test_cc_name = TEST_CC_NAME;
     54     char *p1, *p2, *p3;
     55 
     56     p = krb5_cc_default_name(context);
     57     if (p == NULL)
     58 	krb5_errx (context, 1, "krb5_cc_default_name 1 failed");
     59     p1 = estrdup(p);
     60 
     61     ret = krb5_cc_set_default_name(context, NULL);
     62     if (p == NULL)
     63 	krb5_errx (context, 1, "krb5_cc_set_default_name failed");
     64 
     65     p = krb5_cc_default_name(context);
     66     if (p == NULL)
     67 	krb5_errx (context, 1, "krb5_cc_default_name 2 failed");
     68     p2 = estrdup(p);
     69 
     70     if (strcmp(p1, p2) != 0)
     71 	krb5_errx (context, 1, "krb5_cc_default_name no longer same");
     72 
     73     ret = krb5_cc_set_default_name(context, test_cc_name);
     74     if (p == NULL)
     75 	krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed");
     76 
     77     p = krb5_cc_default_name(context);
     78     if (p == NULL)
     79 	krb5_errx (context, 1, "krb5_cc_default_name 2 failed");
     80     p3 = estrdup(p);
     81 
     82 #ifndef KRB5_USE_PATH_TOKENS
     83     /* If we are using path tokens, we don't expect the p3 and
     84        test_cc_name to match since p3 is going to have expanded
     85        tokens. */
     86     if (strcmp(p3, test_cc_name) != 0)
     87 	krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed");
     88 #endif
     89 
     90     free(p1);
     91     free(p2);
     92     free(p3);
     93 }
     94 
     95 /*
     96  * Check that a closed cc still keeps it data and that it's no longer
     97  * there when it's destroyed.
     98  */
     99 
    100 static void
    101 test_mcache(krb5_context context)
    102 {
    103     krb5_error_code ret;
    104     krb5_ccache id, id2;
    105     const char *nc, *tc;
    106     char *c;
    107     krb5_principal p, p2;
    108 
    109     ret = krb5_parse_name(context, "lha (at) SU.SE", &p);
    110     if (ret)
    111 	krb5_err(context, 1, ret, "krb5_parse_name");
    112 
    113     ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
    114     if (ret)
    115 	krb5_err(context, 1, ret, "krb5_cc_new_unique");
    116 
    117     ret = krb5_cc_initialize(context, id, p);
    118     if (ret)
    119 	krb5_err(context, 1, ret, "krb5_cc_initialize");
    120 
    121     nc = krb5_cc_get_name(context, id);
    122     if (nc == NULL)
    123 	krb5_errx(context, 1, "krb5_cc_get_name");
    124 
    125     tc = krb5_cc_get_type(context, id);
    126     if (tc == NULL)
    127 	krb5_errx(context, 1, "krb5_cc_get_name");
    128 
    129     if (asprintf(&c, "%s:%s", tc, nc) < 0 || c == NULL)
    130 	errx(1, "malloc");
    131 
    132     krb5_cc_close(context, id);
    133 
    134     ret = krb5_cc_resolve(context, c, &id2);
    135     if (ret)
    136 	krb5_err(context, 1, ret, "krb5_cc_resolve");
    137 
    138     ret = krb5_cc_get_principal(context, id2, &p2);
    139     if (ret)
    140 	krb5_err(context, 1, ret, "krb5_cc_get_principal");
    141 
    142     if (krb5_principal_compare(context, p, p2) == FALSE)
    143 	krb5_errx(context, 1, "p != p2");
    144 
    145     krb5_cc_destroy(context, id2);
    146     krb5_free_principal(context, p);
    147     krb5_free_principal(context, p2);
    148 
    149     ret = krb5_cc_resolve(context, c, &id2);
    150     if (ret)
    151 	krb5_err(context, 1, ret, "krb5_cc_resolve");
    152 
    153     ret = krb5_cc_get_principal(context, id2, &p2);
    154     if (ret == 0)
    155 	krb5_errx(context, 1, "krb5_cc_get_principal");
    156 
    157     krb5_cc_destroy(context, id2);
    158     free(c);
    159 }
    160 
    161 /*
    162  * Test that init works on a destroyed cc.
    163  */
    164 
    165 static void
    166 test_init_vs_destroy(krb5_context context, const char *type)
    167 {
    168     krb5_error_code ret;
    169     krb5_ccache id, id2;
    170     krb5_principal p, p2;
    171     char *n = NULL;
    172 
    173     ret = krb5_parse_name(context, "lha (at) SU.SE", &p);
    174     if (ret)
    175 	krb5_err(context, 1, ret, "krb5_parse_name");
    176 
    177     ret = krb5_cc_new_unique(context, type, NULL, &id);
    178     if (ret)
    179 	krb5_err(context, 1, ret, "krb5_cc_new_unique: %s", type);
    180 
    181     if (asprintf(&n, "%s:%s",
    182 		 krb5_cc_get_type(context, id),
    183 		 krb5_cc_get_name(context, id)) < 0 || n == NULL)
    184 	errx(1, "malloc");
    185 
    186 
    187     ret = krb5_cc_resolve(context, n, &id2);
    188     free(n);
    189     if (ret)
    190 	krb5_err(context, 1, ret, "krb5_cc_resolve");
    191 
    192     krb5_cc_destroy(context, id);
    193 
    194     ret = krb5_cc_initialize(context, id2, p);
    195     if (ret)
    196 	krb5_err(context, 1, ret, "krb5_cc_initialize");
    197 
    198     ret = krb5_cc_get_principal(context, id2, &p2);
    199     if (ret)
    200 	krb5_err(context, 1, ret, "krb5_cc_get_principal");
    201 
    202     krb5_cc_destroy(context, id2);
    203     krb5_free_principal(context, p);
    204     krb5_free_principal(context, p2);
    205 }
    206 
    207 static void
    208 test_cache_remove(krb5_context context, const char *type)
    209 {
    210     krb5_error_code ret;
    211     krb5_ccache id;
    212     krb5_principal p;
    213     krb5_creds cred;
    214 
    215     ret = krb5_parse_name(context, "lha (at) SU.SE", &p);
    216     if (ret)
    217 	krb5_err(context, 1, ret, "krb5_parse_name");
    218 
    219     ret = krb5_cc_new_unique(context, type, NULL, &id);
    220     if (ret)
    221 	krb5_err(context, 1, ret, "krb5_cc_gen_new: %s", type);
    222 
    223     ret = krb5_cc_initialize(context, id, p);
    224     if (ret)
    225 	krb5_err(context, 1, ret, "krb5_cc_initialize");
    226 
    227     /* */
    228     memset(&cred, 0, sizeof(cred));
    229     ret = krb5_parse_name(context, "krbtgt/SU.SE@SU.SE", &cred.server);
    230     if (ret)
    231 	krb5_err(context, 1, ret, "krb5_parse_name");
    232     ret = krb5_parse_name(context, "lha (at) SU.SE", &cred.client);
    233     if (ret)
    234 	krb5_err(context, 1, ret, "krb5_parse_name");
    235 
    236     ret = krb5_cc_store_cred(context, id, &cred);
    237     if (ret)
    238 	krb5_err(context, 1, ret, "krb5_cc_store_cred");
    239 
    240     ret = krb5_cc_remove_cred(context, id, 0, &cred);
    241     if (ret)
    242 	krb5_err(context, 1, ret, "krb5_cc_remove_cred");
    243 
    244     ret = krb5_cc_destroy(context, id);
    245     if (ret)
    246 	krb5_err(context, 1, ret, "krb5_cc_destroy");
    247 
    248     krb5_free_principal(context, p);
    249     krb5_free_principal(context, cred.server);
    250     krb5_free_principal(context, cred.client);
    251 }
    252 
    253 static void
    254 test_mcc_default(void)
    255 {
    256     krb5_context context;
    257     krb5_error_code ret;
    258     krb5_ccache id, id2;
    259     int i;
    260 
    261     for (i = 0; i < 10; i++) {
    262 
    263 	ret = krb5_init_context(&context);
    264 	if (ret)
    265 	    krb5_err(context, 1, ret, "krb5_init_context");
    266 
    267 	ret = krb5_cc_set_default_name(context, "MEMORY:foo");
    268 	if (ret)
    269 	    krb5_err(context, 1, ret, "krb5_cc_set_default_name");
    270 
    271 	ret = krb5_cc_default(context, &id);
    272 	if (ret)
    273 	    krb5_err(context, 1, ret, "krb5_cc_default");
    274 
    275 	ret = krb5_cc_default(context, &id2);
    276 	if (ret)
    277 	    krb5_err(context, 1, ret, "krb5_cc_default");
    278 
    279 	ret = krb5_cc_close(context, id);
    280 	if (ret)
    281 	    krb5_err(context, 1, ret, "krb5_cc_close");
    282 
    283 	ret = krb5_cc_close(context, id2);
    284 	if (ret)
    285 	    krb5_err(context, 1, ret, "krb5_cc_close");
    286 
    287 	krb5_free_context(context);
    288     }
    289 }
    290 
    291 struct {
    292     char *str;
    293     int fail;
    294     char *res;
    295 } cc_names[] = {
    296     { "foo", 0, "foo" },
    297     { "foo%}", 0, "foo%}" },
    298     { "%{uid}", 0 },
    299     { "foo%{null}", 0, "foo" },
    300     { "foo%{null}bar", 0, "foobar" },
    301     { "%{", 1 },
    302     { "%{foo %{", 1 },
    303     { "%{{", 1 },
    304     { "%{{}", 1 },
    305     { "%{nulll}", 1 },
    306     { "%{does not exist}", 1 },
    307     { "%{}", 1 },
    308 #ifdef KRB5_USE_PATH_TOKENS
    309     { "%{APPDATA}", 0 },
    310     { "%{COMMON_APPDATA}", 0},
    311     { "%{LOCAL_APPDATA}", 0},
    312     { "%{SYSTEM}", 0},
    313     { "%{WINDOWS}", 0},
    314     { "%{TEMP}", 0},
    315     { "%{USERID}", 0},
    316     { "%{uid}", 0},
    317     { "%{USERCONFIG}", 0},
    318     { "%{COMMONCONFIG}", 0},
    319     { "%{LIBDIR}", 0},
    320     { "%{BINDIR}", 0},
    321     { "%{LIBEXEC}", 0},
    322     { "%{SBINDIR}", 0},
    323 #endif
    324 };
    325 
    326 static void
    327 test_def_cc_name(krb5_context context)
    328 {
    329     krb5_error_code ret;
    330     char *str;
    331     int i;
    332 
    333     for (i = 0; i < sizeof(cc_names)/sizeof(cc_names[0]); i++) {
    334 	ret = _krb5_expand_default_cc_name(context, cc_names[i].str, &str);
    335 	if (ret) {
    336 	    if (cc_names[i].fail == 0)
    337 		krb5_errx(context, 1, "test %d \"%s\" failed",
    338 			  i, cc_names[i].str);
    339 	} else {
    340 	    if (cc_names[i].fail)
    341 		krb5_errx(context, 1, "test %d \"%s\" was successful",
    342 			  i, cc_names[i].str);
    343 	    if (cc_names[i].res && strcmp(cc_names[i].res, str) != 0)
    344 		krb5_errx(context, 1, "test %d %s != %s",
    345 			  i, cc_names[i].res, str);
    346 	    if (debug_flag)
    347 		printf("%s => %s\n", cc_names[i].str, str);
    348 	    free(str);
    349 	}
    350     }
    351 }
    352 
    353 static void
    354 test_cache_find(krb5_context context, const char *principal, int find)
    355 {
    356     krb5_principal client;
    357     krb5_error_code ret;
    358     krb5_ccache id = NULL;
    359 
    360     ret = krb5_parse_name(context, principal, &client);
    361     if (ret)
    362 	krb5_err(context, 1, ret, "parse_name for %s failed", principal);
    363 
    364     ret = krb5_cc_cache_match(context, client, &id);
    365     if (ret && find)
    366 	krb5_err(context, 1, ret, "cc_cache_match for %s failed", principal);
    367     if (ret == 0 && !find)
    368 	krb5_err(context, 1, ret, "cc_cache_match for %s found", principal);
    369 
    370     if (id)
    371 	krb5_cc_close(context, id);
    372     krb5_free_principal(context, client);
    373 }
    374 
    375 
    376 static void
    377 test_cache_iter(krb5_context context, const char *type, int destroy)
    378 {
    379     krb5_cc_cache_cursor cursor;
    380     krb5_error_code ret;
    381     krb5_ccache id;
    382 
    383     ret = krb5_cc_cache_get_first (context, type, &cursor);
    384     if (ret == KRB5_CC_NOSUPP)
    385 	return;
    386     else if (ret)
    387 	krb5_err(context, 1, ret, "krb5_cc_cache_get_first(%s)", type);
    388 
    389 
    390     while ((ret = krb5_cc_cache_next (context, cursor, &id)) == 0) {
    391 	krb5_principal principal;
    392 	char *name;
    393 
    394 	if (debug_flag)
    395 	    printf("name: %s\n", krb5_cc_get_name(context, id));
    396 	ret = krb5_cc_get_principal(context, id, &principal);
    397 	if (ret == 0) {
    398 	    ret = krb5_unparse_name(context, principal, &name);
    399 	    if (ret == 0) {
    400 		if (debug_flag)
    401 		    printf("\tprincipal: %s\n", name);
    402 		free(name);
    403 	    }
    404 	    krb5_free_principal(context, principal);
    405 	}
    406 	if (destroy)
    407 	    krb5_cc_destroy(context, id);
    408 	else
    409 	    krb5_cc_close(context, id);
    410     }
    411 
    412     krb5_cc_cache_end_seq_get(context, cursor);
    413 }
    414 
    415 static void
    416 test_cache_iter_all(krb5_context context)
    417 {
    418     krb5_cccol_cursor cursor;
    419     krb5_error_code ret;
    420     krb5_ccache id;
    421 
    422     ret = krb5_cccol_cursor_new (context, &cursor);
    423     if (ret)
    424 	krb5_err(context, 1, ret, "krb5_cccol_cursor_new");
    425 
    426 
    427     while ((ret = krb5_cccol_cursor_next (context, cursor, &id)) == 0 && id != NULL) {
    428 	krb5_principal principal;
    429 	char *name;
    430 
    431 	if (debug_flag)
    432 	    printf("name: %s\n", krb5_cc_get_name(context, id));
    433 	ret = krb5_cc_get_principal(context, id, &principal);
    434 	if (ret == 0) {
    435 	    ret = krb5_unparse_name(context, principal, &name);
    436 	    if (ret == 0) {
    437 		if (debug_flag)
    438 		    printf("\tprincipal: %s\n", name);
    439 		free(name);
    440 	    }
    441 	    krb5_free_principal(context, principal);
    442 	}
    443 	krb5_cc_close(context, id);
    444     }
    445 
    446     krb5_cccol_cursor_free(context, &cursor);
    447 }
    448 
    449 
    450 static void
    451 test_copy(krb5_context context, const char *from, const char *to)
    452 {
    453     krb5_ccache fromid, toid;
    454     krb5_error_code ret;
    455     krb5_principal p, p2;
    456 
    457     ret = krb5_parse_name(context, "lha (at) SU.SE", &p);
    458     if (ret)
    459 	krb5_err(context, 1, ret, "krb5_parse_name");
    460 
    461     ret = krb5_cc_new_unique(context, from, NULL, &fromid);
    462     if (ret)
    463 	krb5_err(context, 1, ret, "krb5_cc_new_unique: %s", from);
    464 
    465     ret = krb5_cc_initialize(context, fromid, p);
    466     if (ret)
    467 	krb5_err(context, 1, ret, "krb5_cc_initialize");
    468 
    469     ret = krb5_cc_new_unique(context, to, NULL, &toid);
    470     if (ret)
    471 	krb5_err(context, 1, ret, "krb5_cc_gen_new: %s", to);
    472 
    473     ret = krb5_cc_copy_cache(context, fromid, toid);
    474     if (ret)
    475 	krb5_err(context, 1, ret, "krb5_cc_copy_cache");
    476 
    477     ret = krb5_cc_get_principal(context, toid, &p2);
    478     if (ret)
    479 	krb5_err(context, 1, ret, "krb5_cc_get_principal");
    480 
    481     if (krb5_principal_compare(context, p, p2) == FALSE)
    482 	krb5_errx(context, 1, "p != p2");
    483 
    484     krb5_free_principal(context, p);
    485     krb5_free_principal(context, p2);
    486 
    487     krb5_cc_destroy(context, fromid);
    488     krb5_cc_destroy(context, toid);
    489 }
    490 
    491 static void
    492 test_move(krb5_context context, const char *type)
    493 {
    494     const krb5_cc_ops *ops;
    495     krb5_ccache fromid, toid;
    496     krb5_error_code ret;
    497     krb5_principal p, p2;
    498 
    499     ops = krb5_cc_get_prefix_ops(context, type);
    500     if (ops == NULL)
    501 	return;
    502 
    503     ret = krb5_cc_new_unique(context, type, NULL, &fromid);
    504     if (ret == KRB5_CC_NOSUPP)
    505 	return;
    506     else if (ret)
    507 	krb5_err(context, 1, ret, "krb5_cc_new_unique: %s", type);
    508 
    509     ret = krb5_parse_name(context, "lha (at) SU.SE", &p);
    510     if (ret)
    511 	krb5_err(context, 1, ret, "krb5_parse_name");
    512 
    513     ret = krb5_cc_initialize(context, fromid, p);
    514     if (ret)
    515 	krb5_err(context, 1, ret, "krb5_cc_initialize");
    516 
    517     ret = krb5_cc_new_unique(context, type, NULL, &toid);
    518     if (ret)
    519 	krb5_err(context, 1, ret, "krb5_cc_new_unique");
    520 
    521     ret = krb5_cc_initialize(context, toid, p);
    522     if (ret)
    523 	krb5_err(context, 1, ret, "krb5_cc_initialize");
    524 
    525     ret = krb5_cc_get_principal(context, toid, &p2);
    526     if (ret)
    527 	krb5_err(context, 1, ret, "krb5_cc_get_principal");
    528 
    529     if (krb5_principal_compare(context, p, p2) == FALSE)
    530 	krb5_errx(context, 1, "p != p2");
    531 
    532     krb5_free_principal(context, p);
    533     krb5_free_principal(context, p2);
    534 
    535     krb5_cc_destroy(context, toid);
    536     krb5_cc_destroy(context, fromid);
    537 }
    538 
    539 
    540 static void
    541 test_prefix_ops(krb5_context context, const char *name, const krb5_cc_ops *ops)
    542 {
    543     const krb5_cc_ops *o;
    544 
    545     o = krb5_cc_get_prefix_ops(context, name);
    546     if (o == NULL)
    547 	krb5_errx(context, 1, "found no match for prefix '%s'", name);
    548     if (strcmp(o->prefix, ops->prefix) != 0)
    549 	krb5_errx(context, 1, "ops for prefix '%s' is not "
    550 		  "the expected %s != %s", name, o->prefix, ops->prefix);
    551 }
    552 
    553 static void
    554 test_cc_config(krb5_context context)
    555 {
    556     krb5_error_code ret;
    557     krb5_principal p;
    558     krb5_ccache id;
    559     unsigned int i;
    560 
    561     ret = krb5_cc_new_unique(context, "MEMORY", "bar", &id);
    562     if (ret)
    563 	krb5_err(context, 1, ret, "krb5_cc_new_unique");
    564 
    565     ret = krb5_parse_name(context, "lha (at) SU.SE", &p);
    566     if (ret)
    567 	krb5_err(context, 1, ret, "krb5_parse_name");
    568 
    569     ret = krb5_cc_initialize(context, id, p);
    570     if (ret)
    571 	krb5_err(context, 1, ret, "krb5_cc_initialize");
    572 
    573     for (i = 0; i < 1000; i++) {
    574 	krb5_data data, data2;
    575 	const char *name = "foo";
    576 	krb5_principal p1 = NULL;
    577 
    578 	if (i & 1)
    579 	    p1 = p;
    580 
    581 	data.data = rk_UNCONST(name);
    582 	data.length = strlen(name);
    583 
    584 	ret = krb5_cc_set_config(context, id, p1, "FriendlyName", &data);
    585 	if (ret)
    586 	    krb5_errx(context, 1, "krb5_cc_set_config: add");
    587 
    588 	ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2);
    589 	if (ret)
    590 	    krb5_errx(context, 1, "krb5_cc_get_config: first");
    591 	krb5_data_free(&data2);
    592 
    593 	ret = krb5_cc_set_config(context, id, p1, "FriendlyName", &data);
    594 	if (ret)
    595 	    krb5_errx(context, 1, "krb5_cc_set_config: add -second");
    596 
    597 	ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2);
    598 	if (ret)
    599 	    krb5_errx(context, 1, "krb5_cc_get_config: second");
    600 	krb5_data_free(&data2);
    601 
    602 	ret = krb5_cc_set_config(context, id, p1, "FriendlyName", NULL);
    603 	if (ret)
    604 	    krb5_errx(context, 1, "krb5_cc_set_config: delete");
    605 
    606 	ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2);
    607 	if (ret == 0)
    608 	    krb5_errx(context, 1, "krb5_cc_get_config: non-existant");
    609     }
    610 
    611     krb5_cc_destroy(context, id);
    612     krb5_free_principal(context, p);
    613 }
    614 
    615 
    616 static struct getargs args[] = {
    617     {"debug",	'd',	arg_flag,	&debug_flag,
    618      "turn on debuggin", NULL },
    619     {"version",	0,	arg_flag,	&version_flag,
    620      "print version", NULL },
    621     {"help",	0,	arg_flag,	&help_flag,
    622      NULL, NULL }
    623 };
    624 
    625 static void
    626 usage (int ret)
    627 {
    628     arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "hostname ...");
    629     exit (ret);
    630 }
    631 
    632 int
    633 main(int argc, char **argv)
    634 {
    635     krb5_context context;
    636     krb5_error_code ret;
    637     int optidx = 0;
    638     krb5_ccache id1, id2;
    639 
    640     setprogname(argv[0]);
    641 
    642     if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
    643 	usage(1);
    644 
    645     if (help_flag)
    646 	usage (0);
    647 
    648     if(version_flag){
    649 	print_version(NULL);
    650 	exit(0);
    651     }
    652 
    653     argc -= optidx;
    654     argv += optidx;
    655 
    656     ret = krb5_init_context(&context);
    657     if (ret)
    658 	errx (1, "krb5_init_context failed: %d", ret);
    659 
    660     test_cache_remove(context, krb5_cc_type_file);
    661     test_cache_remove(context, krb5_cc_type_memory);
    662 #ifdef USE_SQLITE
    663     test_cache_remove(context, krb5_cc_type_scc);
    664 #endif
    665 
    666     test_default_name(context);
    667     test_mcache(context);
    668     test_init_vs_destroy(context, krb5_cc_type_memory);
    669     test_init_vs_destroy(context, krb5_cc_type_file);
    670 #if 0
    671     test_init_vs_destroy(context, krb5_cc_type_api);
    672 #endif
    673     test_init_vs_destroy(context, krb5_cc_type_scc);
    674     test_mcc_default();
    675     test_def_cc_name(context);
    676 
    677     test_cache_iter_all(context);
    678 
    679     test_cache_iter(context, krb5_cc_type_memory, 0);
    680     {
    681 	krb5_principal p;
    682 	krb5_cc_new_unique(context, krb5_cc_type_memory, "bar", &id1);
    683 	krb5_cc_new_unique(context, krb5_cc_type_memory, "baz", &id2);
    684 	krb5_parse_name(context, "lha (at) SU.SE", &p);
    685 	krb5_cc_initialize(context, id1, p);
    686 	krb5_free_principal(context, p);
    687     }
    688 
    689     test_cache_find(context, "lha (at) SU.SE", 1);
    690     test_cache_find(context, "hulabundulahotentot (at) SU.SE", 0);
    691 
    692     test_cache_iter(context, krb5_cc_type_memory, 0);
    693     test_cache_iter(context, krb5_cc_type_memory, 1);
    694     test_cache_iter(context, krb5_cc_type_memory, 0);
    695     test_cache_iter(context, krb5_cc_type_file, 0);
    696     test_cache_iter(context, krb5_cc_type_api, 0);
    697     test_cache_iter(context, krb5_cc_type_scc, 0);
    698     test_cache_iter(context, krb5_cc_type_scc, 1);
    699 
    700     test_copy(context, krb5_cc_type_file, krb5_cc_type_file);
    701     test_copy(context, krb5_cc_type_memory, krb5_cc_type_memory);
    702     test_copy(context, krb5_cc_type_file, krb5_cc_type_memory);
    703     test_copy(context, krb5_cc_type_memory, krb5_cc_type_file);
    704     test_copy(context, krb5_cc_type_scc, krb5_cc_type_file);
    705     test_copy(context, krb5_cc_type_file, krb5_cc_type_scc);
    706     test_copy(context, krb5_cc_type_scc, krb5_cc_type_memory);
    707     test_copy(context, krb5_cc_type_memory, krb5_cc_type_scc);
    708 
    709     test_move(context, krb5_cc_type_file);
    710     test_move(context, krb5_cc_type_memory);
    711 #ifdef HAVE_KCM
    712     test_move(context, krb5_cc_type_kcm);
    713 #endif
    714     test_move(context, krb5_cc_type_scc);
    715 
    716     test_prefix_ops(context, "FILE:/tmp/foo", &krb5_fcc_ops);
    717     test_prefix_ops(context, "FILE", &krb5_fcc_ops);
    718     test_prefix_ops(context, "MEMORY", &krb5_mcc_ops);
    719     test_prefix_ops(context, "MEMORY:foo", &krb5_mcc_ops);
    720     test_prefix_ops(context, "/tmp/kaka", &krb5_fcc_ops);
    721 #ifdef HAVE_SCC
    722     test_prefix_ops(context, "SCC:", &krb5_scc_ops);
    723     test_prefix_ops(context, "SCC:foo", &krb5_scc_ops);
    724 #endif
    725 
    726     krb5_cc_destroy(context, id1);
    727     krb5_cc_destroy(context, id2);
    728 
    729     test_cc_config(context);
    730 
    731     krb5_free_context(context);
    732 
    733 #if 0
    734     sleep(60);
    735 #endif
    736 
    737     return 0;
    738 }
    739