2011-02-15 66 views
3

在Java策略文件中,grant codeBase語法指定應授予哪個代碼庫哪些權限。例如,Java策略文件 - 拒絕對代碼庫的權限

授權代碼庫 「的文件:/ C:/abc.jar」{ 許可 java.security.AllPermission; };

補助AllPermission裏面abc.jar

代碼以類似的方式,有沒有辦法來deny權限特定的語法?就像這樣:

拒絕代碼庫 「文件:/ C:/def.jar」{ 許可 java.io.FilePermission中; };

這樣def.jar裏面的代碼獲得除FilePermission以外的所有其他權限?

這甚至可能嗎?

我知道這可以很容易地使用SecurityManager類完成,但我只想知道這是否可能通過僅使用策略文件。

回答

2

不,沒有什麼這樣的政策文件實施。如果你真的很絕望,你可以編寫自己的系統。

+0

哦!好的,謝謝你的回答:) – securitypolicymanager 2011-02-16 04:58:50

11

我意識到這已經快一年了,但我想我正在嘗試做類似的事情。

有一種方法可以設置運行時權限,以便Java不會授予全局權限。然後,您只能指定您希望爲您的應用授予的權限。關鍵是用下面的選項運行你的應用程序。

java -Djava.security.manager -Djava.security.policy==policyFile.txt MyClass 

注意雙等於-Djava.security.policy==policyFile.txt。雙等於==意味着僅使用指定文件中的權限,而不是單個等號-Djava.security.policy=policyFile.txt,這意味着除了繼承的全局權限之外還使用這些權限。

然後創建一個不包括你要拒絕的權限策略文件:

// policyFile.txt 
grant codeBase "file:/C:/abc.jar" { 

    // list of permissions minus the ones you want to deny 
    // for example, the following would give the application 
    // ONLY AudioPermission and AWTPermission. Other 
    // permissions such as java.io.FilePermission would be 
    // denied. 

    permission javax.sound.sampled.AudioPermission; 
    permission java.awt.AWTPermission; 

} 
+2

而且我意識到,這是另一個2年後...有點'否認'的是,它是不可能知道一個未知的,所謂託管的應用程序的'允許'的完整列表在服務器上,應用程序。舉例來說,您想禁止寫入「java。*」系統屬性,但所有其他應用程序都可以使用。正因爲如此,'拒絕代碼庫'會很好。這就是我想要做的... – 2013-12-10 13:46:25

+0

這是這個問題的正確答案。 – hfontanez 2016-03-11 23:01:08

4

您可以使用Prograde庫,它實現了與拒絕規則的政策文件。

添加以下Maven依賴於你的應用程序

<dependency> 
    <groupId>net.sourceforge.pro-grade</groupId> 
    <artifactId>pro-grade</artifactId> 
    <version>1.0</version> 
</dependency> 

,然後通過使用標準的系統特性使之成爲您的應用程序:

-Djava.security.manager=net.sourceforge.prograde.sm.ProgradeSecurityManager -Djava.security.policy==/path/to/your/application.policy 

或只需更換你的代碼編程的政策執行:

System.setProperty("java.security.policy","/path/to/your/application.policy"); 
Policy.setPolicy(new ProgradePolicyFile()); 

策略文件停留的語法類似於標準實現,但您可以使用deny而不是grant,也可以使用關鍵字priority更改優先級(默認值爲"deny" - 保持向後兼容)。

例如,你可以做某事。如:

grant { 
    permission java.lang.RuntimePermission "*"; 
}; 

deny { 
    permission java.lang.RuntimePermission "exitVM.*"; 
}; 

其他示例是here

0

一個朝着實現拒絕規則支持最少參與的辦法,就是要:

  • 定義一個「負」 Permission子類,包裝了一個普通的正許可,取消它;和
  • 包裝默認Policy,使它(它的包裝)理解這種權限。

DeniedPermission

package com.example.q5003565; 

import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Modifier; 
import java.security.BasicPermission; 
import java.security.Permission; 
import java.security.UnresolvedPermission; 
import java.text.MessageFormat; 

