1 /* 2 * Copyright (c) 1997-1999 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 36 RCSID("$Id: klist.c,v 1.53 2000/02/06 08:15:40 assar Exp $"); 37 38 static char* 39 printable_time(time_t t) 40 { 41 static char s[128]; 42 strcpy(s, ctime(&t)+ 4); 43 s[15] = 0; 44 return s; 45 } 46 47 static char* 48 printable_time_long(time_t t) 49 { 50 static char s[128]; 51 strcpy(s, ctime(&t)+ 4); 52 s[20] = 0; 53 return s; 54 } 55 56 static void 57 print_cred(krb5_context context, krb5_creds *cred) 58 { 59 char *str; 60 krb5_error_code ret; 61 krb5_timestamp sec; 62 63 krb5_timeofday (context, &sec); 64 65 if(cred->times.starttime) 66 printf ("%s ", printable_time(cred->times.starttime)); 67 else 68 printf ("%s ", printable_time(cred->times.authtime)); 69 70 if(cred->times.endtime > sec) 71 printf ("%s ", printable_time(cred->times.endtime)); 72 else 73 printf ("%-15s ", ">>>Expired<<<"); 74 ret = krb5_unparse_name (context, cred->server, &str); 75 if (ret) 76 krb5_err(context, 1, ret, "krb5_unparse_name"); 77 printf ("%s\n", str); 78 free (str); 79 } 80 81 static void 82 print_cred_verbose(krb5_context context, krb5_creds *cred) 83 { 84 int j; 85 char *str; 86 krb5_error_code ret; 87 int first_flag; 88 krb5_timestamp sec; 89 90 krb5_timeofday (context, &sec); 91 92 ret = krb5_unparse_name(context, cred->server, &str); 93 if(ret) 94 exit(1); 95 printf("Server: %s\n", str); 96 free (str); 97 { 98 Ticket t; 99 size_t len; 100 char *s; 101 102 decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len); 103 ret = krb5_enctype_to_string(context, t.enc_part.etype, &s); 104 if (ret == 0) { 105 printf("Ticket etype: %s", s); 106 free(s); 107 } else { 108 printf("Unknown etype: %d", t.enc_part.etype); 109 } 110 if(t.enc_part.kvno) 111 printf(", kvno %d", *t.enc_part.kvno); 112 printf("\n"); 113 if(cred->session.keytype != t.enc_part.etype) { 114 ret = krb5_keytype_to_string(context, cred->session.keytype, &str); 115 if(ret == KRB5_PROG_KEYTYPE_NOSUPP) 116 ret = krb5_enctype_to_string(context, cred->session.keytype, 117 &str); 118 if(ret) 119 krb5_warn(context, ret, "session keytype"); 120 else { 121 printf("Session key: %s\n", str); 122 free(str); 123 } 124 } 125 free_Ticket(&t); 126 } 127 printf("Auth time: %s\n", printable_time_long(cred->times.authtime)); 128 if(cred->times.authtime != cred->times.starttime) 129 printf("Start time: %s\n", printable_time_long(cred->times.starttime)); 130 printf("End time: %s", printable_time_long(cred->times.endtime)); 131 if(sec > cred->times.endtime) 132 printf(" (expired)"); 133 printf("\n"); 134 if(cred->flags.b.renewable) 135 printf("Renew till: %s\n", 136 printable_time_long(cred->times.renew_till)); 137 printf("Ticket flags: "); 138 #define PRINT_FLAG2(f, s) if(cred->flags.b.f) { if(!first_flag) printf(", "); printf("%s", #s); first_flag = 0; } 139 #define PRINT_FLAG(f) PRINT_FLAG2(f, f) 140 first_flag = 1; 141 PRINT_FLAG(forwardable); 142 PRINT_FLAG(forwarded); 143 PRINT_FLAG(proxiable); 144 PRINT_FLAG(proxy); 145 PRINT_FLAG2(may_postdate, may-postdate); 146 PRINT_FLAG(postdated); 147 PRINT_FLAG(invalid); 148 PRINT_FLAG(renewable); 149 PRINT_FLAG(initial); 150 PRINT_FLAG2(pre_authent, pre-authenticated); 151 PRINT_FLAG2(hw_authent, hw-authenticated); 152 PRINT_FLAG2(transited_policy_checked, transited-policy-checked); 153 PRINT_FLAG2(ok_as_delegate, ok-as-delegate); 154 PRINT_FLAG(anonymous); 155 printf("\n"); 156 printf("Addresses: "); 157 for(j = 0; j < cred->addresses.len; j++){ 158 char buf[128]; 159 size_t len; 160 if(j) printf(", "); 161 ret = krb5_print_address(&cred->addresses.val[j], 162 buf, sizeof(buf), &len); 163 164 if(ret == 0) 165 printf("%s", buf); 166 } 167 printf("\n\n"); 168 } 169 170 /* 171 * Print all tickets in `ccache' on stdout, verbosily iff do_verbose. 172 */ 173 174 static void 175 print_tickets (krb5_context context, 176 krb5_ccache ccache, 177 krb5_principal principal, 178 int do_verbose) 179 { 180 krb5_error_code ret; 181 char *str; 182 krb5_cc_cursor cursor; 183 krb5_creds creds; 184 185 ret = krb5_unparse_name (context, principal, &str); 186 if (ret) 187 krb5_err (context, 1, ret, "krb5_unparse_name"); 188 189 printf ("%17s: %s:%s\n", 190 "Credentials cache", 191 krb5_cc_get_type(context, ccache), 192 krb5_cc_get_name(context, ccache)); 193 printf ("%17s: %s\n", "Principal", str); 194 free (str); 195 196 if(do_verbose) 197 printf ("%17s: %d\n", "Cache version", 198 krb5_cc_get_version(context, ccache)); 199 200 if (do_verbose && context->kdc_sec_offset) { 201 char buf[BUFSIZ]; 202 int val; 203 int sig; 204 205 val = context->kdc_sec_offset; 206 sig = 1; 207 if (val < 0) { 208 sig = -1; 209 val = -val; 210 } 211 212 unparse_time (val, buf, sizeof(buf)); 213 214 printf ("%17s: %s%s\n", "KDC time offset", 215 sig == -1 ? "-" : "", buf); 216 } 217 218 printf("\n"); 219 220 ret = krb5_cc_start_seq_get (context, ccache, &cursor); 221 if (ret) 222 krb5_err(context, 1, ret, "krb5_cc_start_seq_get"); 223 224 if(!do_verbose) 225 printf(" %-15s %-15s %s\n", "Issued", "Expires", "Principal"); 226 227 while (krb5_cc_next_cred (context, 228 ccache, 229 &creds, 230 &cursor) == 0) { 231 if(do_verbose){ 232 print_cred_verbose(context, &creds); 233 }else{ 234 print_cred(context, &creds); 235 } 236 krb5_free_creds_contents (context, &creds); 237 } 238 ret = krb5_cc_end_seq_get (context, ccache, &cursor); 239 if (ret) 240 krb5_err (context, 1, ret, "krb5_cc_end_seq_get"); 241 } 242 243 /* 244 * Check if there's a tgt for the realm of `principal' and ccache and 245 * if so return 0, else 1 246 */ 247 248 static int 249 check_for_tgt (krb5_context context, 250 krb5_ccache ccache, 251 krb5_principal principal) 252 { 253 krb5_error_code ret; 254 krb5_creds pattern; 255 krb5_creds creds; 256 krb5_realm *client_realm; 257 int expired; 258 259 client_realm = krb5_princ_realm (context, principal); 260 261 ret = krb5_make_principal (context, &pattern.server, 262 *client_realm, KRB5_TGS_NAME, *client_realm, 263 NULL); 264 if (ret) 265 krb5_err (context, 1, ret, "krb5_make_principal"); 266 267 ret = krb5_cc_retrieve_cred (context, ccache, 0, &pattern, &creds); 268 expired = time(NULL) > creds.times.endtime; 269 krb5_free_principal (context, pattern.server); 270 krb5_free_creds_contents (context, &creds); 271 if (ret) { 272 if (ret == KRB5_CC_END) 273 return 1; 274 krb5_err (context, 1, ret, "krb5_cc_retrieve_cred"); 275 } 276 return expired; 277 } 278 279 #ifdef KRB4 280 /* 281 * Print a list of all AFS tokens 282 */ 283 284 static void 285 display_tokens(int do_verbose) 286 { 287 u_int32_t i; 288 unsigned char t[128]; 289 struct ViceIoctl parms; 290 291 parms.in = (void *)&i; 292 parms.in_size = sizeof(i); 293 parms.out = (void *)t; 294 parms.out_size = sizeof(t); 295 296 for (i = 0; k_pioctl(NULL, VIOCGETTOK, &parms, 0) == 0; i++) { 297 int32_t size_secret_tok, size_public_tok; 298 unsigned char *cell; 299 struct ClearToken ct; 300 unsigned char *r = t; 301 struct timeval tv; 302 char buf1[20], buf2[20]; 303 304 memcpy(&size_secret_tok, r, sizeof(size_secret_tok)); 305 /* dont bother about the secret token */ 306 r += size_secret_tok + sizeof(size_secret_tok); 307 memcpy(&size_public_tok, r, sizeof(size_public_tok)); 308 r += sizeof(size_public_tok); 309 memcpy(&ct, r, size_public_tok); 310 r += size_public_tok; 311 /* there is a int32_t with length of cellname, but we dont read it */ 312 r += sizeof(int32_t); 313 cell = r; 314 315 gettimeofday (&tv, NULL); 316 strlcpy (buf1, printable_time(ct.BeginTimestamp), 317 sizeof(buf1)); 318 if (do_verbose || tv.tv_sec < ct.EndTimestamp) 319 strlcpy (buf2, printable_time(ct.EndTimestamp), 320 sizeof(buf2)); 321 else 322 strlcpy (buf2, ">>> Expired <<<", sizeof(buf2)); 323 324 printf("%s %s ", buf1, buf2); 325 326 if ((ct.EndTimestamp - ct.BeginTimestamp) & 1) 327 printf("User's (AFS ID %d) tokens for %s", ct.ViceId, cell); 328 else 329 printf("Tokens for %s", cell); 330 if (do_verbose) 331 printf(" (%d)", ct.AuthHandle); 332 putchar('\n'); 333 } 334 } 335 #endif 336 337 static int version_flag = 0; 338 static int help_flag = 0; 339 static int do_verbose = 0; 340 static int do_test = 0; 341 #ifdef KRB4 342 static int do_tokens = 0; 343 #endif 344 static char *cred_cache; 345 346 static struct getargs args[] = { 347 { "cache", 'c', arg_string, &cred_cache, 348 "credentials cache to list", "cache" }, 349 { "test", 't', arg_flag, &do_test, 350 "test for having tickets", NULL }, 351 #ifdef KRB4 352 { "tokens", 'T', arg_flag, &do_tokens, 353 "display AFS tokens", NULL }, 354 #endif 355 { "verbose", 'v', arg_flag, &do_verbose, 356 "Verbose output", NULL }, 357 { "version", 0, arg_flag, &version_flag, 358 "print version", NULL }, 359 { "help", 0, arg_flag, &help_flag, 360 NULL, NULL} 361 }; 362 363 static void 364 usage (int ret) 365 { 366 arg_printusage (args, 367 sizeof(args)/sizeof(*args), 368 NULL, 369 ""); 370 exit (ret); 371 } 372 373 int 374 main (int argc, char **argv) 375 { 376 krb5_error_code ret; 377 krb5_context context; 378 krb5_ccache ccache; 379 krb5_principal principal; 380 int optind = 0; 381 int exit_status = 0; 382 383 set_progname (argv[0]); 384 385 if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind)) 386 usage(1); 387 388 if (help_flag) 389 usage (0); 390 391 if(version_flag){ 392 print_version(NULL); 393 exit(0); 394 } 395 396 argc -= optind; 397 argv += optind; 398 399 if (argc != 0) 400 usage (1); 401 402 ret = krb5_init_context (&context); 403 if (ret) 404 krb5_err(context, 1, ret, "krb5_init_context"); 405 406 if(cred_cache) { 407 ret = krb5_cc_resolve(context, cred_cache, &ccache); 408 if (ret) 409 krb5_err (context, 1, ret, "%s", cred_cache); 410 } else { 411 ret = krb5_cc_default (context, &ccache); 412 if (ret) 413 krb5_err (context, 1, ret, "krb5_cc_resolve"); 414 } 415 416 ret = krb5_cc_get_principal (context, ccache, &principal); 417 if (ret) { 418 if(ret == ENOENT) { 419 if (do_test) 420 return 1; 421 else 422 krb5_errx(context, 1, "No ticket file: %s", 423 krb5_cc_get_name(context, ccache)); 424 } else 425 krb5_err (context, 1, ret, "krb5_cc_get_principal"); 426 } 427 if (do_test) 428 exit_status = check_for_tgt (context, ccache, principal); 429 else 430 print_tickets (context, ccache, principal, do_verbose); 431 432 ret = krb5_cc_close (context, ccache); 433 if (ret) 434 krb5_err (context, 1, ret, "krb5_cc_close"); 435 436 krb5_free_principal (context, principal); 437 krb5_free_context (context); 438 439 #ifdef KRB4 440 if (!do_test && do_tokens && k_hasafs ()) 441 display_tokens (do_verbose); 442 #endif 443 444 return exit_status; 445 } 446