1 /*
2  * Copyright (c) 1998, 2014, 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 package sun.security.util;
27 
28 import java.math.BigInteger;
29 import java.util.Locale;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32 
33 /**
34  * A utility class for debuging.
35  *
36  * @author Roland Schemers
37  */
38 public class Debug {
39 
40     private static final String args = null;
41 
42     private final String prefix;
43 
Debug(String prefix)44     private Debug(String prefix) {
45         this.prefix = prefix;
46     }
47 
48     /*
49         From public static void Help() : Serves as a documentation of the
50         values that "args" accepts.
51 
52         System.err.println();
53         System.err.println("all           turn on all debugging");
54         System.err.println("access        print all checkPermission results");
55         System.err.println("certpath      PKIX CertPathBuilder and");
56         System.err.println("              CertPathValidator debugging");
57         System.err.println("combiner      SubjectDomainCombiner debugging");
58         System.err.println("gssloginconfig");
59         System.err.println("              GSS LoginConfigImpl debugging");
60         System.err.println("configfile    JAAS ConfigFile loading");
61         System.err.println("configparser  JAAS ConfigFile parsing");
62         System.err.println("jar           jar verification");
63         System.err.println("logincontext  login context results");
64         System.err.println("jca           JCA engine class debugging");
65         System.err.println("policy        loading and granting");
66         System.err.println("provider      security provider debugging");
67         System.err.println("pkcs11        PKCS11 session manager debugging");
68         System.err.println("pkcs11keystore");
69         System.err.println("              PKCS11 KeyStore debugging");
70         System.err.println("sunpkcs11     SunPKCS11 provider debugging");
71         System.err.println("scl           permissions SecureClassLoader assigns");
72         System.err.println("ts            timestamping");
73         System.err.println();
74         System.err.println("The following can be used with access:");
75         System.err.println();
76         System.err.println("stack         include stack trace");
77         System.err.println("domain        dump all domains in context");
78         System.err.println("failure       before throwing exception, dump stack");
79         System.err.println("              and domain that didn't have permission");
80         System.err.println();
81         System.err.println("The following can be used with stack and domain:");
82         System.err.println();
83         System.err.println("permission=<classname>");
84         System.err.println("              only dump output if specified permission");
85         System.err.println("              is being checked");
86         System.err.println("codebase=<URL>");
87         System.err.println("              only dump output if specified codebase");
88         System.err.println("              is being checked");
89         System.err.println();
90         System.err.println("The following can be used with provider:");
91         System.err.println();
92         System.err.println("engine=<engines>");
93         System.err.println("              only dump output for the specified list");
94         System.err.println("              of JCA engines. Supported values:");
95         System.err.println("              Cipher, KeyAgreement, KeyGenerator,");
96         System.err.println("              KeyPairGenerator, KeyStore, Mac,");
97         System.err.println("              MessageDigest, SecureRandom, Signature.");
98         System.err.println();
99         System.err.println("Note: Separate multiple options with a comma");
100         System.exit(0);
101     */
102 
103     /**
104      * Get a Debug object corresponding to whether or not the given
105      * option is set. Set the prefix to be the same as option.
106      */
107 
getInstance(String option)108     public static Debug getInstance(String option)
109     {
110         return getInstance(option, option);
111     }
112 
113     /**
114      * Get a Debug object corresponding to whether or not the given
115      * option is set. Set the prefix to be prefix.
116      */
getInstance(String option, String prefix)117     public static Debug getInstance(String option, String prefix)
118     {
119         if (isOn(option)) {
120             Debug d = new Debug(prefix);
121             return d;
122         } else {
123             return null;
124         }
125     }
126 
127     /**
128      * True if the system property "security.debug" contains the
129      * string "option".
130      */
isOn(String option)131     public static boolean isOn(String option)
132     {
133         if (args == null)
134             return false;
135         else {
136             if (args.indexOf("all") != -1)
137                 return true;
138             else
139                 return (args.indexOf(option) != -1);
140         }
141     }
142 
143     /**
144      * print a message to stderr that is prefixed with the prefix
145      * created from the call to getInstance.
146      */
147 
println(String message)148     public void println(String message)
149     {
150         System.err.println(prefix + ": "+message);
151     }
152 
153     /**
154      * print a blank line to stderr that is prefixed with the prefix.
155      */
156 
println()157     public void println()
158     {
159         System.err.println(prefix + ":");
160     }
161 
162 
163     /**
164      * return a hexadecimal printed representation of the specified
165      * BigInteger object. the value is formatted to fit on lines of
166      * at least 75 characters, with embedded newlines. Words are
167      * separated for readability, with eight words (32 bytes) per line.
168      */
toHexString(BigInteger b)169     public static String toHexString(BigInteger b) {
170         String hexValue = b.toString(16);
171         StringBuffer buf = new StringBuffer(hexValue.length()*2);
172 
173         if (hexValue.startsWith("-")) {
174             buf.append("   -");
175             hexValue = hexValue.substring(1);
176         } else {
177             buf.append("    ");     // four spaces
178         }
179         if ((hexValue.length()%2) != 0) {
180             // add back the leading 0
181             hexValue = "0" + hexValue;
182         }
183         int i=0;
184         while (i < hexValue.length()) {
185             // one byte at a time
186             buf.append(hexValue.substring(i, i+2));
187             i+=2;
188             if (i!= hexValue.length()) {
189                 if ((i%64) == 0) {
190                     buf.append("\n    ");     // line after eight words
191                 } else if (i%8 == 0) {
192                     buf.append(" ");     // space between words
193                 }
194             }
195         }
196         return buf.toString();
197     }
198 
199     /**
200      * change a string into lower case except permission classes and URLs.
201      */
marshal(String args)202     private static String marshal(String args) {
203         if (args != null) {
204             StringBuffer target = new StringBuffer();
205             StringBuffer source = new StringBuffer(args);
206 
207             // obtain the "permission=<classname>" options
208             // the syntax of classname: IDENTIFIER.IDENTIFIER
209             // the regular express to match a class name:
210             // "[a-zA-Z_$][a-zA-Z0-9_$]*([.][a-zA-Z_$][a-zA-Z0-9_$]*)*"
211             String keyReg = "[Pp][Ee][Rr][Mm][Ii][Ss][Ss][Ii][Oo][Nn]=";
212             String keyStr = "permission=";
213             String reg = keyReg +
214                 "[a-zA-Z_$][a-zA-Z0-9_$]*([.][a-zA-Z_$][a-zA-Z0-9_$]*)*";
215             Pattern pattern = Pattern.compile(reg);
216             Matcher matcher = pattern.matcher(source);
217             StringBuffer left = new StringBuffer();
218             while (matcher.find()) {
219                 String matched = matcher.group();
220                 target.append(matched.replaceFirst(keyReg, keyStr));
221                 target.append("  ");
222 
223                 // delete the matched sequence
224                 matcher.appendReplacement(left, "");
225             }
226             matcher.appendTail(left);
227             source = left;
228 
229             // obtain the "codebase=<URL>" options
230             // the syntax of URL is too flexible, and here assumes that the
231             // URL contains no space, comma(','), and semicolon(';'). That
232             // also means those characters also could be used as separator
233             // after codebase option.
234             // However, the assumption is incorrect in some special situation
235             // when the URL contains comma or semicolon
236             keyReg = "[Cc][Oo][Dd][Ee][Bb][Aa][Ss][Ee]=";
237             keyStr = "codebase=";
238             reg = keyReg + "[^, ;]*";
239             pattern = Pattern.compile(reg);
240             matcher = pattern.matcher(source);
241             left = new StringBuffer();
242             while (matcher.find()) {
243                 String matched = matcher.group();
244                 target.append(matched.replaceFirst(keyReg, keyStr));
245                 target.append("  ");
246 
247                 // delete the matched sequence
248                 matcher.appendReplacement(left, "");
249             }
250             matcher.appendTail(left);
251             source = left;
252 
253             // convert the rest to lower-case characters
254             target.append(source.toString().toLowerCase(Locale.ENGLISH));
255 
256             return target.toString();
257         }
258 
259         return null;
260     }
261 
262     private final static char[] hexDigits = "0123456789abcdef".toCharArray();
263 
toString(byte[] b)264     public static String toString(byte[] b) {
265         if (b == null) {
266             return "(null)";
267         }
268         StringBuilder sb = new StringBuilder(b.length * 3);
269         for (int i = 0; i < b.length; i++) {
270             int k = b[i] & 0xff;
271             if (i != 0) {
272                 sb.append(':');
273             }
274             sb.append(hexDigits[k >>> 4]);
275             sb.append(hexDigits[k & 0xf]);
276         }
277         return sb.toString();
278     }
279 
280 }
281