/** 
* A representation of a "negative" privilege. 
* <p> 
* A <code>DeniedPermission</code>, when "granted" to some <code>ProtectionDomain</code>, represents 
* a privilege which <em>cannot</em> be exercised, regardless of any positive permissions 
* (<code>AllPermission</code> included) possessed. In other words, if a set of granted permissions, 
* <em>P</em>, contains a permission of this class, <em>D</em>, then the set of effectively granted 
* permissions is<br/> 
* <br/> 
* &nbsp;&nbsp;&nbsp;&nbsp;<em>{ P<sub>implied</sub> - D<sub>implied</sub> }</em>. 
* </p> 
* <p> 
* Each instance of this class encapsulates a <em>target permission</em>, representing the 
* "positive" permission being negated. 
* </p> 
* Denied permissions employ the following naming scheme:<br/> 
* <br/> 
* &nbsp;&nbsp;&nbsp;&nbsp;<em>&lt;target_class_name&gt;:&lt;target_name&gt;(:&lt;target_actions&gt;)</em><br/> 
* <br/> 
* where: 
* <ul> 
* <li><em>&lt;target_class_name&gt;</em> is the fully qualified name of the target permission's 
* class,</li> 
* <li><em>&lt;target_name&gt;</em> is the {@linkplain #getName() name} of the target 
* permission,</li> 
* <li><em>(&lt;target_actions&gt;)</em> is, optionally, the {@linkplain #getActions() actions 
* string} of the target permission, and</li> 
* <li>the <em>':'</em> character stands for itself.</li> 
* </ul> 
* A denied permission, having a target permission <em>t</em>, is said to 
* {@linkplain #implies(Permission) <em>imply</em>} another permission <em>p</em>, iff: 
* <ul> 
* <li>p <em>is not</em> itself a denied permission, and <code>(t.implies(p) == true)</code>, 
* or</li> 
* <li>p <em>is</em> a denied permission, with a target <em>t1</em>, and 
* <code>(t.implies(t1) == true)</code>.</li> 
* </ul> 
* <p> 
* It is the responsibility of the policy decision point (e.g., the <code>Policy</code> provider) to 
* take denied permission semantics into account when issuing authorization statements. 
* </p> 
*/ 
public final class DeniedPermission extends BasicPermission { 

    private static final String NULL_STR_ARG = "<null>", EMPTY_STR_ARG = "<empty> "; 
    private static final long serialVersionUID = 2102974454790623344L; 

    private final Permission target; 

    /** 
    * Instantiates a <code>DeniedPermission</code> that encapsulates a target permission of the 
    * indicated class, specified name and, optionally, actions. 
    * 
    * @throws IllegalArgumentException 
    *    if: 
    *    <ul> 
    *    <li><code>targetClassName</code> is <code>null</code>, the empty string, does not 
    *    refer to a concrete <code>Permission</code> descendant, or refers to 
    *    <code>DeniedPermission.class</code> or <code>UnresolvedPermission.class</code>.</li> 
    *    <li><code>targetName</code> is <code>null</code>.</li> 
    *    <li><code>targetClassName</code> cannot be instantiated, and it's the caller's fault; 
    *    e.g., because <code>targetName</code> and/or <code>targetActions</code> do not adhere 
    *    to the naming constraints of the target class; or due to the target class not 
    *    exposing a <code>(String name)</code>, or <code>(String name, String actions)</code> 
    *    constructor, depending on whether <code>targetActions</code> is <code>null</code> or 
    *    not.</li> 
    *    </ul> 
    * @throws SecurityException 
    *    if a <code>SecurityManager</code>, <code>sm</code>, is installed, and the invocation 
    *    <code>sm.checkPackageAccess(targetClassPackageName)</code> (where 
    *    <code>targetClassPackageName</code> is the package of the class referred to 
    *    by <code>targetClassName</code>) denies access. 
    */ 
    public static DeniedPermission newDeniedPermission(String targetClassName, String targetName, 
      String targetActions) { 
     if (targetClassName == null || targetClassName.trim().isEmpty() || targetName == null) { 
      throw new IllegalArgumentException("[targetClassName] and [targetName] must not be null or empty."); 
     } 
     StringBuilder sb = new StringBuilder(targetClassName).append(":").append(targetName); 
     if (targetName != null) { 
      sb.append(":").append(targetName); 
     } 
     return new DeniedPermission(sb.toString()); 
    } 

