001
014
015 package com.liferay.portal.security.pacl;
016
017 import com.liferay.portal.kernel.util.WeakValueConcurrentHashMap;
018 import com.liferay.portal.util.Portal;
019
020 import java.lang.reflect.Field;
021
022 import java.security.AccessController;
023 import java.security.AllPermission;
024 import java.security.CodeSource;
025 import java.security.Permission;
026 import java.security.PermissionCollection;
027 import java.security.Permissions;
028 import java.security.Policy;
029 import java.security.PrivilegedActionException;
030 import java.security.PrivilegedExceptionAction;
031 import java.security.ProtectionDomain;
032 import java.security.Provider;
033
034 import java.util.ArrayList;
035 import java.util.Collections;
036 import java.util.Enumeration;
037 import java.util.List;
038 import java.util.Map;
039 import java.util.concurrent.ConcurrentHashMap;
040 import java.util.concurrent.ConcurrentMap;
041
042 import javax.servlet.Servlet;
043
044
047 public class PortalPolicy extends Policy {
048
049 public PortalPolicy(Policy policy) {
050 _policy = policy;
051
052 try {
053 _init();
054 }
055 catch (PrivilegedActionException pae) {
056 throw new IllegalStateException(
057 "Liferay needs to be able to change the accessibility of the " +
058 "'key' field in " + ProtectionDomain.class.getName() +
059 " as well as get the protection domains of classes",
060 pae.getException());
061 }
062 }
063
064 @Override
065 public Parameters getParameters() {
066 Parameters parameters = null;
067
068 if (_policy != null) {
069 parameters = _policy.getParameters();
070 }
071
072 return parameters;
073 }
074
075 @Override
076 public PermissionCollection getPermissions(CodeSource codeSource) {
077 PermissionCollection permissionCollection = null;
078
079 if (_policy != null) {
080 permissionCollection = _policy.getPermissions(codeSource);
081 }
082
083 if (permissionCollection == null) {
084 permissionCollection = new Permissions();
085 }
086
087 return permissionCollection;
088 }
089
090 @Override
091 public PermissionCollection getPermissions(
092 ProtectionDomain protectionDomain) {
093
094 if (protectionDomain == null) {
095 return new Permissions();
096 }
097
098 Object key = _getKey(protectionDomain);
099
100 PermissionCollection permissionCollection = _getPermissionCollection(
101 key);
102
103 if (permissionCollection != null) {
104 return permissionCollection;
105 }
106
107 permissionCollection = getPermissions(protectionDomain.getCodeSource());
108
109 if (permissionCollection == null) {
110 permissionCollection = new Permissions();
111 }
112
113 if (_policy != null) {
114 _addExtraPermissions(
115 permissionCollection, _policy.getPermissions(protectionDomain));
116 }
117
118 _addExtraPermissions(
119 permissionCollection, protectionDomain.getPermissions());
120
121 PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(
122 protectionDomain.getClassLoader());
123
124 if (paclPolicy != null) {
125 return new PortalPermissionCollection(
126 paclPolicy, permissionCollection);
127 }
128
129 permissionCollection.add(_allPermission);
130
131 return permissionCollection;
132 }
133
134 @Override
135 public Provider getProvider() {
136 Provider provider = null;
137
138 if (_policy != null) {
139 provider = _policy.getProvider();
140 }
141
142 return provider;
143 }
144
145 @Override
146 public String getType() {
147 String type = null;
148
149 if (_policy != null) {
150 type= _policy.getType();
151 }
152
153 return type;
154 }
155
156 @Override
157 public boolean implies(
158 ProtectionDomain protectionDomain, Permission permission) {
159
160 if (!(permission instanceof PACLUtil.Permission) &&
161 ((protectionDomain.getClassLoader() == null) ||
162 !PACLPolicyManager.isActive() ||
163 !_paclPolicy.isCheckablePermission(permission))) {
164
165 return _checkWithParentPolicy(protectionDomain, permission);
166 }
167
168 Object key = _getKey(protectionDomain);
169
170 PermissionCollection permissionCollection = _getPermissionCollection(
171 key);
172
173 if (permissionCollection != null) {
174 if (permissionCollection.implies(permission)) {
175 return _checkWithParentPolicy(protectionDomain, permission);
176 }
177 else if (_checkWithPACLPolicyPolicy(
178 protectionDomain, permission, permissionCollection)) {
179
180 return _checkWithParentPolicy(protectionDomain, permission);
181 }
182
183 return false;
184 }
185
186 permissionCollection = getPermissions(protectionDomain);
187
188 _permissionCollections.putIfAbsent(key, permissionCollection);
189
190 if (permissionCollection.implies(permission)) {
191 return _checkWithParentPolicy(protectionDomain, permission);
192 }
193 else if (_checkWithPACLPolicyPolicy(
194 protectionDomain, permission, permissionCollection)) {
195
196 return _checkWithParentPolicy(protectionDomain, permission);
197 }
198
199 return false;
200 }
201
202 @Override
203 public void refresh() {
204 if (_policy != null) {
205 _policy.refresh();
206 }
207
208 synchronized (_permissionCollections) {
209 _permissionCollections.clear();
210
211 _permissionCollections.putAll(_rootPermissionCollections);
212 }
213 }
214
215 private void _addExtraPermissions(
216 PermissionCollection permissionCollection,
217 PermissionCollection staticPermissionCollection) {
218
219 if (staticPermissionCollection == null) {
220 return;
221 }
222
223 synchronized (staticPermissionCollection) {
224 Enumeration<Permission> enumeration =
225 staticPermissionCollection.elements();
226
227 while (enumeration.hasMoreElements()) {
228 permissionCollection.add(enumeration.nextElement());
229 }
230 }
231 }
232
233 private boolean _checkWithPACLPolicyPolicy(
234 ProtectionDomain protectionDomain, Permission permission,
235 PermissionCollection permissionCollection) {
236
237 if (!(permissionCollection instanceof PortalPermissionCollection)) {
238 return false;
239 }
240
241 PortalPermissionCollection portalPermissionCollection =
242 (PortalPermissionCollection)permissionCollection;
243
244 Policy policy = portalPermissionCollection.getPolicy();
245
246 ClassLoader classLoader = portalPermissionCollection.getClassLoader();
247
248 if ((policy != null) &&
249 (classLoader == protectionDomain.getClassLoader())) {
250
251 return policy.implies(protectionDomain, permission);
252 }
253
254 return false;
255 }
256
257 private boolean _checkWithParentPolicy(
258 ProtectionDomain protectionDomain, Permission permission) {
259
260 if (_policy != null) {
261 return _policy.implies(protectionDomain, permission);
262 }
263
264 return true;
265 }
266
267 private Object _getKey(ProtectionDomain protectionDomain) {
268 try {
269 return _field.get(protectionDomain);
270 }
271 catch (Exception e) {
272 String string = protectionDomain.toString();
273
274 return string.hashCode();
275 }
276 }
277
278 private PermissionCollection _getPermissionCollection(Object key) {
279 PermissionCollection permissionCollection = _permissionCollections.get(
280 key);
281
282 if (permissionCollection == null) {
283 permissionCollection = _rootPermissionCollections.get(key);
284
285 if (permissionCollection != null) {
286 _permissionCollections.putIfAbsent(key, permissionCollection);
287 }
288 }
289
290 return permissionCollection;
291 }
292
293 private void _init() throws PrivilegedActionException {
294 _field = AccessController.doPrivileged(
295 new FieldPrivilegedExceptionAction());
296
297 List<ProtectionDomain> protectionDomains =
298 AccessController.doPrivileged(
299 new ProtectionDomainsPrivilegedExceptionAction());
300
301 PermissionCollection permissionCollection = new Permissions();
302
303 permissionCollection.add(_allPermission);
304
305 _rootPermissionCollections =
306 new ConcurrentHashMap<Object, PermissionCollection>();
307
308 for (ProtectionDomain protectionDomain : protectionDomains) {
309 _rootPermissionCollections.put(
310 _getKey(protectionDomain), permissionCollection);
311 }
312
313 _rootPermissionCollections = Collections.unmodifiableMap(
314 _rootPermissionCollections);
315 }
316
317 private static AllPermission _allPermission = new AllPermission();
318
319 private Field _field;
320 private PACLPolicy _paclPolicy = PACLPolicyManager.getDefaultPACLPolicy();
321 private ConcurrentMap<Object, PermissionCollection> _permissionCollections =
322 new WeakValueConcurrentHashMap<Object, PermissionCollection>();
323 private Policy _policy;
324
325 private Map<Object, PermissionCollection> _rootPermissionCollections;
326
327 private class FieldPrivilegedExceptionAction
328 implements PrivilegedExceptionAction<Field> {
329
330 public Field run() throws Exception {
331 Field field = ProtectionDomain.class.getDeclaredField("key");
332
333 field.setAccessible(true);
334
335 return field;
336 }
337
338 }
339
340 private class ProtectionDomainsPrivilegedExceptionAction
341 implements PrivilegedExceptionAction<List<ProtectionDomain>> {
342
343 public List<ProtectionDomain> run() throws Exception {
344 List<ProtectionDomain> protectionDomains =
345 new ArrayList<ProtectionDomain>();
346
347 Class<?> clazz = getClass();
348
349 protectionDomains.add(clazz.getProtectionDomain());
350 protectionDomains.add(Object.class.getProtectionDomain());
351 protectionDomains.add(Portal.class.getProtectionDomain());
352 protectionDomains.add(Servlet.class.getProtectionDomain());
353
354 return protectionDomains;
355 }
356
357 }
358
359 }