1120945Snectar/*
2233294Sstas * Copyright (c) 2003 - 2007 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5120945Snectar *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9120945Snectar *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12120945Snectar *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16120945Snectar *
17120945Snectar * 3. Neither the name of KTH nor the names of its contributors may be
18120945Snectar *    used to endorse or promote products derived from this software without
19120945Snectar *    specific prior written permission.
20120945Snectar *
21120945Snectar * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22120945Snectar * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23120945Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24120945Snectar * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25120945Snectar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26120945Snectar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27120945Snectar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28120945Snectar * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29120945Snectar * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30120945Snectar * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31120945Snectar * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32120945Snectar
33120945Snectar#include "krb5_locl.h"
34178825Sdfr#include <getarg.h>
35120945Snectar#include <err.h>
36120945Snectar
37178825Sdfrstatic int debug_flag	= 0;
38178825Sdfrstatic int version_flag = 0;
39178825Sdfrstatic int help_flag	= 0;
40120945Snectar
41233294Sstas#ifdef KRB5_USE_PATH_TOKENS
42233294Sstas#define TEST_CC_NAME "%{TEMP}/krb5-cc-test-foo"
43233294Sstas#else
44233294Sstas#define TEST_CC_NAME "/tmp/krb5-cc-test-foo"
45233294Sstas#endif
46233294Sstas
47178825Sdfrstatic void
48178825Sdfrtest_default_name(krb5_context context)
49120945Snectar{
50120945Snectar    krb5_error_code ret;
51233294Sstas    const char *p, *test_cc_name = TEST_CC_NAME;
52120945Snectar    char *p1, *p2, *p3;
53120945Snectar
54120945Snectar    p = krb5_cc_default_name(context);
55120945Snectar    if (p == NULL)
56120945Snectar	krb5_errx (context, 1, "krb5_cc_default_name 1 failed");
57120945Snectar    p1 = estrdup(p);
58120945Snectar
59120945Snectar    ret = krb5_cc_set_default_name(context, NULL);
60120945Snectar    if (p == NULL)
61120945Snectar	krb5_errx (context, 1, "krb5_cc_set_default_name failed");
62120945Snectar
63120945Snectar    p = krb5_cc_default_name(context);
64120945Snectar    if (p == NULL)
65120945Snectar	krb5_errx (context, 1, "krb5_cc_default_name 2 failed");
66120945Snectar    p2 = estrdup(p);
67120945Snectar
68120945Snectar    if (strcmp(p1, p2) != 0)
69120945Snectar	krb5_errx (context, 1, "krb5_cc_default_name no longer same");
70233294Sstas
71178825Sdfr    ret = krb5_cc_set_default_name(context, test_cc_name);
72120945Snectar    if (p == NULL)
73120945Snectar	krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed");
74233294Sstas
75120945Snectar    p = krb5_cc_default_name(context);
76120945Snectar    if (p == NULL)
77120945Snectar	krb5_errx (context, 1, "krb5_cc_default_name 2 failed");
78120945Snectar    p3 = estrdup(p);
79233294Sstas
80233294Sstas#ifndef KRB5_USE_PATH_TOKENS
81233294Sstas    /* If we are using path tokens, we don't expect the p3 and
82233294Sstas       test_cc_name to match since p3 is going to have expanded
83233294Sstas       tokens. */
84178825Sdfr    if (strcmp(p3, test_cc_name) != 0)
85120945Snectar	krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed");
86233294Sstas#endif
87120945Snectar
88178825Sdfr    free(p1);
89178825Sdfr    free(p2);
90178825Sdfr    free(p3);
91178825Sdfr}
92178825Sdfr
93178825Sdfr/*
94178825Sdfr * Check that a closed cc still keeps it data and that it's no longer
95178825Sdfr * there when it's destroyed.
96178825Sdfr */
97178825Sdfr
98178825Sdfrstatic void
99178825Sdfrtest_mcache(krb5_context context)
100178825Sdfr{
101178825Sdfr    krb5_error_code ret;
102178825Sdfr    krb5_ccache id, id2;
103178825Sdfr    const char *nc, *tc;
104178825Sdfr    char *c;
105178825Sdfr    krb5_principal p, p2;
106178825Sdfr
107178825Sdfr    ret = krb5_parse_name(context, "lha@SU.SE", &p);
108178825Sdfr    if (ret)
109178825Sdfr	krb5_err(context, 1, ret, "krb5_parse_name");
110178825Sdfr
111233294Sstas    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
112178825Sdfr    if (ret)
113233294Sstas	krb5_err(context, 1, ret, "krb5_cc_new_unique");
114178825Sdfr
115178825Sdfr    ret = krb5_cc_initialize(context, id, p);
116178825Sdfr    if (ret)
117178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_initialize");
118178825Sdfr
119178825Sdfr    nc = krb5_cc_get_name(context, id);
120178825Sdfr    if (nc == NULL)
121178825Sdfr	krb5_errx(context, 1, "krb5_cc_get_name");
122178825Sdfr
123178825Sdfr    tc = krb5_cc_get_type(context, id);
124178825Sdfr    if (tc == NULL)
125178825Sdfr	krb5_errx(context, 1, "krb5_cc_get_name");
126178825Sdfr
127233294Sstas    if (asprintf(&c, "%s:%s", tc, nc) < 0 || c == NULL)
128233294Sstas	errx(1, "malloc");
129233294Sstas
130178825Sdfr    krb5_cc_close(context, id);
131233294Sstas
132178825Sdfr    ret = krb5_cc_resolve(context, c, &id2);
133178825Sdfr    if (ret)
134178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_resolve");
135178825Sdfr
136178825Sdfr    ret = krb5_cc_get_principal(context, id2, &p2);
137178825Sdfr    if (ret)
138178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_get_principal");
139178825Sdfr
140178825Sdfr    if (krb5_principal_compare(context, p, p2) == FALSE)
141178825Sdfr	krb5_errx(context, 1, "p != p2");
142178825Sdfr
143178825Sdfr    krb5_cc_destroy(context, id2);
144178825Sdfr    krb5_free_principal(context, p);
145178825Sdfr    krb5_free_principal(context, p2);
146178825Sdfr
147178825Sdfr    ret = krb5_cc_resolve(context, c, &id2);
148178825Sdfr    if (ret)
149178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_resolve");
150178825Sdfr
151178825Sdfr    ret = krb5_cc_get_principal(context, id2, &p2);
152178825Sdfr    if (ret == 0)
153178825Sdfr	krb5_errx(context, 1, "krb5_cc_get_principal");
154178825Sdfr
155178825Sdfr    krb5_cc_destroy(context, id2);
156178825Sdfr    free(c);
157178825Sdfr}
158178825Sdfr
159178825Sdfr/*
160178825Sdfr * Test that init works on a destroyed cc.
161178825Sdfr */
162178825Sdfr
163178825Sdfrstatic void
164233294Sstastest_init_vs_destroy(krb5_context context, const char *type)
165178825Sdfr{
166178825Sdfr    krb5_error_code ret;
167178825Sdfr    krb5_ccache id, id2;
168178825Sdfr    krb5_principal p, p2;
169233294Sstas    char *n = NULL;
170178825Sdfr
171178825Sdfr    ret = krb5_parse_name(context, "lha@SU.SE", &p);
172178825Sdfr    if (ret)
173178825Sdfr	krb5_err(context, 1, ret, "krb5_parse_name");
174178825Sdfr
175233294Sstas    ret = krb5_cc_new_unique(context, type, NULL, &id);
176178825Sdfr    if (ret)
177233294Sstas	krb5_err(context, 1, ret, "krb5_cc_new_unique: %s", type);
178178825Sdfr
179233294Sstas    if (asprintf(&n, "%s:%s",
180233294Sstas		 krb5_cc_get_type(context, id),
181233294Sstas		 krb5_cc_get_name(context, id)) < 0 || n == NULL)
182233294Sstas	errx(1, "malloc");
183178825Sdfr
184233294Sstas
185178825Sdfr    ret = krb5_cc_resolve(context, n, &id2);
186178825Sdfr    free(n);
187178825Sdfr    if (ret)
188178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_resolve");
189178825Sdfr
190178825Sdfr    krb5_cc_destroy(context, id);
191178825Sdfr
192178825Sdfr    ret = krb5_cc_initialize(context, id2, p);
193178825Sdfr    if (ret)
194178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_initialize");
195178825Sdfr
196178825Sdfr    ret = krb5_cc_get_principal(context, id2, &p2);
197178825Sdfr    if (ret)
198178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_get_principal");
199178825Sdfr
200178825Sdfr    krb5_cc_destroy(context, id2);
201178825Sdfr    krb5_free_principal(context, p);
202178825Sdfr    krb5_free_principal(context, p2);
203178825Sdfr}
204178825Sdfr
205178825Sdfrstatic void
206233294Sstastest_cache_remove(krb5_context context, const char *type)
207178825Sdfr{
208178825Sdfr    krb5_error_code ret;
209178825Sdfr    krb5_ccache id;
210178825Sdfr    krb5_principal p;
211178825Sdfr    krb5_creds cred;
212178825Sdfr
213178825Sdfr    ret = krb5_parse_name(context, "lha@SU.SE", &p);
214178825Sdfr    if (ret)
215178825Sdfr	krb5_err(context, 1, ret, "krb5_parse_name");
216178825Sdfr
217233294Sstas    ret = krb5_cc_new_unique(context, type, NULL, &id);
218178825Sdfr    if (ret)
219233294Sstas	krb5_err(context, 1, ret, "krb5_cc_gen_new: %s", type);
220178825Sdfr
221178825Sdfr    ret = krb5_cc_initialize(context, id, p);
222178825Sdfr    if (ret)
223178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_initialize");
224178825Sdfr
225178825Sdfr    /* */
226178825Sdfr    memset(&cred, 0, sizeof(cred));
227178825Sdfr    ret = krb5_parse_name(context, "krbtgt/SU.SE@SU.SE", &cred.server);
228178825Sdfr    if (ret)
229178825Sdfr	krb5_err(context, 1, ret, "krb5_parse_name");
230178825Sdfr    ret = krb5_parse_name(context, "lha@SU.SE", &cred.client);
231178825Sdfr    if (ret)
232178825Sdfr	krb5_err(context, 1, ret, "krb5_parse_name");
233178825Sdfr
234178825Sdfr    ret = krb5_cc_store_cred(context, id, &cred);
235178825Sdfr    if (ret)
236178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_store_cred");
237178825Sdfr
238178825Sdfr    ret = krb5_cc_remove_cred(context, id, 0, &cred);
239178825Sdfr    if (ret)
240178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_remove_cred");
241178825Sdfr
242178825Sdfr    ret = krb5_cc_destroy(context, id);
243178825Sdfr    if (ret)
244178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_destroy");
245178825Sdfr
246178825Sdfr    krb5_free_principal(context, p);
247178825Sdfr    krb5_free_principal(context, cred.server);
248178825Sdfr    krb5_free_principal(context, cred.client);
249178825Sdfr}
250178825Sdfr
251178825Sdfrstatic void
252178825Sdfrtest_mcc_default(void)
253178825Sdfr{
254178825Sdfr    krb5_context context;
255178825Sdfr    krb5_error_code ret;
256178825Sdfr    krb5_ccache id, id2;
257178825Sdfr    int i;
258178825Sdfr
259178825Sdfr    for (i = 0; i < 10; i++) {
260178825Sdfr
261178825Sdfr	ret = krb5_init_context(&context);
262178825Sdfr	if (ret)
263178825Sdfr	    krb5_err(context, 1, ret, "krb5_init_context");
264178825Sdfr
265178825Sdfr	ret = krb5_cc_set_default_name(context, "MEMORY:foo");
266178825Sdfr	if (ret)
267178825Sdfr	    krb5_err(context, 1, ret, "krb5_cc_set_default_name");
268178825Sdfr
269178825Sdfr	ret = krb5_cc_default(context, &id);
270178825Sdfr	if (ret)
271178825Sdfr	    krb5_err(context, 1, ret, "krb5_cc_default");
272178825Sdfr
273178825Sdfr	ret = krb5_cc_default(context, &id2);
274178825Sdfr	if (ret)
275178825Sdfr	    krb5_err(context, 1, ret, "krb5_cc_default");
276178825Sdfr
277178825Sdfr	ret = krb5_cc_close(context, id);
278178825Sdfr	if (ret)
279178825Sdfr	    krb5_err(context, 1, ret, "krb5_cc_close");
280178825Sdfr
281178825Sdfr	ret = krb5_cc_close(context, id2);
282178825Sdfr	if (ret)
283178825Sdfr	    krb5_err(context, 1, ret, "krb5_cc_close");
284178825Sdfr
285178825Sdfr	krb5_free_context(context);
286178825Sdfr    }
287178825Sdfr}
288178825Sdfr
289178825Sdfrstruct {
290178825Sdfr    char *str;
291178825Sdfr    int fail;
292178825Sdfr    char *res;
293178825Sdfr} cc_names[] = {
294178825Sdfr    { "foo", 0, "foo" },
295233294Sstas    { "foo%}", 0, "foo%}" },
296178825Sdfr    { "%{uid}", 0 },
297178825Sdfr    { "foo%{null}", 0, "foo" },
298178825Sdfr    { "foo%{null}bar", 0, "foobar" },
299178825Sdfr    { "%{", 1 },
300178825Sdfr    { "%{foo %{", 1 },
301178825Sdfr    { "%{{", 1 },
302233294Sstas    { "%{{}", 1 },
303233294Sstas    { "%{nulll}", 1 },
304233294Sstas    { "%{does not exist}", 1 },
305233294Sstas    { "%{}", 1 },
306233294Sstas#ifdef KRB5_USE_PATH_TOKENS
307233294Sstas    { "%{APPDATA}", 0 },
308233294Sstas    { "%{COMMON_APPDATA}", 0},
309233294Sstas    { "%{LOCAL_APPDATA}", 0},
310233294Sstas    { "%{SYSTEM}", 0},
311233294Sstas    { "%{WINDOWS}", 0},
312233294Sstas    { "%{TEMP}", 0},
313233294Sstas    { "%{USERID}", 0},
314233294Sstas    { "%{uid}", 0},
315233294Sstas    { "%{USERCONFIG}", 0},
316233294Sstas    { "%{COMMONCONFIG}", 0},
317233294Sstas    { "%{LIBDIR}", 0},
318233294Sstas    { "%{BINDIR}", 0},
319233294Sstas    { "%{LIBEXEC}", 0},
320233294Sstas    { "%{SBINDIR}", 0},
321233294Sstas#endif
322178825Sdfr};
323178825Sdfr
324178825Sdfrstatic void
325178825Sdfrtest_def_cc_name(krb5_context context)
326178825Sdfr{
327178825Sdfr    krb5_error_code ret;
328178825Sdfr    char *str;
329178825Sdfr    int i;
330178825Sdfr
331178825Sdfr    for (i = 0; i < sizeof(cc_names)/sizeof(cc_names[0]); i++) {
332178825Sdfr	ret = _krb5_expand_default_cc_name(context, cc_names[i].str, &str);
333178825Sdfr	if (ret) {
334178825Sdfr	    if (cc_names[i].fail == 0)
335233294Sstas		krb5_errx(context, 1, "test %d \"%s\" failed",
336178825Sdfr			  i, cc_names[i].str);
337178825Sdfr	} else {
338178825Sdfr	    if (cc_names[i].fail)
339233294Sstas		krb5_errx(context, 1, "test %d \"%s\" was successful",
340178825Sdfr			  i, cc_names[i].str);
341178825Sdfr	    if (cc_names[i].res && strcmp(cc_names[i].res, str) != 0)
342233294Sstas		krb5_errx(context, 1, "test %d %s != %s",
343178825Sdfr			  i, cc_names[i].res, str);
344178825Sdfr	    if (debug_flag)
345178825Sdfr		printf("%s => %s\n", cc_names[i].str, str);
346178825Sdfr	    free(str);
347178825Sdfr	}
348178825Sdfr    }
349178825Sdfr}
350178825Sdfr
351178825Sdfrstatic void
352233294Sstastest_cache_find(krb5_context context, const char *principal, int find)
353178825Sdfr{
354178825Sdfr    krb5_principal client;
355178825Sdfr    krb5_error_code ret;
356178825Sdfr    krb5_ccache id = NULL;
357178825Sdfr
358178825Sdfr    ret = krb5_parse_name(context, principal, &client);
359178825Sdfr    if (ret)
360178825Sdfr	krb5_err(context, 1, ret, "parse_name for %s failed", principal);
361233294Sstas
362233294Sstas    ret = krb5_cc_cache_match(context, client, &id);
363178825Sdfr    if (ret && find)
364178825Sdfr	krb5_err(context, 1, ret, "cc_cache_match for %s failed", principal);
365178825Sdfr    if (ret == 0 && !find)
366178825Sdfr	krb5_err(context, 1, ret, "cc_cache_match for %s found", principal);
367178825Sdfr
368178825Sdfr    if (id)
369178825Sdfr	krb5_cc_close(context, id);
370178825Sdfr    krb5_free_principal(context, client);
371178825Sdfr}
372178825Sdfr
373178825Sdfr
374178825Sdfrstatic void
375178825Sdfrtest_cache_iter(krb5_context context, const char *type, int destroy)
376178825Sdfr{
377178825Sdfr    krb5_cc_cache_cursor cursor;
378178825Sdfr    krb5_error_code ret;
379178825Sdfr    krb5_ccache id;
380233294Sstas
381178825Sdfr    ret = krb5_cc_cache_get_first (context, type, &cursor);
382178825Sdfr    if (ret == KRB5_CC_NOSUPP)
383178825Sdfr	return;
384178825Sdfr    else if (ret)
385178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_cache_get_first(%s)", type);
386178825Sdfr
387178825Sdfr
388178825Sdfr    while ((ret = krb5_cc_cache_next (context, cursor, &id)) == 0) {
389178825Sdfr	krb5_principal principal;
390178825Sdfr	char *name;
391178825Sdfr
392178825Sdfr	if (debug_flag)
393178825Sdfr	    printf("name: %s\n", krb5_cc_get_name(context, id));
394178825Sdfr	ret = krb5_cc_get_principal(context, id, &principal);
395178825Sdfr	if (ret == 0) {
396178825Sdfr	    ret = krb5_unparse_name(context, principal, &name);
397178825Sdfr	    if (ret == 0) {
398178825Sdfr		if (debug_flag)
399178825Sdfr		    printf("\tprincipal: %s\n", name);
400178825Sdfr		free(name);
401178825Sdfr	    }
402178825Sdfr	    krb5_free_principal(context, principal);
403178825Sdfr	}
404178825Sdfr	if (destroy)
405178825Sdfr	    krb5_cc_destroy(context, id);
406178825Sdfr	else
407178825Sdfr	    krb5_cc_close(context, id);
408178825Sdfr    }
409178825Sdfr
410178825Sdfr    krb5_cc_cache_end_seq_get(context, cursor);
411178825Sdfr}
412178825Sdfr
413178825Sdfrstatic void
414233294Sstastest_cache_iter_all(krb5_context context)
415178825Sdfr{
416233294Sstas    krb5_cccol_cursor cursor;
417233294Sstas    krb5_error_code ret;
418233294Sstas    krb5_ccache id;
419233294Sstas
420233294Sstas    ret = krb5_cccol_cursor_new (context, &cursor);
421233294Sstas    if (ret)
422233294Sstas	krb5_err(context, 1, ret, "krb5_cccol_cursor_new");
423233294Sstas
424233294Sstas
425233294Sstas    while ((ret = krb5_cccol_cursor_next (context, cursor, &id)) == 0 && id != NULL) {
426233294Sstas	krb5_principal principal;
427233294Sstas	char *name;
428233294Sstas
429233294Sstas	if (debug_flag)
430233294Sstas	    printf("name: %s\n", krb5_cc_get_name(context, id));
431233294Sstas	ret = krb5_cc_get_principal(context, id, &principal);
432233294Sstas	if (ret == 0) {
433233294Sstas	    ret = krb5_unparse_name(context, principal, &name);
434233294Sstas	    if (ret == 0) {
435233294Sstas		if (debug_flag)
436233294Sstas		    printf("\tprincipal: %s\n", name);
437233294Sstas		free(name);
438233294Sstas	    }
439233294Sstas	    krb5_free_principal(context, principal);
440233294Sstas	}
441233294Sstas	krb5_cc_close(context, id);
442233294Sstas    }
443233294Sstas
444233294Sstas    krb5_cccol_cursor_free(context, &cursor);
445233294Sstas}
446233294Sstas
447233294Sstas
448233294Sstasstatic void
449233294Sstastest_copy(krb5_context context, const char *from, const char *to)
450233294Sstas{
451178825Sdfr    krb5_ccache fromid, toid;
452178825Sdfr    krb5_error_code ret;
453178825Sdfr    krb5_principal p, p2;
454178825Sdfr
455178825Sdfr    ret = krb5_parse_name(context, "lha@SU.SE", &p);
456178825Sdfr    if (ret)
457178825Sdfr	krb5_err(context, 1, ret, "krb5_parse_name");
458178825Sdfr
459233294Sstas    ret = krb5_cc_new_unique(context, from, NULL, &fromid);
460178825Sdfr    if (ret)
461233294Sstas	krb5_err(context, 1, ret, "krb5_cc_new_unique: %s", from);
462178825Sdfr
463178825Sdfr    ret = krb5_cc_initialize(context, fromid, p);
464178825Sdfr    if (ret)
465178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_initialize");
466178825Sdfr
467233294Sstas    ret = krb5_cc_new_unique(context, to, NULL, &toid);
468178825Sdfr    if (ret)
469233294Sstas	krb5_err(context, 1, ret, "krb5_cc_gen_new: %s", to);
470178825Sdfr
471178825Sdfr    ret = krb5_cc_copy_cache(context, fromid, toid);
472178825Sdfr    if (ret)
473178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_copy_cache");
474178825Sdfr
475178825Sdfr    ret = krb5_cc_get_principal(context, toid, &p2);
476178825Sdfr    if (ret)
477178825Sdfr	krb5_err(context, 1, ret, "krb5_cc_get_principal");
478178825Sdfr
479178825Sdfr    if (krb5_principal_compare(context, p, p2) == FALSE)
480178825Sdfr	krb5_errx(context, 1, "p != p2");
481178825Sdfr
482178825Sdfr    krb5_free_principal(context, p);
483178825Sdfr    krb5_free_principal(context, p2);
484178825Sdfr
485178825Sdfr    krb5_cc_destroy(context, fromid);
486178825Sdfr    krb5_cc_destroy(context, toid);
487178825Sdfr}
488178825Sdfr
489178825Sdfrstatic void
490233294Sstastest_move(krb5_context context, const char *type)
491233294Sstas{
492233294Sstas    const krb5_cc_ops *ops;
493233294Sstas    krb5_ccache fromid, toid;
494233294Sstas    krb5_error_code ret;
495233294Sstas    krb5_principal p, p2;
496233294Sstas
497233294Sstas    ops = krb5_cc_get_prefix_ops(context, type);
498233294Sstas    if (ops == NULL)
499233294Sstas	return;
500233294Sstas
501233294Sstas    ret = krb5_cc_new_unique(context, type, NULL, &fromid);
502233294Sstas    if (ret == KRB5_CC_NOSUPP)
503233294Sstas	return;
504233294Sstas    else if (ret)
505233294Sstas	krb5_err(context, 1, ret, "krb5_cc_new_unique: %s", type);
506233294Sstas
507233294Sstas    ret = krb5_parse_name(context, "lha@SU.SE", &p);
508233294Sstas    if (ret)
509233294Sstas	krb5_err(context, 1, ret, "krb5_parse_name");
510233294Sstas
511233294Sstas    ret = krb5_cc_initialize(context, fromid, p);
512233294Sstas    if (ret)
513233294Sstas	krb5_err(context, 1, ret, "krb5_cc_initialize");
514233294Sstas
515233294Sstas    ret = krb5_cc_new_unique(context, type, NULL, &toid);
516233294Sstas    if (ret)
517233294Sstas	krb5_err(context, 1, ret, "krb5_cc_new_unique");
518233294Sstas
519233294Sstas    ret = krb5_cc_initialize(context, toid, p);
520233294Sstas    if (ret)
521233294Sstas	krb5_err(context, 1, ret, "krb5_cc_initialize");
522233294Sstas
523233294Sstas    ret = krb5_cc_get_principal(context, toid, &p2);
524233294Sstas    if (ret)
525233294Sstas	krb5_err(context, 1, ret, "krb5_cc_get_principal");
526233294Sstas
527233294Sstas    if (krb5_principal_compare(context, p, p2) == FALSE)
528233294Sstas	krb5_errx(context, 1, "p != p2");
529233294Sstas
530233294Sstas    krb5_free_principal(context, p);
531233294Sstas    krb5_free_principal(context, p2);
532233294Sstas
533233294Sstas    krb5_cc_destroy(context, toid);
534233294Sstas    krb5_cc_destroy(context, fromid);
535233294Sstas}
536233294Sstas
537233294Sstas
538233294Sstasstatic void
539178825Sdfrtest_prefix_ops(krb5_context context, const char *name, const krb5_cc_ops *ops)
540178825Sdfr{
541178825Sdfr    const krb5_cc_ops *o;
542178825Sdfr
543178825Sdfr    o = krb5_cc_get_prefix_ops(context, name);
544178825Sdfr    if (o == NULL)
545178825Sdfr	krb5_errx(context, 1, "found no match for prefix '%s'", name);
546178825Sdfr    if (strcmp(o->prefix, ops->prefix) != 0)
547178825Sdfr	krb5_errx(context, 1, "ops for prefix '%s' is not "
548178825Sdfr		  "the expected %s != %s", name, o->prefix, ops->prefix);
549178825Sdfr}
550178825Sdfr
551233294Sstasstatic void
552233294Sstastest_cc_config(krb5_context context)
553233294Sstas{
554233294Sstas    krb5_error_code ret;
555233294Sstas    krb5_principal p;
556233294Sstas    krb5_ccache id;
557233294Sstas    unsigned int i;
558178825Sdfr
559233294Sstas    ret = krb5_cc_new_unique(context, "MEMORY", "bar", &id);
560233294Sstas    if (ret)
561233294Sstas	krb5_err(context, 1, ret, "krb5_cc_new_unique");
562233294Sstas
563233294Sstas    ret = krb5_parse_name(context, "lha@SU.SE", &p);
564233294Sstas    if (ret)
565233294Sstas	krb5_err(context, 1, ret, "krb5_parse_name");
566233294Sstas
567233294Sstas    ret = krb5_cc_initialize(context, id, p);
568233294Sstas    if (ret)
569233294Sstas	krb5_err(context, 1, ret, "krb5_cc_initialize");
570233294Sstas
571233294Sstas    for (i = 0; i < 1000; i++) {
572233294Sstas	krb5_data data, data2;
573233294Sstas	const char *name = "foo";
574233294Sstas	krb5_principal p1 = NULL;
575233294Sstas
576233294Sstas	if (i & 1)
577233294Sstas	    p1 = p;
578233294Sstas
579233294Sstas	data.data = rk_UNCONST(name);
580233294Sstas	data.length = strlen(name);
581233294Sstas
582233294Sstas	ret = krb5_cc_set_config(context, id, p1, "FriendlyName", &data);
583233294Sstas	if (ret)
584233294Sstas	    krb5_errx(context, 1, "krb5_cc_set_config: add");
585233294Sstas
586233294Sstas	ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2);
587233294Sstas	if (ret)
588233294Sstas	    krb5_errx(context, 1, "krb5_cc_get_config: first");
589233294Sstas	krb5_data_free(&data2);
590233294Sstas
591233294Sstas	ret = krb5_cc_set_config(context, id, p1, "FriendlyName", &data);
592233294Sstas	if (ret)
593233294Sstas	    krb5_errx(context, 1, "krb5_cc_set_config: add -second");
594233294Sstas
595233294Sstas	ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2);
596233294Sstas	if (ret)
597233294Sstas	    krb5_errx(context, 1, "krb5_cc_get_config: second");
598233294Sstas	krb5_data_free(&data2);
599233294Sstas
600233294Sstas	ret = krb5_cc_set_config(context, id, p1, "FriendlyName", NULL);
601233294Sstas	if (ret)
602233294Sstas	    krb5_errx(context, 1, "krb5_cc_set_config: delete");
603233294Sstas
604233294Sstas	ret = krb5_cc_get_config(context, id, p1, "FriendlyName", &data2);
605233294Sstas	if (ret == 0)
606233294Sstas	    krb5_errx(context, 1, "krb5_cc_get_config: non-existant");
607233294Sstas    }
608233294Sstas
609233294Sstas    krb5_cc_destroy(context, id);
610233294Sstas    krb5_free_principal(context, p);
611233294Sstas}
612233294Sstas
613233294Sstas
614178825Sdfrstatic struct getargs args[] = {
615178825Sdfr    {"debug",	'd',	arg_flag,	&debug_flag,
616178825Sdfr     "turn on debuggin", NULL },
617178825Sdfr    {"version",	0,	arg_flag,	&version_flag,
618178825Sdfr     "print version", NULL },
619178825Sdfr    {"help",	0,	arg_flag,	&help_flag,
620178825Sdfr     NULL, NULL }
621178825Sdfr};
622178825Sdfr
623178825Sdfrstatic void
624178825Sdfrusage (int ret)
625178825Sdfr{
626178825Sdfr    arg_printusage (args, sizeof(args)/sizeof(*args), NULL, "hostname ...");
627178825Sdfr    exit (ret);
628178825Sdfr}
629178825Sdfr
630178825Sdfrint
631178825Sdfrmain(int argc, char **argv)
632178825Sdfr{
633178825Sdfr    krb5_context context;
634178825Sdfr    krb5_error_code ret;
635178825Sdfr    int optidx = 0;
636178825Sdfr    krb5_ccache id1, id2;
637178825Sdfr
638178825Sdfr    setprogname(argv[0]);
639178825Sdfr
640178825Sdfr    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
641178825Sdfr	usage(1);
642233294Sstas
643178825Sdfr    if (help_flag)
644178825Sdfr	usage (0);
645178825Sdfr
646178825Sdfr    if(version_flag){
647178825Sdfr	print_version(NULL);
648178825Sdfr	exit(0);
649178825Sdfr    }
650178825Sdfr
651178825Sdfr    argc -= optidx;
652178825Sdfr    argv += optidx;
653178825Sdfr
654178825Sdfr    ret = krb5_init_context(&context);
655178825Sdfr    if (ret)
656178825Sdfr	errx (1, "krb5_init_context failed: %d", ret);
657178825Sdfr
658233294Sstas    test_cache_remove(context, krb5_cc_type_file);
659233294Sstas    test_cache_remove(context, krb5_cc_type_memory);
660233294Sstas#ifdef USE_SQLITE
661233294Sstas    test_cache_remove(context, krb5_cc_type_scc);
662233294Sstas#endif
663233294Sstas
664178825Sdfr    test_default_name(context);
665178825Sdfr    test_mcache(context);
666233294Sstas    test_init_vs_destroy(context, krb5_cc_type_memory);
667233294Sstas    test_init_vs_destroy(context, krb5_cc_type_file);
668233294Sstas#if 0
669233294Sstas    test_init_vs_destroy(context, krb5_cc_type_api);
670233294Sstas#endif
671233294Sstas    test_init_vs_destroy(context, krb5_cc_type_scc);
672178825Sdfr    test_mcc_default();
673178825Sdfr    test_def_cc_name(context);
674233294Sstas
675233294Sstas    test_cache_iter_all(context);
676233294Sstas
677233294Sstas    test_cache_iter(context, krb5_cc_type_memory, 0);
678178825Sdfr    {
679178825Sdfr	krb5_principal p;
680233294Sstas	krb5_cc_new_unique(context, krb5_cc_type_memory, "bar", &id1);
681233294Sstas	krb5_cc_new_unique(context, krb5_cc_type_memory, "baz", &id2);
682178825Sdfr	krb5_parse_name(context, "lha@SU.SE", &p);
683178825Sdfr	krb5_cc_initialize(context, id1, p);
684178825Sdfr	krb5_free_principal(context, p);
685178825Sdfr    }
686178825Sdfr
687233294Sstas    test_cache_find(context, "lha@SU.SE", 1);
688233294Sstas    test_cache_find(context, "hulabundulahotentot@SU.SE", 0);
689178825Sdfr
690233294Sstas    test_cache_iter(context, krb5_cc_type_memory, 0);
691233294Sstas    test_cache_iter(context, krb5_cc_type_memory, 1);
692233294Sstas    test_cache_iter(context, krb5_cc_type_memory, 0);
693233294Sstas    test_cache_iter(context, krb5_cc_type_file, 0);
694233294Sstas    test_cache_iter(context, krb5_cc_type_api, 0);
695233294Sstas    test_cache_iter(context, krb5_cc_type_scc, 0);
696233294Sstas    test_cache_iter(context, krb5_cc_type_scc, 1);
697178825Sdfr
698233294Sstas    test_copy(context, krb5_cc_type_file, krb5_cc_type_file);
699233294Sstas    test_copy(context, krb5_cc_type_memory, krb5_cc_type_memory);
700233294Sstas    test_copy(context, krb5_cc_type_file, krb5_cc_type_memory);
701233294Sstas    test_copy(context, krb5_cc_type_memory, krb5_cc_type_file);
702233294Sstas    test_copy(context, krb5_cc_type_scc, krb5_cc_type_file);
703233294Sstas    test_copy(context, krb5_cc_type_file, krb5_cc_type_scc);
704233294Sstas    test_copy(context, krb5_cc_type_scc, krb5_cc_type_memory);
705233294Sstas    test_copy(context, krb5_cc_type_memory, krb5_cc_type_scc);
706178825Sdfr
707233294Sstas    test_move(context, krb5_cc_type_file);
708233294Sstas    test_move(context, krb5_cc_type_memory);
709233294Sstas#ifdef HAVE_KCM
710233294Sstas    test_move(context, krb5_cc_type_kcm);
711233294Sstas#endif
712233294Sstas    test_move(context, krb5_cc_type_scc);
713233294Sstas
714178825Sdfr    test_prefix_ops(context, "FILE:/tmp/foo", &krb5_fcc_ops);
715178825Sdfr    test_prefix_ops(context, "FILE", &krb5_fcc_ops);
716178825Sdfr    test_prefix_ops(context, "MEMORY", &krb5_mcc_ops);
717178825Sdfr    test_prefix_ops(context, "MEMORY:foo", &krb5_mcc_ops);
718178825Sdfr    test_prefix_ops(context, "/tmp/kaka", &krb5_fcc_ops);
719233294Sstas#ifdef HAVE_SCC
720233294Sstas    test_prefix_ops(context, "SCC:", &krb5_scc_ops);
721233294Sstas    test_prefix_ops(context, "SCC:foo", &krb5_scc_ops);
722233294Sstas#endif
723178825Sdfr
724178825Sdfr    krb5_cc_destroy(context, id1);
725178825Sdfr    krb5_cc_destroy(context, id2);
726178825Sdfr
727233294Sstas    test_cc_config(context);
728233294Sstas
729120945Snectar    krb5_free_context(context);
730120945Snectar
731233294Sstas#if 0
732233294Sstas    sleep(60);
733233294Sstas#endif
734233294Sstas
735120945Snectar    return 0;
736120945Snectar}
737