    /** 
    * Instantiates a <code>DeniedPermission</code> that encapsulates the given target permission. 
    * 
    * @throws IllegalArgumentException 
    *    if <code>target</code> is <code>null</code>, a <code>DeniedPermission</code>, or an 
    *    <code>UnresolvedPermission</code>. 
    */ 
    public static DeniedPermission newDeniedPermission(Permission target) { 
     if (target == null) { 
      throw new IllegalArgumentException("[target] must not be null."); 
     } 
     if (target instanceof DeniedPermission || target instanceof UnresolvedPermission) { 
      throw new IllegalArgumentException("[target] must not be a DeniedPermission or an UnresolvedPermission."); 
     } 
     StringBuilder sb = new StringBuilder(target.getClass().getName()).append(":").append(target.getName()); 
     String targetActions = target.getActions(); 
     if (targetActions != null) { 
      sb.append(":").append(targetActions); 
     } 
     return new DeniedPermission(sb.toString(), target); 
    } 

    private static Permission constructTargetPermission(String targetClassName, String targetName, 
      String targetActions) { 
     Class<?> targetClass; 
     try { 
      targetClass = Class.forName(targetClassName); 
     } 
     catch (ClassNotFoundException cnfe) { 
      if (targetClassName.trim().isEmpty()) { 
       targetClassName = EMPTY_STR_ARG; 
      } 
      throw new IllegalArgumentException(
        MessageFormat.format("Target Permission class [{0}] not found.", targetClassName)); 
     } 
     if (!Permission.class.isAssignableFrom(targetClass) || Modifier.isAbstract(targetClass.getModifiers())) { 
      throw new IllegalArgumentException(MessageFormat 
        .format("Target Permission class [{0}] is not a (concrete) Permission.", targetClassName)); 
     } 
     if (targetClass == DeniedPermission.class || targetClass == UnresolvedPermission.class) { 
      throw new IllegalArgumentException(
        "Target Permission class must not be a DeniedPermission itself, nor an UnresolvedPermission."); 
     } 
     Constructor<?> targetCtor; 
     try { 
      if (targetActions == null) { 
       targetCtor = targetClass.getConstructor(String.class); 
      } 
      else { 
       targetCtor = targetClass.getConstructor(String.class, String.class); 
      } 
     } 
     catch (NoSuchMethodException nsme) { 
      throw new IllegalArgumentException(MessageFormat.format(
        "Target Permission class [{0}] (String name) or (String name, String actions) constructor.", 
        targetClassName)); 
     } 
     try { 
      return (Permission) targetCtor 
        .newInstance(((targetCtor.getParameterCount() == 1) ? new Object[] { targetName } 
          : new Object[] { targetName, targetActions })); 
     } 
     catch (ReflectiveOperationException roe) { 
      if (roe instanceof InvocationTargetException) { 
       if (targetName == null) { 
        targetName = NULL_STR_ARG; 
       } 
       else if (targetName.trim().isEmpty()) { 
        targetName = EMPTY_STR_ARG; 
       } 
       if (targetActions == null) { 
        targetActions = NULL_STR_ARG; 
       } 
       else if (targetActions.trim().isEmpty()) { 
        targetActions = EMPTY_STR_ARG; 
       } 
       throw new IllegalArgumentException(MessageFormat.format(
         "Could not instantiate target Permission class [{0}]; provided target name [{1}] and/or target [{2}] actions potentially erroneous.", 
         targetClassName, targetName, targetActions), roe); 
      } 
      throw new RuntimeException(MessageFormat.format(
        "Could not instantiate target Permission class [{0}] - an unforeseen error occurred, see attached cause for details.", 
        targetClassName), roe); 
     } 
    } 

