2013-12-11 3 views
1

이 질문은 높은 수준에서 my previous question about unusual exceptions generated by a custom security manager.의 후속, 내가 신뢰할 수없는 코드와 함께 신뢰할 수있는 코드를 실행하는 응용 프로그램을 구축에 관심이 있어요. 나의 초기 아이디어는 대부분의 작업이 실행되지 않도록하는 사용자 정의 SecurityManager을 작성하는 것이 었습니다. 이로 인해 신뢰할 수없는 객체를 인스턴스화하는 신뢰할 수있는 반사 코드가 16 번의 호출 후에 실패한 비정상적인 동작이 발생했습니다.왜 이처럼 겉으로는 동등한 SecurityManager 코드가 잘못된 예외를 유발합니까?

코드를 다시 작성하여 SecurityManager 사용자 지정을 사용하는 대신 신뢰할 수없는 코드가 실행되는 새로운 보호 도메인을 만들고 해당 신뢰할 수없는 코드에서 사용 권한을 제거합니다. 이 새로운 코드는 여기에 표시됩니다 :

import java.io.FilePermission; 
import java.lang.reflect.*; 
import java.security.*; 

public class Main { 
    /* Track how many instances have been created so that we can see when the exception 
    * is thrown. 
    */ 
    private static int numInstances = 0; 
    public Main() { 
     System.out.println("Number created: " + ++numInstances); 
    } 

    /* Utility function that returns a Constructor object for main. */ 
    private static Constructor<Main> getCtor() { 
     try { 
      return Main.class.getConstructor(); 
     } catch (NoSuchMethodException e) { 
      e.printStackTrace(); 
      System.exit(-1); 
      return null; // Unreachable, needed to appease compiler. 
     } 
    } 

    /* Utility function that creates an AccessControlContext that only has file 
    * read permissions. 
    */ 
    private static AccessControlContext getContext() { 
     CodeSource c = new CodeSource(null, (java.security.cert.Certificate[])null); 
     Permissions permissions = new Permissions(); 

     /* Grant specific permission to read files. This is necessary, since otherwise the 
     * class loader can't read classes from disk. 
     */ 
     permissions.add(new FilePermission("*", "read")); 

     /* Construct an AccessControlContext from these permissions. */ 
     return new AccessControlContext(new ProtectionDomain[] {new ProtectionDomain(c, permissions)}); 
    } 

    public static void main(String[] args) { 
     /* Get a very restrictive AccessControlContext that does not allow for anything to run. */ 
     AccessControlContext noPermissions = getContext(); 

     /* Install a standard security manager to enable security. */ 
     System.setSecurityManager(new SecurityManager()); 

     /* Sit in an infinite loop using reflection to create Main objects. This code is 
     * run in a context where its only permissions are file reading. 
     */ 
     AccessController.doPrivileged(new PrivilegedAction<Void>() { 
      @Override 
      public Void run() { 
       /* Continuously create new Main objects. */ 
       Constructor<Main> ctor = getCtor(); 
       try { 
        while (true) { 
         ctor.newInstance(); 
        } 
       } catch (Exception e) { 
        e.printStackTrace(); 
        return null; 
       } 
      } 
     }, noPermissions); 

    } 
} 

이 코드는 이제 완벽하게 잘 작동 - 그것은 어떠한 문제없이 Main 객체의 모든 종류를 구축합니다. 나는에 대한 혼란 스러워요 무엇

은 다음과 같다. AccessController에 치아가 있으려면 보안 관리자를 켜야합니다. 나는 지금

/* Install a standard security manager to enable security. */ 
System.setSecurityManager(new SecurityManager()); 

를 호출하여이 작업을 수행, 내가이 사용자 정의 SecurityManager기본 SecurityManager에서이 설정을 변경한다고 가정하면 :이 때 발생하는 로그를 제외

/* Install a standard security manager to enable security. */ 
System.setSecurityManager(new SecurityManager() { 
    @Override 
    public void checkPermission(Permission p) { 
     /* Log the permission. */ 
     System.out.println("Checking " + p); 
     super.checkPermission(p); 
    } 
}); 

