1
+ package org.utbot.instrumentation.process
2
+
3
+ import sun.security.provider.PolicyFile
4
+ import java.lang.reflect.ReflectPermission
5
+ import java.net.URI
6
+ import java.nio.file.Files
7
+ import java.nio.file.Paths
8
+ import java.security.AccessControlContext
9
+ import java.security.AccessController
10
+ import java.security.CodeSource
11
+ import java.security.Permission
12
+ import java.security.PermissionCollection
13
+ import java.security.Permissions
14
+ import java.security.Policy
15
+ import java.security.PrivilegedAction
16
+ import java.security.ProtectionDomain
17
+ import java.security.cert.Certificate
18
+ import java.util.PropertyPermission
19
+
20
+ internal fun permissions (block : SimplePolicy .() -> Unit ) {
21
+ val policy = Policy .getPolicy()
22
+ if (policy !is SimplePolicy ) {
23
+ Policy .setPolicy(SimplePolicy (block))
24
+ System .setSecurityManager(SecurityManager ())
25
+ } else {
26
+ policy.block()
27
+ }
28
+ }
29
+
30
+ /* *
31
+ * Run [block] in sandbox mode.
32
+ *
33
+ * When running in sandbox by default only necessary to instrumentation permissions are enabled.
34
+ * Other options are not enabled by default and rises [java.security.AccessControlException].
35
+ *
36
+ * To add new permissions create and/or edit file "{user.home}/.utbot/sandbox.policy".
37
+ *
38
+ * For example to enable property reading (`System.getProperty("user.home")`):
39
+ *
40
+ * ```
41
+ * grant {
42
+ * permission java.util.PropertyPermission "user.home", "read";
43
+ * };
44
+ * ```
45
+ * Read more [about policy file and syntax](https://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html#Examples)
46
+ */
47
+ internal fun <T > sandbox (block : () -> T ): T {
48
+ val policyPath = Paths .get(System .getProperty(" user.home" ), " .utbot" , " sandbox.policy" )
49
+ return sandbox(policyPath.toUri()) { block() }
50
+ }
51
+
52
+ internal fun <T > sandbox (file : URI , block : () -> T ): T {
53
+ val path = Paths .get(file)
54
+ val perms = mutableListOf<Permission >(
55
+ RuntimePermission (" accessDeclaredMembers" ),
56
+ RuntimePermission (" getProtectionDomain" ),
57
+ RuntimePermission (" accessClassInPackage.*" ),
58
+ RuntimePermission (" getClassLoader" ),
59
+ RuntimePermission (" reflectionFactoryAccess" ),
60
+ PropertyPermission (" org.mockito.internal.*" , " read,write" ),
61
+ ReflectPermission (" *" ),
62
+ )
63
+ if (Files .exists(path)) {
64
+ val policyFile = PolicyFile (file.toURL())
65
+ val collection = policyFile.getPermissions(CodeSource (null , emptyArray<Certificate >()))
66
+ perms + = collection.elements().toList()
67
+ }
68
+ return sandbox(perms) { block() }
69
+ }
70
+
71
+ internal fun <T > sandbox (permission : List <Permission >, block : () -> T ): T {
72
+ val perms = permission.fold(Permissions ()) { acc, p -> acc.add(p); acc }
73
+ return sandbox(perms) { block() }
74
+ }
75
+
76
+ internal fun <T > sandbox (perms : PermissionCollection , block : () -> T ): T {
77
+ val acc = AccessControlContext (arrayOf(ProtectionDomain (null , perms)))
78
+ return AccessController .doPrivileged(
79
+ PrivilegedAction {
80
+ block()
81
+ },
82
+ acc
83
+ )
84
+ }
85
+
86
+ /* *
87
+ * This policy can add grant or denial rules for permissions.
88
+ *
89
+ * To add a grant permission use like this in any place:
90
+ *
91
+ * ```
92
+ * permissions {
93
+ * + java.security.PropertyPolicy("user.home", "read,write")
94
+ * }
95
+ * ```
96
+ *
97
+ * After first call [SecurityManager] is set with this policy
98
+ *
99
+ * To deny a permission:
100
+ *
101
+ * ```
102
+ * permissions {
103
+ * - java.security.PropertyPolicy("user.home", "read,write")
104
+ * }
105
+ * ```
106
+ *
107
+ * To delete all concrete permissions (if it was added before):
108
+ *
109
+ * ```
110
+ * permissions {
111
+ * ! java.security.PropertyPolicy("user.home", "read,write")
112
+ * }
113
+ * ```
114
+ *
115
+ * The last permission has priority. Enable all property read for "user.*", but forbid to read only "user.home":
116
+ *
117
+ * ```
118
+ * permissions {
119
+ * + java.security.PropertyPolicy("user.*", "read,write")
120
+ * - java.security.PropertyPolicy("user.home", "read,write")
121
+ * }
122
+ * ```
123
+ */
124
+ internal class SimplePolicy (init : SimplePolicy .() -> Unit = {}) : Policy() {
125
+ sealed class Access (val permission : Permission ) {
126
+ class Allow (permission : Permission ) : Access(permission)
127
+ class Deny (permission : Permission ) : Access(permission)
128
+ }
129
+ private var permissions = mutableListOf<Access >()
130
+
131
+ init { apply (init ) }
132
+
133
+ operator fun Permission.unaryPlus () = permissions.add(Access .Allow (this ))
134
+
135
+ operator fun Permission.unaryMinus () = permissions.add(Access .Deny (this ))
136
+
137
+ operator fun Permission.not () = permissions.removeAll { it.permission == this }
138
+
139
+ override fun getPermissions (codesource : CodeSource ) = UNSUPPORTED_EMPTY_COLLECTION !!
140
+ override fun getPermissions (domain : ProtectionDomain ) = UNSUPPORTED_EMPTY_COLLECTION !!
141
+ override fun implies (domain : ProtectionDomain , permission : Permission ): Boolean {
142
+ // 0 means no info, < 0 is denied and > 0 is allowed
143
+ val result = permissions.lastOrNull { it.permission.implies(permission) }?.let {
144
+ when (it) {
145
+ is Access .Allow -> 1
146
+ is Access .Deny -> - 1
147
+ }
148
+ } ? : 0
149
+ return result > 0
150
+ }
151
+ }
0 commit comments