PageRenderTime 56ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/netbeans-7.3/o.n.bootstrap/src/org/netbeans/TopSecurityManager.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 817 lines | 565 code | 76 blank | 176 comment | 126 complexity | 5b026eafadec51ab9f8e0d697346968c MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.netbeans;
  45. import java.awt.AWTPermission;
  46. import java.io.FileDescriptor;
  47. import java.lang.reflect.Field;
  48. import java.lang.reflect.Method;
  49. import java.net.InetAddress;
  50. import java.net.URL;
  51. import java.net.UnknownHostException;
  52. import java.security.AccessControlContext;
  53. import java.security.AccessController;
  54. import java.security.AllPermission;
  55. import java.security.Permission;
  56. import java.security.PrivilegedActionException;
  57. import java.security.PrivilegedExceptionAction;
  58. import java.util.ArrayList;
  59. import java.util.HashSet;
  60. import java.util.Iterator;
  61. import java.util.List;
  62. import java.util.Set;
  63. import java.util.logging.Level;
  64. import java.util.logging.Logger;
  65. import java.util.logging.LoggingPermission;
  66. import org.openide.util.Lookup;
  67. import org.openide.util.WeakSet;
  68. /** NetBeans security manager implementation.
  69. * @author Ales Novak, Jesse Glick
  70. */
  71. public class TopSecurityManager extends SecurityManager {
  72. private static final boolean check = !Boolean.getBoolean("netbeans.security.nocheck"); // NOI18N
  73. private static final Logger LOG = Logger.getLogger(TopSecurityManager.class.getName());
  74. private Permission allPermission;
  75. /* JVMPI sometimes deadlocks sync getForeignClassLoader
  76. and Class.forName
  77. */
  78. private static final Class<?> classLoaderClass = ClassLoader.class;
  79. private static final Class URLClass = URL.class;
  80. private static final Class runtimePermissionClass = RuntimePermission.class;
  81. private static final Class accessControllerClass = AccessController.class;
  82. private static final Class awtPermissionClass = AWTPermission.class;
  83. private static SecurityManager fsSecManager;
  84. private static final List<SecurityManager> delegates = new ArrayList<SecurityManager>();
  85. /** Register a delegate security manager that can handle some checks for us.
  86. * Currently only checkExit and checkTopLevelWindow are supported.
  87. * @param sm the delegate to register
  88. * @throws SecurityException without RuntimePermission "TopSecurityManager.register"
  89. */
  90. public static void register(SecurityManager sm) throws SecurityException {
  91. /* if (check) {
  92. try {
  93. AccessController.checkPermission(new RuntimePermission("TopSecurityManager.register")); // NOI18N
  94. } catch (SecurityException se) {
  95. // Something is probably wrong; debug it better.
  96. ProtectionDomain pd = sm.getClass().getProtectionDomain();
  97. CodeSource cs = pd.getCodeSource();
  98. System.err.println("Code source of attempted secman: " + (cs != null ? cs.getLocation().toExternalForm() : "<none>")); // NOI18N
  99. System.err.println("Its permissions: " + pd); // NOI18N
  100. throw se;
  101. }
  102. }
  103. */
  104. synchronized (delegates) {
  105. if (delegates.contains(sm)) throw new SecurityException();
  106. delegates.add(sm);
  107. if (fsSecManager == null) {
  108. for (Lookup.Item<SecurityManager> item : Lookup.getDefault().lookupResult(SecurityManager.class).allItems()) {
  109. if (item != null && "org.netbeans.modules.masterfs.filebasedfs.utils.FileChangedManager".equals(item.getId())) {//NOI18N
  110. fsSecManager = item.getInstance();
  111. break;
  112. }
  113. }
  114. assert fsSecManager != null;
  115. }
  116. }
  117. }
  118. /** Unregister a delegate security manager.
  119. * @param sm the delegate to unregister
  120. * @throws SecurityException without RuntimePermission "TopSecurityManager.unregister"
  121. */
  122. public static void unregister(SecurityManager sm) throws SecurityException {
  123. /* if (check) {
  124. AccessController.checkPermission(new RuntimePermission("TopSecurityManager.unregister")); // NOI18N
  125. }
  126. */
  127. synchronized (delegates) {
  128. if (!delegates.contains(sm)) throw new SecurityException();
  129. delegates.remove(sm);
  130. }
  131. }
  132. /**
  133. * constructs new TopSecurityManager
  134. */
  135. public TopSecurityManager () {
  136. allPermission = new AllPermission();
  137. }
  138. public @Override void checkExit(int status) throws SecurityException {
  139. if (! check) {
  140. return;
  141. }
  142. synchronized (delegates) {
  143. Iterator it = delegates.iterator();
  144. while (it.hasNext()) {
  145. ((SecurityManager)it.next()).checkExit(status);
  146. }
  147. }
  148. PrivilegedCheck.checkExit(status, this);
  149. }
  150. SecurityManager getSecurityManager() {
  151. if (fsSecManager == null) {
  152. synchronized (delegates) {
  153. return fsSecManager;
  154. }
  155. }
  156. return fsSecManager;
  157. }
  158. private void notifyDelete(String file) {
  159. SecurityManager s = getSecurityManager();
  160. if (s != null) {
  161. s.checkDelete(file);
  162. }
  163. }
  164. private void notifyRead(String file) {
  165. SecurityManager s = getSecurityManager();
  166. if (s != null) {
  167. s.checkRead(file);
  168. }
  169. }
  170. private void notifyWrite(String file) {
  171. SecurityManager s = getSecurityManager();
  172. if (s != null) {
  173. s.checkWrite(file);
  174. }
  175. }
  176. static boolean officialExit = false;
  177. static Class[] getStack() {
  178. SecurityManager s = System.getSecurityManager();
  179. TopSecurityManager t;
  180. if (s instanceof TopSecurityManager) {
  181. t = (TopSecurityManager)s;
  182. } else {
  183. t = new TopSecurityManager();
  184. }
  185. return t.getClassContext();
  186. }
  187. /** Can be called from core classes to exit the system.
  188. * Direct calls to System.exit will not be honored, for safety.
  189. * @param status the status code to exit with
  190. * @see "#20751"
  191. */
  192. public static void exit(int status) {
  193. if (officialExit) {
  194. return; // already inside a shutdown hook
  195. }
  196. officialExit = true;
  197. System.exit(status);
  198. }
  199. final void checkExitImpl(int status, AccessControlContext acc) throws SecurityException {
  200. if (!officialExit) {
  201. throw new ExitSecurityException("Illegal attempt to exit early"); // NOI18N
  202. }
  203. super.checkExit(status);
  204. }
  205. public @Override boolean checkTopLevelWindow(Object window) {
  206. synchronized (delegates) {
  207. for (SecurityManager sm : delegates) {
  208. sm.checkTopLevelWindow(window);
  209. }
  210. }
  211. return super.checkTopLevelWindow(window);
  212. }
  213. /* XXX probably unnecessary:
  214. // Hack against permissions of Launcher$AppLoader.
  215. public void checkPackageAccess(String pckg) {
  216. if (pckg == null) return;
  217. if (pckg.startsWith("sun.")) { // NOI18N
  218. if (inClazz("sun.misc.Launcher") || inClazz("java.lang.Class")) { // NOI18N
  219. return;
  220. }
  221. }
  222. super.checkPackageAccess(pckg);
  223. }
  224. private boolean inClazz(String s) {
  225. Class[] classes = getClassContext();
  226. int i = 0;
  227. for (; (i < classes.length) && (classes[i] == TopSecurityManager.class); i++);
  228. if (i == classes.length) {
  229. return false;
  230. }
  231. return classes[i].getName().startsWith(s);
  232. }
  233. */
  234. /** Performance - all props accessible */
  235. public @Override final void checkPropertyAccess(String x) {
  236. if ("netbeans.debug.exceptions".equals(x)) { // NOI18N
  237. // Get rid of this old system property.
  238. for (Class<?> c : getClassContext()) {
  239. if (c != TopSecurityManager.class &&
  240. c != System.class &&
  241. c != Boolean.class) {
  242. String n = c.getName();
  243. synchronized (warnedClassesNDE) {
  244. if (warnedClassesNDE.add(n)) {
  245. LOG.log(Level.WARNING, "use of system property netbeans.debug.exceptions has been obsoleted in favor of java.util.logging.Logger at {0}", findCallStackLine(n));
  246. }
  247. }
  248. break;
  249. }
  250. }
  251. }
  252. if ("netbeans.home".equals(x) || "netbeans.user".equals(x)) { // NOI18N
  253. // Control access to this system property.
  254. for (Class<?> c : getClassContext()) {
  255. if (c != TopSecurityManager.class &&
  256. c != System.class &&
  257. c != Boolean.class) {
  258. String n = c.getName();
  259. boolean log;
  260. synchronized (warnedClassesNH) {
  261. log = warnedClassesNH.add(n);
  262. }
  263. if (log) {
  264. LOG.log(Level.WARNING, "use of system property {0} has been obsoleted in favor of InstalledFileLocator/Places at {1}", new Object[] {x, findCallStackLine(n)});
  265. }
  266. break;
  267. }
  268. }
  269. }
  270. }
  271. private static String findCallStackLine(String callerClazz) {
  272. for (StackTraceElement line : Thread.currentThread().getStackTrace()) {
  273. if (line.getClassName().equals(callerClazz)) {
  274. return line.toString();
  275. }
  276. }
  277. return callerClazz;
  278. }
  279. private final Set<String> warnedClassesNDE = new HashSet<String>(25);
  280. private static final Set<String> warnedClassesNH = new HashSet<String>(25);
  281. static {
  282. // XXX cleaner would be to use @SuppressWarnings, but that has Retention(SOURCE), and not all these can use org.netbeans.api.annotations.common
  283. warnedClassesNH.add("org.openide.modules.Places");
  284. warnedClassesNH.add("org.netbeans.MainImpl"); // NOI18N
  285. warnedClassesNH.add("org.netbeans.MainImpl$BootClassLoader");
  286. warnedClassesNH.add("org.netbeans.CLIHandler");
  287. warnedClassesNH.add("org.netbeans.Stamps"); // NOI18N
  288. warnedClassesNH.add("org.netbeans.core.startup.InstalledFileLocatorImpl"); // NOI18N
  289. warnedClassesNH.add("org.netbeans.core.startup.CLIOptions");
  290. warnedClassesNH.add("org.netbeans.core.startup.preferences.RelPaths");
  291. warnedClassesNH.add("org.netbeans.core.startup.layers.BinaryFS");
  292. warnedClassesNH.add("org.netbeans.modules.netbinox.NetbinoxFactory");
  293. warnedClassesNH.add("org.netbeans.updater.UpdateTracking"); // NOI18N
  294. warnedClassesNH.add("org.netbeans.core.ui.ProductInformationPanel"); // #47429; NOI18N
  295. warnedClassesNH.add("org.netbeans.lib.uihandler.LogFormatter");
  296. warnedClassesNH.add("org.netbeans.modules.project.libraries.LibrariesStorage");
  297. warnedClassesNH.add("org.netbeans.modules.j2ee.sun.ide.j2ee.PluginProperties"); // AS bundle is not in any cluster
  298. warnedClassesNH.add("org.netbeans.modules.apisupport.project.universe.NbPlatform"); // defaultPlatformLocation
  299. }
  300. /* ----------------- private methods ------------- */
  301. /**
  302. * The method is empty. This is not "secure", but on the other hand,
  303. * it reduces performance penalty of startup about 10%
  304. */
  305. public @Override void checkRead(String file) {
  306. notifyRead(file);
  307. }
  308. public @Override void checkRead(FileDescriptor fd) {
  309. }
  310. public @Override void checkWrite(FileDescriptor fd) {
  311. }
  312. /** The method has awful performance in super class */
  313. public @Override void checkDelete(String file) {
  314. notifyDelete(file);
  315. try {
  316. checkPermission(allPermission);
  317. return;
  318. } catch (SecurityException e) {
  319. super.checkDelete(file);
  320. }
  321. }
  322. /** The method has awful performance in super class */
  323. public @Override void checkWrite(String file) {
  324. notifyWrite(file);
  325. try {
  326. checkPermission(allPermission);
  327. return;
  328. } catch (SecurityException e) {
  329. super.checkWrite(file);
  330. }
  331. }
  332. /** Checks connect */
  333. public @Override void checkConnect(String host, int port) {
  334. if (! check) {
  335. return;
  336. }
  337. try {
  338. checkPermission(allPermission);
  339. return;
  340. } catch (SecurityException e) {
  341. }
  342. try {
  343. super.checkConnect(host, port);
  344. return;
  345. } catch (SecurityException e) {
  346. }
  347. PrivilegedCheck.checkConnect(host, port, this);
  348. }
  349. final void checkConnectImpl(String host, int port) {
  350. Class insecure = getInsecureClass();
  351. if (insecure != null) {
  352. URL ctx = getClassURL(insecure);
  353. if (ctx != null) {
  354. try {
  355. String fromHost = ctx.getHost();
  356. InetAddress ia2 = InetAddress.getByName(host);
  357. InetAddress ia3 = InetAddress.getByName(fromHost);
  358. if (ia2.equals(ia3)) {
  359. return;
  360. }
  361. } catch (UnknownHostException e) { // ignore
  362. e.printStackTrace();
  363. }
  364. }
  365. throw new SecurityException();
  366. }
  367. }
  368. public @Override void checkConnect(String s, int port, Object context) {
  369. checkConnect(s, port);
  370. }
  371. private final Set<Class> warnedSunMisc = new WeakSet<Class>();
  372. private final Set<String> callerWhiteList = createCallerWhiteList();
  373. @Override
  374. public void checkMemberAccess(Class<?> clazz, int which) {
  375. final String n = clazz.getName();
  376. if (n.startsWith("sun.misc")) { // NOI18N
  377. Class<?> caller = null;
  378. Class[] arr = getClassContext();
  379. for (int i = 0; i < arr.length; i++) {
  380. if (arr[i] == TopSecurityManager.class) {
  381. continue;
  382. }
  383. if (arr[i] != Class.class) {
  384. caller = arr[i];
  385. break;
  386. }
  387. }
  388. final String msg = "Dangerous reflection access to " + n + " by " + caller + " detected!";
  389. if (caller != null && isDangerous(caller.getName(), n)) {
  390. throw new SecurityException(msg);
  391. }
  392. Level l;
  393. if (caller != null && callerWhiteList.contains(caller.getName())) {
  394. l = Level.FINEST;
  395. } else {
  396. l = Level.FINE;
  397. assert (l = Level.INFO) != null;
  398. }
  399. if (!warnedSunMisc.add(caller)) {
  400. LOG.log(l, msg);
  401. return;
  402. }
  403. Exception ex = new Exception(msg); // NOI18N
  404. LOG.log(l, null, ex);
  405. }
  406. super.checkMemberAccess(clazz, which);
  407. }
  408. /**
  409. * Create list of safe callers for {@link #checkMemberAccess(Class, int)}.
  410. */
  411. private static Set<String> createCallerWhiteList() {
  412. Set<String> wl = new HashSet<String>();
  413. wl.add("org.netbeans.core.output2.FileMapStorage"); //NOI18N
  414. wl.add("com.sun.tools.javac.util.CloseableURLClassLoader"); //NOI18N
  415. wl.add("java.lang.Thread$1"); //NOI18N
  416. wl.add("org.apache.lucene.store.MMapDirectory$1"); //NOI18N
  417. wl.add("org.apache.lucene.util.Constants"); //#217037
  418. wl.add("org.apache.lucene.util.RamUsageEstimator");//#217037
  419. wl.add("com.google.gson.internal.UnsafeAllocator"); //#219464 //NOI18N
  420. wl.add("org.netbeans.modules.web.jspparser_ext.WebAppParseSupport$ParserClassLoader"); //#218690 // NOI18N
  421. return wl;
  422. }
  423. private static boolean isDangerous(String caller, String accessTo) {
  424. if ("com.sun.istack.tools.ProtectedTask".equals(caller)) { // NOI18N
  425. if ("sun.misc.ClassLoaderUtil".equals(accessTo)) { // NOI18N
  426. // calling ClassLoaderUtil is allowed
  427. return false;
  428. }
  429. return true;
  430. }
  431. return false;
  432. }
  433. public @Override void checkPermission(Permission perm) {
  434. // assert checkLogger(perm); //#178013 & JDK bug 1694855
  435. checkSetSecurityManager(perm);
  436. //
  437. // part of makeSwingUseSpecialClipboard that makes it work on
  438. // JDK 1.5
  439. //
  440. if (awtPermissionClass.isInstance(perm)) {
  441. if ("accessClipboard".equals (perm.getName ())) { // NOI18N
  442. ThreadLocal<Object> t;
  443. synchronized (TopSecurityManager.class) {
  444. t = CLIPBOARD_FORBIDDEN;
  445. }
  446. if (t == null) {
  447. return;
  448. }
  449. if (t.get () != null) {
  450. t.set (this);
  451. throw new SecurityException ();
  452. } else {
  453. checkWhetherAccessedFromSwingTransfer ();
  454. }
  455. }
  456. }
  457. return;
  458. }
  459. public @Override void checkPermission(Permission perm, Object context) {
  460. // assert checkLogger(perm); //#178013 & JDK bug 1694855
  461. checkSetSecurityManager(perm);
  462. return;
  463. }
  464. private boolean checkLogger(Permission perm) {
  465. //Do not allow foreign code to replace NetBeans logger with its own
  466. //(particularly java.util.logging.FileLogger, which will deadlock)
  467. //see http://netbeans.org/bugzilla/show_bug.cgi?id=178013
  468. if (LoggingPermission.class.isInstance(perm)) {
  469. //This code will run every time a logger is created; if this
  470. //proves too performance-degrading, replace the assertion test
  471. //with a system property so that mysterious logger-related deadlocks
  472. //can still be done, but leave it off by default
  473. Throwable t = new Exception().fillInStackTrace();
  474. for (StackTraceElement e : t.getStackTrace()) {
  475. //Currently no other reliable way to determine that the call
  476. //is to reset the logging infrastructure, not just create
  477. //a logger - see JDK bug 1694855
  478. if ("java.util.logging.LogManager".equals(e.getClassName()) && "reset".equals(e.getMethodName())) { //NOI18N
  479. SecurityException se = new SecurityException("Illegal attempt to reset system logger"); //NOI18N
  480. throw se;
  481. }
  482. if ("java.util.logging.LogManager".equals(e.getClassName()) && "readConfiguration".equals(e.getMethodName())) { //NOI18N
  483. SecurityException se = new SecurityException("Illegal attempt to replace system logger configuration"); //NOI18N
  484. throw se;
  485. }
  486. }
  487. }
  488. return true;
  489. }
  490. public static void install() {
  491. try {
  492. System.setSecurityManager(new TopSecurityManager());
  493. } catch (SecurityException ex) {
  494. LOG.log(Level.WARNING, "Cannot associated own security manager"); // NOI18N
  495. LOG.log(Level.INFO, "Cannot associated own security manager", ex); // NOI18N
  496. }
  497. }
  498. static void uninstall() {
  499. System.setSecurityManager(null);
  500. }
  501. /** Prohibits to set another SecurityManager */
  502. private void checkSetSecurityManager(Permission perm) {
  503. if (runtimePermissionClass.isInstance(perm)) {
  504. if (perm.getName().equals("setSecurityManager")) { // NOI18N - hardcoded in java.lang
  505. if (!check) {
  506. return;
  507. }
  508. Class[] arr = getClassContext();
  509. boolean seenJava = false;
  510. for (int i = 0; i < arr.length; i++) {
  511. if (arr[i].getName().equals("org.netbeans.TopSecurityManager")) { // NOI18N
  512. if (seenJava) {
  513. // if the change of security manager is called from my own
  514. // class or the class loaded by other classloader, then it is likely ok
  515. return;
  516. } else {
  517. continue;
  518. }
  519. }
  520. if (arr[i] != System.class) {
  521. // if there is a non-java class on stack, skip and throw exception
  522. break;
  523. }
  524. seenJava = true;
  525. }
  526. throw new SecurityException();
  527. }
  528. }
  529. }
  530. //
  531. // public void checkMemberAccess(Class clazz, int which) {
  532. // if ((which == java.lang.reflect.Member.PUBLIC) ||
  533. // javax.swing.text.JTextComponent.class.isAssignableFrom(clazz)) {
  534. // return;
  535. // } else {
  536. // super.checkMemberAccess(clazz, which);
  537. // }
  538. // }
  539. //
  540. private Class getInsecureClass() {
  541. Class[] ctx = getClassContext();
  542. boolean firstACClass = false;
  543. LOOP: for (int i = 0; i < ctx.length; i++) {
  544. if (ctx[i] == accessControllerClass) {
  545. // privileged action is on the stack before an untrusted class loader
  546. // #3950
  547. if (firstACClass) {
  548. return null;
  549. } else {
  550. firstACClass = true;
  551. continue LOOP;
  552. }
  553. } else if (ctx[i].getClassLoader() != null) {
  554. if (isSecureClass(ctx[i])) {
  555. if (classLoaderClass.isAssignableFrom(ctx[i])) {
  556. return null;
  557. } else {
  558. // OK process next one
  559. continue LOOP;
  560. }
  561. }
  562. return ctx[i];
  563. } else if (classLoaderClass.isAssignableFrom(ctx[i])) { // cloader == null
  564. return null; // foreign classloader wants to do work...
  565. }
  566. }
  567. return null;
  568. }
  569. /** Checks if the class is loaded through the nbfs URL */
  570. static boolean isSecureClass(final Class clazz) {
  571. URL source = getClassURL(clazz);
  572. if (source != null) {
  573. return isSecureProtocol(source.getProtocol());
  574. } else {
  575. return true;
  576. }
  577. }
  578. /** @return a protocol through which was the class loaded (file://...) or null
  579. */
  580. static URL getClassURL(Class clazz) {
  581. java.security.CodeSource cs = clazz.getProtectionDomain().getCodeSource();
  582. if (cs != null) {
  583. URL url = cs.getLocation();
  584. return url;
  585. } else { // PROXY CLASS?
  586. return null;
  587. }
  588. }
  589. static Field getUrlField(Class clazz) {
  590. if (urlField == null) {
  591. try {
  592. Field[] fds = clazz.getDeclaredFields();
  593. for (int i = 0; i < fds.length; i++) {
  594. if (fds[i].getType() == URLClass) {
  595. fds[i].setAccessible(true);
  596. urlField = fds[i];
  597. break;
  598. }
  599. }
  600. } catch (Exception e) {
  601. e.printStackTrace();
  602. }
  603. }
  604. return urlField;
  605. }
  606. private static Field urlField;
  607. /** @return Boolean.TRUE iff the string is a safe protocol (file, nbfs, ...) */
  608. static boolean isSecureProtocol(String protocol) {
  609. if (protocol.equals("http") || // NOI18N
  610. protocol.equals("ftp") || // NOI18N
  611. protocol.equals("rmi")) { // NOI18N
  612. return false;
  613. } else {
  614. return true;
  615. }
  616. }
  617. // Workaround for bug
  618. //
  619. // http://developer.java.sun.com/developer/bugParade/bugs/4818143.html
  620. //
  621. // sun.awt.datatransfer.ClipboardTransferable.getClipboardData() can hang
  622. // for very long time (maxlong == eternity). We tries to avoid the hang by
  623. // access the system clipboard from a separate thread. If the hang happens
  624. // the thread will wait for the system clipboard forever but not the whole
  625. // IDE. See also NbClipboard
  626. private static ThreadLocal<Object> CLIPBOARD_FORBIDDEN;
  627. /** Convinces Swing components that they should use special clipboard
  628. * and not Toolkit.getSystemClipboard.
  629. *
  630. * @param clip clipboard to use
  631. */
  632. public static void makeSwingUseSpecialClipboard (java.awt.datatransfer.Clipboard clip) {
  633. try {
  634. synchronized (TopSecurityManager.class) {
  635. if (! (System.getSecurityManager() instanceof TopSecurityManager)) {
  636. LOG.warning("Our manager has to be active: " + System.getSecurityManager());
  637. return;
  638. } // NOI18N
  639. if (CLIPBOARD_FORBIDDEN != null) {
  640. return;
  641. }
  642. CLIPBOARD_FORBIDDEN = new ThreadLocal<Object>();
  643. CLIPBOARD_FORBIDDEN.set (clip);
  644. }
  645. javax.swing.JComponent source = new javax.swing.JPanel ();
  646. javax.swing.TransferHandler.getPasteAction ().actionPerformed (
  647. new java.awt.event.ActionEvent (source, 0, "")
  648. );
  649. javax.swing.TransferHandler.getCopyAction ().actionPerformed (
  650. new java.awt.event.ActionEvent (source, 0, "")
  651. );
  652. javax.swing.TransferHandler.getCutAction ().actionPerformed (
  653. new java.awt.event.ActionEvent (source, 0, "")
  654. );
  655. Object forb = CLIPBOARD_FORBIDDEN.get ();
  656. CLIPBOARD_FORBIDDEN.set(null);
  657. if (! (forb instanceof TopSecurityManager) ) {
  658. System.err.println("Cannot install our clipboard to swing components, TopSecurityManager is not the security manager: " + forb); // NOI18N
  659. return;
  660. }
  661. Class<?> appContextClass = ClassLoader.getSystemClassLoader().loadClass("sun.awt.AppContext"); // NOI18N
  662. Method getAppContext = appContextClass.getMethod ("getAppContext"); // NOI18N
  663. Object appContext = getAppContext.invoke (null, new Object[0]);
  664. Class actionClass = javax.swing.TransferHandler.getCopyAction ().getClass ();
  665. java.lang.reflect.Field sandboxKeyField = actionClass.getDeclaredField ("SandboxClipboardKey"); // NOI18N
  666. sandboxKeyField.setAccessible (true);
  667. Object value = sandboxKeyField.get (null);
  668. Method put = appContextClass.getMethod ("put", Object.class, Object.class); // NOI18N
  669. put.invoke (appContext, new Object[] { value, clip });
  670. } catch (ThreadDeath ex) {
  671. throw ex;
  672. } catch (Throwable t) {
  673. t.printStackTrace();
  674. } finally {
  675. if (CLIPBOARD_FORBIDDEN != null) {
  676. CLIPBOARD_FORBIDDEN.set (null);
  677. }
  678. }
  679. }
  680. /** Throws exception if accessed from javax.swing.TransferHandler class
  681. */
  682. private void checkWhetherAccessedFromSwingTransfer () throws SecurityException {
  683. for (Class<?> c : getClassContext()) {
  684. if (c.getName().equals("javax.swing.TransferHandler$TransferAction")) {
  685. throw new SecurityException ("All swing access to clipboard should be redirected to ExClipboard"); // NOI18N
  686. }
  687. }
  688. }
  689. private static final class PrivilegedCheck implements PrivilegedExceptionAction<Object> {
  690. int action;
  691. TopSecurityManager tsm;
  692. // exit
  693. int status;
  694. AccessControlContext acc;
  695. // connect
  696. String host;
  697. int port;
  698. public PrivilegedCheck(int action, TopSecurityManager tsm) {
  699. this.action = action;
  700. this.tsm = tsm;
  701. if (action == 0) {
  702. acc = AccessController.getContext();
  703. }
  704. }
  705. public Object run() throws Exception {
  706. switch (action) {
  707. case 0 :
  708. tsm.checkExitImpl(status, acc);
  709. break;
  710. case 1 :
  711. tsm.checkConnectImpl(host, port);
  712. break;
  713. default :
  714. }
  715. return null;
  716. }
  717. static void checkExit(int status, TopSecurityManager tsm) {
  718. PrivilegedCheck pea = new PrivilegedCheck(0, tsm);
  719. pea.status = status;
  720. check(pea);
  721. }
  722. static void checkConnect(String host, int port, TopSecurityManager tsm) {
  723. PrivilegedCheck pea = new PrivilegedCheck(1, tsm);
  724. pea.host = host;
  725. pea.port = port;
  726. check(pea);
  727. }
  728. private static void check(PrivilegedCheck action) {
  729. try {
  730. AccessController.doPrivileged(action);
  731. } catch (PrivilegedActionException e) {
  732. Exception orig = e.getException();
  733. if (orig instanceof RuntimeException) {
  734. throw ((RuntimeException) orig);
  735. }
  736. orig.printStackTrace();
  737. }
  738. }
  739. }
  740. }