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.PACLClassLoaderUtil;
026 import com.liferay.portal.security.pacl.PACLPolicy;
027 import com.liferay.portal.security.pacl.PACLPolicyManager;
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
042 public class PortalServiceChecker extends BaseChecker {
043
044 public void afterPropertiesSet() {
045 initServices();
046 }
047
048 public void checkPermission(Permission permission) {
049 PortalServicePermission portalServicePermission =
050 (PortalServicePermission)permission;
051
052 String name = portalServicePermission.getName();
053 Object object = portalServicePermission.getObject();
054
055 if (name.equals(PORTAL_SERVICE_PERMISSION_DYNAMIC_QUERY)) {
056 Class<?> implClass = (Class<?>)object;
057
058 if (!hasDynamicQuery(implClass)) {
059 throwSecurityException(
060 _log,
061 "Attempted to create a dynamic query for " + implClass);
062 }
063 }
064 }
065
066 public boolean hasService(
067 Object object, Method method, Object[] arguments) {
068
069 Class<?> clazz = object.getClass();
070
071 if (ProxyUtil.isProxyClass(clazz)) {
072 Class<?>[] interfaces = clazz.getInterfaces();
073
074 if (interfaces.length == 0) {
075 return false;
076 }
077
078 clazz = interfaces[0];
079 }
080
081 ClassLoader classLoader = PACLClassLoaderUtil.getClassLoader(clazz);
082
083 PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(classLoader);
084
085 if (paclPolicy == getPACLPolicy()) {
086 return true;
087 }
088
089 Set<String> services = getServices(paclPolicy);
090
091 String className = getInterfaceName(clazz.getName());
092
093 if (services.contains(className)) {
094 return true;
095 }
096
097 String methodName = method.getName();
098
099 if (methodName.equals("invokeMethod")) {
100 methodName = (String)arguments[0];
101 }
102
103 if (services.contains(
104 className.concat(StringPool.POUND).concat(methodName))) {
105
106 return true;
107 }
108
109 return false;
110 }
111
112 protected String getInterfaceName(String className) {
113 int pos = className.indexOf(".impl.");
114
115 if (pos != -1) {
116 className =
117 className.substring(0, pos + 1) + className.substring(pos + 6);
118 }
119
120 if (className.endsWith("Impl")) {
121 className = className.substring(0, className.length() - 4);
122 }
123
124 return className;
125 }
126
127 protected Set<String> getServices(PACLPolicy paclPolicy) {
128 Set<String> services = null;
129
130 if (paclPolicy == null) {
131 services = _portalServices;
132 }
133 else {
134 services = _pluginServices.get(paclPolicy.getServletContextName());
135 }
136
137 return services;
138 }
139
140 protected boolean hasDynamicQuery(Class<?> clazz) {
141 ClassLoader classLoader = PACLClassLoaderUtil.getClassLoader(clazz);
142
143 PACLPolicy paclPolicy = PACLPolicyManager.getPACLPolicy(classLoader);
144
145 if (paclPolicy == getPACLPolicy()) {
146 return true;
147 }
148
149
156
157 return false;
158 }
159
160 protected void initServices() {
161 Properties properties = getProperties();
162
163 for (Map.Entry<Object, Object> entry : properties.entrySet()) {
164 String key = (String)entry.getKey();
165 String value = (String)entry.getValue();
166
167 if (!key.startsWith("security-manager-services[")) {
168 continue;
169 }
170
171 int x = key.indexOf("[");
172 int y = key.indexOf("]", x);
173
174 String servicesServletContextName = key.substring(x + 1, y);
175
176 Set<String> services = SetUtil.fromArray(StringUtil.split(value));
177
178 if (servicesServletContextName.equals(
179 _PORTAL_SERVLET_CONTEXT_NAME)) {
180
181 _portalServices = services;
182
183 touchServices(_portalServices);
184 }
185 else {
186 _pluginServices.put(servicesServletContextName, services);
187 }
188 }
189 }
190
191 protected void touchService(String service) {
192 String className = service;
193
194 if (!className.contains(".service.")) {
195 return;
196 }
197
198 String methodName = null;
199
200 if (className.contains(".service.persistence.") &&
201 (className.endsWith("Persistence") ||
202 className.contains("Persistence#"))) {
203
204 methodName = "getPersistence";
205 }
206 else if (className.endsWith("Service") ||
207 className.contains("Service#")) {
208
209 methodName = "getService";
210 }
211 else {
212 _log.error("Invalid service " + service);
213
214 return;
215 }
216
217 int pos = className.indexOf(StringPool.POUND);
218
219 if (pos != -1) {
220 className = className.substring(0, pos);
221 }
222
223 if (className.endsWith("Persistence")) {
224 className = className.substring(0, className.length() - 11);
225 }
226
227 className += "Util";
228
229 if (_log.isDebugEnabled()) {
230 _log.debug("Invoking " + className + "#" + methodName);
231 }
232
233
234
235 ClassLoader classLoader = getCommonClassLoader();
236
237 if (ServerDetector.isGeronimo() || ServerDetector.isJBoss()) {
238 classLoader = getPortalClassLoader();
239 }
240
241 try {
242 Class<?> clazz = classLoader.loadClass(className);
243
244 Method method = clazz.getMethod(methodName);
245
246 method.invoke(clazz);
247 }
248 catch (Exception e) {
249 _log.error(e, e);
250 }
251 }
252
253 protected void touchServices(Set<String> services) {
254 for (String service : services) {
255 touchService(service);
256 }
257 }
258
259 private static final String _PORTAL_SERVLET_CONTEXT_NAME = "portal";
260
261 private static Log _log = LogFactoryUtil.getLog(PortalServiceChecker.class);
262
263 private Map<String, Set<String>> _pluginServices =
264 new HashMap<String, Set<String>>();
265 private Set<String> _portalServices = Collections.emptySet();
266
267 }