home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / prog / VJ11 / VJTRIAL.EXE / IE30Java.exe / classd.exe / sun / applet / AppletSecurity.java < prev    next >
Encoding:
Java Source  |  1997-01-27  |  15.4 KB  |  545 lines

  1. /*
  2.  * @(#)AppletSecurity.java    1.38 96/04/29 
  3.  *
  4.  * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19.  
  20. package sun.applet;
  21.  
  22. import java.io.File;
  23. import java.io.FileDescriptor;
  24. import java.net.URL;
  25. import java.net.InetAddress;
  26. import java.net.UnknownHostException;
  27. import java.util.StringTokenizer;
  28. import java.util.Vector;
  29.  
  30. /**
  31.  * This class defines an applet security policy
  32.  *
  33.  * @version     1.38, 04/29/96
  34.  * @author    Sami Shaio
  35.  * @author     Arthur van Hoff
  36.  */
  37. public
  38. class AppletSecurity extends SecurityManager {
  39.     private static boolean debug = false;
  40.     
  41.     boolean initACL;
  42.     String readACL[];
  43.     String writeACL[];
  44.     int networkMode;
  45.  
  46.     final static int NETWORK_NONE = 1;
  47.     final static int NETWORK_HOST = 2;
  48.     final static int NETWORK_UNRESTRICTED = 3;
  49.  
  50.     /**
  51.      * Construct and initialize.
  52.      */
  53.     public AppletSecurity() {
  54.     reset();
  55.     }
  56.  
  57.     /**
  58.      * Reset from Properties
  59.      */
  60.     public void reset() {
  61.     String str = System.getProperty("appletviewer.security.mode");
  62.     if (str == null) {
  63.         str = "host";
  64.     }
  65.  
  66.     if (str.equals("unrestricted")) {
  67.         networkMode = NETWORK_UNRESTRICTED;
  68.     } else if (str.equals("none")) {
  69.         networkMode = NETWORK_NONE;
  70.     } else {
  71.         networkMode = NETWORK_HOST;
  72.     }
  73.     }
  74.  
  75.     /**
  76.      * True if called directly from an applet.
  77.      */
  78.     boolean fromApplet() {
  79.     return classLoaderDepth() == 1;
  80.     }
  81.  
  82.     /**
  83.      * True if called indirectly from an applet.
  84.      */
  85.     boolean inApplet() {
  86.     return inClassLoader();
  87.     }
  88.  
  89.     /**
  90.      * The only variable that currently affects whether an applet can
  91.      * perform certain operations is the host it came from.
  92.      */
  93.     public Object getSecurityContext() {
  94.     AppletClassLoader loader = (AppletClassLoader)currentClassLoader();
  95.     if (loader == null) {
  96.         return null;
  97.     } else {
  98.         return loader.base;
  99.     }
  100.     }
  101.  
  102.     /**
  103.      * Applets are not allowed to create class loaders, or even execute any
  104.      * of ClassLoader's methods. The name of this method should be changed to
  105.      * checkClassLoaderOperation or somesuch.
  106.      */
  107.     public synchronized void checkCreateClassLoader() {
  108.     if (classLoaderDepth() == 2) {
  109.         throw new AppletSecurityException("classloader");
  110.     }
  111.     }
  112.  
  113.     /**
  114.      * Applets are not allowed to manipulate threads outside
  115.      * applet thread groups.
  116.      */
  117.     public synchronized void checkAccess(Thread t) {
  118.     if (classLoaderDepth()==2 && !(t.getThreadGroup() instanceof AppletThreadGroup)) {
  119.         throw new AppletSecurityException("thread");
  120.     }
  121.     }
  122.  
  123.     /**
  124.      * Applets are not allowed to manipulate thread groups outside
  125.      * applet thread groups.
  126.      */
  127.     public synchronized void checkAccess(ThreadGroup g) {
  128.     if (classLoaderDepth()==4 && !(g instanceof AppletThreadGroup)) {
  129.         throw new AppletSecurityException("threadgroup", g.toString());
  130.     }
  131.     }
  132.  
  133.     /**
  134.      * Applets are not allowed to exit the VM.
  135.      */
  136.     public synchronized void checkExit(int status) {
  137.     if (inApplet()) {
  138.         throw new AppletSecurityException("exit", String.valueOf(status));
  139.     }
  140.     }
  141.  
  142.     /**
  143.      * Applets are not allowed to fork processes.
  144.      */
  145.     public synchronized void checkExec(String cmd){
  146.     if (inApplet()) {
  147.         throw new AppletSecurityException("exec", cmd);
  148.     }
  149.     }
  150.  
  151.     /**
  152.      * Applets are not allowed to link dynamic libraries.
  153.      */
  154.     public synchronized void checkLink(String lib){
  155.     switch (classLoaderDepth()) {
  156.       case 2: // Runtime.load
  157.       case 3: // System.loadLibrary
  158.         throw new AppletSecurityException("link", lib);
  159.       default:
  160.         break;
  161.     }
  162.     }
  163.  
  164.     /**
  165.      * Applets are not allowed to access the entire system properties
  166.      * list, only properties explicitly labeled as accessible to applets.
  167.      */
  168.     public synchronized void checkPropertiesAccess() {
  169.     if (classLoaderDepth() == 2) {
  170.         throw new AppletSecurityException("properties");
  171.     }
  172.     }
  173.  
  174.     /**
  175.      * Applets can access the system property named by <i>key</i>
  176.      * only if its twin <i>key.applet</i> property is set to true.
  177.      * For example, the property <code>java.home</code> can be read by
  178.      * applets only if <code>java.home.applet</code> is <code>true</code>.
  179.      */
  180.     public synchronized void checkPropertyAccess(String key) {
  181.     if (classLoaderDepth() == 2) {
  182.         if (!"true".equalsIgnoreCase(System.getProperty(key + ".applet"))) {
  183.         throw new AppletSecurityException("properties");
  184.             }
  185.     }
  186.     }
  187.  
  188.     /**
  189.      * Parse an ACL. Deals with "~" and "+"
  190.      */
  191.     void parseACL(Vector v, String path, String defaultPath) {
  192.     StringTokenizer t = new StringTokenizer(path, System.getProperty("path.separator"));
  193.     while (t.hasMoreTokens()) {
  194.         String dir = t.nextToken();
  195.         if (dir.startsWith("~")) {
  196.         v.addElement(System.getProperty("user.home") + dir.substring(1));
  197.         } else if (dir.equals("+")) {
  198.         if (defaultPath != null) {
  199.             parseACL(v, defaultPath, null);
  200.         }
  201.         } else {
  202.         v.addElement(dir);
  203.         }
  204.     }
  205.     }
  206.  
  207.     /**
  208.      * Parse an ACL.
  209.      */
  210.     String[] parseACL(String path, String defaultPath) {
  211.     if (path == null) {
  212.         return new String[0];
  213.     }
  214.     if (path.equals("*")) {
  215.         return null;
  216.     }
  217.     Vector v = new Vector();
  218.     parseACL(v, path, defaultPath);
  219.  
  220.     String acl[] = new String[v.size()];
  221.     v.copyInto(acl);
  222.     return acl;
  223.     }
  224.  
  225.     /**
  226.      * Initialize ACLs. Called only once.
  227.      */
  228.     void initializeACLs() {
  229.     readACL = parseACL(System.getProperty("acl.read"), 
  230.                System.getProperty("acl.read.default"));
  231.     writeACL = parseACL(System.getProperty("acl.write"), 
  232.                 System.getProperty("acl.write.default"));
  233.     initACL = true;
  234.     }
  235.  
  236.     /**
  237.      * Check if an applet can read a particular file.
  238.      */
  239.     public synchronized void checkRead(String file) {
  240.     AppletClassLoader loader = (AppletClassLoader)currentClassLoader();
  241.     if (loader != null) {
  242.         checkRead(file, loader.base);
  243.     }
  244.     }
  245.  
  246.     public synchronized void checkRead(String file, URL base) {
  247.     if (base != null) {
  248.         if (!initACL) {
  249.         initializeACLs();
  250.         }
  251.         if (readACL == null) {
  252.         return;
  253.         }
  254.         for (int i = readACL.length ; i-- > 0 ;) {
  255.         if (file.startsWith(readACL[i])) {
  256.             return;
  257.         }
  258.         }
  259.                         // if the applet is loaded from a file URL, allow reading
  260.                         // in that directory
  261.         if (base.getProtocol().equals("file")) {
  262.         String dir = base.getFile().replace('/', File.separatorChar);
  263.                 if (file.replace('/', File.separatorChar).startsWith(dir)) {
  264.             return;
  265.         }
  266.         }
  267.         
  268.         throw new AppletSecurityException("file.read", file);
  269.     }
  270.     }
  271.  
  272.     /**
  273.      * Checks to see if the current context or the indicated context are
  274.      * both allowed to read the given file name.
  275.      * @param file the system dependent file name
  276.      * @param context the alternate execution context which must also
  277.      * be checked
  278.      * @exception  SecurityException If the file is not found.
  279.      */
  280.     public void checkRead(String file, Object context) {
  281.     checkRead(file);
  282.     if (context != null) {
  283.         checkRead(file, (URL) context);
  284.     }
  285.     }
  286.  
  287.     /**
  288.      * Check if an applet can write a particular file.
  289.      */
  290.     public synchronized void checkWrite(String file) {
  291.     if (inApplet()) {
  292.         if (!initACL) {
  293.         initializeACLs();
  294.         }
  295.         if (writeACL == null) {
  296.         return;
  297.         }
  298.         for (int i = writeACL.length ; i-- > 0 ;) {
  299.         if (file.startsWith(writeACL[i])) {
  300.             return;
  301.         }
  302.         }
  303.         throw new AppletSecurityException("file.write", file);
  304.     }
  305.     }
  306.  
  307.     /**
  308.      * Check if an applet can delete a particular file.
  309.      */ 
  310.     public void checkDelete(String file) {
  311.         if (inApplet()) {
  312.             throw new AppletSecurityException("file.delete",file);
  313.         }
  314.     }
  315.  
  316.     /**
  317.      * Applets are not allowed to open file descriptors unless
  318.      * it is done through a socket, in which case other access
  319.      * restrictions still apply.
  320.      */
  321.     public synchronized void checkRead(FileDescriptor fd) {
  322.     if ((inApplet() && !inClass("java.net.SocketInputStream"))
  323.         || (!fd.valid()) ) {
  324.         throw new AppletSecurityException("fd.read");
  325.     }
  326.     }
  327.  
  328.     /**
  329.      * Applets are not allowed to open file descriptors unless
  330.      * it is done through a socket, in which case other access
  331.      * restrictions still apply.
  332.      */
  333.     public synchronized void checkWrite(FileDescriptor fd) {
  334.     if ( (inApplet() && !inClass("java.net.SocketOutputStream")) 
  335.          || (!fd.valid()) ) {
  336.         throw new AppletSecurityException("fd.write");
  337.     }
  338.     }
  339.  
  340.     /**
  341.      * For now applets can't listen on any port.
  342.      */
  343.     public synchronized void checkListen(int port) {
  344.     if (inApplet()) {
  345.         throw new AppletSecurityException("socket.listen", String.valueOf(port));
  346.     }
  347.     }
  348.  
  349.     /**
  350.      * For now applets can't accept connections on any port.
  351.      */
  352.     public synchronized void checkAccept(String host, int port) {
  353.     if (inApplet()) {
  354.         throw new AppletSecurityException("socket.accept", host + ":" + String.valueOf(port));
  355.     }
  356.     }
  357.  
  358.     /**
  359.      * Check if an applet can connect to the given host:port.
  360.      */
  361.     public synchronized void checkConnect(String host, int port) {
  362.     AppletClassLoader loader = (AppletClassLoader)currentClassLoader();
  363.     if (loader == null) {
  364.         // Not called from an applet, so it is ok
  365.         return;
  366.     }
  367.  
  368.     // This is only appropriate for our protocol handlers.
  369.     int depth = classDepth("sun.net.www.http.HttpClient");
  370.     if (depth > 1) {
  371.         // Called through our http protocol handler
  372.         return;
  373.     }
  374.     checkConnect(loader.base.getHost(), host);
  375.     }
  376.  
  377.     /**
  378.      * Checks to see if the applet and the indicated execution context
  379.      * are both allowed to connect to the indicated host and port.
  380.      */
  381.     public void checkConnect(String host, int port, Object context) {
  382.     checkConnect(host, port);
  383.     if (context != null) {
  384.         checkConnect(((URL) context).getHost(), host);
  385.     }
  386.     }
  387.  
  388.     public synchronized void checkConnect(String fromHost, String toHost, boolean trustP) {
  389.     if (fromHost == null) {
  390.         return;
  391.     }
  392.  
  393.     switch (networkMode) {
  394.       case NETWORK_NONE:
  395.         throw new AppletSecurityException("socket.connect", fromHost + "->" + toHost);
  396.  
  397.       case NETWORK_HOST:
  398.         /*
  399.          * The policy here is as follows:
  400.          *
  401.          * - if the strings match, and we know the IP address for it
  402.          * we allow the connection. The calling code downstream will
  403.          * substitute the IP in their request to the proxy if needed.
  404.          * - if the strings don't match, and we can get the IP of
  405.          * both hosts then
  406.          *   - if the IPs match, we allow the connection
  407.          *   - if they don't we throw an exception
  408.          * - if the string match works and we don't know the IP address
  409.          * then we consult the trustProxy property, and if that is true,
  410.          * we allow the connection.
  411.          * set inCheck so InetAddress knows it doesn't have to
  412.          * check security.
  413.          */
  414.         try {
  415.         inCheck = true;
  416.         InetAddress toHostAddr, fromHostAddr;
  417.         if (!fromHost.equals(toHost)) {
  418.             try {
  419.             // the only time we allow non-matching strings is when get have
  420.             // IPs and the IPs match.
  421.             toHostAddr = InetAddress.getByName(toHost);            
  422.             fromHostAddr = InetAddress.getByName(fromHost);
  423.             if (fromHostAddr.equals(toHostAddr)) {
  424.                 return;
  425.             } else {
  426.                 throw new AppletSecurityException("Couldn't connect to " +
  427.                                   toHost + 
  428.                                   " with origin from " +
  429.                                   fromHost);
  430.             }
  431.             } catch (UnknownHostException e) {
  432.             throw new AppletSecurityException("Couldn't resolve IP for host " + toHost
  433.                               + " or for " + fromHost + ".");
  434.             }  
  435.         } else {
  436.             try {
  437.             toHostAddr = InetAddress.getByName(toHost);                
  438.             // strings match: if we have IP, we're homefree, otherwise we check
  439.             // the properties.
  440.             return;
  441.             // getBoolean really defaults to false.        
  442.             } catch (UnknownHostException e) {
  443.             if (trustP) {
  444.                 return;
  445.             } else {
  446.                 throw new AppletSecurityException("Could not resolve IP for host " +
  447.                                   toHost +
  448.                                   ". See the trustProxy property.");
  449.             }
  450.             }
  451.         }
  452.  
  453.         } finally {
  454.         inCheck = false;
  455.         }
  456.  
  457.  
  458.       case NETWORK_UNRESTRICTED:
  459.         return;
  460.     }
  461.     throw new AppletSecurityException("connect", fromHost + "->" + toHost);
  462.     }
  463.     
  464.    /**
  465.      * Check if an applet from a host can connect to another
  466.      * host. This usually means that you need to determine whether
  467.      * the hosts are inside or outside the firewall. For now applets
  468.      * can only access the host they came from.
  469.      */
  470.     public synchronized void checkConnect(String fromHost, String toHost) {
  471.     checkConnect(fromHost, toHost, Boolean.getBoolean("trustProxy"));
  472.     }
  473.  
  474.     /**
  475.      * Checks to see if top-level windows can be created by the caller.
  476.      */
  477.     public synchronized boolean checkTopLevelWindow(Object window) {
  478.     if (inClassLoader()) {
  479.         /* XXX: this used to return depth > 3. However, this lets */
  480.         /* some applets create frames without warning strings. */
  481.         return false;
  482.     }
  483.     return true;
  484.     }
  485.  
  486.     /**
  487.      * Check if an applet can access a package.
  488.      */
  489.     public synchronized void checkPackageAccess(String pkg) {
  490.         int i = pkg.indexOf('.');
  491.         while (i > 0)
  492.         {
  493.             String subpkg = pkg.substring(0,i);
  494.             if (inClassLoader() && Boolean.getBoolean("package.restrict.access." + subpkg)) {
  495.                 throw new SecurityException();
  496.             }
  497.             i = pkg.indexOf('.',i+1);
  498.         }
  499.         if (inClassLoader() && Boolean.getBoolean("package.restrict.access." + pkg)) {
  500.             throw new SecurityException();
  501.         }
  502.     }
  503.  
  504.     /**
  505.      * Check if an applet can define classes in a package.
  506.      */
  507.     public synchronized void checkPackageDefinition(String pkg) {
  508.         int i = pkg.indexOf('.');
  509.         while (i > 0)
  510.         {
  511.             String subpkg = pkg.substring(0,i);
  512.             if (Boolean.getBoolean("package.restrict.definition." + subpkg)) {
  513.                 throw new SecurityException();
  514.             }
  515.             i = pkg.indexOf('.',i+1);
  516.         }
  517.         if (Boolean.getBoolean("package.restrict.definition." + pkg)) {
  518.             throw new SecurityException();
  519.         }
  520.     }
  521.  
  522.     /**
  523.      * Check if an applet can set a networking-related object factory.
  524.      */
  525.     public synchronized void checkSetFactory() {
  526.     throw new SecurityException();
  527.     }
  528.     
  529.     public void debug(String s) {
  530.     if (debug) {
  531.         System.err.println(s);
  532.     }
  533.     }
  534.  
  535.     /**
  536.      * Applets are not allowed to put up file dialogs.
  537.      */
  538.     public synchronized void checkFileDialog(){
  539.         if (inApplet()) {
  540.             throw new AppletSecurityException("filedialog");
  541.         }
  542.     }
  543.  
  544. }
  545.