2 * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 #include "kuser_locl.h"
40 printable_time(time_t t
)
43 strcpy(s
, ctime(&t
)+ 4);
49 printable_time_long(time_t t
)
52 strcpy(s
, ctime(&t
)+ 4);
57 #define COL_ISSUED " Issued"
58 #define COL_EXPIRES " Expires"
59 #define COL_FLAGS "Flags"
60 #define COL_PRINCIPAL " Principal"
61 #define COL_PRINCIPAL_KVNO " Principal (kvno)"
64 print_cred(krb5_context context
, krb5_creds
*cred
, rtbl_t ct
, int do_flags
)
70 krb5_timeofday (context
, &sec
);
73 if(cred
->times
.starttime
)
74 rtbl_add_column_entry(ct
, COL_ISSUED
,
75 printable_time(cred
->times
.starttime
));
77 rtbl_add_column_entry(ct
, COL_ISSUED
,
78 printable_time(cred
->times
.authtime
));
80 if(cred
->times
.endtime
> sec
)
81 rtbl_add_column_entry(ct
, COL_EXPIRES
,
82 printable_time(cred
->times
.endtime
));
84 rtbl_add_column_entry(ct
, COL_EXPIRES
, ">>>Expired<<<");
85 ret
= krb5_unparse_name (context
, cred
->server
, &str
);
87 krb5_err(context
, 1, ret
, "krb5_unparse_name");
88 rtbl_add_column_entry(ct
, COL_PRINCIPAL
, str
);
91 if(cred
->flags
.b
.forwardable
)
93 if(cred
->flags
.b
.forwarded
)
95 if(cred
->flags
.b
.proxiable
)
97 if(cred
->flags
.b
.proxy
)
99 if(cred
->flags
.b
.may_postdate
)
101 if(cred
->flags
.b
.postdated
)
103 if(cred
->flags
.b
.renewable
)
105 if(cred
->flags
.b
.initial
)
107 if(cred
->flags
.b
.invalid
)
109 if(cred
->flags
.b
.pre_authent
)
111 if(cred
->flags
.b
.hw_authent
)
114 rtbl_add_column_entry(ct
, COL_FLAGS
, s
);
120 print_cred_verbose(krb5_context context
, krb5_creds
*cred
)
128 krb5_timeofday (context
, &sec
);
130 ret
= krb5_unparse_name(context
, cred
->server
, &str
);
133 printf("Server: %s\n", str
);
140 decode_Ticket(cred
->ticket
.data
, cred
->ticket
.length
, &t
, &len
);
141 ret
= krb5_enctype_to_string(context
, t
.enc_part
.etype
, &s
);
142 printf("Ticket etype: ");
147 printf("unknown(%d)", t
.enc_part
.etype
);
150 printf(", kvno %d", *t
.enc_part
.kvno
);
152 if(cred
->session
.keytype
!= t
.enc_part
.etype
) {
153 ret
= krb5_keytype_to_string(context
, cred
->session
.keytype
, &str
);
154 if(ret
== KRB5_PROG_KEYTYPE_NOSUPP
)
155 ret
= krb5_enctype_to_string(context
, cred
->session
.keytype
,
158 krb5_warn(context
, ret
, "session keytype");
160 printf("Session key: %s\n", str
);
166 printf("Auth time: %s\n", printable_time_long(cred
->times
.authtime
));
167 if(cred
->times
.authtime
!= cred
->times
.starttime
)
168 printf("Start time: %s\n", printable_time_long(cred
->times
.starttime
));
169 printf("End time: %s", printable_time_long(cred
->times
.endtime
));
170 if(sec
> cred
->times
.endtime
)
171 printf(" (expired)");
173 if(cred
->flags
.b
.renewable
)
174 printf("Renew till: %s\n",
175 printable_time_long(cred
->times
.renew_till
));
176 printf("Ticket flags: ");
177 #define PRINT_FLAG2(f, s) if(cred->flags.b.f) { if(!first_flag) printf(", "); printf("%s", #s); first_flag = 0; }
178 #define PRINT_FLAG(f) PRINT_FLAG2(f, f)
180 PRINT_FLAG(forwardable
);
181 PRINT_FLAG(forwarded
);
182 PRINT_FLAG(proxiable
);
184 PRINT_FLAG2(may_postdate
, may
-postdate
);
185 PRINT_FLAG(postdated
);
187 PRINT_FLAG(renewable
);
189 PRINT_FLAG2(pre_authent
, pre
-authenticated
);
190 PRINT_FLAG2(hw_authent
, hw
-authenticated
);
191 PRINT_FLAG2(transited_policy_checked
, transited
-policy
-checked
);
192 PRINT_FLAG2(ok_as_delegate
, ok
-as
-delegate
);
193 PRINT_FLAG(anonymous
);
195 printf("Addresses: ");
196 for(j
= 0; j
< cred
->addresses
.len
; j
++){
200 ret
= krb5_print_address(&cred
->addresses
.val
[j
],
201 buf
, sizeof(buf
), &len
);
210 * Print all tickets in `ccache' on stdout, verbosily iff do_verbose.
214 print_tickets (krb5_context context
,
216 krb5_principal principal
,
222 krb5_cc_cursor cursor
;
227 ret
= krb5_unparse_name (context
, principal
, &str
);
229 krb5_err (context
, 1, ret
, "krb5_unparse_name");
231 printf ("%17s: %s:%s\n",
233 krb5_cc_get_type(context
, ccache
),
234 krb5_cc_get_name(context
, ccache
));
235 printf ("%17s: %s\n", "Principal", str
);
239 printf ("%17s: %d\n", "Cache version",
240 krb5_cc_get_version(context
, ccache
));
242 if (do_verbose
&& context
->kdc_sec_offset
) {
247 val
= context
->kdc_sec_offset
;
254 unparse_time (val
, buf
, sizeof(buf
));
256 printf ("%17s: %s%s\n", "KDC time offset",
257 sig
== -1 ? "-" : "", buf
);
262 ret
= krb5_cc_start_seq_get (context
, ccache
, &cursor
);
264 krb5_err(context
, 1, ret
, "krb5_cc_start_seq_get");
268 rtbl_add_column(ct
, COL_ISSUED
, 0);
269 rtbl_add_column(ct
, COL_EXPIRES
, 0);
271 rtbl_add_column(ct
, COL_FLAGS
, 0);
272 rtbl_add_column(ct
, COL_PRINCIPAL
, 0);
273 rtbl_set_prefix(ct
, " ");
274 rtbl_set_column_prefix(ct
, COL_ISSUED
, "");
276 while (krb5_cc_next_cred (context
,
281 print_cred_verbose(context
, &creds
);
283 print_cred(context
, &creds
, ct
, do_flags
);
285 krb5_free_creds_contents (context
, &creds
);
287 ret
= krb5_cc_end_seq_get (context
, ccache
, &cursor
);
289 krb5_err (context
, 1, ret
, "krb5_cc_end_seq_get");
291 rtbl_format(ct
, stdout
);
297 * Check if there's a tgt for the realm of `principal' and ccache and
298 * if so return 0, else 1
302 check_for_tgt (krb5_context context
,
304 krb5_principal principal
)
309 krb5_realm
*client_realm
;
312 client_realm
= krb5_princ_realm (context
, principal
);
314 ret
= krb5_make_principal (context
, &pattern
.server
,
315 *client_realm
, KRB5_TGS_NAME
, *client_realm
,
318 krb5_err (context
, 1, ret
, "krb5_make_principal");
320 ret
= krb5_cc_retrieve_cred (context
, ccache
, 0, &pattern
, &creds
);
321 expired
= time(NULL
) > creds
.times
.endtime
;
322 krb5_free_principal (context
, pattern
.server
);
323 krb5_free_creds_contents (context
, &creds
);
325 if (ret
== KRB5_CC_END
)
327 krb5_err (context
, 1, ret
, "krb5_cc_retrieve_cred");
333 /* prints the approximate kdc time differential as something human
337 print_time_diff(int do_verbose
)
339 int d
= abs(krb_get_kdc_time_diff());
342 if ((do_verbose
&& d
> 0) || d
> 60) {
343 unparse_time_approx (d
, buf
, sizeof(buf
));
344 printf ("Time diff:\t%s\n", buf
);
349 * return a short representation of `dp' in string form.
353 short_date(int32_t dp
)
356 time_t t
= (time_t)dp
;
358 if (t
== (time_t)(-1L)) return "*** Never *** ";
365 * Print a list of all the v4 tickets
369 display_v4_tickets (int do_verbose
)
379 file
= getenv ("KRBTKFILE");
383 printf("%17s: %s\n", "V4-ticket file", file
);
385 ret
= krb_get_tf_realm (file
, princ
.realm
);
387 warnx ("%s", krb_get_err_text(ret
));
391 ret
= tf_init (file
, R_TKT_FIL
);
393 warnx ("tf_init: %s", krb_get_err_text(ret
));
396 ret
= tf_get_pname (princ
.name
);
399 warnx ("tf_get_pname: %s", krb_get_err_text(ret
));
402 ret
= tf_get_pinst (princ
.instance
);
405 warnx ("tf_get_pname: %s", krb_get_err_text(ret
));
409 printf ("%17s: %s\n", "Principal", krb_unparse_name(&princ
));
410 print_time_diff(do_verbose
);
414 rtbl_add_column(ct
, COL_ISSUED
, 0);
415 rtbl_add_column(ct
, COL_EXPIRES
, 0);
417 rtbl_add_column(ct
, COL_PRINCIPAL_KVNO
, 0);
419 rtbl_add_column(ct
, COL_PRINCIPAL
, 0);
420 rtbl_set_prefix(ct
, " ");
421 rtbl_set_column_prefix(ct
, COL_ISSUED
, "");
423 while ((ret
= tf_get_cred(&cred
)) == KSUCCESS
) {
425 char buf1
[20], buf2
[20];
431 short_date(cred
.issue_date
),
433 cred
.issue_date
= krb_life_to_time(cred
.issue_date
, cred
.lifetime
);
434 krb_kdctimeofday(&tv
);
435 if (do_verbose
|| tv
.tv_sec
< (unsigned long) cred
.issue_date
)
437 short_date(cred
.issue_date
),
443 rtbl_add_column_entry(ct
, COL_ISSUED
, buf1
);
444 rtbl_add_column_entry(ct
, COL_EXPIRES
, buf2
);
445 pp
= krb_unparse_name_long(cred
.service
,
451 asprintf(&tmp
, "%s (%d)", pp
, cred
.kvno
);
452 rtbl_add_column_entry(ct
, COL_PRINCIPAL_KVNO
, tmp
);
455 rtbl_add_column_entry(ct
, COL_PRINCIPAL
, pp
);
458 rtbl_format(ct
, stdout
);
460 if (!found
&& ret
== EOF
)
461 printf("No tickets in file.\n");
465 * should do NAT stuff here
471 * Print a list of all AFS tokens
475 display_tokens(int do_verbose
)
478 unsigned char t
[4096];
479 struct ViceIoctl parms
;
481 parms
.in
= (void *)&i
;
482 parms
.in_size
= sizeof(i
);
483 parms
.out
= (void *)t
;
484 parms
.out_size
= sizeof(t
);
487 int32_t size_secret_tok
, size_public_tok
;
489 struct ClearToken ct
;
490 unsigned char *r
= t
;
492 char buf1
[20], buf2
[20];
494 if(k_pioctl(NULL
, VIOCGETTOK
, &parms
, 0) < 0) {
499 if(parms
.out_size
> sizeof(t
))
501 if(parms
.out_size
< sizeof(size_secret_tok
))
503 t
[parms
.out_size
] = 0;
504 memcpy(&size_secret_tok
, r
, sizeof(size_secret_tok
));
505 /* dont bother about the secret token */
506 r
+= size_secret_tok
+ sizeof(size_secret_tok
);
507 if (parms
.out_size
< (r
- t
) + sizeof(size_public_tok
))
509 memcpy(&size_public_tok
, r
, sizeof(size_public_tok
));
510 r
+= sizeof(size_public_tok
);
511 if (parms
.out_size
< (r
- t
) + size_public_tok
+ sizeof(int32_t))
513 memcpy(&ct
, r
, size_public_tok
);
514 r
+= size_public_tok
;
515 /* there is a int32_t with length of cellname, but we dont read it */
516 r
+= sizeof(int32_t);
519 gettimeofday (&tv
, NULL
);
520 strlcpy (buf1
, printable_time(ct
.BeginTimestamp
),
522 if (do_verbose
|| tv
.tv_sec
< ct
.EndTimestamp
)
523 strlcpy (buf2
, printable_time(ct
.EndTimestamp
),
526 strlcpy (buf2
, ">>> Expired <<<", sizeof(buf2
));
528 printf("%s %s ", buf1
, buf2
);
530 if ((ct
.EndTimestamp
- ct
.BeginTimestamp
) & 1)
531 printf("User's (AFS ID %d) tokens for %s", ct
.ViceId
, cell
);
533 printf("Tokens for %s", cell
);
535 printf(" (%d)", ct
.AuthHandle
);
542 * display the ccache in `cred_cache'
546 display_v5_ccache (const char *cred_cache
, int do_test
, int do_verbose
,
550 krb5_context context
;
552 krb5_principal principal
;
555 ret
= krb5_init_context (&context
);
557 errx (1, "krb5_init_context failed: %d", ret
);
560 ret
= krb5_cc_resolve(context
, cred_cache
, &ccache
);
562 krb5_err (context
, 1, ret
, "%s", cred_cache
);
564 ret
= krb5_cc_default (context
, &ccache
);
566 krb5_err (context
, 1, ret
, "krb5_cc_resolve");
569 ret
= krb5_cc_get_principal (context
, ccache
, &principal
);
573 krb5_warnx(context
, "No ticket file: %s",
574 krb5_cc_get_name(context
, ccache
));
577 krb5_err (context
, 1, ret
, "krb5_cc_get_principal");
580 exit_status
= check_for_tgt (context
, ccache
, principal
);
582 print_tickets (context
, ccache
, principal
, do_verbose
, do_flags
);
584 ret
= krb5_cc_close (context
, ccache
);
586 krb5_err (context
, 1, ret
, "krb5_cc_close");
588 krb5_free_principal (context
, principal
);
589 krb5_free_context (context
);
593 static int version_flag
= 0;
594 static int help_flag
= 0;
595 static int do_verbose
= 0;
596 static int do_test
= 0;
598 static int do_v4
= 1;
599 static int do_tokens
= 0;
601 static int do_v5
= 1;
602 static char *cred_cache
;
603 static int do_flags
= 0;
605 static struct getargs args
[] = {
606 { NULL
, 'f', arg_flag
, &do_flags
},
607 { "cache", 'c', arg_string
, &cred_cache
,
608 "credentials cache to list", "cache" },
609 { "test", 't', arg_flag
, &do_test
,
610 "test for having tickets", NULL
},
611 { NULL
, 's', arg_flag
, &do_test
},
613 { "v4", '4', arg_flag
, &do_v4
,
614 "display v4 tickets", NULL
},
615 { "tokens", 'T', arg_flag
, &do_tokens
,
616 "display AFS tokens", NULL
},
618 { "v5", '5', arg_flag
, &do_v5
,
619 "display v5 cred cache", NULL
},
620 { "verbose", 'v', arg_flag
, &do_verbose
,
621 "verbose output", NULL
},
622 { NULL
, 'a', arg_flag
, &do_verbose
},
623 { NULL
, 'n', arg_flag
, &do_verbose
},
624 { "version", 0, arg_flag
, &version_flag
,
625 "print version", NULL
},
626 { "help", 0, arg_flag
, &help_flag
,
633 arg_printusage (args
,
634 sizeof(args
)/sizeof(*args
),
641 main (int argc
, char **argv
)
646 setprogname (argv
[0]);
648 if(getarg(args
, sizeof(args
) / sizeof(args
[0]), argc
, argv
, &optind
))
666 exit_status
= display_v5_ccache (cred_cache
, do_test
,
667 do_verbose
, do_flags
);
674 display_v4_tickets (do_verbose
);
676 if (do_tokens
&& k_hasafs ()) {
679 display_tokens (do_verbose
);