KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > functionTests > util > SecurityCheck


1 /*
2
3    Derby - Class org.apache.derbyTesting.functionTests.util.SecurityCheck
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.functionTests.util;
23
24 import java.lang.reflect.Constructor JavaDoc;
25 import java.lang.reflect.Field JavaDoc;
26 import java.lang.reflect.Method JavaDoc;
27 import java.lang.reflect.Modifier JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.SortedMap JavaDoc;
30 import java.util.TreeMap JavaDoc;
31
32
33 /**
34  * Code to aid in checking the Security of Derby.
35  * This initial implementation only handles the emebdded code.
36  * Future work could expand to the client driver and network server.
37  */

38 public class SecurityCheck {
39     
40     /**
41      * List of classes in the public api for the embedded engine.
42      */

43     private static final String JavaDoc[] EMBEDDED_PUBLIC_API =
44     {
45         "org.apache.derby.jdbc.EmbeddedDriver",
46         "org.apache.derby.jdbc.EmbeddedDataSource",
47         "org.apache.derby.jdbc.EmbeddedSimpleDataSource",
48         "org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource",
49         "org.apache.derby.jdbc.EmbeddedXADataSource",
50         "org.apache.derby.authentication.UserAuthenticator",
51     };
52     
53     /**
54      * Is the passed in class part of the declared public api.
55      * Currently only the emebdded public api
56      * @param c class to be checked
57      * @return true if the class is part of the public api, false otherwise.
58      */

59     private static boolean isPublicApi(Class JavaDoc c)
60     {
61         for (int i = 0; i < EMBEDDED_PUBLIC_API.length; i++)
62         {
63             if (EMBEDDED_PUBLIC_API[i].equals(c.getName()))
64                 return true;
65         }
66         return false;
67     }
68     
69     /**
70      * Map of all classes that have been inspected.
71      * The key is the class name, if the value is null then
72      * the class is being inspected. Otherwise the value is
73      * a String description of the risks.
74      */

75     private static final SortedMap JavaDoc allInspectedClasses = new TreeMap JavaDoc();
76     
77     /**
78      * Perform security analysis of the public api for the embedded engine.
79      * Prints a report to System.out on completion.
80      * @throws ClassNotFoundException
81      */

82     public static void checkEmbeddedPublicApi() throws ClassNotFoundException JavaDoc
83     {
84         System.out.println("SecurityCheck: embedded public api classes");
85         allInspectedClasses.clear();
86         for (int i = 0; i < EMBEDDED_PUBLIC_API.length; i++)
87             SecurityCheck.inspectClass(EMBEDDED_PUBLIC_API[i]);
88
89         SecurityCheck.report(true);
90     }
91     
92     /**
93      * Produce a report on System.out of all inspected classes
94      * that have risks associated with them.
95      *
96      */

97     public static void report()
98     {
99         SecurityCheck.report(false);
100     }
101     
102     /**
103      * Produce a report on System.out of all inspected classes
104      * that have risks associated with them. If reportClear is
105      * true then additionally all classes that have been inspected
106      * will be returned.
107      *
108      */

109     private static void report(boolean reportClear)
110     {
111         synchronized (allInspectedClasses)
112         {
113         for (Iterator JavaDoc it = allInspectedClasses.keySet().iterator(); it.hasNext(); )
114         {
115             Object JavaDoc key = it.next();
116             Object JavaDoc value = allInspectedClasses.get(key);
117             if (value == null)
118             {
119                 if (reportClear)
120                     System.out.println("CLEAR: " + key);
121             }
122             else
123             {
124                 System.out.print(value);
125             }
126         }
127         }
128     }
129     
130     /**
131      * Inspect a class for security risks. No output is generated
132      * by this call, the caller must call report() to obtain the risks.
133      * @param className
134      * @throws ClassNotFoundException
135      */

136     public static void inspectClass(String JavaDoc className) throws ClassNotFoundException JavaDoc
137     {
138         SecurityCheck.inspectClass(Class.forName(className), null);
139     }
140     
141     /**
142      * Inspect the class of the passed in Object for security risks.
143      * This inspects, at this level only, the actual type of
144      * the object, not the declared type. E.g. for DriverManager.getConnection
145      * the declared type is java.sql.Connection which has no security risks,
146      * but the implementation type returned may have many.
147      *
148      * <code>
149      * Connection conn = DriverManager.getConnection(url);
150      * // will inspect the implementation call, eg. EmbedConnection30
151      * SecurityManager.inspect(conn);
152      * </code>
153      * No output is generated by this call,
154      * the caller must call report() to obtain the risks.
155      * @param o Obejct to be inspected
156      * @param declared the declared type of the object.
157      */

158     public static void inspect(Object JavaDoc o, String JavaDoc declared)
159     {
160         if (o == null)
161             return;
162                 
163         SecurityCheck.inspectClass(o.getClass(), declared);
164     }
165     
166     /**
167      * Inspect a Derby class for security risks. This includes following potential
168      * references exposed through the class.
169      * <P>
170      * Risks looked at:
171      * <UL>
172      * <LI> public constructors in non-public class -
173      * No justification for the constructor to be public.
174      * <LI> public constructors in non-final class and non-sealed package -
175      * Allows the class to be sub-classes through a injected class in
176      * the same package.
177      * <LI> public non-final field - Allows any one with a handle to
178      * the object to change the field.
179      * </UL>
180      * <P>
181      * The type of any public field or return type of any public method
182      * is also inspected. The assumption is that if such a field or method
183      * exists they have the potential to be called and return a valid object.
184      * <P>
185      * Note that this inspection is through the declared type of exposed
186      * references, not the actual runtime type. The actual runtime type
187      * might expose other classes that should be inspected.
188      * @param className
189      * @throws ClassNotFoundException
190      */

191     private static boolean inspectClass(Class JavaDoc c, String JavaDoc declared)
192     {
193         if (!c.getName().startsWith("org.apache.derby."))
194             return false;
195         
196         // Initial focus on embedded engine
197
if (c.getName().startsWith("org.apache.derby.client."))
198             return false;
199         
200         synchronized (allInspectedClasses)
201         {
202         if (allInspectedClasses.containsKey(c.getName()))
203             return true;
204         
205         allInspectedClasses.put(c.getName(), null);
206                 
207         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
208         
209         sb.append("Class ");
210         sb.append(c.getName());
211         sb.append('\n');
212         
213         if (declared != null)
214         {
215             allInspectedClasses.put(declared, "Checked class declared as: " + declared + "\n");
216             
217         }
218
219         boolean isPublicApi = SecurityCheck.isPublicApi(c);
220     
221         boolean hasIssues = false;
222         
223         boolean isSealed = c.getPackage().isSealed();
224         boolean isFinal = Modifier.isFinal(c.getModifiers());
225         boolean isPublic = Modifier.isPublic(c.getModifiers());
226         boolean isAbstract = Modifier.isAbstract(c.getModifiers());
227         
228         Constructor JavaDoc[] constructors = c.getConstructors();
229         
230         boolean hasPublicConstructor = constructors.length != 0;
231         
232         if (hasPublicConstructor && !isPublic)
233         {
234             hasIssues = true;
235             
236             // No reason for a public constructor in a non-public class
237
sb.append("..public constructors in non-public class\n");
238             
239             // class can be sub-classed even though it is not public
240
if (!isFinal && !isSealed)
241                 sb.append("..public constructors in non-final class and non-sealed package\n");
242         }
243         
244         if (hasPublicConstructor && isPublic)
245         {
246             // TODO: Need to work on these checks.
247
if (!isPublicApi)
248             {
249                 //hasIssues = true;
250

251                 // anyone can create instances of this class
252
//sb.append("..public constructors in public class\n");
253
}
254
255             // and anyone can sub-class this class
256
if (!isFinal)
257             {
258                 //hasIssues = true;
259
//sb.append("..public constructors in public non-final class\n");
260
}
261         }
262         
263         for (int i = 0; i < constructors.length; i++)
264         {
265             if (hasIssues)
266             {
267                 sb.append("..public constructor: ");
268                 sb.append(constructors[i].toString());
269                 sb.append('\n');
270             }
271         }
272         
273         Field JavaDoc[] fields = c.getFields();
274         for (int i = 0; i < fields.length; i++)
275         {
276             Field JavaDoc f = fields[i];
277             boolean isStatic = Modifier.isStatic(f.getModifiers());
278                         
279             Class JavaDoc fieldType = f.getType();
280             SecurityCheck.inspectClass(fieldType, null);
281             
282             if (Modifier.isFinal(f.getModifiers()))
283             {
284                 // TODO: Should this be a concern if non-static?
285
continue;
286             }
287             
288             hasIssues = true;
289             sb.append("..public non-final field: ");
290             sb.append(f.toString());
291             sb.append('\n');
292         }
293
294         Method JavaDoc[] methods = c.getMethods();
295         for (int i = 0; i < methods.length; i++)
296         {
297             Method JavaDoc m = methods[i];
298                         
299             Class JavaDoc methodType = m.getReturnType();
300             if (SecurityCheck.inspectClass(methodType, null))
301             {
302                 // method returns a class of interest to us.
303

304                 // just a method returning a public api
305
if (SecurityCheck.isPublicApi(methodType))
306                     continue;
307                 
308                 /*
309                  * Not sure this is a vaild risk.
310                 hasIssues = true;
311                 sb.append("..public method returning non-public api class: ");
312                 sb.append(m.toString());
313                 sb.append("\n");
314                 */

315             }
316             
317         }
318         if (hasIssues)
319             allInspectedClasses.put(c.getName(), sb.toString());
320         }
321         
322         return true;
323         
324     }
325 }
Popular Tags