|
1 /* |
|
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
3 * |
|
4 * This code is free software; you can redistribute it and/or modify it |
|
5 * under the terms of the GNU General Public License version 2 only, as |
|
6 * published by the Free Software Foundation. Sun designates this |
|
7 * particular file as subject to the "Classpath" exception as provided |
|
8 * by Sun in the LICENSE file that accompanied this code. |
|
9 * |
|
10 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13 * version 2 for more details (a copy is included in the LICENSE file that |
|
14 * accompanied this code). |
|
15 * |
|
16 * You should have received a copy of the GNU General Public License version |
|
17 * 2 along with this work; if not, write to the Free Software Foundation, |
|
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
19 * |
|
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
21 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
22 * have any questions. |
|
23 */ |
|
24 |
|
25 /* |
|
26 * (C) Copyright IBM Corp. 1999 All Rights Reserved. |
|
27 * Copyright 1997 The Open Group Research Institute. All rights reserved. |
|
28 */ |
|
29 |
|
30 package sun.security.krb5.internal.tools; |
|
31 |
|
32 import sun.security.krb5.*; |
|
33 import sun.security.krb5.internal.*; |
|
34 import sun.security.krb5.internal.ktab.*; |
|
35 import sun.security.krb5.KrbCryptoException; |
|
36 import java.lang.RuntimeException; |
|
37 import java.io.IOException; |
|
38 import java.io.BufferedReader; |
|
39 import java.io.InputStreamReader; |
|
40 import java.io.FileOutputStream; |
|
41 import java.io.File; |
|
42 import java.util.Arrays; |
|
43 /** |
|
44 * This class can execute as a command-line tool to help the user manage |
|
45 * entires in the key table. |
|
46 * Available functions include list/add/update/delete service key(s). |
|
47 * |
|
48 * @author Yanni Zhang |
|
49 * @author Ram Marti |
|
50 */ |
|
51 |
|
52 public class Ktab { |
|
53 // KeyTabAdmin admin; |
|
54 KeyTab table; |
|
55 char action; |
|
56 String name; // name and directory of key table |
|
57 String principal; |
|
58 char[] password = null; |
|
59 |
|
60 /** |
|
61 * The main program that can be invoked at command line. |
|
62 * <br>Usage: ktab <options> |
|
63 * <br>available options to Ktab: |
|
64 * <ul> |
|
65 * <li><b>-l</b> list the keytab name and entries |
|
66 * <li><b>-a</b> <<i>principal name</i>> |
|
67 * (<<i>password</i>>) add an entry to the keytab. |
|
68 * The entry is added only to the keytab. No changes are made to the |
|
69 * Kerberos database. |
|
70 * <li><b>-d</b> <<i>principal name</i>> |
|
71 * delete an entry from the keytab |
|
72 * The entry is deleted only from the keytab. No changes are made to the |
|
73 * Kerberos database. |
|
74 * <li><b>-k</b> <<i>keytab name</i> > |
|
75 * specify keytab name and path with prefix FILE: |
|
76 * <li><b>-help</b> display instructions. |
|
77 */ |
|
78 public static void main(String[] args) { |
|
79 Ktab ktab = new Ktab(); |
|
80 if ((args.length == 1) && (args[0].equalsIgnoreCase("-help"))) { |
|
81 ktab.printHelp(); |
|
82 System.exit(0); |
|
83 } else if ((args == null) || (args.length == 0)) { |
|
84 ktab.action = 'l'; |
|
85 } else { |
|
86 ktab.processArgs(args); |
|
87 } |
|
88 try { |
|
89 if (ktab.name == null) { |
|
90 // ktab.admin = new KeyTabAdmin(); // use the default keytab. |
|
91 ktab.table = KeyTab.getInstance(); |
|
92 if (ktab.table == null) { |
|
93 if (ktab.action == 'a') { |
|
94 ktab.table = KeyTab.create(); |
|
95 } else { |
|
96 System.out.println("No default key table exists."); |
|
97 System.exit(-1); |
|
98 } |
|
99 } |
|
100 } else { |
|
101 if ((ktab.action != 'a') && |
|
102 !(new File(ktab.name)).exists()) { |
|
103 System.out.println("Key table " + |
|
104 ktab.name + " does not exist."); |
|
105 System.exit(-1); |
|
106 } else { |
|
107 ktab.table = KeyTab.getInstance(ktab.name); |
|
108 } |
|
109 if (ktab.table == null) { |
|
110 if (ktab.action == 'a') { |
|
111 ktab.table = KeyTab.create(ktab.name); |
|
112 } else { |
|
113 System.out.println("The format of key table " + |
|
114 ktab.name + " is incorrect."); |
|
115 System.exit(-1); |
|
116 } |
|
117 } |
|
118 } |
|
119 } catch (RealmException e) { |
|
120 System.err.println("Error loading key table."); |
|
121 System.exit(-1); |
|
122 } catch (IOException e) { |
|
123 System.err.println("Error loading key table."); |
|
124 System.exit(-1); |
|
125 } |
|
126 switch (ktab.action) { |
|
127 case 'l': |
|
128 ktab.listKt(); |
|
129 break; |
|
130 case 'a': |
|
131 ktab.addEntry(); |
|
132 break; |
|
133 case 'd': |
|
134 ktab.deleteEntry(); |
|
135 break; |
|
136 default: |
|
137 ktab.printHelp(); |
|
138 System.exit(-1); |
|
139 } |
|
140 } |
|
141 |
|
142 /** |
|
143 * Parses the command line arguments. |
|
144 */ |
|
145 void processArgs(String[] args) { |
|
146 Character arg = null; |
|
147 for (int i = 0; i < args.length; i++) { |
|
148 if ((args[i].length() == 2) && (args[i].startsWith("-"))) { |
|
149 arg = new Character(args[i].charAt(1)); |
|
150 } else { |
|
151 printHelp(); |
|
152 System.exit(-1); |
|
153 } |
|
154 switch (arg.charValue()) { |
|
155 case 'l': |
|
156 case 'L': |
|
157 action = 'l'; // list keytab location, name and entries |
|
158 break; |
|
159 case 'a': |
|
160 case 'A': |
|
161 action = 'a'; // add a new entry to keytab. |
|
162 i++; |
|
163 if ((i < args.length) && (!args[i].startsWith("-"))) { |
|
164 principal = args[i]; |
|
165 } else { |
|
166 System.out.println("Please specify the principal name"+ |
|
167 " after -a option."); |
|
168 printHelp(); |
|
169 System.exit(-1); |
|
170 } |
|
171 if ((i + 1 < args.length) && |
|
172 (!args[i + 1].startsWith("-"))) { |
|
173 password = args[i + 1].toCharArray(); |
|
174 i++; |
|
175 } else { |
|
176 password = null; // prompt user for password later. |
|
177 } |
|
178 break; |
|
179 case 'd': |
|
180 case 'D': |
|
181 action = 'd'; // delete an entry. |
|
182 i++; |
|
183 if ((i < args.length) && (!args[i].startsWith("-"))) { |
|
184 principal = args[i]; |
|
185 } else { |
|
186 System.out.println("Please specify the principal" + |
|
187 "name of the entry you want to " + |
|
188 " delete after -d option."); |
|
189 printHelp(); |
|
190 System.exit(-1); |
|
191 } |
|
192 break; |
|
193 case 'k': |
|
194 case 'K': |
|
195 i++; |
|
196 if ((i < args.length) && (!args[i].startsWith("-"))) { |
|
197 if (args[i].length() >= 5 && |
|
198 args[i].substring(0, 5).equalsIgnoreCase("FILE:")) { |
|
199 name = args[i].substring(5); |
|
200 } else |
|
201 name = args[i]; |
|
202 } else { |
|
203 System.out.println("Please specify the keytab "+ |
|
204 "file name and location " + |
|
205 "after -k option"); |
|
206 printHelp(); |
|
207 System.exit(-1); |
|
208 } |
|
209 break; |
|
210 default: |
|
211 printHelp(); |
|
212 System.exit(-1); |
|
213 } |
|
214 } |
|
215 } |
|
216 |
|
217 /** |
|
218 * Adds a service key to key table. If the specified key table does not |
|
219 * exist, the program will automatically generate |
|
220 * a new key table. |
|
221 */ |
|
222 void addEntry() { |
|
223 PrincipalName pname = null; |
|
224 try { |
|
225 pname = new PrincipalName(principal); |
|
226 if (pname.getRealm() == null) { |
|
227 pname.setRealm(Config.getInstance().getDefaultRealm()); |
|
228 } |
|
229 } catch (KrbException e) { |
|
230 System.err.println("Failed to add " + principal + |
|
231 " to keytab."); |
|
232 e.printStackTrace(); |
|
233 System.exit(-1); |
|
234 } |
|
235 if (password == null) { |
|
236 try { |
|
237 BufferedReader cis = |
|
238 new BufferedReader(new InputStreamReader(System.in)); |
|
239 System.out.print("Password for " + pname.toString() + ":"); |
|
240 System.out.flush(); |
|
241 password = cis.readLine().toCharArray(); |
|
242 } catch (IOException e) { |
|
243 System.err.println("Failed to read the password."); |
|
244 e.printStackTrace(); |
|
245 System.exit(-1); |
|
246 } |
|
247 |
|
248 } |
|
249 try { |
|
250 // admin.addEntry(pname, password); |
|
251 table.addEntry(pname, password); |
|
252 Arrays.fill(password, '0'); // clear password |
|
253 // admin.save(); |
|
254 table.save(); |
|
255 System.out.println("Done!"); |
|
256 System.out.println("Service key for " + principal + |
|
257 " is saved in " + table.tabName()); |
|
258 |
|
259 } catch (KrbException e) { |
|
260 System.err.println("Failed to add " + principal + " to keytab."); |
|
261 e.printStackTrace(); |
|
262 System.exit(-1); |
|
263 } catch (IOException e) { |
|
264 System.err.println("Failed to save new entry."); |
|
265 e.printStackTrace(); |
|
266 System.exit(-1); |
|
267 } |
|
268 } |
|
269 |
|
270 /** |
|
271 * Lists key table name and entries in it. |
|
272 */ |
|
273 void listKt() { |
|
274 int version; |
|
275 String principal; |
|
276 // System.out.println("Keytab name: " + admin.getKeyTabName()); |
|
277 System.out.println("Keytab name: " + table.tabName()); |
|
278 // KeyTabEntry[] entries = admin.getEntries(); |
|
279 KeyTabEntry[] entries = table.getEntries(); |
|
280 if ((entries != null) && (entries.length > 0)) { |
|
281 System.out.println("KVNO Principal"); |
|
282 for (int i = 0; i < entries.length; i++) { |
|
283 version = entries[i].getKey().getKeyVersionNumber().intValue(); |
|
284 principal = entries[i].getService().toString(); |
|
285 if (i == 0) { |
|
286 StringBuffer separator = new StringBuffer(); |
|
287 for (int j = 0; j < 9 + principal.length(); j++) { |
|
288 separator.append("-"); |
|
289 } |
|
290 System.out.println(separator.toString()); |
|
291 } |
|
292 System.out.println(" " + version + " " + principal); |
|
293 } |
|
294 } else { |
|
295 System.out.println("0 entry."); |
|
296 } |
|
297 } |
|
298 |
|
299 /** |
|
300 * Deletes an entry from the key table. |
|
301 */ |
|
302 void deleteEntry() { |
|
303 PrincipalName pname = null; |
|
304 try { |
|
305 pname = new PrincipalName(principal); |
|
306 if (pname.getRealm() == null) { |
|
307 pname.setRealm(Config.getInstance().getDefaultRealm()); |
|
308 } |
|
309 String answer; |
|
310 BufferedReader cis = |
|
311 new BufferedReader(new InputStreamReader(System.in)); |
|
312 System.out.print("Are you sure you want to "+ |
|
313 " delete service key for " + pname.toString() + |
|
314 " in " + table.tabName() + "?(Y/N) :"); |
|
315 |
|
316 System.out.flush(); |
|
317 answer = cis.readLine(); |
|
318 if (answer.equalsIgnoreCase("Y") || |
|
319 answer.equalsIgnoreCase("Yes")); |
|
320 else { |
|
321 // no error, the user did not want to delete the entry |
|
322 System.exit(0); |
|
323 } |
|
324 |
|
325 } catch (KrbException e) { |
|
326 System.err.println("Error occured while deleting the entry. "+ |
|
327 "Deletion failed."); |
|
328 e.printStackTrace(); |
|
329 System.exit(-1); |
|
330 } catch (IOException e) { |
|
331 System.err.println("Error occured while deleting the entry. "+ |
|
332 " Deletion failed."); |
|
333 e.printStackTrace(); |
|
334 System.exit(-1); |
|
335 } |
|
336 // admin.deleteEntry(pname); |
|
337 table.deleteEntry(pname); |
|
338 |
|
339 try { |
|
340 table.save(); |
|
341 } catch (IOException e) { |
|
342 System.err.println("Error occurs while saving the keytab." + |
|
343 "Deletion fails."); |
|
344 e.printStackTrace(); |
|
345 System.exit(-1); |
|
346 } |
|
347 System.out.println("Done!"); |
|
348 |
|
349 } |
|
350 |
|
351 /** |
|
352 * Prints out the help information. |
|
353 */ |
|
354 void printHelp() { |
|
355 System.out.println("\nUsage: ktab " + |
|
356 "<options>"); |
|
357 System.out.println("available options to Ktab:"); |
|
358 System.out.println("-l\t\t\t\tlist the keytab name and entries"); |
|
359 System.out.println("-a <principal name> (<password>)add an entry " + |
|
360 "to the keytab"); |
|
361 System.out.println("-d <principal name>\t\tdelete an entry from "+ |
|
362 "the keytab"); |
|
363 System.out.println("-k <keytab name>\t\tspecify keytab name and "+ |
|
364 " path with prefix FILE:"); |
|
365 } |
|
366 } |