001
014
015 package com.liferay.portal.security.pacl.checker;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.security.pacl.permission.PortalServicePermission;
020 import com.liferay.portal.kernel.util.ProxyUtil;
021 import com.liferay.portal.kernel.util.ServerDetector;
022 import com.liferay.portal.kernel.util.SetUtil;
023 import com.liferay.portal.kernel.util.StringPool;
024 import com.liferay.portal.kernel.util.StringUtil;
025 import com.liferay.portal.security.pacl.PACLPolicy;
026 import com.liferay.portal.security.pacl.PACLPolicyManager;
027 import com.liferay.portal.util.ClassLoaderUtil;
028
029 import java.lang.reflect.Method;
030
031 import java.security.Permission;
032
033 import java.util.Collections;
034 import java.util.HashMap;
035 import java.util.Map;
036 import java.util.Properties;
037 import java.util.Set;
038
039
043 public class PortalServiceChecker extends BaseChecker {
044
045 public void afterPropertiesSet() {
046 initServices();
047 }
048
049 public void checkPermission(Permission permission) {
050 PortalServicePermission portalServicePermission =
051 (PortalServicePermission)permission;
052
053 String name = portalServicePermission.getName();
054 Object object = portalServicePermission.getObject();
055
056 if (name.equals(PORTAL_SERVICE_PERMISSION_DYNAMIC_QUERY)) {
057 Class<?> implClass = (Class<?>)object;
058
059 if (!hasDynamicQuery(implClass)) {
060 throwSecurityException(
061 _log,
062 "Attempted to create a dynamic query for " + implClass);
063 }
064 }
065 }
066
067 @Override
068 public AuthorizationProperty generateAuthorizationProperty(
069 Object... arguments) {
070
071 if ((arguments == null) || (arguments.length == 0)) {
072 return null;
073 }
074
075 Object object = null;
076 Method method = null;
077
078 if (arguments[0] instanceof Permission) {
079 PortalServicePermission portalServicePermission =
080 (PortalServicePermission)arguments[0];
081
082 object = portalServicePermission.getObject();
083 method = portalServicePermission.getMethod();
084 }
085 else {
086 object = arguments[0];
087 method = (Method)arguments[1];
088 }
089
090 Class<?> clazz = getClass(object);
091
092 if (clazz == null) {
093 return null;
094 }
095
096 ClassLoader classLoader = ClassLoaderUtil.getClassLoader(clazz);
097
098 PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(classLoader);
099
100 String filter = "[portal]";
101
102 if (paclPolicy != null) {
103 filter =
104 StringPool.OPEN_BRACKET + paclPolicy.getServletContextName() +
105 StringPool.CLOSE_BRACKET;
106 }
107
108 String className = getInterfaceName(clazz.getName());
109
110 String methodName = method.getName();
111
112 if (methodName.equals("invokeMethod")) {
113 methodName = (String)arguments[0];
114 }
115
116 AuthorizationProperty authorizationProperty =
117 new AuthorizationProperty();
118
119 authorizationProperty.setKey("security-manager-services" + filter);
120 authorizationProperty.setValue(
121 className + StringPool.POUND + methodName);
122
123 return authorizationProperty;
124 }
125
126 public boolean hasService(
127 Object object, Method method, Object[] arguments) {
128
129 Class<?> clazz = getClass(object);
130
131 if (clazz == null) {
132 return false;
133 }
134
135 ClassLoader classLoader = ClassLoaderUtil.getClassLoader(clazz);
136
137 PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(classLoader);
138
139 if (paclPolicy == getPACLPolicy()) {
140 return true;
141 }
142
143 Set<String> services = getServices(paclPolicy);
144
145 String className = getInterfaceName(clazz.getName());
146
147 if (services.contains(className)) {
148 return true;
149 }
150
151 String methodName = method.getName();
152
153 if (methodName.equals("invokeMethod")) {
154 methodName = (String)arguments[0];
155 }
156
157 if (services.contains(
158 className.concat(StringPool.POUND).concat(methodName))) {
159
160 return true;
161 }
162
163 return false;
164 }
165
166 protected Class<?> getClass(Object object) {
167 Class<?> clazz = object.getClass();
168
169 if (ProxyUtil.isProxyClass(clazz)) {
170 Class<?>[] interfaces = clazz.getInterfaces();
171
172 if (interfaces.length == 0) {
173 return null;
174 }
175
176 clazz = interfaces[0];
177 }
178
179 return clazz;
180 }
181
182 protected String getInterfaceName(String className) {
183 int pos = className.indexOf(".impl.");
184
185 if (pos != -1) {
186 className =
187 className.substring(0, pos + 1) + className.substring(pos + 6);
188 }
189
190 if (className.endsWith("Impl")) {
191 className = className.substring(0, className.length() - 4);
192 }
193
194 return className;
195 }
196
197 protected Set<String> getServices(PACLPolicy paclPolicy) {
198 Set<String> services = null;
199
200 if (paclPolicy == null) {
201 services = _portalServices;
202 }
203 else {
204 services = _pluginServices.get(paclPolicy.getServletContextName());
205 }
206
207 return services;
208 }
209
210 protected boolean hasDynamicQuery(Class<?> clazz) {
211 ClassLoader classLoader = ClassLoaderUtil.getClassLoader(clazz);
212
213 PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(classLoader);
214
215 if (paclPolicy == getPACLPolicy()) {
216 return true;
217 }
218
219
226
227 return false;
228 }
229
230 protected void initServices() {
231 Properties properties = getProperties();
232
233 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
234 String key = (String)entry.getKey();
235 String value = (String)entry.getValue();
236
237 if (!key.startsWith("security-manager-services[")) {
238 continue;
239 }
240
241 int x = key.indexOf("[");
242 int y = key.indexOf("]", x);
243
244 String servicesServletContextName = key.substring(x + 1, y);
245
246 Set<String> services = SetUtil.fromArray(StringUtil.split(value));
247
248 if (servicesServletContextName.equals(
249 _PORTAL_SERVLET_CONTEXT_NAME)) {
250
251 _portalServices = services;
252
253 touchServices(_portalServices);
254 }
255 else {
256 _pluginServices.put(servicesServletContextName, services);
257 }
258 }
259 }
260
261 protected void touchService(String service) {
262 String className = service;
263
264 if (!className.contains(".service.")) {
265 return;
266 }
267
268 String methodName = null;
269
270 if (className.contains(".service.persistence.") &&
271 (className.endsWith("Persistence") ||
272 className.contains("Persistence#"))) {
273
274 methodName = "getPersistence";
275 }
276 else if (className.endsWith("Service") ||
277 className.contains("Service#")) {
278
279 methodName = "getService";
280 }
281 else {
282 _log.error("Invalid service " + service);
283
284 return;
285 }
286
287 int pos = className.indexOf(StringPool.POUND);
288
289 if (pos != -1) {
290 className = className.substring(0, pos);
291 }
292
293 if (className.endsWith("Persistence")) {
294 className = className.substring(0, className.length() - 11);
295 }
296
297 className += "Util";
298
299 if (_log.isDebugEnabled()) {
300 _log.debug("Invoking " + className + "#" + methodName);
301 }
302
303
304
305 ClassLoader classLoader = getCommonClassLoader();
306
307 if (ServerDetector.isGeronimo() || ServerDetector.isJBoss()) {
308 classLoader = getPortalClassLoader();
309 }
310
311 try {
312 Class<?> clazz = classLoader.loadClass(className);
313
314 Method method = clazz.getMethod(methodName);
315
316 method.invoke(clazz);
317 }
318 catch (Exception e) {
319 _log.error(e, e);
320 }
321 }
322
323 protected void touchServices(Set<String> services) {
324 for (String service : services) {
325 touchService(service);
326 }
327 }
328
329 private static final String _PORTAL_SERVLET_CONTEXT_NAME = "portal";
330
331 private static Log _log = LogFactoryUtil.getLog(PortalServiceChecker.class);
332
333 private Map<String, Set<String>> _pluginServices =
334 new HashMap<String, Set<String>>();
335 private Set<String> _portalServices = Collections.emptySet();
336
337 }