001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.PACLConstants;
020    import com.liferay.portal.kernel.util.PathUtil;
021    import com.liferay.portal.kernel.util.ServerDetector;
022    import com.liferay.portal.kernel.util.Validator;
023    import com.liferay.portal.security.pacl.PACLClassLoaderUtil;
024    import com.liferay.portal.security.pacl.PACLClassUtil;
025    import com.liferay.portal.security.pacl.PACLPolicy;
026    
027    import java.util.Properties;
028    import java.util.Set;
029    
030    import sun.reflect.Reflection;
031    
032    /**
033     * @author Brian Wing Shun Chan
034     * @author Raymond Augé
035     */
036    public abstract class BaseChecker implements Checker, PACLConstants {
037    
038            public BaseChecker() {
039                    ClassLoader portalClassLoader = BaseChecker.class.getClassLoader();
040    
041                    _portalClassLoader = portalClassLoader;
042                    _commonClassLoader = portalClassLoader.getParent();
043                    _systemClassLoader = ClassLoader.getSystemClassLoader();
044            }
045    
046            public ClassLoader getClassLoader() {
047                    return _paclPolicy.getClassLoader();
048            }
049    
050            public ClassLoader getCommonClassLoader() {
051                    return _commonClassLoader;
052            }
053    
054            public PACLPolicy getPACLPolicy() {
055                    return _paclPolicy;
056            }
057    
058            public ClassLoader getPortalClassLoader() {
059                    return _portalClassLoader;
060            }
061    
062            public String getServletContextName() {
063                    return _paclPolicy.getServletContextName();
064            }
065    
066            public ClassLoader getSystemClassLoader() {
067                    return _systemClassLoader;
068            }
069    
070            public void setPACLPolicy(PACLPolicy paclPolicy) {
071                    _paclPolicy = paclPolicy;
072            }
073    
074            protected Properties getProperties() {
075                    return _paclPolicy.getProperties();
076            }
077    
078            protected String getProperty(String key) {
079                    return _paclPolicy.getProperty(key);
080            }
081    
082            protected String[] getPropertyArray(String key) {
083                    return _paclPolicy.getPropertyArray(key);
084            }
085    
086            protected boolean getPropertyBoolean(String key) {
087                    return _paclPolicy.getPropertyBoolean(key);
088            }
089    
090            protected Set<String> getPropertySet(String key) {
091                    return _paclPolicy.getPropertySet(key);
092            }
093    
094            protected boolean isJSPCompiler(String subject, String actions) {
095                    for (int i = 7;; i++) {
096                            Class<?> callerClass = Reflection.getCallerClass(i);
097    
098                            if (callerClass == null) {
099                                    return false;
100                            }
101    
102                            Boolean allowed = null;
103    
104                            String callerClassName = callerClass.getName();
105    
106                            if (ServerDetector.isGeronimo()) {
107                                    if (callerClassName.equals(_ClASS_NAME_COMPILER) ||
108                                            callerClassName.startsWith(
109                                                    _CLASS_NAME_JASPER_SERVLET_CONTEXT_CUSTOMIZER) ||
110                                            callerClassName.equals(_ClASS_NAME_TAG_HANDLER_POOL)) {
111    
112                                            String actualClassLocation = PACLClassUtil.getClassLocation(
113                                                    callerClass);
114                                            String expectedClassLocation = PathUtil.toUnixPath(
115                                                    System.getProperty("org.apache.geronimo.home.dir") +
116                                                            "/repository/org/apache/geronimo/");
117    
118                                            allowed = actualClassLocation.contains(
119                                                    expectedClassLocation);
120                                    }
121                            }
122                            else if (ServerDetector.isGlassfish()) {
123                                    if (callerClassName.equals(_ClASS_NAME_COMPILER) ||
124                                            callerClassName.equals(
125                                                    _ClASS_NAME_JSP_COMPILATION_CONTEXT)) {
126    
127                                            String classLocation = PACLClassUtil.getClassLocation(
128                                                    callerClass);
129    
130                                            allowed = classLocation.startsWith("bundle://");
131                                    }
132                            }
133                            else if (ServerDetector.isJBoss()) {
134                                    if (callerClassName.equals(_ClASS_NAME_COMPILER)) {
135                                            ClassLoader callerClassLoader =
136                                                    PACLClassLoaderUtil.getClassLoader(callerClass);
137    
138                                            String callerClassLoaderString =
139                                                    callerClassLoader.toString();
140    
141                                            allowed = callerClassLoaderString.contains(
142                                                    _MODULE_NAME_ORG_JBOSS_AS_WEB_MAIN);
143                                    }
144                            }
145                            else if (ServerDetector.isJetty()) {
146                                    if (callerClassName.equals(_ClASS_NAME_COMPILER) ||
147                                            callerClassName.equals(_ClASS_NAME_JASPER_LOADER)) {
148    
149                                            ClassLoader callerClassLoader =
150                                                    PACLClassLoaderUtil.getClassLoader(callerClass);
151    
152                                            allowed = (callerClassLoader == _commonClassLoader);
153                                    }
154                            }
155                            else if (ServerDetector.isJOnAS()) {
156                                    if (callerClassName.equals(
157                                                    _ClASS_NAME_DEFAULT_ANNOTATION_PROCESSOR) ||
158                                            callerClassName.equals(_ClASS_NAME_JASPER_LOADER) ||
159                                            callerClassName.equals(
160                                                    _ClASS_NAME_JSP_COMPILATION_CONTEXT)) {
161    
162                                            String classLocation = PACLClassUtil.getClassLocation(
163                                                    callerClass);
164    
165                                            allowed = classLocation.startsWith("bundle://");
166                                    }
167                            }
168                            else if (ServerDetector.isResin()) {
169                                    if (callerClassName.equals(_ClASS_NAME_JSP_MANAGER) ||
170                                            callerClassName.equals(_ClASS_NAME_PAGE_MANAGER)) {
171    
172                                            String actualClassLocation = PACLClassUtil.getClassLocation(
173                                                    callerClass);
174                                            String expectedClassLocation = PathUtil.toUnixPath(
175                                                    System.getProperty("resin.home") + "/lib/resin.jar!/");
176    
177                                            allowed = actualClassLocation.contains(
178                                                    expectedClassLocation);
179                                    }
180                            }
181                            else if (ServerDetector.isTomcat()) {
182                                    if (callerClassName.equals(
183                                                    _ClASS_NAME_DEFAULT_INSTANCE_MANAGER) ||
184                                            callerClassName.equals(_ClASS_NAME_COMPILER) ||
185                                            callerClassName.equals(_ClASS_NAME_TAG_HANDLER_POOL)) {
186    
187                                            ClassLoader callerClassLoader =
188                                                    PACLClassLoaderUtil.getClassLoader(callerClass);
189    
190                                            allowed = (callerClassLoader == _commonClassLoader);
191                                    }
192                            }
193                            else if (ServerDetector.isWebLogic()) {
194                                    if (callerClassName.equals(_CLASS_NAME_JSP_CLASS_LOADER) ||
195                                            callerClassName.equals(_CLASS_NAME_JSP_STUB)) {
196    
197                                            String classLocation = PACLClassUtil.getClassLocation(
198                                                    callerClass);
199    
200                                            allowed = classLocation.contains(
201                                                    "/wlserver/server/lib/weblogic.jar!/");
202                                    }
203                            }
204                            else if (ServerDetector.isWebSphere()) {
205                                    if (callerClassName.equals(
206                                                    _CLASS_NAME_JSP_EXTENSION_CLASS_LOADER) ||
207                                            callerClassName.equals(_ClASS_NAME_JSP_TRANSLATOR_UTIL)) {
208    
209                                            String classLocation = PACLClassUtil.getClassLocation(
210                                                    callerClass);
211    
212                                            return classLocation.startsWith("bundleresource://");
213                                    }
214                            }
215    
216                            if (allowed == null) {
217                                    continue;
218                            }
219    
220                            if (allowed) {
221                                    if (_log.isDebugEnabled()) {
222                                            if (Validator.isNotNull(actions)) {
223                                                    _log.debug(
224                                                            "Allowing the JSP compiler via " + callerClassName +
225                                                                    " to " + actions + " " + subject);
226                                            }
227                                            else {
228                                                    _log.debug(
229                                                            "Allowing the JSP compiler via " + callerClassName +
230                                                                    " to " + subject);
231                                            }
232                                    }
233    
234                                    return true;
235                            }
236                            else {
237                                    if (Validator.isNotNull(actions)) {
238                                            _log.error(
239                                                    "A plugin is hijacking the JSP compiler via " +
240                                                            callerClassName + " to " + actions + " " +
241                                                                    subject);
242                                    }
243                                    else {
244                                            _log.error(
245                                                    "A plugin is hijacking the JSP compiler via " +
246                                                            callerClassName + " to " + subject);
247                                    }
248    
249                                    return false;
250                            }
251                    }
252            }
253    
254            protected void throwSecurityException(Log log, String message) {
255                    if (log.isWarnEnabled()) {
256                            log.warn(message);
257                    }
258    
259                    throw new SecurityException(message);
260            }
261    
262            private static final String _ClASS_NAME_COMPILER =
263                    "org.apache.jasper.compiler.Compiler";
264    
265            private static final String _ClASS_NAME_DEFAULT_ANNOTATION_PROCESSOR =
266                    "org.apache.catalina.util.DefaultAnnotationProcessor";
267    
268            private static final String _ClASS_NAME_DEFAULT_INSTANCE_MANAGER =
269                    "org.apache.catalina.core.DefaultInstanceManager";
270    
271            private static final String _ClASS_NAME_JASPER_LOADER =
272                    "org.apache.jasper.servlet.JasperLoader";
273    
274            private static final String _CLASS_NAME_JASPER_SERVLET_CONTEXT_CUSTOMIZER =
275                    "org.apache.geronimo.jasper.JasperServletContextCustomizer$";
276    
277            private static final String _CLASS_NAME_JSP_CLASS_LOADER =
278                    "weblogic.servlet.jsp.JspClassLoader";
279    
280            private static final String _ClASS_NAME_JSP_COMPILATION_CONTEXT =
281                    "org.apache.jasper.JspCompilationContext";
282    
283            private static final String _CLASS_NAME_JSP_EXTENSION_CLASS_LOADER =
284                    "com.ibm.ws.jsp.webcontainerext.JSPExtensionClassLoader";
285    
286            private static final String _ClASS_NAME_JSP_MANAGER =
287                    "com.caucho.jsp.JspManager";
288    
289            private static final String _CLASS_NAME_JSP_STUB =
290                    "weblogic.servlet.jsp.JspStub";
291    
292            private static final String _ClASS_NAME_JSP_TRANSLATOR_UTIL =
293                    "com.ibm.ws.jsp.translator.utils.JspTranslatorUtil";
294    
295            private static final String _ClASS_NAME_PAGE_MANAGER =
296                    "com.caucho.jsp.PageManager";
297    
298            private static final String _ClASS_NAME_TAG_HANDLER_POOL =
299                    "org.apache.jasper.runtime.TagHandlerPool";
300    
301            private static final String _MODULE_NAME_ORG_JBOSS_AS_WEB_MAIN =
302                    "org.jboss.as.web:main";
303    
304            private static Log _log = LogFactoryUtil.getLog(BaseChecker.class);
305    
306            private ClassLoader _commonClassLoader;
307            private PACLPolicy _paclPolicy;
308            private ClassLoader _portalClassLoader;
309            private ClassLoader _systemClassLoader;
310    
311    }