001: /*
002: * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.security.util;
027:
028: import java.math.BigInteger;
029: import java.util.regex.Pattern;
030: import java.util.regex.Matcher;
031:
032: /**
033: * A utility class for debuging.
034: *
035: * @version 1.32
036: * @author Roland Schemers
037: */
038: public class Debug {
039:
040: private String prefix;
041:
042: private static String args;
043:
044: static {
045: args = (String) java.security.AccessController
046: .doPrivileged(new sun.security.action.GetPropertyAction(
047: "java.security.debug"));
048:
049: String args2 = (String) java.security.AccessController
050: .doPrivileged(new sun.security.action.GetPropertyAction(
051: "java.security.auth.debug"));
052:
053: if (args == null) {
054: args = args2;
055: } else {
056: if (args2 != null)
057: args = args + "," + args2;
058: }
059:
060: if (args != null) {
061: args = marshal(args);
062: if (args.equals("help")) {
063: Help();
064: }
065: }
066: }
067:
068: public static void Help() {
069: System.err.println();
070: System.err.println("all turn on all debugging");
071: System.err
072: .println("access print all checkPermission results");
073: System.err
074: .println("combiner SubjectDomainCombiner debugging");
075: System.err.println("gssloginconfig");
076: System.err.println("configfile JAAS ConfigFile loading");
077: System.err.println("configparser JAAS ConfigFile parsing");
078: System.err
079: .println(" GSS LoginConfigImpl debugging");
080: System.err.println("jar jar verification");
081: System.err.println("logincontext login context results");
082: System.err.println("policy loading and granting");
083: System.err.println("provider security provider debugging");
084: System.err
085: .println("scl permissions SecureClassLoader assigns");
086: System.err.println();
087: System.err.println("The following can be used with access:");
088: System.err.println();
089: System.err.println("stack include stack trace");
090: System.err.println("domain dump all domains in context");
091: System.err
092: .println("failure before throwing exception, dump stack");
093: System.err
094: .println(" and domain that didn't have permission");
095: System.err.println();
096: System.err
097: .println("The following can be used with stack and domain:");
098: System.err.println();
099: System.err.println("permission=<classname>");
100: System.err
101: .println(" only dump output if specified permission");
102: System.err.println(" is being checked");
103: System.err.println("codebase=<URL>");
104: System.err
105: .println(" only dump output if specified codebase");
106: System.err.println(" is being checked");
107:
108: System.err.println();
109: System.err
110: .println("Note: Separate multiple options with a comma");
111: System.exit(0);
112: }
113:
114: /**
115: * Get a Debug object corresponding to whether or not the given
116: * option is set. Set the prefix to be the same as option.
117: */
118:
119: public static Debug getInstance(String option) {
120: return getInstance(option, option);
121: }
122:
123: /**
124: * Get a Debug object corresponding to whether or not the given
125: * option is set. Set the prefix to be prefix.
126: */
127: public static Debug getInstance(String option, String prefix) {
128: if (isOn(option)) {
129: Debug d = new Debug();
130: d.prefix = prefix;
131: return d;
132: } else {
133: return null;
134: }
135: }
136:
137: /**
138: * True if the system property "security.debug" contains the
139: * string "option".
140: */
141: public static boolean isOn(String option) {
142: if (args == null)
143: return false;
144: else {
145: if (args.indexOf("all") != -1)
146: return true;
147: else
148: return (args.indexOf(option) != -1);
149: }
150: }
151:
152: /**
153: * print a message to stderr that is prefixed with the prefix
154: * created from the call to getInstance.
155: */
156:
157: public void println(String message) {
158: System.err.println(prefix + ": " + message);
159: }
160:
161: /**
162: * print a blank line to stderr that is prefixed with the prefix.
163: */
164:
165: public void println() {
166: System.err.println(prefix + ":");
167: }
168:
169: /**
170: * print a message to stderr that is prefixed with the prefix.
171: */
172:
173: public static void println(String prefix, String message) {
174: System.err.println(prefix + ": " + message);
175: }
176:
177: /**
178: * return a hexadecimal printed representation of the specified
179: * BigInteger object. the value is formatted to fit on lines of
180: * at least 75 characters, with embedded newlines. Words are
181: * separated for readability, with eight words (32 bytes) per line.
182: */
183: public static String toHexString(BigInteger b) {
184: String hexValue = b.toString(16);
185: StringBuffer buf = new StringBuffer(hexValue.length() * 2);
186:
187: if (hexValue.startsWith("-")) {
188: buf.append(" -");
189: hexValue = hexValue.substring(1);
190: } else {
191: buf.append(" "); // four spaces
192: }
193: if ((hexValue.length() % 2) != 0) {
194: // add back the leading 0
195: hexValue = "0" + hexValue;
196: }
197: int i = 0;
198: while (i < hexValue.length()) {
199: // one byte at a time
200: buf.append(hexValue.substring(i, i + 2));
201: i += 2;
202: if (i != hexValue.length()) {
203: if ((i % 64) == 0) {
204: buf.append("\n "); // line after eight words
205: } else if (i % 8 == 0) {
206: buf.append(" "); // space between words
207: }
208: }
209: }
210: return buf.toString();
211: }
212:
213: /**
214: * change a string into lower case except permission classes and URLs.
215: */
216: private static String marshal(String args) {
217: if (args != null) {
218: StringBuffer target = new StringBuffer();
219: StringBuffer source = new StringBuffer(args);
220:
221: // obtain the "permission=<classname>" options
222: // the syntax of classname: IDENTIFIER.IDENTIFIER
223: // the regular express to match a class name:
224: // "[a-zA-Z_$][a-zA-Z0-9_$]*([.][a-zA-Z_$][a-zA-Z0-9_$]*)*"
225: String keyReg = "[Pp][Ee][Rr][Mm][Ii][Ss][Ss][Ii][Oo][Nn]=";
226: String keyStr = "permission=";
227: String reg = keyReg
228: + "[a-zA-Z_$][a-zA-Z0-9_$]*([.][a-zA-Z_$][a-zA-Z0-9_$]*)*";
229: Pattern pattern = Pattern.compile(reg);
230: Matcher matcher = pattern.matcher(source);
231: StringBuffer left = new StringBuffer();
232: while (matcher.find()) {
233: String matched = matcher.group();
234: target.append(matched.replaceFirst(keyReg, keyStr));
235: target.append(" ");
236:
237: // delete the matched sequence
238: matcher.appendReplacement(left, "");
239: }
240: matcher.appendTail(left);
241: source = left;
242:
243: // obtain the "codebase=<URL>" options
244: // the syntax of URL is too flexible, and here assumes that the
245: // URL contains no space, comma(','), and semicolon(';'). That
246: // also means those characters also could be used as separator
247: // after codebase option.
248: // However, the assumption is incorrect in some special situation
249: // when the URL contains comma or semicolon
250: keyReg = "[Cc][Oo][Dd][Ee][Bb][Aa][Ss][Ee]=";
251: keyStr = "codebase=";
252: reg = keyReg + "[^, ;]*";
253: pattern = Pattern.compile(reg);
254: matcher = pattern.matcher(source);
255: left = new StringBuffer();
256: while (matcher.find()) {
257: String matched = matcher.group();
258: target.append(matched.replaceFirst(keyReg, keyStr));
259: target.append(" ");
260:
261: // delete the matched sequence
262: matcher.appendReplacement(left, "");
263: }
264: matcher.appendTail(left);
265: source = left;
266:
267: // convert the rest to lower-case characters
268: target.append(source.toString().toLowerCase());
269:
270: return target.toString();
271: }
272:
273: return null;
274: }
275:
276: private final static char[] hexDigits = "0123456789abcdef"
277: .toCharArray();
278:
279: public static String toString(byte[] b) {
280: if (b == null) {
281: return "(null)";
282: }
283: StringBuilder sb = new StringBuilder(b.length * 3);
284: for (int i = 0; i < b.length; i++) {
285: int k = b[i] & 0xff;
286: if (i != 0) {
287: sb.append(':');
288: }
289: sb.append(hexDigits[k >>> 4]);
290: sb.append(hexDigits[k & 0xf]);
291: }
292: return sb.toString();
293: }
294:
295: }
|