1 /* 2 * Copyright (c) 2003, 2017, 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 printHelp(); 140 System.exit(0); 141 } 142 if ((args[i].length() >= 2) && (args[i].startsWith("-"))) { 143 arg = Character.valueOf(args[i].charAt(1)); 144 switch (arg.charValue()) { 145 case 'c': 146 action = 'c'; 147 break; 148 case 'k': 149 action = 'k'; 150 break; 151 case 'a': 152 options[2] = 'a'; 153 break; 154 case 'n': 155 options[3] = 'n'; 156 break; 157 case 'f': 158 options[1] = 'f'; 159 break; 160 case 'e': 161 options[0] = 'e'; 162 break; 163 case 'K': 164 options[1] = 'K'; 165 break; 166 case 't': 167 options[2] = 't'; 168 break; 169 default: 170 printHelp(); 171 System.exit(-1); 172 } 173 174 } else { 175 if (!args[i].startsWith("-") && (i == args.length - 1)) { 176 // the argument is the last one. 177 name = args[i]; 178 arg = null; 179 } else { 180 printHelp(); // incorrect input format. 181 System.exit(-1); 182 } 183 } 184 } 185 } 186 187 void displayTab() { 188 KeyTab table = (KeyTab)target; 189 KeyTabEntry[] entries = table.getEntries(); 190 if (entries.length == 0) { 191 System.out.println("\nKey tab: " + name + 192 ", " + " 0 entries found.\n"); 193 } else { 194 if (entries.length == 1) 195 System.out.println("\nKey tab: " + name + 196 ", " + entries.length + " entry found.\n"); 197 else 198 System.out.println("\nKey tab: " + name + ", " + 199 entries.length + " entries found.\n"); 200 for (int i = 0; i < entries.length; i++) { 201 System.out.println("[" + (i + 1) + "] " + 202 "Service principal: " + 203 entries[i].getService().toString()); 204 System.out.println("\t KVNO: " + 205 entries[i].getKey().getKeyVersionNumber()); 206 if (options[0] == 'e') { 207 EncryptionKey key = entries[i].getKey(); 208 System.out.println("\t Key type: " + 209 key.getEType()); 210 } 211 if (options[1] == 'K') { 212 EncryptionKey key = entries[i].getKey(); 213 System.out.println("\t Key: " + 214 entries[i].getKeyString()); 215 } 216 if (options[2] == 't') { 217 System.out.println("\t Time stamp: " + 218 format(entries[i].getTimeStamp())); 219 } 220 } 221 } 222 } 223 224 void displayCache() { 225 CredentialsCache cache = (CredentialsCache)target; 226 sun.security.krb5.internal.ccache.Credentials[] creds = 227 cache.getCredsList(); 228 if (creds == null) { 229 System.out.println ("No credentials available in the cache " + 230 name); 231 System.exit(-1); 232 } 233 System.out.println("\nCredentials cache: " + name); 234 String defaultPrincipal = cache.getPrimaryPrincipal().toString(); 235 int num = creds.length; 236 237 if (num == 1) 238 System.out.println("\nDefault principal: " + 239 defaultPrincipal + ", " + 240 creds.length + " entry found.\n"); 241 else 242 System.out.println("\nDefault principal: " + 243 defaultPrincipal + ", " + 244 creds.length + " entries found.\n"); 245 if (creds != null) { 246 for (int i = 0; i < creds.length; i++) { 247 try { 248 String starttime; 249 String endtime; 250 String renewTill; 251 String servicePrincipal; 252 if (creds[i].getStartTime() != null) { 253 starttime = format(creds[i].getStartTime()); 254 } else { 255 starttime = format(creds[i].getAuthTime()); 256 } 257 endtime = format(creds[i].getEndTime()); 258 servicePrincipal = 259 creds[i].getServicePrincipal().toString(); 260 System.out.println("[" + (i + 1) + "] " + 261 " Service Principal: " + 262 servicePrincipal); 263 System.out.println(" Valid starting: " + starttime); 264 System.out.println(" Expires: " + endtime); 265 if (creds[i].getRenewTill() != null) { 266 renewTill = format(creds[i].getRenewTill()); 267 System.out.println( 268 " Renew until: " + renewTill); 269 } 270 if (options[0] == 'e') { 271 String eskey = EType.toString(creds[i].getEType()); 272 String etkt = EType.toString(creds[i].getTktEType()); 273 System.out.println(" EType (skey, tkt): " 274 + eskey + ", " + etkt); 275 } 276 if (options[1] == 'f') { 277 System.out.println(" Flags: " + 278 creds[i].getTicketFlags().toString()); 279 } 280 if (options[2] == 'a') { 281 boolean first = true; 282 InetAddress[] caddr 283 = creds[i].setKrbCreds().getClientAddresses(); 284 if (caddr != null) { 285 for (InetAddress ia: caddr) { 286 String out; 287 if (options[3] == 'n') { 288 out = ia.getHostAddress(); 289 } else { 290 out = ia.getCanonicalHostName(); 291 } 292 System.out.println(" " + 293 (first?"Addresses:":" ") + 294 " " + out); 295 first = false; 296 } 297 } else { 298 System.out.println(" [No host addresses info]"); 299 } 300 } 301 } catch (RealmException e) { 302 System.out.println("Error reading principal from "+ 303 "the entry."); 304 if (DEBUG) { 305 e.printStackTrace(); 306 } 307 System.exit(-1); 308 } 309 } 310 } else { 311 System.out.println("\nNo entries found."); 312 } 313 } 314 315 void displayMessage(String target) { 316 if (name == null) { 317 System.out.println("Default " + target + " not found."); 318 } else { 319 System.out.println(target + " " + name + " not found."); 320 } 321 } 322 /** 323 * Reformats the date from the form - 324 * dow mon dd hh:mm:ss zzz yyyy to mon/dd/yyyy hh:mm 325 * where dow is the day of the week, mon is the month, 326 * dd is the day of the month, hh is the hour of 327 * the day, mm is the minute within the hour, 328 * ss is the second within the minute, zzz is the time zone, 329 * and yyyy is the year. 330 * @param date the string form of Date object. 331 */ 332 private String format(KerberosTime kt) { 333 String date = kt.toDate().toString(); 334 return (date.substring(4, 7) + " " + date.substring(8, 10) + 335 ", " + date.substring(24) 336 + " " + date.substring(11, 19)); 337 } 338 /** 339 * Prints out the help information. 340 */ 341 void printHelp() { 342 System.out.println("\nUsage: klist " + 343 "[[-c] [-f] [-e] [-a [-n]]] [-k [-t] [-K]] [name]"); 344 System.out.println(" name\t name of credentials cache or " + 345 " keytab with the prefix. File-based cache or " 346 + "keytab's prefix is FILE:."); 347 System.out.println(" -c specifies that credential cache is to be " + 348 "listed"); 349 System.out.println(" -k specifies that key tab is to be listed"); 350 System.out.println(" options for credentials caches:"); 351 System.out.println("\t-f \t shows credentials flags"); 352 System.out.println("\t-e \t shows the encryption type"); 353 System.out.println("\t-a \t shows addresses"); 354 System.out.println("\t -n \t do not reverse-resolve addresses"); 355 System.out.println(" options for keytabs:"); 356 System.out.println("\t-t \t shows keytab entry timestamps"); 357 System.out.println("\t-K \t shows keytab entry key value"); 358 System.out.println("\t-e \t shows keytab entry key type"); 359 } 360 }