KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > TopSecurityManager


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans;
21
22 import java.io.FileDescriptor JavaDoc;
23 import java.lang.reflect.Field JavaDoc;
24 import java.lang.reflect.Method JavaDoc;
25 import java.net.InetAddress JavaDoc;
26 import java.net.URL JavaDoc;
27 import java.net.UnknownHostException JavaDoc;
28 import java.security.AccessControlContext JavaDoc;
29 import java.security.AccessController JavaDoc;
30 import java.security.AllPermission JavaDoc;
31 import java.security.Permission JavaDoc;
32 import java.security.PrivilegedActionException JavaDoc;
33 import java.security.PrivilegedExceptionAction JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.HashSet JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.List JavaDoc;
38 import java.util.Set JavaDoc;
39
40 /** NetBeans security manager implementation.
41 * @author Ales Novak, Jesse Glick
42 */

43 public class TopSecurityManager extends SecurityManager JavaDoc {
44
45     private static boolean check = !Boolean.getBoolean("netbeans.security.nocheck"); // NOI18N
46

47     private Permission JavaDoc allPermission;
48     
49     /* JVMPI sometimes deadlocks sync getForeignClassLoader
50         and Class.forName
51     */

52     private static final Class JavaDoc<?> classLoaderClass = ClassLoader JavaDoc.class;
53     private static final Class JavaDoc URLClass = URL JavaDoc.class;
54     private static final Class JavaDoc runtimePermissionClass = RuntimePermission JavaDoc.class;
55     private static final Class JavaDoc accessControllerClass = AccessController JavaDoc.class;
56
57     private static List JavaDoc<SecurityManager JavaDoc> delegates = new ArrayList JavaDoc<SecurityManager JavaDoc>();
58     /** Register a delegate security manager that can handle some checks for us.
59      * Currently only checkExit and checkTopLevelWindow are supported.
60      * @param sm the delegate to register
61      * @throws SecurityException without RuntimePermission "TopSecurityManager.register"
62      */

63     public static void register(SecurityManager JavaDoc sm) throws SecurityException JavaDoc {
64 /* if (check) {
65             try {
66                 AccessController.checkPermission(new RuntimePermission("TopSecurityManager.register")); // NOI18N
67             } catch (SecurityException se) {
68                 // Something is probably wrong; debug it better.
69                 ProtectionDomain pd = sm.getClass().getProtectionDomain();
70                 CodeSource cs = pd.getCodeSource();
71                 System.err.println("Code source of attempted secman: " + (cs != null ? cs.getLocation().toExternalForm() : "<none>")); // NOI18N
72                 System.err.println("Its permissions: " + pd); // NOI18N
73                 throw se;
74             }
75         }
76 */

77         synchronized (delegates) {
78             if (delegates.contains(sm)) throw new SecurityException JavaDoc();
79             delegates.add(sm);
80         }
81     }
82     /** Unregister a delegate security manager.
83      * @param sm the delegate to unregister
84      * @throws SecurityException without RuntimePermission "TopSecurityManager.unregister"
85      */

86     public static void unregister(SecurityManager JavaDoc sm) throws SecurityException JavaDoc {
87 /* if (check) {
88             AccessController.checkPermission(new RuntimePermission("TopSecurityManager.unregister")); // NOI18N
89         }
90 */

91         synchronized (delegates) {
92             if (!delegates.contains(sm)) throw new SecurityException JavaDoc();
93             delegates.remove(sm);
94         }
95     }
96
97     /**
98     * constructs new TopSecurityManager
99     */

100     public TopSecurityManager () {
101         allPermission = new AllPermission JavaDoc();
102     }
103
104     public void checkExit(int status) throws SecurityException JavaDoc {
105         if (! check) {
106             return;
107         }
108         
109         synchronized (delegates) {
110             Iterator JavaDoc it = delegates.iterator();
111             while (it.hasNext()) {
112                 ((SecurityManager JavaDoc)it.next()).checkExit(status);
113             }
114         }
115         
116         PrivilegedCheck.checkExit(status, this);
117     }
118
119
120     private static boolean officialExit = false;
121     /** Can be called from core classes to exit the system.
122      * Direct calls to System.exit will not be honored, for safety.
123      * @param status the status code to exit with
124      * @see "#20751"
125      */

126     public static void exit(int status) {
127         officialExit = true;
128         System.exit(status);
129     }
130
131     final void checkExitImpl(int status, AccessControlContext JavaDoc acc) throws SecurityException JavaDoc {
132         if (!officialExit) {
133             throw new ExitSecurityException("Illegal attempt to exit early"); // NOI18N
134
}
135
136         super.checkExit(status);
137     }
138
139     public boolean checkTopLevelWindow(Object JavaDoc window) {
140         synchronized (delegates) {
141             Iterator JavaDoc it = delegates.iterator();
142             while (it.hasNext()) {
143                 ((SecurityManager JavaDoc)it.next()).checkTopLevelWindow(window);
144             }
145         }
146         
147         return super.checkTopLevelWindow(window);
148     }
149
150     /* XXX probably unnecessary:
151     // Hack against permissions of Launcher$AppLoader.
152     public void checkPackageAccess(String pckg) {
153         if (pckg == null) return;
154         if (pckg.startsWith("sun.")) { // NOI18N
155             if (inClazz("sun.misc.Launcher") || inClazz("java.lang.Class")) { // NOI18N
156                 return;
157             }
158         }
159         super.checkPackageAccess(pckg);
160     }
161
162     private boolean inClazz(String s) {
163         Class[] classes = getClassContext();
164         int i = 0;
165         for (; (i < classes.length) && (classes[i] == TopSecurityManager.class); i++);
166         if (i == classes.length) {
167             return false;
168         }
169         return classes[i].getName().startsWith(s);
170     }
171      */

172
173     /** Performance - all props accessible */
174     public final void checkPropertyAccess(String JavaDoc x) {
175         if ("netbeans.debug.exceptions".equals(x)) { // NOI18N
176
// Get rid of this old system property.
177
Class JavaDoc[] ctxt = getClassContext();
178             for (int i = 0; i < ctxt.length; i++) {
179                 Class JavaDoc c = ctxt[i];
180                 if (c != TopSecurityManager.class &&
181                         c != System JavaDoc.class &&
182                         c != Boolean JavaDoc.class) {
183                     String JavaDoc n = c.getName();
184                     synchronized (warnedClassesNDE) {
185                         if (warnedClassesNDE.add(n)) {
186                             System.err.println("Warning: use of system property netbeans.debug.exceptions in " + n + " has been obsoleted in favor of ErrorManager"); // NOI18N
187
}
188                     }
189                     break;
190                 }
191             }
192         }
193         if ("netbeans.home".equals(x)) { // NOI18N
194
// Get rid of this old system property.
195
Class JavaDoc[] ctxt = getClassContext();
196             for (int i = 0; i < ctxt.length; i++) {
197                 Class JavaDoc c = ctxt[i];
198                 if (c != TopSecurityManager.class &&
199                         c != System JavaDoc.class &&
200                         c != Boolean JavaDoc.class) {
201                     String JavaDoc n = c.getName();
202                     synchronized (warnedClassesNH) {
203                         if (warnedClassesNH.add(n)) {
204                             System.err.println("Warning: use of system property netbeans.home in " + n + " has been obsoleted in favor of InstalledFileLocator"); // NOI18N
205
}
206                     }
207                     break;
208                 }
209             }
210         }
211         
212         if ("javax.xml.parsers.SAXParserFactory".equals(x)) {
213             if (Thread.currentThread().getContextClassLoader().getResource(
214                     "org/netbeans/core/startup/SAXFactoryImpl.class") != null) return;
215             throw new SecurityException JavaDoc ("");
216         }
217         
218         if ("javax.xml.parsers.DocumentBuilderFactory".equals(x)) {
219             if (Thread.currentThread().getContextClassLoader().getResource(
220                     "org/netbeans/core/startup/DOMFactoryImpl.class") != null) return;
221             throw new SecurityException JavaDoc ("");
222         }
223         
224         return;
225     }
226     private final Set JavaDoc<String JavaDoc> warnedClassesNDE = new HashSet JavaDoc<String JavaDoc>(25);
227     private static final Set JavaDoc<String JavaDoc> warnedClassesNH = new HashSet JavaDoc<String JavaDoc>(25);
228     static {
229         warnedClassesNH.add ("org.netbeans.core.LookupCache"); // NOI18N
230
warnedClassesNH.add ("org.netbeans.updater.UpdateTracking"); // NOI18N
231
warnedClassesNH.add("org.netbeans.core.ui.ProductInformationPanel"); // #47429; NOI18N
232
}
233
234     /* ----------------- private methods ------------- */
235
236     /**
237      * The method is empty. This is not "secure", but on the other hand,
238      * it reduces performance penalty of startup about 10%
239      */

240     public void checkRead(String JavaDoc file) {
241         // XXX reconsider!
242
}
243     
244     public void checkRead(FileDescriptor JavaDoc fd) {
245     }
246
247     public void checkWrite(FileDescriptor JavaDoc fd) {
248     }
249
250     /** The method has awful performance in super class */
251     public void checkDelete(String JavaDoc file) {
252         try {
253             checkPermission(allPermission);
254             return;
255         } catch (SecurityException JavaDoc e) {
256             super.checkDelete(file);
257         }
258     }
259     /** The method has awful performance in super class */
260     public void checkWrite(String JavaDoc file) {
261         try {
262             checkPermission(allPermission);
263             return;
264         } catch (SecurityException JavaDoc e) {
265             super.checkWrite(file);
266         }
267     }
268     
269     /** Checks connect */
270     public void checkConnect(String JavaDoc host, int port) {
271         if (! check) {
272             return;
273         }
274         
275         try {
276             checkPermission(allPermission);
277             return;
278         } catch (SecurityException JavaDoc e) {
279         }
280         
281         try {
282             super.checkConnect(host, port);
283             return;
284         } catch (SecurityException JavaDoc e) {
285         }
286         
287         PrivilegedCheck.checkConnect(host, port, this);
288     }
289      
290     final void checkConnectImpl(String JavaDoc host, int port) {
291         Class JavaDoc insecure = getInsecureClass();
292         if (insecure != null) {
293             URL JavaDoc ctx = getClassURL(insecure);
294             if (ctx != null) {
295                 try {
296                     String JavaDoc fromHost = ctx.getHost();
297                     InetAddress JavaDoc ia2 = InetAddress.getByName(host);
298                     InetAddress JavaDoc ia3 = InetAddress.getByName(fromHost);
299                     if (ia2.equals(ia3)) {
300                         return;
301                     }
302                 } catch (UnknownHostException JavaDoc e) { // ignore
303
e.printStackTrace();
304                 }
305             }
306             throw new SecurityException JavaDoc();
307         }
308     }
309
310     public void checkConnect(String JavaDoc s, int port, Object JavaDoc context) {
311         checkConnect(s, port);
312     }
313
314     public void checkPermission(Permission JavaDoc perm) {
315         checkSetSecurityManager(perm);
316         
317         //
318
// part of makeSwingUseSpecialClipboard that makes it work on
319
// JDK 1.5
320
//
321
if (perm instanceof java.awt.AWTPermission JavaDoc) {
322             if ("accessClipboard".equals (perm.getName ())) { // NOI18N
323
ThreadLocal JavaDoc<Object JavaDoc> t;
324                 synchronized (TopSecurityManager.class) {
325                     t = CLIPBOARD_FORBIDDEN;
326                 }
327                 if (t == null) {
328                     return;
329                 }
330                 
331                 if (t.get () != null) {
332                     t.set (this);
333                     throw new SecurityException JavaDoc ();
334                 } else {
335                     checkWhetherAccessedFromSwingTransfer ();
336                 }
337             }
338         }
339         return;
340     }
341     
342     public void checkPermission(Permission JavaDoc perm, Object JavaDoc context) {
343         checkSetSecurityManager(perm);
344         return;
345     }
346     
347     /** Prohibits to set another SecurityManager */
348     private static void checkSetSecurityManager(Permission JavaDoc perm) {
349         if (runtimePermissionClass.isInstance(perm)) {
350             if ("setSecurityManager".equals(perm.getName())) { // NOI18N - hardcoded in java.lang
351
throw new SecurityException JavaDoc();
352             }
353         }
354     }
355
356 //
357
// public void checkMemberAccess(Class clazz, int which) {
358
// if ((which == java.lang.reflect.Member.PUBLIC) ||
359
// javax.swing.text.JTextComponent.class.isAssignableFrom(clazz)) {
360
// return;
361
// } else {
362
// super.checkMemberAccess(clazz, which);
363
// }
364
// }
365
//
366
private Class JavaDoc getInsecureClass() {
367
368         Class JavaDoc[] ctx = getClassContext();
369         boolean firstACClass = false;
370
371 LOOP: for (int i = 0; i < ctx.length; i++) {
372
373             if (ctx[i] == accessControllerClass) {
374                 // privileged action is on the stack before an untrusted class loader
375
// #3950
376
if (firstACClass) {
377                     return null;
378                 } else {
379                     firstACClass = true;
380                     continue LOOP;
381                 }
382             } else if (ctx[i].getClassLoader() != null) {
383
384                 if (isSecureClass(ctx[i])) {
385                     if (classLoaderClass.isAssignableFrom(ctx[i])) {
386                         return null;
387                     } else {
388                         // OK process next one
389
continue LOOP;
390                     }
391                 }
392
393                 return ctx[i];
394             } else if (classLoaderClass.isAssignableFrom(ctx[i])) { // cloader == null
395
return null; // foreign classloader wants to do work...
396
}
397         }
398
399         return null;
400     }
401
402     /** Checks if the class is loaded through the nbfs URL */
403     static boolean isSecureClass(final Class JavaDoc clazz) {
404         URL JavaDoc source = getClassURL(clazz);
405         if (source != null) {
406             return isSecureProtocol(source.getProtocol());
407         } else {
408             return true;
409         }
410     }
411     
412     /** @return a protocol through which was the class loaded (file://...) or null
413     */

414     static URL JavaDoc getClassURL(Class JavaDoc clazz) {
415         java.security.CodeSource JavaDoc cs = clazz.getProtectionDomain().getCodeSource();
416         if (cs != null) {
417             URL JavaDoc url = cs.getLocation();
418             return url;
419         } else { // PROXY CLASS?
420
return null;
421         }
422     }
423
424     static Field JavaDoc getUrlField(Class JavaDoc clazz) {
425         if (urlField == null) {
426             try {
427                 Field JavaDoc[] fds = clazz.getDeclaredFields();
428                 for (int i = 0; i < fds.length; i++) {
429                     if (fds[i].getType() == URLClass) {
430                         fds[i].setAccessible(true);
431                         urlField = fds[i];
432                         break;
433                     }
434                 }
435             } catch (Exception JavaDoc e) {
436                 e.printStackTrace();
437             }
438         }
439         return urlField;
440     }
441
442     private static Field JavaDoc urlField;
443
444     /** @return Boolean.TRUE iff the string is a safe protocol (file, nbfs, ...) */
445     static boolean isSecureProtocol(String JavaDoc protocol) {
446         if (protocol.equals("http") || // NOI18N
447
protocol.equals("ftp") || // NOI18N
448
protocol.equals("rmi")) { // NOI18N
449
return false;
450         } else {
451             return true;
452         }
453     }
454
455     // Workaround for bug
456
//
457
// http://developer.java.sun.com/developer/bugParade/bugs/4818143.html
458
//
459
// sun.awt.datatransfer.ClipboardTransferable.getClipboardData() can hang
460
// for very long time (maxlong == eternity). We tries to avoid the hang by
461
// access the system clipboard from a separate thread. If the hang happens
462
// the thread will wait for the system clipboard forever but not the whole
463
// IDE. See also NbClipboard
464

465     private static ThreadLocal JavaDoc<Object JavaDoc> CLIPBOARD_FORBIDDEN;
466     
467     /** Convinces Swing components that they should use special clipboard
468      * and not Toolkit.getSystemClipboard.
469      *
470      * @param clip clipboard to use
471      */

472     public static void makeSwingUseSpecialClipboard (java.awt.datatransfer.Clipboard JavaDoc clip) {
473         try {
474             synchronized (TopSecurityManager.class) {
475                 assert System.getSecurityManager() instanceof TopSecurityManager : "Our manager has to be active: " + System.getSecurityManager(); // NOI18N
476
if (CLIPBOARD_FORBIDDEN != null) {
477                     return;
478                 }
479                 CLIPBOARD_FORBIDDEN = new ThreadLocal JavaDoc<Object JavaDoc>();
480                 CLIPBOARD_FORBIDDEN.set (clip);
481             }
482             
483             javax.swing.JComponent JavaDoc source = new javax.swing.JPanel JavaDoc ();
484             javax.swing.TransferHandler.getPasteAction ().actionPerformed (
485                 new java.awt.event.ActionEvent JavaDoc (source, 0, "")
486             );
487             javax.swing.TransferHandler.getCopyAction ().actionPerformed (
488                 new java.awt.event.ActionEvent JavaDoc (source, 0, "")
489             );
490             javax.swing.TransferHandler.getCutAction ().actionPerformed (
491                 new java.awt.event.ActionEvent JavaDoc (source, 0, "")
492             );
493             Object JavaDoc forb = CLIPBOARD_FORBIDDEN.get ();
494             CLIPBOARD_FORBIDDEN.set(null);
495             if (! (forb instanceof TopSecurityManager) ) {
496                 System.err.println("Cannot install our clipboard to swing components, TopSecurityManager is not the security manager: " + forb); // NOI18N
497
return;
498             }
499
500             Class JavaDoc<?> appContextClass = Class.forName ("sun.awt.AppContext"); // NOI18N
501
Method JavaDoc getAppContext = appContextClass.getMethod ("getAppContext"); // NOI18N
502
Object JavaDoc appContext = getAppContext.invoke (null, new Object JavaDoc[0]);
503             
504             Class JavaDoc actionClass = javax.swing.TransferHandler.getCopyAction ().getClass ();
505             java.lang.reflect.Field JavaDoc sandboxKeyField = actionClass.getDeclaredField ("SandboxClipboardKey"); // NOI18N
506
sandboxKeyField.setAccessible (true);
507             Object JavaDoc value = sandboxKeyField.get (null);
508             
509             Method JavaDoc put = appContextClass.getMethod ("put", Object JavaDoc.class, Object JavaDoc.class); // NOI18N
510
put.invoke (appContext, new Object JavaDoc[] { value, clip });
511         } catch (ThreadDeath JavaDoc ex) {
512             throw ex;
513         } catch (Throwable JavaDoc t) {
514             t.printStackTrace();
515         } finally {
516             CLIPBOARD_FORBIDDEN.set (null);
517         }
518     }
519     
520     /** the class that needs to be non accessible */
521     private static Class JavaDoc transferHandlerTransferAction;
522     /** Throws exception if accessed from javax.swing.TransferHandler class
523      */

524     private void checkWhetherAccessedFromSwingTransfer () throws SecurityException JavaDoc {
525         if (transferHandlerTransferAction == null) {
526             try {
527                 transferHandlerTransferAction = Class.forName ("javax.swing.TransferHandler$TransferAction"); // NOI18N
528
} catch (ClassNotFoundException JavaDoc ex) {
529                 ex.printStackTrace();
530                 throw new SecurityException JavaDoc (ex.getMessage ());
531             }
532         }
533         Class JavaDoc[] arr = getClassContext ();
534         for (int i = 0; i < arr.length; i++) {
535             if (arr[i] == transferHandlerTransferAction) {
536                 throw new SecurityException JavaDoc ("All swing access to clipboard should be redirected to ExClipboard"); // NOI18N
537
}
538         }
539     }
540
541
542     private static final class PrivilegedCheck implements PrivilegedExceptionAction JavaDoc<Object JavaDoc> {
543         int action;
544         TopSecurityManager tsm;
545         
546         // exit
547
int status;
548         AccessControlContext JavaDoc acc;
549
550         // connect
551
String JavaDoc host;
552         int port;
553         
554         
555         public PrivilegedCheck(int action, TopSecurityManager tsm) {
556             this.action = action;
557             this.tsm = tsm;
558             
559             if (action == 0) {
560                 acc = AccessController.getContext();
561             }
562         }
563         
564         public Object JavaDoc run() throws Exception JavaDoc {
565             switch (action) {
566                 case 0 :
567                     tsm.checkExitImpl(status, acc);
568                     break;
569                 case 1 :
570                     tsm.checkConnectImpl(host, port);
571                     break;
572                 default :
573             }
574             return null;
575         }
576         
577         static void checkExit(int status, TopSecurityManager tsm) {
578             PrivilegedCheck pea = new PrivilegedCheck(0, tsm);
579             pea.status = status;
580             check(pea);
581         }
582         
583         static void checkConnect(String JavaDoc host, int port, TopSecurityManager tsm) {
584             PrivilegedCheck pea = new PrivilegedCheck(1, tsm);
585             pea.host = host;
586             pea.port = port;
587             check(pea);
588         }
589         
590         private static void check(PrivilegedCheck action) {
591             try {
592                 AccessController.doPrivileged(action);
593             } catch (PrivilegedActionException JavaDoc e) {
594                 Exception JavaDoc orig = e.getException();
595                 if (orig instanceof RuntimeException JavaDoc) {
596                     throw ((RuntimeException JavaDoc) orig);
597                 }
598                 orig.printStackTrace();
599             }
600         }
601     }
602     
603 }
604
Popular Tags