    /** 
    * Instantiates a <code>DeniedPermission</code> that encapsulates a target permission of the class, 
    * name and, optionally, actions, collectively provided as the <code>name</code> argument. 
    * 
    * @throws IllegalArgumentException 
    *    if: 
    *    <ul> 
    *    <li><code>name</code>'s target permission class name component is empty, does not 
    *    refer to a concrete <code>Permission</code> descendant, or refers to 
    *    <code>DeniedPermission.class</code> or <code>UnresolvedPermission.class</code>.</li> 
    *    <li><code>name</code>'s target name component is <code>empty</code></li> 
    *    <li>the target permission class cannot be instantiated, and it's the caller's fault; 
    *    e.g., because <code>name</code>'s target name and/or target actions component(s) do 
    *    not adhere to the naming constraints of the target class; or due to the target class 
    *    not exposing a <code>(String name)</code>, or 
    *    <code>(String name, String actions)</code> constructor, depending on whether the 
    *    target actions component is empty or not.</li> 
    *    </ul> 
    * @throws SecurityException 
    *    if a <code>SecurityManager</code>, <code>sm</code>, is installed, and the invocation 
    *    <code>sm.checkPackageAccess(targetClassPackageName)</code> 
    *    (where <code>targetClassPackageName</code> is the package of the class referred to 
    *    by <code>name</code>'s target name component) denies access. 
    */ 
    public DeniedPermission(String name) { 
     super(name); 
     String[] comps = name.split(":"); 
     if (comps.length < 2) { 
      throw new IllegalArgumentException(MessageFormat.format("Malformed [name] argument: {0}", name)); 
     } 
     this.target = constructTargetPermission(comps[0], comps[1], ((comps.length < 3) ? null : comps[2])); 
    } 

    private DeniedPermission(String name, Permission target) { 
     super(name); 
     this.target = target; 
    } 

    /** 
    * Checks whether the given permission is implied by this one, as per the 
    * {@linkplain DeniedPermission overview}. 
    */ 
    @Override 
    public boolean implies(Permission p) { 
     if (p instanceof DeniedPermission) { 
      return target.implies(((DeniedPermission) p).target); 
     } 
     return target.implies(p); 
    } 

    /** 
    * Returns this denied permission's target permission. 
    */ 
    public Permission getTargetPermission() { 
     return target; 
    } 

} 

DenyingPolicy

package com.example.q5003565; 

import java.security.AccessController; 
import java.security.CodeSource; 
import java.security.NoSuchAlgorithmException; 
import java.security.NoSuchProviderException; 
import java.security.Permission; 
import java.security.PermissionCollection; 
import java.security.Policy; 
import java.security.PrivilegedAction; 
import java.security.ProtectionDomain; 
import java.security.UnresolvedPermission; 
import java.util.Enumeration; 

/** 
* Wrapper that adds rudimentary {@link DeniedPermission} processing capabilities to the standard 
* file-backed <code>Policy</code>. 
*/ 
public final class DenyingPolicy extends Policy { 

    /* 
    * doPrivileged needed just in case there's already a SecurityManager installed at class loading 
    * time. 
    */ 
    private static final ProtectionDomain OWN_PD = AccessController 
      .doPrivileged((PrivilegedAction<ProtectionDomain>) DenyingPolicy.class::getProtectionDomain); 

    private final Policy defaultPolicy; 

    { 
     try { 
      // will fail unless the calling acc has SecurityPermission "createPolicy.javaPolicy" 
      defaultPolicy = Policy.getInstance("javaPolicy", null, "SUN"); 
     } 
     catch (NoSuchProviderException | NoSuchAlgorithmException e) { 
      throw new RuntimeException("Could not acquire default Policy.", e); 
     } 
    } 

    @Override 
    public PermissionCollection getPermissions(CodeSource codesource) { 
     return defaultPolicy.getPermissions(codesource); 
    } 

    @Override 
    public PermissionCollection getPermissions(ProtectionDomain domain) { 
     return defaultPolicy.getPermissions(domain); 
    } 

