klist.c revision 178825
155682Smarkm/*
2178825Sdfr * Copyright (c) 1997-2004 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "kuser_locl.h"
3572445Sassar#include "rtbl.h"
3655682Smarkm
37178825SdfrRCSID("$Id: klist.c 20516 2007-04-22 10:40:41Z lha $");
3855682Smarkm
3955682Smarkmstatic char*
4055682Smarkmprintable_time(time_t t)
4155682Smarkm{
4255682Smarkm    static char s[128];
43178825Sdfr    strlcpy(s, ctime(&t)+ 4, sizeof(s));
4455682Smarkm    s[15] = 0;
4555682Smarkm    return s;
4655682Smarkm}
4755682Smarkm
4855682Smarkmstatic char*
4955682Smarkmprintable_time_long(time_t t)
5055682Smarkm{
5155682Smarkm    static char s[128];
52178825Sdfr    strlcpy(s, ctime(&t)+ 4, sizeof(s));
5355682Smarkm    s[20] = 0;
5455682Smarkm    return s;
5555682Smarkm}
5655682Smarkm
5772445Sassar#define COL_ISSUED		"  Issued"
5872445Sassar#define COL_EXPIRES		"  Expires"
5972445Sassar#define COL_FLAGS		"Flags"
6072445Sassar#define COL_PRINCIPAL		"  Principal"
6172445Sassar#define COL_PRINCIPAL_KVNO	"  Principal (kvno)"
62178825Sdfr#define COL_CACHENAME		"  Cache name"
6372445Sassar
6455682Smarkmstatic void
6572445Sassarprint_cred(krb5_context context, krb5_creds *cred, rtbl_t ct, int do_flags)
6655682Smarkm{
6755682Smarkm    char *str;
6855682Smarkm    krb5_error_code ret;
6957416Smarkm    krb5_timestamp sec;
7055682Smarkm
7155682Smarkm    krb5_timeofday (context, &sec);
7255682Smarkm
7372445Sassar
7455682Smarkm    if(cred->times.starttime)
7572445Sassar	rtbl_add_column_entry(ct, COL_ISSUED,
7672445Sassar			      printable_time(cred->times.starttime));
7755682Smarkm    else
7872445Sassar	rtbl_add_column_entry(ct, COL_ISSUED,
7972445Sassar			      printable_time(cred->times.authtime));
8055682Smarkm
8155682Smarkm    if(cred->times.endtime > sec)
8272445Sassar	rtbl_add_column_entry(ct, COL_EXPIRES,
8372445Sassar			      printable_time(cred->times.endtime));
8455682Smarkm    else
8572445Sassar	rtbl_add_column_entry(ct, COL_EXPIRES, ">>>Expired<<<");
8655682Smarkm    ret = krb5_unparse_name (context, cred->server, &str);
8755682Smarkm    if (ret)
8855682Smarkm	krb5_err(context, 1, ret, "krb5_unparse_name");
8972445Sassar    rtbl_add_column_entry(ct, COL_PRINCIPAL, str);
9072445Sassar    if(do_flags) {
9172445Sassar	char s[16], *sp = s;
9272445Sassar	if(cred->flags.b.forwardable)
9372445Sassar	    *sp++ = 'F';
9472445Sassar	if(cred->flags.b.forwarded)
9572445Sassar	    *sp++ = 'f';
9672445Sassar	if(cred->flags.b.proxiable)
9772445Sassar	    *sp++ = 'P';
9872445Sassar	if(cred->flags.b.proxy)
9972445Sassar	    *sp++ = 'p';
10072445Sassar	if(cred->flags.b.may_postdate)
10172445Sassar	    *sp++ = 'D';
10272445Sassar	if(cred->flags.b.postdated)
10372445Sassar	    *sp++ = 'd';
10472445Sassar	if(cred->flags.b.renewable)
10572445Sassar	    *sp++ = 'R';
10672445Sassar	if(cred->flags.b.initial)
10772445Sassar	    *sp++ = 'I';
10872445Sassar	if(cred->flags.b.invalid)
10972445Sassar	    *sp++ = 'i';
11072445Sassar	if(cred->flags.b.pre_authent)
11172445Sassar	    *sp++ = 'A';
11272445Sassar	if(cred->flags.b.hw_authent)
11372445Sassar	    *sp++ = 'H';
11472445Sassar	*sp++ = '\0';
11572445Sassar	rtbl_add_column_entry(ct, COL_FLAGS, s);
11672445Sassar    }
11772445Sassar    free(str);
11855682Smarkm}
11955682Smarkm
12055682Smarkmstatic void
12155682Smarkmprint_cred_verbose(krb5_context context, krb5_creds *cred)
12255682Smarkm{
12355682Smarkm    int j;
12455682Smarkm    char *str;
12555682Smarkm    krb5_error_code ret;
12655682Smarkm    int first_flag;
12757416Smarkm    krb5_timestamp sec;
12855682Smarkm
12955682Smarkm    krb5_timeofday (context, &sec);
13055682Smarkm
13155682Smarkm    ret = krb5_unparse_name(context, cred->server, &str);
13255682Smarkm    if(ret)
13355682Smarkm	exit(1);
13455682Smarkm    printf("Server: %s\n", str);
13555682Smarkm    free (str);
136178825Sdfr
137178825Sdfr    ret = krb5_unparse_name(context, cred->client, &str);
138178825Sdfr    if(ret)
139178825Sdfr	exit(1);
140178825Sdfr    printf("Client: %s\n", str);
141178825Sdfr    free (str);
142178825Sdfr
14355682Smarkm    {
14455682Smarkm	Ticket t;
14555682Smarkm	size_t len;
14655682Smarkm	char *s;
14755682Smarkm
14855682Smarkm	decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
14955682Smarkm	ret = krb5_enctype_to_string(context, t.enc_part.etype, &s);
15072445Sassar	printf("Ticket etype: ");
15155682Smarkm	if (ret == 0) {
15272445Sassar	    printf("%s", s);
15355682Smarkm	    free(s);
15455682Smarkm	} else {
15572445Sassar	    printf("unknown(%d)", t.enc_part.etype);
15655682Smarkm	}
15755682Smarkm	if(t.enc_part.kvno)
15855682Smarkm	    printf(", kvno %d", *t.enc_part.kvno);
15955682Smarkm	printf("\n");
16055682Smarkm	if(cred->session.keytype != t.enc_part.etype) {
161178825Sdfr	    ret = krb5_enctype_to_string(context, cred->session.keytype, &str);
16255682Smarkm	    if(ret)
16355682Smarkm		krb5_warn(context, ret, "session keytype");
16455682Smarkm	    else {
16555682Smarkm		printf("Session key: %s\n", str);
16655682Smarkm		free(str);
16755682Smarkm	    }
16855682Smarkm	}
16955682Smarkm	free_Ticket(&t);
170178825Sdfr	printf("Ticket length: %lu\n", (unsigned long)cred->ticket.length);
17155682Smarkm    }
17255682Smarkm    printf("Auth time:  %s\n", printable_time_long(cred->times.authtime));
17355682Smarkm    if(cred->times.authtime != cred->times.starttime)
17455682Smarkm	printf("Start time: %s\n", printable_time_long(cred->times.starttime));
17555682Smarkm    printf("End time:   %s", printable_time_long(cred->times.endtime));
17655682Smarkm    if(sec > cred->times.endtime)
17755682Smarkm	printf(" (expired)");
17855682Smarkm    printf("\n");
17955682Smarkm    if(cred->flags.b.renewable)
18055682Smarkm	printf("Renew till: %s\n",
18155682Smarkm	       printable_time_long(cred->times.renew_till));
18255682Smarkm    printf("Ticket flags: ");
18355682Smarkm#define PRINT_FLAG2(f, s) if(cred->flags.b.f) { if(!first_flag) printf(", "); printf("%s", #s); first_flag = 0; }
18455682Smarkm#define PRINT_FLAG(f) PRINT_FLAG2(f, f)
18555682Smarkm    first_flag = 1;
18655682Smarkm    PRINT_FLAG(forwardable);
18755682Smarkm    PRINT_FLAG(forwarded);
18855682Smarkm    PRINT_FLAG(proxiable);
18955682Smarkm    PRINT_FLAG(proxy);
19055682Smarkm    PRINT_FLAG2(may_postdate, may-postdate);
19155682Smarkm    PRINT_FLAG(postdated);
19255682Smarkm    PRINT_FLAG(invalid);
19355682Smarkm    PRINT_FLAG(renewable);
19455682Smarkm    PRINT_FLAG(initial);
19555682Smarkm    PRINT_FLAG2(pre_authent, pre-authenticated);
19655682Smarkm    PRINT_FLAG2(hw_authent, hw-authenticated);
19755682Smarkm    PRINT_FLAG2(transited_policy_checked, transited-policy-checked);
19855682Smarkm    PRINT_FLAG2(ok_as_delegate, ok-as-delegate);
19955682Smarkm    PRINT_FLAG(anonymous);
20055682Smarkm    printf("\n");
20155682Smarkm    printf("Addresses: ");
202178825Sdfr    if (cred->addresses.len != 0) {
203178825Sdfr	for(j = 0; j < cred->addresses.len; j++){
204178825Sdfr	    char buf[128];
205178825Sdfr	    size_t len;
206178825Sdfr	    if(j) printf(", ");
207178825Sdfr	    ret = krb5_print_address(&cred->addresses.val[j],
208178825Sdfr				     buf, sizeof(buf), &len);
209178825Sdfr
210178825Sdfr	    if(ret == 0)
211178825Sdfr		printf("%s", buf);
212178825Sdfr	}
213178825Sdfr    } else {
214178825Sdfr	printf("addressless");
21555682Smarkm    }
21655682Smarkm    printf("\n\n");
21755682Smarkm}
21855682Smarkm
21955682Smarkm/*
22055682Smarkm * Print all tickets in `ccache' on stdout, verbosily iff do_verbose.
22155682Smarkm */
22255682Smarkm
22355682Smarkmstatic void
22455682Smarkmprint_tickets (krb5_context context,
22555682Smarkm	       krb5_ccache ccache,
22655682Smarkm	       krb5_principal principal,
22772445Sassar	       int do_verbose,
228178825Sdfr	       int do_flags,
229178825Sdfr	       int do_hidden)
23055682Smarkm{
23155682Smarkm    krb5_error_code ret;
23255682Smarkm    char *str;
23355682Smarkm    krb5_cc_cursor cursor;
23455682Smarkm    krb5_creds creds;
235178825Sdfr    int32_t sec, usec;
23655682Smarkm
23772445Sassar    rtbl_t ct = NULL;
23872445Sassar
23955682Smarkm    ret = krb5_unparse_name (context, principal, &str);
24055682Smarkm    if (ret)
24155682Smarkm	krb5_err (context, 1, ret, "krb5_unparse_name");
24255682Smarkm
24355682Smarkm    printf ("%17s: %s:%s\n",
24455682Smarkm	    "Credentials cache",
24555682Smarkm	    krb5_cc_get_type(context, ccache),
24655682Smarkm	    krb5_cc_get_name(context, ccache));
24755682Smarkm    printf ("%17s: %s\n", "Principal", str);
24855682Smarkm    free (str);
24955682Smarkm
25055682Smarkm    if(do_verbose)
25155682Smarkm	printf ("%17s: %d\n", "Cache version",
25255682Smarkm		krb5_cc_get_version(context, ccache));
25355682Smarkm
254178825Sdfr    krb5_get_kdc_sec_offset(context, &sec, &usec);
255178825Sdfr
256178825Sdfr    if (do_verbose && sec != 0) {
25755682Smarkm	char buf[BUFSIZ];
25855682Smarkm	int val;
25955682Smarkm	int sig;
26055682Smarkm
261178825Sdfr	val = sec;
26255682Smarkm	sig = 1;
26355682Smarkm	if (val < 0) {
26455682Smarkm	    sig = -1;
26555682Smarkm	    val = -val;
26655682Smarkm	}
26772445Sassar
26855682Smarkm	unparse_time (val, buf, sizeof(buf));
26955682Smarkm
27055682Smarkm	printf ("%17s: %s%s\n", "KDC time offset",
27155682Smarkm		sig == -1 ? "-" : "", buf);
27255682Smarkm    }
27355682Smarkm
27455682Smarkm    printf("\n");
27555682Smarkm
27655682Smarkm    ret = krb5_cc_start_seq_get (context, ccache, &cursor);
27755682Smarkm    if (ret)
27855682Smarkm	krb5_err(context, 1, ret, "krb5_cc_start_seq_get");
27955682Smarkm
28072445Sassar    if(!do_verbose) {
28172445Sassar	ct = rtbl_create();
28272445Sassar	rtbl_add_column(ct, COL_ISSUED, 0);
28372445Sassar	rtbl_add_column(ct, COL_EXPIRES, 0);
28472445Sassar	if(do_flags)
28572445Sassar	    rtbl_add_column(ct, COL_FLAGS, 0);
28672445Sassar	rtbl_add_column(ct, COL_PRINCIPAL, 0);
287178825Sdfr	rtbl_set_separator(ct, "  ");
28872445Sassar    }
289127808Snectar    while ((ret = krb5_cc_next_cred (context,
290127808Snectar				     ccache,
291127808Snectar				     &cursor,
292127808Snectar				     &creds)) == 0) {
293178825Sdfr	const char *str;
294178825Sdfr	str = krb5_principal_get_comp_string(context, creds.server, 0);
295178825Sdfr	if (!do_hidden && str && str[0] == '@') {
296178825Sdfr	    ;
297178825Sdfr	}else if(do_verbose){
29855682Smarkm	    print_cred_verbose(context, &creds);
29955682Smarkm	}else{
30072445Sassar	    print_cred(context, &creds, ct, do_flags);
30155682Smarkm	}
302178825Sdfr	krb5_free_cred_contents (context, &creds);
30355682Smarkm    }
304127808Snectar    if(ret != KRB5_CC_END)
305127808Snectar	krb5_err(context, 1, ret, "krb5_cc_get_next");
30655682Smarkm    ret = krb5_cc_end_seq_get (context, ccache, &cursor);
30755682Smarkm    if (ret)
30855682Smarkm	krb5_err (context, 1, ret, "krb5_cc_end_seq_get");
30972445Sassar    if(!do_verbose) {
31072445Sassar	rtbl_format(ct, stdout);
31172445Sassar	rtbl_destroy(ct);
31272445Sassar    }
31355682Smarkm}
31455682Smarkm
31555682Smarkm/*
31655682Smarkm * Check if there's a tgt for the realm of `principal' and ccache and
31755682Smarkm * if so return 0, else 1
31855682Smarkm */
31955682Smarkm
32055682Smarkmstatic int
32155682Smarkmcheck_for_tgt (krb5_context context,
32255682Smarkm	       krb5_ccache ccache,
323178825Sdfr	       krb5_principal principal,
324178825Sdfr	       time_t *expiration)
32555682Smarkm{
32655682Smarkm    krb5_error_code ret;
32755682Smarkm    krb5_creds pattern;
32855682Smarkm    krb5_creds creds;
32955682Smarkm    krb5_realm *client_realm;
33055682Smarkm    int expired;
33155682Smarkm
332178825Sdfr    krb5_cc_clear_mcred(&pattern);
333178825Sdfr
33455682Smarkm    client_realm = krb5_princ_realm (context, principal);
33555682Smarkm
33655682Smarkm    ret = krb5_make_principal (context, &pattern.server,
33755682Smarkm			       *client_realm, KRB5_TGS_NAME, *client_realm,
33855682Smarkm			       NULL);
33955682Smarkm    if (ret)
34055682Smarkm	krb5_err (context, 1, ret, "krb5_make_principal");
341178825Sdfr    pattern.client = principal;
34255682Smarkm
34355682Smarkm    ret = krb5_cc_retrieve_cred (context, ccache, 0, &pattern, &creds);
34455682Smarkm    krb5_free_principal (context, pattern.server);
34555682Smarkm    if (ret) {
34655682Smarkm	if (ret == KRB5_CC_END)
34755682Smarkm	    return 1;
34855682Smarkm	krb5_err (context, 1, ret, "krb5_cc_retrieve_cred");
34955682Smarkm    }
35055682Smarkm
351178825Sdfr    expired = time(NULL) > creds.times.endtime;
35272445Sassar
353178825Sdfr    if (expiration)
354178825Sdfr	*expiration = creds.times.endtime;
35572445Sassar
356178825Sdfr    krb5_free_cred_contents (context, &creds);
35772445Sassar
358178825Sdfr    return expired;
35972445Sassar}
36072445Sassar
36172445Sassar/*
36255682Smarkm * Print a list of all AFS tokens
36355682Smarkm */
36455682Smarkm
36555682Smarkmstatic void
36655682Smarkmdisplay_tokens(int do_verbose)
36755682Smarkm{
368178825Sdfr    uint32_t i;
369102644Snectar    unsigned char t[4096];
37055682Smarkm    struct ViceIoctl parms;
37155682Smarkm
37255682Smarkm    parms.in = (void *)&i;
37355682Smarkm    parms.in_size = sizeof(i);
37455682Smarkm    parms.out = (void *)t;
37555682Smarkm    parms.out_size = sizeof(t);
37655682Smarkm
377102644Snectar    for (i = 0;; i++) {
37855682Smarkm        int32_t size_secret_tok, size_public_tok;
37955682Smarkm        unsigned char *cell;
38055682Smarkm	struct ClearToken ct;
38155682Smarkm	unsigned char *r = t;
38255682Smarkm	struct timeval tv;
38355682Smarkm	char buf1[20], buf2[20];
38455682Smarkm
385102644Snectar	if(k_pioctl(NULL, VIOCGETTOK, &parms, 0) < 0) {
386102644Snectar	    if(errno == EDOM)
387102644Snectar		break;
388102644Snectar	    continue;
389102644Snectar	}
390107207Snectar	if(parms.out_size > sizeof(t))
391102644Snectar	    continue;
392102644Snectar	if(parms.out_size < sizeof(size_secret_tok))
393102644Snectar	    continue;
394120945Snectar	t[min(parms.out_size,sizeof(t)-1)] = 0;
39555682Smarkm	memcpy(&size_secret_tok, r, sizeof(size_secret_tok));
39655682Smarkm	/* dont bother about the secret token */
39755682Smarkm	r += size_secret_tok + sizeof(size_secret_tok);
398102644Snectar	if (parms.out_size < (r - t) + sizeof(size_public_tok))
399102644Snectar	    continue;
40055682Smarkm	memcpy(&size_public_tok, r, sizeof(size_public_tok));
40155682Smarkm	r += sizeof(size_public_tok);
402102644Snectar	if (parms.out_size < (r - t) + size_public_tok + sizeof(int32_t))
403102644Snectar	    continue;
40455682Smarkm	memcpy(&ct, r, size_public_tok);
40555682Smarkm	r += size_public_tok;
40655682Smarkm	/* there is a int32_t with length of cellname, but we dont read it */
40755682Smarkm	r += sizeof(int32_t);
40855682Smarkm	cell = r;
40955682Smarkm
41055682Smarkm	gettimeofday (&tv, NULL);
41155682Smarkm	strlcpy (buf1, printable_time(ct.BeginTimestamp),
412102644Snectar		 sizeof(buf1));
41355682Smarkm	if (do_verbose || tv.tv_sec < ct.EndTimestamp)
41455682Smarkm	    strlcpy (buf2, printable_time(ct.EndTimestamp),
415102644Snectar		     sizeof(buf2));
41655682Smarkm	else
41755682Smarkm	    strlcpy (buf2, ">>> Expired <<<", sizeof(buf2));
41855682Smarkm
41955682Smarkm	printf("%s  %s  ", buf1, buf2);
42055682Smarkm
42155682Smarkm	if ((ct.EndTimestamp - ct.BeginTimestamp) & 1)
422102644Snectar	    printf("User's (AFS ID %d) tokens for %s", ct.ViceId, cell);
42355682Smarkm	else
424102644Snectar	    printf("Tokens for %s", cell);
42555682Smarkm	if (do_verbose)
42655682Smarkm	    printf(" (%d)", ct.AuthHandle);
42755682Smarkm	putchar('\n');
42855682Smarkm    }
42955682Smarkm}
43055682Smarkm
43172445Sassar/*
43272445Sassar * display the ccache in `cred_cache'
43372445Sassar */
43472445Sassar
43572445Sassarstatic int
43672445Sassardisplay_v5_ccache (const char *cred_cache, int do_test, int do_verbose,
437178825Sdfr		   int do_flags, int do_hidden)
43872445Sassar{
43972445Sassar    krb5_error_code ret;
44072445Sassar    krb5_context context;
44172445Sassar    krb5_ccache ccache;
44272445Sassar    krb5_principal principal;
44372445Sassar    int exit_status = 0;
44472445Sassar
44572445Sassar    ret = krb5_init_context (&context);
44672445Sassar    if (ret)
44772445Sassar	errx (1, "krb5_init_context failed: %d", ret);
44872445Sassar
44972445Sassar    if(cred_cache) {
45072445Sassar	ret = krb5_cc_resolve(context, cred_cache, &ccache);
45172445Sassar	if (ret)
45272445Sassar	    krb5_err (context, 1, ret, "%s", cred_cache);
45372445Sassar    } else {
45472445Sassar	ret = krb5_cc_default (context, &ccache);
45572445Sassar	if (ret)
45672445Sassar	    krb5_err (context, 1, ret, "krb5_cc_resolve");
45772445Sassar    }
45872445Sassar
45972445Sassar    ret = krb5_cc_get_principal (context, ccache, &principal);
46072445Sassar    if (ret) {
46172445Sassar	if(ret == ENOENT) {
46272445Sassar	    if (!do_test)
46372445Sassar		krb5_warnx(context, "No ticket file: %s",
46472445Sassar			   krb5_cc_get_name(context, ccache));
46572445Sassar	    return 1;
46672445Sassar	} else
46772445Sassar	    krb5_err (context, 1, ret, "krb5_cc_get_principal");
46872445Sassar    }
46972445Sassar    if (do_test)
470178825Sdfr	exit_status = check_for_tgt (context, ccache, principal, NULL);
47172445Sassar    else
472178825Sdfr	print_tickets (context, ccache, principal, do_verbose,
473178825Sdfr		       do_flags, do_hidden);
47472445Sassar
47572445Sassar    ret = krb5_cc_close (context, ccache);
47672445Sassar    if (ret)
47772445Sassar	krb5_err (context, 1, ret, "krb5_cc_close");
47872445Sassar
47972445Sassar    krb5_free_principal (context, principal);
48072445Sassar    krb5_free_context (context);
48172445Sassar    return exit_status;
48272445Sassar}
48372445Sassar
484178825Sdfr/*
485178825Sdfr *
486178825Sdfr */
487178825Sdfr
488178825Sdfrstatic int
489178825Sdfrlist_caches(void)
490178825Sdfr{
491178825Sdfr    krb5_cc_cache_cursor cursor;
492178825Sdfr    krb5_context context;
493178825Sdfr    krb5_error_code ret;
494178825Sdfr    krb5_ccache id;
495178825Sdfr    rtbl_t ct;
496178825Sdfr
497178825Sdfr    ret = krb5_init_context (&context);
498178825Sdfr    if (ret)
499178825Sdfr	errx (1, "krb5_init_context failed: %d", ret);
500178825Sdfr
501178825Sdfr    ret = krb5_cc_cache_get_first (context, NULL, &cursor);
502178825Sdfr    if (ret == KRB5_CC_NOSUPP)
503178825Sdfr	return 0;
504178825Sdfr    else if (ret)
505178825Sdfr	krb5_err (context, 1, ret, "krb5_cc_cache_get_first");
506178825Sdfr
507178825Sdfr    ct = rtbl_create();
508178825Sdfr    rtbl_add_column(ct, COL_PRINCIPAL, 0);
509178825Sdfr    rtbl_add_column(ct, COL_CACHENAME, 0);
510178825Sdfr    rtbl_add_column(ct, COL_EXPIRES, 0);
511178825Sdfr    rtbl_set_prefix(ct, "   ");
512178825Sdfr    rtbl_set_column_prefix(ct, COL_PRINCIPAL, "");
513178825Sdfr
514178825Sdfr    while ((ret = krb5_cc_cache_next (context, cursor, &id)) == 0) {
515178825Sdfr	krb5_principal principal;
516178825Sdfr	char *name;
517178825Sdfr
518178825Sdfr	ret = krb5_cc_get_principal(context, id, &principal);
519178825Sdfr	if (ret == 0) {
520178825Sdfr	    time_t t;
521178825Sdfr	    int expired = check_for_tgt (context, id, principal, &t);
522178825Sdfr
523178825Sdfr	    ret = krb5_unparse_name(context, principal, &name);
524178825Sdfr	    if (ret == 0) {
525178825Sdfr		rtbl_add_column_entry(ct, COL_PRINCIPAL, name);
526178825Sdfr		rtbl_add_column_entry(ct, COL_CACHENAME,
527178825Sdfr				      krb5_cc_get_name(context, id));
528178825Sdfr		rtbl_add_column_entry(ct, COL_EXPIRES,
529178825Sdfr				      expired ? ">>> Expired <<<" :
530178825Sdfr				      printable_time(t));
531178825Sdfr		free(name);
532178825Sdfr		krb5_free_principal(context, principal);
533178825Sdfr	    }
534178825Sdfr	}
535178825Sdfr	krb5_cc_close(context, id);
536178825Sdfr    }
537178825Sdfr
538178825Sdfr    krb5_cc_cache_end_seq_get(context, cursor);
539178825Sdfr
540178825Sdfr    rtbl_format(ct, stdout);
541178825Sdfr    rtbl_destroy(ct);
542178825Sdfr
543178825Sdfr    return 0;
544178825Sdfr}
545178825Sdfr
546178825Sdfr/*
547178825Sdfr *
548178825Sdfr */
549178825Sdfr
550178825Sdfrstatic int version_flag		= 0;
551178825Sdfrstatic int help_flag		= 0;
552178825Sdfrstatic int do_verbose		= 0;
553178825Sdfrstatic int do_list_caches	= 0;
554178825Sdfrstatic int do_test		= 0;
555178825Sdfrstatic int do_tokens		= 0;
556178825Sdfrstatic int do_v5		= 1;
55755682Smarkmstatic char *cred_cache;
558178825Sdfrstatic int do_flags	 	= 0;
559178825Sdfrstatic int do_hidden	 	= 0;
56055682Smarkm
56155682Smarkmstatic struct getargs args[] = {
56272445Sassar    { NULL, 'f', arg_flag, &do_flags },
56355682Smarkm    { "cache",			'c', arg_string, &cred_cache,
56455682Smarkm      "credentials cache to list", "cache" },
56555682Smarkm    { "test",			't', arg_flag, &do_test,
56655682Smarkm      "test for having tickets", NULL },
56772445Sassar    { NULL,			's', arg_flag, &do_test },
56855682Smarkm    { "tokens",			'T',   arg_flag, &do_tokens,
56955682Smarkm      "display AFS tokens", NULL },
57072445Sassar    { "v5",			'5',	arg_flag, &do_v5,
57172445Sassar      "display v5 cred cache", NULL},
572178825Sdfr    { "list-caches",		'l', arg_flag, &do_list_caches,
573178825Sdfr      "verbose output", NULL },
57455682Smarkm    { "verbose",		'v', arg_flag, &do_verbose,
57572445Sassar      "verbose output", NULL },
576178825Sdfr    { "hidden",			0,   arg_flag, &do_hidden,
577178825Sdfr      "display hidden credentials", NULL },
57872445Sassar    { NULL,			'a', arg_flag, &do_verbose },
57972445Sassar    { NULL,			'n', arg_flag, &do_verbose },
58055682Smarkm    { "version", 		0,   arg_flag, &version_flag,
58155682Smarkm      "print version", NULL },
58255682Smarkm    { "help",			0,   arg_flag, &help_flag,
58355682Smarkm      NULL, NULL}
58455682Smarkm};
58555682Smarkm
58655682Smarkmstatic void
58755682Smarkmusage (int ret)
58855682Smarkm{
58955682Smarkm    arg_printusage (args,
59055682Smarkm		    sizeof(args)/sizeof(*args),
59155682Smarkm		    NULL,
59255682Smarkm		    "");
59355682Smarkm    exit (ret);
59455682Smarkm}
59555682Smarkm
59655682Smarkmint
59755682Smarkmmain (int argc, char **argv)
59855682Smarkm{
599178825Sdfr    int optidx = 0;
60055682Smarkm    int exit_status = 0;
60155682Smarkm
60278527Sassar    setprogname (argv[0]);
60355682Smarkm
604178825Sdfr    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
60555682Smarkm	usage(1);
60655682Smarkm
60755682Smarkm    if (help_flag)
60855682Smarkm	usage (0);
60955682Smarkm
61055682Smarkm    if(version_flag){
61155682Smarkm	print_version(NULL);
61255682Smarkm	exit(0);
61355682Smarkm    }
61455682Smarkm
615178825Sdfr    argc -= optidx;
616178825Sdfr    argv += optidx;
61755682Smarkm
61855682Smarkm    if (argc != 0)
61955682Smarkm	usage (1);
62055682Smarkm
621178825Sdfr    if (do_list_caches) {
622178825Sdfr	exit_status = list_caches();
623178825Sdfr	return exit_status;
624178825Sdfr    }
625178825Sdfr
62672445Sassar    if (do_v5)
62772445Sassar	exit_status = display_v5_ccache (cred_cache, do_test,
628178825Sdfr					 do_verbose, do_flags, do_hidden);
62955682Smarkm
630120945Snectar    if (!do_test) {
63172445Sassar	if (do_tokens && k_hasafs ()) {
632120945Snectar	    if (do_v5)
63372445Sassar		printf ("\n");
63472445Sassar	    display_tokens (do_verbose);
63572445Sassar	}
63655682Smarkm    }
63755682Smarkm
63855682Smarkm    return exit_status;
63955682Smarkm}
640