#include <k5-int.h>
#include "int-proto.h"
static void
bail_on_err(krb5_context context, const char *msg, krb5_error_code code)
{
const char *errmsg;
if (code) {
errmsg = krb5_get_error_message(context, code);
printf("%s: %s\n", msg, errmsg);
krb5_free_error_message(context, errmsg);
exit(1);
}
}
static void
unset_config(krb5_context context, krb5_ccache ccache,
krb5_principal server, const char *key)
{
krb5_ccache tmp1, tmp2;
krb5_cc_cursor cursor;
krb5_creds mcreds, creds;
memset(&mcreds, 0, sizeof(mcreds));
memset(&creds, 0, sizeof(creds));
bail_on_err(context, "Error while deriving configuration principal names",
k5_build_conf_principals(context, ccache, server, key,
&mcreds));
bail_on_err(context, "Error resolving first in-memory ccache",
krb5_cc_resolve(context, "MEMORY:tmp1", &tmp1));
bail_on_err(context, "Error initializing first in-memory ccache",
krb5_cc_initialize(context, tmp1, mcreds.client));
bail_on_err(context, "Error resolving second in-memory ccache",
krb5_cc_resolve(context, "MEMORY:tmp2", &tmp2));
bail_on_err(context, "Error initializing second in-memory ccache",
krb5_cc_initialize(context, tmp2, mcreds.client));
bail_on_err(context, "Error copying credentials to first in-memory ccache",
krb5_cc_copy_creds(context, ccache, tmp1));
bail_on_err(context, "Error starting traversal of first in-memory ccache",
krb5_cc_start_seq_get(context, tmp1, &cursor));
while (krb5_cc_next_cred(context, tmp1, &cursor, &creds) == 0) {
if (!krb5_is_config_principal(context, creds.server) ||
!krb5_principal_compare(context, mcreds.server, creds.server) ||
!krb5_principal_compare(context, mcreds.client, creds.client)) {
bail_on_err(context,
"Error storing non-config item to in-memory ccache",
krb5_cc_store_cred(context, tmp2, &creds));
}
krb5_free_cred_contents(context, &creds);
}
bail_on_err(context, "Error ending traversal of first in-memory ccache",
krb5_cc_end_seq_get(context, tmp1, &cursor));
bail_on_err(context, "Error clearing ccache",
krb5_cc_initialize(context, ccache, mcreds.client));
bail_on_err(context, "Error storing creds to the ccache",
krb5_cc_copy_creds(context, tmp2, ccache));
bail_on_err(context, "Error cleaning up first in-memory ccache",
krb5_cc_destroy(context, tmp1));
bail_on_err(context, "Error cleaning up second in-memory ccache",
krb5_cc_destroy(context, tmp2));
krb5_free_principal(context, mcreds.client);
krb5_free_principal(context, mcreds.server);
}
int
main(int argc, char **argv)
{
krb5_context context;
krb5_principal server;
krb5_ccache ccache;
krb5_data data;
krb5_error_code ret;
char *perr;
int c;
unsigned int i;
bail_on_err(NULL, "Error initializing Kerberos library",
krb5_init_context(&context));
bail_on_err(context, "Error getting location of default ccache",
krb5_cc_default(context, &ccache));
server = NULL;
while ((c = getopt(argc, argv, "p:")) != -1) {
switch (c) {
case 'p':
if (asprintf(&perr, "Error parsing principal name \"%s\"",
optarg) < 0)
abort();
bail_on_err(context, perr,
krb5_parse_name(context, optarg, &server));
free(perr);
break;
}
}
if (argc - optind < 1 || argc - optind > 2) {
fprintf(stderr, "Usage: %s [-p principal] key [value]\n", argv[0]);
return 1;
}
memset(&data, 0, sizeof(data));
if (argc - optind == 2) {
unset_config(context, ccache, server, argv[optind]);
data = string2data(argv[optind + 1]);
bail_on_err(context, "Error adding configuration data to ccache",
krb5_cc_set_config(context, ccache, server, argv[optind],
&data));
} else {
ret = krb5_cc_get_config(context, ccache, server, argv[optind], &data);
if (ret == 0) {
for (i = 0; i < data.length; i++)
putc((unsigned int)data.data[i], stdout);
krb5_free_data_contents(context, &data);
}
}
krb5_free_principal(context, server);
krb5_cc_close(context, ccache);
krb5_free_context(context);
return 0;
}