SecurityManager은 이전과 동일하다 권한이 확인 된 다음 요청을 기본값 SecurityManager으로 전달합니다.

Checking ("java.io.FilePermission" "/home/keith/Documents/secret-eclipse-workspace/Security Manager Test/bin/Main$2.class" "read") 
Checking ("java.io.FilePermission" "/home/keith/Documents/secret-eclipse-workspace/Security Manager Test/bin/Main$2.class" "read") 
Checking ("java.io.FilePermission" "/home/keith/Documents/secret-eclipse-workspace/Security Manager Test/bin/Main$2.class" "read") 
Number created: 1 
Number created: 2 
Number created: 3 
Number created: 4 
Number created: 5 
Number created: 6 
Number created: 7 
Number created: 8 
Number created: 9 
Number created: 10 
Number created: 11 
Number created: 12 
Number created: 13 
Number created: 14 
Number created: 15 
Checking ("java.lang.RuntimePermission" "createClassLoader") 
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "createClassLoader") 
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372) 
    at java.security.AccessController.checkPermission(AccessController.java:559) 
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) 
    at Main$1.checkPermission(Main.java:51) 
    at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:611) 
    at java.lang.ClassLoader.checkCreateClassLoader(ClassLoader.java:274) 
    at java.lang.ClassLoader.<init>(ClassLoader.java:316) 
    at sun.reflect.DelegatingClassLoader.<init>(ClassDefiner.java:72) 
    at sun.reflect.ClassDefiner$1.run(ClassDefiner.java:60) 
    at sun.reflect.ClassDefiner$1.run(ClassDefiner.java:58) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:57) 
    at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399) 
    at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:396) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:395) 
    at sun.reflect.MethodAccessorGenerator.generateConstructor(MethodAccessorGenerator.java:94) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:48) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
    at Main$2.run(Main.java:65) 
    at Main$2.run(Main.java:1) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at Main.main(Main.java:58) 

왜 내가 전에이 사용자 정의 SecurityManager 사용 후 다른 동작을 얻고있다 :이 변경하고 프로그램을 실행하면

은, 지금은 이전과 동일한 동작을 얻을? 두 경우 모두 기본값 인 SecurityManager이 실제로 모든 보안 검사를 수행하는 것이므로 프로그램에서 이러한 경우 다른 결과를 산출하는 이유는 알 수 없습니다.

감사합니다. 당신의 SecurityManager

답변

1

코드는 신뢰할 수 나타나지 않습니다. 따라서 스택 검사 중에 나타나면 보안 검사가 실패합니다.

하지 않는 이유는 같은 문제 원인 코드 mainrun? 보안 검사와 관련된 스택 요소를 스택 추적에서 확인할 수 있습니다.

at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372) 
at java.security.AccessController.checkPermission(AccessController.java:559) 
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) 
at Main$1.checkPermission(Main.java:51) 
at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:611) 
at java.lang.ClassLoader.checkCreateClassLoader(ClassLoader.java:274) 
at java.lang.ClassLoader.<init>(ClassLoader.java:316) 
at sun.reflect.DelegatingClassLoader.<init>(ClassDefiner.java:72) 
at sun.reflect.ClassDefiner$1.run(ClassDefiner.java:60) 
at sun.reflect.ClassDefiner$1.run(ClassDefiner.java:58) 
at java.security.AccessController.doPrivileged(Native Method) 
at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:57) 

유일한 비 시스템 프레임은 Main$1.checkPermission(Main.java:51)입니다. 그것을 제거하면 문제가 사라집니다.

+0

감사합니다! 이 코드를 어떻게 신뢰할 수 있습니까? 아니면 완전히 다른 접근법을 찾아야합니까? – templatetypedef

+0

@templatetypedef 일반적으로, 정책 파일에 java.security.AllPermission 코드베이스를 부여 할 수 있습니다. –