1 /* 2 * Copyright (c) 2000, 2012, 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 sun.security.krb5.*; 34 import sun.security.krb5.internal.*; 35 import sun.security.krb5.internal.ccache.*; 36 import java.io.IOException; 37 import java.time.Instant; 38 import java.io.FileInputStream; 39 40 /** 41 * Maintains user-specific options or default settings when the user requests 42 * a KDC ticket using Kinit. 43 * 44 * @author Yanni Zhang 45 * @author Ram Marti 46 */ 47 class KinitOptions { 48 49 // 1. acquire, 2. renew, 3. validate 50 public int action = 1; 51 52 // forwardable and proxiable flags have two states: 53 // -1 - flag set to be not forwardable or proxiable; 54 // 1 - flag set to be forwardable or proxiable. 55 public short forwardable = 0; 56 public short proxiable = 0; 57 public KerberosTime lifetime; 58 public KerberosTime renewable_lifetime; 59 public String target_service; 60 public String keytab_file; 61 public String cachename; 62 private PrincipalName principal; 63 public String realm; 64 char[] password = null; 65 public boolean keytab; 66 private boolean DEBUG = Krb5.DEBUG; 67 private boolean includeAddresses = true; // default. 68 private boolean useKeytab = false; // default = false. 69 private String ktabName; // keytab file name 70 71 public KinitOptions() throws RuntimeException, RealmException { 72 // no args were specified in the command line; 73 // use default values 74 cachename = FileCredentialsCache.getDefaultCacheName(); 75 if (cachename == null) { 76 throw new RuntimeException("default cache name error"); 77 } 78 principal = getDefaultPrincipal(); 79 } 80 81 public void setKDCRealm(String r) throws RealmException { 82 realm = r; 83 } 84 85 public String getKDCRealm() { 86 if (realm == null) { 87 if (principal != null) { 88 return principal.getRealmString(); 89 } 90 } 91 return null; 92 } 93 94 public KinitOptions(String[] args) 95 throws KrbException, RuntimeException, IOException { 96 // currently we provide support for -f -p -c principal options 97 String p = null; // store principal 98 99 for (int i = 0; i < args.length; i++) { 100 if (args[i].equals("-f")) { 101 forwardable = 1; 102 } else if (args[i].equals("-p")) { 103 proxiable = 1; 104 } else if (args[i].equals("-c")) { 105 106 if (args[i + 1].startsWith("-")) { 107 throw new IllegalArgumentException("input format " + 108 " not correct: " + 109 " -c option " + 110 "must be followed " + 111 "by the cache name"); 112 } 113 cachename = args[++i]; 114 if ((cachename.length() >= 5) && 115 cachename.substring(0, 5).equalsIgnoreCase("FILE:")) { 116 cachename = cachename.substring(5); 117 }; 118 } else if (args[i].equals("-A")) { 119 includeAddresses = false; 120 } else if (args[i].equals("-k")) { 121 useKeytab = true; 122 } else if (args[i].equals("-t")) { 123 if (ktabName != null) { 124 throw new IllegalArgumentException 125 ("-t option/keytab file name repeated"); 126 } else if (i + 1 < args.length) { 127 ktabName = args[++i]; 128 } else { 129 throw new IllegalArgumentException 130 ("-t option requires keytab file name"); 131 } 132 133 useKeytab = true; 134 } else if (args[i].equals("-R")) { 135 action = 2; 136 } else if (args[i].equals("-l")) { 137 lifetime = getTime(Config.duration(args[++i])); 138 } else if (args[i].equals("-r")) { 139 renewable_lifetime = getTime(Config.duration(args[++i])); 140 } else if (args[i].equalsIgnoreCase("-help")) { 141 printHelp(); 142 System.exit(0); 143 } else if (p == null) { // Haven't yet processed a "principal" 144 p = args[i]; 145 try { 146 principal = new PrincipalName(p); 147 } catch (Exception e) { 148 throw new IllegalArgumentException("invalid " + 149 "Principal name: " + p + 150 e.getMessage()); 151 } 152 } else if (this.password == null) { 153 // Have already processed a Principal, this must be a password 154 password = args[i].toCharArray(); 155 } else { 156 throw new IllegalArgumentException("too many parameters"); 157 } 158 } 159 // we should get cache name before getting the default principal name 160 if (cachename == null) { 161 cachename = FileCredentialsCache.getDefaultCacheName(); 162 if (cachename == null) { 163 throw new RuntimeException("default cache name error"); 164 } 165 } 166 if (principal == null) { 167 principal = getDefaultPrincipal(); 168 } 169 } 170 171 PrincipalName getDefaultPrincipal() { 172 173 // get default principal name from the cachename if it is 174 // available. 175 176 try { 177 CCacheInputStream cis = 178 new CCacheInputStream(new FileInputStream(cachename)); 179 int version; 180 if ((version = cis.readVersion()) == 181 FileCCacheConstants.KRB5_FCC_FVNO_4) { 182 cis.readTag(); 183 } else { 184 if (version == FileCCacheConstants.KRB5_FCC_FVNO_1 || 185 version == FileCCacheConstants.KRB5_FCC_FVNO_2) { 186 cis.setNativeByteOrder(); 187 } 188 } 189 PrincipalName p = cis.readPrincipal(version); 190 cis.close(); 191 if (DEBUG) { 192 System.out.println(">>>KinitOptions principal name from "+ 193 "the cache is :" + p); 194 } 195 return p; 196 } catch (IOException e) { 197 // ignore any exceptions; we will use the user name as the 198 // principal name 199 if (DEBUG) { 200 e.printStackTrace(); 201 } 202 } catch (RealmException e) { 203 if (DEBUG) { 204 e.printStackTrace(); 205 } 206 } 207 208 String username = System.getProperty("user.name"); 209 if (DEBUG) { 210 System.out.println(">>>KinitOptions default username is :" 211 + username); 212 } 213 try { 214 PrincipalName p = new PrincipalName(username); 215 return p; 216 } catch (RealmException e) { 217 // ignore exception , return null 218 if (DEBUG) { 219 System.out.println ("Exception in getting principal " + 220 "name " + e.getMessage()); 221 e.printStackTrace(); 222 } 223 } 224 return null; 225 } 226 227 228 void printHelp() { 229 System.out.println("Usage:\n\n1. Initial ticket request:\n" + 230 " kinit [-A] [-f] [-p] [-c cachename] " + 231 "[-l lifetime] [-r renewable_time]\n" + 232 " [[-k [-t keytab_file_name]] [principal] " + 233 "[password]"); 234 System.out.println("2. Renew a ticket:\n" + 235 " kinit -R [-c cachename] [principal]"); 236 System.out.println("\nAvailable options to " + 237 "Kerberos 5 ticket request:"); 238 System.out.println("\t-A do not include addresses"); 239 System.out.println("\t-f forwardable"); 240 System.out.println("\t-p proxiable"); 241 System.out.println("\t-c cache name " + 242 "(i.e., FILE:\\d:\\myProfiles\\mykrb5cache)"); 243 System.out.println("\t-l lifetime"); 244 System.out.println("\t-r renewable time " + 245 "(total lifetime a ticket can be renewed)"); 246 System.out.println("\t-k use keytab"); 247 System.out.println("\t-t keytab file name"); 248 System.out.println("\tprincipal the principal name "+ 249 "(i.e., qweadf@ATHENA.MIT.EDU qweadf)"); 250 System.out.println("\tpassword the principal's Kerberos password"); 251 } 252 253 public boolean getAddressOption() { 254 return includeAddresses; 255 } 256 257 public boolean useKeytabFile() { 258 return useKeytab; 259 } 260 261 public String keytabFileName() { 262 return ktabName; 263 } 264 265 public PrincipalName getPrincipal() { 266 return principal; 267 } 268 269 private KerberosTime getTime(int s) { 270 return new KerberosTime(Instant.now().plusSeconds(s)); 271 } 272 }