#include <CoreFoundation/CoreFoundation.h>
#include <Kerberos/Kerberos.h>
#include <Kerberos/kim.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
int quiet = 0;
int all = 0;
const char *cache_name = NULL;
const char *principal_name = NULL;
static int usage (void)
{
fprintf (stderr, "Usage: %s [-q] [-[a|A] | -c cache_name | -p principal]\n",
getprogname ());
fprintf (stderr, "\t-q quiet mode\n");
fprintf (stderr, "\t-[a|A] destroy all caches\n");
fprintf (stderr, "\t-c specify name of credentials cache\n");
fprintf (stderr, "\t-p specify name of principal (Kerberos 5 format)\n");
return 2;
}
static void printiferr (errcode_t err, const char *format, ...)
{
if (err) {
va_list pvar;
va_start (pvar, format);
com_err_va (getprogname (), err, format, pvar);
va_end (pvar);
}
}
static void vprinterr (const char *format, va_list args)
{
if (!quiet) {
fprintf (stderr, "%s: ", getprogname ());
vfprintf (stderr, format, args);
}
}
static void printerr (const char *format, ...)
{
va_list pvar;
va_start (pvar, format);
vprinterr (format, pvar);
va_end (pvar);
}
static int destroy_tickets (void)
{
krb5_error_code err = 0;
if (cache_name) {
kim_ccache ccache = NULL;
err = kim_ccache_create_from_display_name (&ccache, cache_name);
printiferr (err, "while locating credentials cache '%s'",
cache_name);
if (!err) {
err = kim_ccache_destroy (&ccache);
printiferr (err, "while destroying credentials cache '%s'",
cache_name);
}
} else if (all) {
kim_ccache_iterator iterator = NULL;
err = kim_ccache_iterator_create (&iterator);
while (!err) {
kim_ccache ccache = NULL;
err = kim_ccache_iterator_next (iterator, &ccache);
if (!err) {
if (ccache) {
err = kim_ccache_destroy (&ccache);
} else {
break;
}
}
}
kim_ccache_iterator_free (&iterator);
} else {
kim_identity identity = KIM_IDENTITY_ANY;
kim_ccache ccache = NULL;
if (principal_name) {
err = kim_identity_create_from_string (&identity, principal_name);
printiferr (err, "while creating identity for '%s'",
principal_name);
}
if (!err) {
kim_ccache_create_from_client_identity (&ccache, identity);
if (identity) {
printiferr (err, "while getting ccache for '%s'",
principal_name);
} else {
printiferr (err, "while getting default ccache");
}
}
if (!err) {
err = kim_ccache_destroy (&ccache);
printiferr (err, "while destroying tickets");
}
kim_identity_free (&identity);
}
return err ? 1 : 0;
}
static int options (int argc, char * const *argv)
{
int option;
while ((option = getopt (argc, argv, "qaAc:p:")) != -1) {
switch (option) {
case 'q':
quiet = 1;
break;
case 'a':
case 'A':
all = 1;
break;
case 'c':
if (cache_name) {
printerr ("Only one -c option allowed\n");
return usage ();
}
cache_name = optarg;
break;
case 'p':
if (principal_name) {
printerr ("Only one -p option allowed\n");
return usage ();
}
principal_name = optarg;
break;
default:
return usage ();
}
}
if (cache_name && principal_name) {
printerr ("Only one of -c or -p allowed\n");
return usage ();
}
if (all && (cache_name || principal_name)) {
printerr ("-a cannot be combined with -c or -p\n");
return usage ();
}
return 0;
}
int main (int argc, char * const *argv)
{
int err = 0;
setprogname (argv[0]);
err = options (argc, argv);
if (!err) {
err = destroy_tickets ();
}
return err;
}