1 /* 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * (C) Copyright IBM Corp. 1999 All Rights Reserved. 28 * Copyright 1997 The Open Group Research Institute. All rights reserved. 29 */ 30 31 package sun.security.krb5.internal.tools; 32 33 import java.net.InetAddress; 34 import sun.security.krb5.*; 35 import sun.security.krb5.internal.*; 36 import sun.security.krb5.internal.ccache.*; 37 import sun.security.krb5.internal.ktab.*; 38 import sun.security.krb5.internal.crypto.EType; 39 40 /** 41 * This class can execute as a command-line tool to list entries in 42 * credential cache and key tab. 43 * 44 * @author Yanni Zhang 45 * @author Ram Marti 46 */ 47 public class Klist { 48 Object target; 49 // for credentials cache, options are 'f', 'e', 'a' and 'n'; 50 // for keytab, optionsare 't' and 'K' and 'e' 51 char[] options = new char[4]; 52 String name; // the name of credentials cache and keytable. 53 char action; // actions would be 'c' for credentials cache 54 // and 'k' for keytable. 55 private static boolean DEBUG = Krb5.DEBUG; 56 57 /** 58 * The main program that can be invoked at command line. 59 * <br>Usage: klist 60 * [[-c] [-f] [-e] [-a [-n]]] [-k [-t] [-K]] [name] 61 * -c specifies that credential cache is to be listed 62 * -k specifies that key tab is to be listed 63 * name name of the credentials cache or keytab 64 * <br>available options for credential caches: 65 * <ul> 66 * <li><b>-f</b> shows credentials flags 67 * <li><b>-e</b> shows the encryption type 68 * <li><b>-a</b> shows addresses 69 * <li><b>-n</b> do not reverse-resolve addresses 70 * </ul> 71 * available options for keytabs: 72 * <ul> 73 * <li><b>-t</b> shows keytab entry timestamps 74 * <li><b>-K</b> shows keytab entry DES keys 75 * </ul> 76 */ 77 public static void main(String[] args) { 78 Klist klist = new Klist(); 79 if ((args == null) || (args.length == 0)) { 80 klist.action = 'c'; // default will list default credentials cache. 81 } else { 82 klist.processArgs(args); 83 } 84 switch (klist.action) { 85 case 'c': 86 if (klist.name == null) { 87 klist.target = CredentialsCache.getInstance(); 88 klist.name = CredentialsCache.cacheName(); 89 } else 90 klist.target = CredentialsCache.getInstance(klist.name); 91 92 if (klist.target != null) { 93 klist.displayCache(); 94 } else { 95 klist.displayMessage("Credentials cache"); 96 System.exit(-1); 97 } 98 break; 99 case 'k': 100 KeyTab ktab = KeyTab.getInstance(klist.name); 101 if (ktab.isMissing()) { 102 System.out.println("KeyTab " + klist.name + " not found."); 103 System.exit(-1); 104 } else if (!ktab.isValid()) { 105 System.out.println("KeyTab " + klist.name 106 + " format not supported."); 107 System.exit(-1); 108 } 109 klist.target = ktab; 110 klist.name = ktab.tabName(); 111 klist.displayTab(); 112 break; 113 default: 114 if (klist.name != null) { 115 klist.printHelp(); 116 System.exit(-1); 117 } else { 118 klist.target = CredentialsCache.getInstance(); 119 klist.name = CredentialsCache.cacheName(); 120 if (klist.target != null) { 121 klist.displayCache(); 122 } else { 123 klist.displayMessage("Credentials cache"); 124 System.exit(-1); 125 } 126 } 127 } 128 } 129 130 /** 131 * Parses the command line arguments. 132 */ 133 void processArgs(String[] args) { 134 Character arg; 135 for (int i = 0; i < args.length; i++) { 136 if (args[i].equals("-?") || 137 args[i].equals("-h") || 138 args[i].equals("--help")) { 139 // -help was documented, but handled as an invalid flag. 140 // Keep handling as is, remove -help from usage. 141 printHelp(); 142 System.exit(0); 143 } 144 if ((args[i].length() >= 2) && (args[i].startsWith("-"))) { 145 arg = Character.valueOf(args[i].charAt(1)); 146 switch (arg.charValue()) { 147 case 'c': 148 action = 'c'; 149 break; 150 case 'k': 151 action = 'k'; 152 break; 153 case 'a': 154 options[2] = 'a'; 155 break; 156 case 'n': 157 options[3] = 'n'; 158 break; 159 case 'f': 160 options[1] = 'f'; 161 break; 162 case 'e': 163 options[0] = 'e'; 164 break; 165 case 'K': 166 options[1] = 'K'; 167 break; 168 case 't': 169 options[2] = 't'; 170 break; 171 default: 172 printHelp(); 173 System.exit(-1); 174 } 175 176 } else { 177 if (!args[i].startsWith("-") && (i == args.length - 1)) { 178 // the argument is the last one. 179 name = args[i]; 180 arg = null; 181 } else { 182 printHelp(); // incorrect input format. 183 System.exit(-1); 184 } 185 } 186 } 187 } 188 189 void displayTab() { 190 KeyTab table = (KeyTab)target; 191 KeyTabEntry[] entries = table.getEntries(); 192 if (entries.length == 0) { 193 System.out.println("\nKey tab: " + name + 194 ", " + " 0 entries found.\n"); 195 } else { 196 if (entries.length == 1) 197 System.out.println("\nKey tab: " + name + 198 ", " + entries.length + " entry found.\n"); 199 else 200 System.out.println("\nKey tab: " + name + ", " + 201 entries.length + " entries found.\n"); 202 for (int i = 0; i < entries.length; i++) { 203 System.out.println("[" + (i + 1) + "] " + 204 "Service principal: " + 205 entries[i].getService().toString()); 206 System.out.println("\t KVNO: " + 207 entries[i].getKey().getKeyVersionNumber()); 208 if (options[0] == 'e') { 209 EncryptionKey key = entries[i].getKey(); 210 System.out.println("\t Key type: " + 211 key.getEType()); 212 } 213 if (options[1] == 'K') { 214 EncryptionKey key = entries[i].getKey(); 215 System.out.println("\t Key: " + 216 entries[i].getKeyString()); 217 } 218 if (options[2] == 't') { 219 System.out.println("\t Time stamp: " + 220 format(entries[i].getTimeStamp())); 221 } 222 } 223 } 224 } 225 226 void displayCache() { 227 CredentialsCache cache = (CredentialsCache)target; 228 sun.security.krb5.internal.ccache.Credentials[] creds = 229 cache.getCredsList(); 230 if (creds == null) { 231 System.out.println ("No credentials available in the cache " + 232 name); 233 System.exit(-1); 234 } 235 System.out.println("\nCredentials cache: " + name); 236 String defaultPrincipal = cache.getPrimaryPrincipal().toString(); 237 int num = creds.length; 238 239 if (num == 1) 240 System.out.println("\nDefault principal: " + 241 defaultPrincipal + ", " + 242 creds.length + " entry found.\n"); 243 else 244 System.out.println("\nDefault principal: " + 245 defaultPrincipal + ", " + 246 creds.length + " entries found.\n"); 247 if (creds != null) { 248 for (int i = 0; i < creds.length; i++) { 249 try { 250 String starttime; 251 String endtime; 252 String renewTill; 253 String servicePrincipal; 254 if (creds[i].getStartTime() != null) { 255 starttime = format(creds[i].getStartTime()); 256 } else { 257 starttime = format(creds[i].getAuthTime()); 258 } 259 endtime = format(creds[i].getEndTime()); 260 servicePrincipal = 261 creds[i].getServicePrincipal().toString(); 262 System.out.println("[" + (i + 1) + "] " + 263 " Service Principal: " + 264 servicePrincipal); 265 System.out.println(" Valid starting: " + starttime); 266 System.out.println(" Expires: " + endtime); 267 if (creds[i].getRenewTill() != null) { 268 renewTill = format(creds[i].getRenewTill()); 269 System.out.println( 270 " Renew until: " + renewTill); 271 } 272 if (options[0] == 'e') { 273 String eskey = EType.toString(creds[i].getEType()); 274 String etkt = EType.toString(creds[i].getTktEType()); 275 System.out.println(" EType (skey, tkt): " 276 + eskey + ", " + etkt); 277 } 278 if (options[1] == 'f') { 279 System.out.println(" Flags: " + 280 creds[i].getTicketFlags().toString()); 281 } 282 if (options[2] == 'a') { 283 boolean first = true; 284 InetAddress[] caddr 285 = creds[i].setKrbCreds().getClientAddresses(); 286 if (caddr != null) { 287 for (InetAddress ia: caddr) { 288 String out; 289 if (options[3] == 'n') { 290 out = ia.getHostAddress(); 291 } else { 292 out = ia.getCanonicalHostName(); 293 } 294 System.out.println(" " + 295 (first?"Addresses:":" ") + 296 " " + out); 297 first = false; 298 } 299 } else { 300 System.out.println(" [No host addresses info]"); 301 } 302 } 303 } catch (RealmException e) { 304 System.out.println("Error reading principal from "+ 305 "the entry."); 306 if (DEBUG) { 307 e.printStackTrace(); 308 } 309 System.exit(-1); 310 } 311 } 312 } else { 313 System.out.println("\nNo entries found."); 314 } 315 } 316 317 void displayMessage(String target) { 318 if (name == null) { 319 System.out.println("Default " + target + " not found."); 320 } else { 321 System.out.println(target + " " + name + " not found."); 322 } 323 } 324 /** 325 * Reformats the date from the form - 326 * dow mon dd hh:mm:ss zzz yyyy to mon/dd/yyyy hh:mm 327 * where dow is the day of the week, mon is the month, 328 * dd is the day of the month, hh is the hour of 329 * the day, mm is the minute within the hour, 330 * ss is the second within the minute, zzz is the time zone, 331 * and yyyy is the year. 332 * @param date the string form of Date object. 333 */ 334 private String format(KerberosTime kt) { 335 String date = kt.toDate().toString(); 336 return (date.substring(4, 7) + " " + date.substring(8, 10) + 337 ", " + date.substring(24) 338 + " " + date.substring(11, 19)); 339 } 340 /** 341 * Prints out the help information. 342 */ 343 void printHelp() { 344 System.out.println("\nUsage: klist " + 345 "[[-c] [-f] [-e] [-a [-n]]] [-k [-t] [-K]] [name]"); 346 System.out.println(" name\t name of credentials cache or " + 347 " keytab with the prefix. File-based cache or " 348 + "keytab's prefix is FILE:."); 349 System.out.println(" -c specifies that credential cache is to be " + 350 "listed"); 351 System.out.println(" -k specifies that key tab is to be listed"); 352 System.out.println(" options for credentials caches:"); 353 System.out.println("\t-f \t shows credentials flags"); 354 System.out.println("\t-e \t shows the encryption type"); 355 System.out.println("\t-a \t shows addresses"); 356 System.out.println("\t -n \t do not reverse-resolve addresses"); 357 System.out.println(" options for keytabs:"); 358 System.out.println("\t-t \t shows keytab entry timestamps"); 359 System.out.println("\t-K \t shows keytab entry key value"); 360 System.out.println("\t-e \t shows keytab entry key type"); 361 System.out.println("\n-? -h --help print this help message and exit"); 362 } 363 }