    /** 
    * @return <code>true</code> iff: 
    *   <ul> 
    *   <li><code>permission</code> <em>is not</em> an instance of 
    *   <code>DeniedPermission</code>,</li> 
    *   <li>an <code>implies(domain, permission)</code> invocation on the system-default 
    *   <code>Policy</code> yields <code>true</code>, and</li> 
    *   <li><code>permission</code> <em>is not</em> implied by any <code>DeniedPermission</code>s 
    *   having potentially been assigned to <code>domain</code>.</li> 
    *   </ul> 
    */ 
    @Override 
    public boolean implies(ProtectionDomain domain, Permission permission) { 
     if (OWN_PD.equals(domain)) { 
      /* 
      * Recursive invocation due to a privilege-requiring method we invoked. If you're uncomfortable with 
      * this, get rid of it and grant (via .policy) a RuntimePermission "accessClassInPackage.*" to 
      * OWN_PD. 
      */ 
      return true; 
     } 
     if (permission instanceof DeniedPermission) { 
      /* 
      * At the policy decision level, DeniedPermissions can only themselves imply, not be implied (as 
      * they take away, rather than grant, privileges). Returning true for a deny rule would be 
      * more confusing than convenient. 
      */ 
      return false; 
     } 

     if (!defaultPolicy.implies(domain, permission)) { 
      // permission not granted--no need to check whether denied 
      return false; 
     } 

     /* 
     * Permission granted--now check whether there's an overriding DeniedPermission. The following 
     * assumes that defaultPolicy (its wrapped PolicySpi) is a sun.security.provider.PolicySpiFile 
     * (other implementations might not support #getPermissions(ProtectionDomain) 
     * and/or handle resolution of UnresolvedPermissions differently). 
     */ 

     Enumeration<Permission> perms = defaultPolicy.getPermissions(domain).elements(); 
     while (perms.hasMoreElements()) { 
      Permission p = perms.nextElement(); 
      /* 
      * DeniedPermissions will generally remain unresolved, as no code is expected to check whether other 
      * code has been "granted" such a permission. 
      */ 
      if (p instanceof UnresolvedPermission) { 
       UnresolvedPermission up = (UnresolvedPermission) p; 
       if (up.getUnresolvedType().equals(DeniedPermission.class.getName())) { 
        // force resolution 
        defaultPolicy.implies(domain, up); 
        // evaluate right away, to avoid reiterating over the collection 
        p = AccessController.doPrivileged(
          (PrivilegedAction<Permission>)() -> new DeniedPermission(up.getUnresolvedName())); 
       } 
      } 
      if (p instanceof DeniedPermission && p.implies(permission)) { 
       // permission denied 
       return false; 
      } 
     } 
     // permission granted 
     return true; 
    } 

    @Override 
    public void refresh() { 
     defaultPolicy.refresh(); 
    } 

} 

使用

剛剛Ë mbed DeniedPermission s普通舊授予規則;例如,下面的規則將授予一切能力閱讀系統屬性與名稱以「用戶」,到some.jar的類。

grant codeBase "file:/home/your_user/classpath/some.jar" { 
    permission java.security.AllPermission; 
    permission com.example.q5003565.DeniedPermission "java.util.PropertyPermission:user.*:read"; 
}; 

然後通過Policy.setPolicy(new DenyingPolicy());安裝DenyingPolicy

警告:雖然語義正確的,因爲在前面的回答的評論中提到的,上面的例子是無效的,因爲它仍然補助危險的權限,例如SecurityPermission "setPolicy",其中隱含允許沙盒代碼爲所欲爲包括DeniedPermission禁止的操作。爲了防止這種情況的發生,而不是從AllPermission減去權限,考慮從AllSafePermission代替,其中AllSafePermission被定義減去它implies一切除了已知沙箱挫敗權限。

  • 任何權限的用戶可以通過一個拒絕的權限被包裹,只要它遵循標準的目標名稱 - 動作(一個或多個)約定,公開了一個(String)和/或(String, String)構造,並且適當地重寫implies(Permission)
  • 要同時拒絕多個權限:
    • 創建一個一般權限子類,implies待被拒絕的權限。
    • 從策略配置中「授予」一個被拒絕的權限,並依次引用您的實現實例。
  • DenyingPolicy防止分配給一個保護域的權限statically(例如,通過默認代碼從類路徑始發授予RuntimePermission "exitVM.*")從被授予,如,一般地,這樣的權限的評價之前,評估發生由策略維護的權限。爲了拒絕任何這些權限,以及,你將有一個更換ClassLoader說:
    • 沒有或者不授予的權限擺在首位,或者它加載到的情況下
    • mapsProtectionDomain亞類中,重寫implies(Permission)使得:
      • 它總是委託給策略或
      • 過程DeniedPermission S IN類似於DenyingPolicy的方式。

1:對於這樣的權限的列表參見例如Maass, M. (2016). A Theory and Tools for Applying Sandboxes Effectively.,表3.1(第47頁)。