1/*
2 * Copyright (c) 1997 - 2000, 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "kuser_locl.h"
35
36static void usage (int status) __attribute__((noreturn));
37
38static const char *cache;
39static const char *credential;
40static const char *principal_str;
41static int help_flag;
42static int version_flag;
43#ifndef NO_AFS
44static int unlog_flag = 1;
45#endif
46static int dest_tkt_flag = 1;
47static int all_flag = 0;
48
49struct getargs args[] = {
50    { "credential",	0,   arg_string, rk_UNCONST(&credential),
51      "remove one credential", "principal" },
52    { "cache",		'c', arg_string, rk_UNCONST(&cache), "cache to destroy", "cache" },
53    { "principal",	'p', arg_string, &principal_str, "client credential to destroy", "principal" },
54    { "all",		'A', arg_flag, &all_flag, "destroy all caches", NULL },
55    { NULL,		'a', arg_flag, &all_flag, "destroy all caches" },
56#ifndef NO_AFS
57    { "unlog",		0,   arg_negative_flag, &unlog_flag,
58      "do not destroy tokens", NULL },
59#endif
60    { "delete-v4",	0,   arg_negative_flag, &dest_tkt_flag,
61      "do not destroy v4 tickets", NULL },
62    { "version", 	0,   arg_flag, &version_flag, NULL, NULL },
63    { "help",		'h', arg_flag, &help_flag, NULL, NULL}
64};
65
66int num_args = sizeof(args) / sizeof(args[0]);
67
68static void
69usage (int status)
70{
71    arg_printusage (args, num_args, NULL, "");
72    exit (status);
73}
74
75int
76main (int argc, char **argv)
77{
78    krb5_error_code ret;
79    krb5_context context;
80    krb5_ccache  ccache;
81    int optidx = 0;
82    int exit_val = 0;
83
84    setprogname (argv[0]);
85
86    if(getarg(args, num_args, argc, argv, &optidx))
87	usage(1);
88
89    if (help_flag)
90	usage (0);
91
92    if(version_flag){
93	print_version(NULL);
94	exit(0);
95    }
96
97    argc -= optidx;
98
99    if (argc != 0)
100	usage (1);
101
102    ret = krb5_init_context (&context);
103    if (ret)
104	errx (1, "krb5_init_context failed: %d", ret);
105
106    if (all_flag) {
107	krb5_cccol_cursor cursor;
108
109	ret = krb5_cccol_cursor_new (context, &cursor);
110	if (ret)
111	    krb5_err(context, 1, ret, "krb5_cccol_cursor_new");
112
113	while (krb5_cccol_cursor_next (context, cursor, &ccache) == 0 && ccache != NULL) {
114
115	    ret = krb5_cc_destroy (context, ccache);
116	    if (ret) {
117		krb5_warn(context, ret, "krb5_cc_destroy");
118		exit_val = 1;
119	    }
120	}
121	krb5_cccol_cursor_free(context, &cursor);
122
123    } else {
124	if (cache != NULL && principal_str != NULL)
125	    krb5_errx(context, 1, "Can't select on credential "
126		      "and principal at the same time");
127
128	if (principal_str) {
129	    krb5_principal p;
130
131	    ret = krb5_parse_name(context, principal_str, &p);
132	    if (ret)
133		krb5_err(context, 1, ret, "can't parse %s", principal_str);
134
135	    ret = krb5_cc_cache_match(context, p, &ccache);
136	    krb5_free_principal(context, p);
137	    if (ret)
138		krb5_err(context, 1, ret, "Can't find cache for %s",
139			 principal_str);
140	} else if(cache == NULL) {
141	    ret = krb5_cc_default(context, &ccache);
142	    if (ret)
143		krb5_err(context, 1, ret, "krb5_cc_default");
144	} else {
145	    ret =  krb5_cc_resolve(context,
146				   cache,
147				   &ccache);
148	    if (ret)
149		krb5_err(context, 1, ret, "krb5_cc_resolve");
150	}
151
152	if (ret == 0) {
153	    if (credential) {
154		krb5_creds mcred;
155
156		krb5_cc_clear_mcred(&mcred);
157
158		ret = krb5_parse_name(context, credential, &mcred.server);
159		if (ret)
160		    krb5_err(context, 1, ret,
161			     "Can't parse principal %s", credential);
162
163		ret = krb5_cc_remove_cred(context, ccache, 0, &mcred);
164		if (ret)
165		    krb5_err(context, 1, ret,
166			     "Failed to remove principal %s", credential);
167
168		krb5_cc_close(context, ccache);
169		krb5_free_principal(context, mcred.server);
170		krb5_free_context(context);
171		return 0;
172	    }
173
174	    ret = krb5_cc_destroy (context, ccache);
175	    if (ret) {
176		krb5_warn(context, ret, "krb5_cc_destroy");
177		exit_val = 1;
178	    }
179	}
180    }
181
182    krb5_free_context (context);
183
184#ifndef NO_AFS
185    if (unlog_flag && k_hasafs ()) {
186	if (k_unlog ())
187	    exit_val = 1;
188    }
189#endif
190
191    return exit_val;
192}
193