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.messaging.config.AbstractMessagingConfigurator;
020    import com.liferay.portal.kernel.util.JavaDetector;
021    import com.liferay.portal.kernel.util.PathUtil;
022    import com.liferay.portal.kernel.util.ServerDetector;
023    import com.liferay.portal.security.pacl.PACLClassUtil;
024    
025    import java.beans.Introspector;
026    
027    import org.hibernate.property.BasicPropertyAccessor;
028    import org.hibernate.tuple.entity.EntityTuplizerFactory;
029    import org.hibernate.util.ReflectHelper;
030    
031    import org.springframework.beans.BeanUtils;
032    import org.springframework.beans.factory.support.SimpleInstantiationStrategy;
033    import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
034    import org.springframework.util.ReflectionUtils;
035    
036    import sun.reflect.Reflection;
037    
038    /**
039     * @author Brian Wing Shun Chan
040     * @author Raymond Augé
041     */
042    public abstract class BaseReflectChecker extends BaseChecker {
043    
044            protected boolean hasReflect(String name, String actions) {
045                    /*for (int i = 6; i <= 15; i++) {
046                            System.out.println(
047                                    "Caller class " + i + " " + Reflection.getCallerClass(i));
048                    }*/
049    
050                    // JSP compiler
051    
052                    if (isJSPCompiler(name, actions)) {
053                            return true;
054                    }
055    
056                    // com.caucho.config.reflect.ReflectionAnnotatedType
057    
058                    Class<?> callerClass9 = Reflection.getCallerClass(9);
059    
060                    if (isResinReflectionAnnotatedType(callerClass9)) {
061                            logReflect(callerClass9, 9);
062    
063                            return true;
064                    }
065    
066                    // com.caucho.server.session.JavaSessionSerializer
067    
068                    if (isResinJavaSessionSerializer()) {
069                            return true;
070                    }
071    
072                    // com.liferay.portal.kernel.messaging.config.
073                    // AbstractMessagingConfigurator
074    
075                    if (callerClass9 == AbstractMessagingConfigurator.class) {
076                            logReflect(callerClass9, 9);
077    
078                            return true;
079                    }
080    
081                    // java.beans.Introspector
082    
083                    //if (JavaDetector.isOpenJDK()) {
084                            if ((callerClass9.getEnclosingClass() == Introspector.class) &&
085                                    CheckerUtil.isAccessControllerDoPrivileged(10)) {
086    
087                                    logReflect(callerClass9, 9);
088    
089                                    return true;
090                            }
091                    //}
092    
093                    // java.lang.Class
094    
095                    Class<?> callerClass7 = Reflection.getCallerClass(7);
096    
097                    if (JavaDetector.isIBM() || JavaDetector.isJDK7()) {
098                            Class<?> callerClass8 = Reflection.getCallerClass(8);
099    
100                            if ((callerClass8.getEnclosingClass() == Class.class) &&
101                                    CheckerUtil.isAccessControllerDoPrivileged(9)) {
102    
103                                    logReflect(callerClass8, 8);
104    
105                                    return true;
106                            }
107                    }
108                    else {
109                            if ((callerClass7.getEnclosingClass() == Class.class) &&
110                                    CheckerUtil.isAccessControllerDoPrivileged(8)) {
111    
112                                    logReflect(callerClass7, 7);
113    
114                                    return true;
115                            }
116                    }
117    
118                    // java.lang.Thread
119    
120                    if (JavaDetector.isJDK7() || JavaDetector.isOpenJDK()) {
121                            Class<?> callerClass10 = Reflection.getCallerClass(10);
122    
123                            if ((callerClass10.getEnclosingClass() == Thread.class) &&
124                                    CheckerUtil.isAccessControllerDoPrivileged(11)) {
125    
126                                    logReflect(callerClass10, 10);
127    
128                                    return true;
129                            }
130                    }
131                    else {
132                            if ((callerClass9.getEnclosingClass() == Thread.class) &&
133                                    CheckerUtil.isAccessControllerDoPrivileged(10)) {
134    
135                                    logReflect(callerClass9, 9);
136    
137                                    return true;
138                            }
139                    }
140    
141                    // org.apache.felix.framework.util.SecureAction
142    
143                    if (isGlassfishSecureAction(
144                                    callerClass7.getEnclosingClass()) &&
145                            CheckerUtil.isAccessControllerDoPrivileged(8)) {
146    
147                            logReflect(callerClass7, 7);
148    
149                            return true;
150                    }
151    
152                    // org.hibernate.property.BasicPropertyAccessor
153    
154                    if (callerClass9 == BasicPropertyAccessor.class) {
155                            logReflect(callerClass9, 9);
156    
157                            return true;
158                    }
159    
160                    // org.hibernate.tuple.entity.EntityTuplizerFactory
161    
162                    if (callerClass7 == EntityTuplizerFactory.class) {
163                            logReflect(callerClass7, 7);
164    
165                            return true;
166                    }
167    
168                    // org.hibernate.util.ReflectHelper
169    
170                    if (callerClass9 == ReflectHelper.class) {
171                            logReflect(callerClass9, 9);
172    
173                            return true;
174                    }
175    
176                    // org.springframework.beans.BeanUtils
177    
178                    if (callerClass9 == BeanUtils.class) {
179                            logReflect(callerClass9, 9);
180    
181                            return true;
182                    }
183    
184                    // org.springframework.beans.factory.support.SimpleInstantiationStrategy
185    
186                    if (callerClass9.getEnclosingClass() ==
187                                    SimpleInstantiationStrategy.class) {
188    
189                            logReflect(callerClass9, 9);
190    
191                            return true;
192                    }
193    
194                    // org.springframework.core.LocalVariableTableParameterNameDiscoverer
195    
196                    if (callerClass9.getEnclosingClass() ==
197                                    LocalVariableTableParameterNameDiscoverer.class) {
198    
199                            logReflect(callerClass9, 9);
200    
201                            return true;
202                    }
203    
204                    // org.springframework.util.ReflectionUtils
205    
206                    if (callerClass7 == ReflectionUtils.class) {
207                            logReflect(callerClass7, 7);
208    
209                            return true;
210                    }
211    
212                    if (callerClass9 == ReflectionUtils.class) {
213                            logReflect(callerClass9, 9);
214    
215                            return true;
216                    }
217    
218                    // weblogic.spring.monitoring.utils.AbstractApplicationContextDelegator
219    
220                    if (isWebLogicAbstractApplicationContextDelegator(callerClass9)) {
221                            logReflect(callerClass9, 9);
222    
223                            return true;
224                    }
225    
226                    // weblogic.spring.monitoring.utils.AbstractBeanDefinitionDelegator
227    
228                    if (isWebLogicAbstractBeanDefinitionDelegator(callerClass9)) {
229                            logReflect(callerClass9, 9);
230    
231                            return true;
232                    }
233    
234                    // Reject
235    
236                    if (_log.isDebugEnabled()) {
237                            _log.debug("Rejecting call stack:");
238    
239                            for (int i = 6; i < 11; i++) {
240                                    _log.debug("Frame " + i + " " + Reflection.getCallerClass(i));
241                            }
242                    }
243    
244                    return false;
245            }
246    
247            protected boolean isGlassfishSecureAction(Class<?> clazz) {
248                    if (!ServerDetector.isGlassfish()) {
249                            return false;
250                    }
251    
252                    if (clazz == null) {
253                            return false;
254                    }
255    
256                    String className = clazz.getName();
257    
258                    if (!className.equals(_CLASS_NAME_SECURE_ACTION)) {
259                            return false;
260                    }
261    
262                    String classLocation = PACLClassUtil.getClassLocation(clazz);
263    
264                    return classLocation.contains("/osgi/felix/bin/felix.jar!");
265            }
266    
267            protected boolean isResinJavaSessionSerializer() {
268                    if (!ServerDetector.isResin()) {
269                            return false;
270                    }
271    
272                    for (int i = 7;; i++) {
273                            Class<?> callerClass = Reflection.getCallerClass(i);
274    
275                            if (callerClass == null) {
276                                    return false;
277                            }
278    
279                            String callerClassName = callerClass.getName();
280    
281                            if (!callerClassName.equals(_CLASS_NAME_JAVA_SESSION_SERIALIZER)) {
282                                    continue;
283                            }
284    
285                            String actualClassLocation = PACLClassUtil.getClassLocation(
286                                    callerClass);
287                            String expectedClassLocation = PathUtil.toUnixPath(
288                                    System.getProperty("resin.home") + "/lib/resin.jar!/");
289    
290                            if (actualClassLocation.contains(expectedClassLocation)) {
291                                    logReflect(callerClass, i);
292    
293                                    return true;
294                            }
295    
296                            return false;
297                    }
298            }
299    
300            protected boolean isResinReflectionAnnotatedType(Class<?> clazz) {
301                    if (!ServerDetector.isResin()) {
302                            return false;
303                    }
304    
305                    String className = clazz.getName();
306    
307                    if (!className.equals(_CLASS_NAME_REFLECTION_ANNOTATED_TYPE)) {
308                            return false;
309                    }
310    
311                    String actualClassLocation = PACLClassUtil.getClassLocation(clazz);
312                    String expectedClassLocation = PathUtil.toUnixPath(
313                            System.getProperty("resin.home") + "/lib/resin.jar!/");
314    
315                    return actualClassLocation.contains(expectedClassLocation);
316            }
317    
318            protected boolean isWebLogicAbstractApplicationContextDelegator(
319                    Class<?> clazz) {
320    
321                    if (!ServerDetector.isWebLogic()) {
322                            return false;
323                    }
324    
325                    String className = clazz.getName();
326    
327                    if (!className.equals(
328                                    _CLASS_NAME_ABSTRACT_APPLICATION_CONTEXT_DELEGATOR)) {
329    
330                            return false;
331                    }
332    
333                    String classLocation = PACLClassUtil.getClassLocation(clazz);
334    
335                    if (classLocation.contains(
336                                    "/modules/com.bea.core.weblogic.spring.instrument_") ||
337                            classLocation.contains("/patch_jars/BUG")) {
338    
339                            return true;
340                    }
341    
342                    return false;
343            }
344    
345            protected boolean isWebLogicAbstractBeanDefinitionDelegator(
346                    Class<?> clazz) {
347    
348                    if (!ServerDetector.isWebLogic()) {
349                            return false;
350                    }
351    
352                    String className = clazz.getName();
353    
354                    if (!className.equals(_CLASS_NAME_ABSTRACT_BEAN_DEFINITION_DELEGATOR)) {
355                            return false;
356                    }
357    
358                    String classLocation = PACLClassUtil.getClassLocation(clazz);
359    
360                    if (classLocation.contains(
361                                    "/modules/com.bea.core.weblogic.spring.instrument_") ||
362                            classLocation.contains("/patch_jars/BUG")) {
363    
364                            return true;
365                    }
366    
367                    return false;
368            }
369    
370            protected void logReflect(Class<?> callerClass, int frame) {
371                    if (_log.isInfoEnabled()) {
372                            _log.info(
373                                    "Allowing frame " + frame + " with caller " + callerClass +
374                                            " to reflect");
375                    }
376            }
377    
378            private static final String _CLASS_NAME_ABSTRACT_BEAN_DEFINITION_DELEGATOR =
379                    "weblogic.spring.monitoring.utils.AbstractBeanDefinitionDelegator";
380    
381            private static final String
382                    _CLASS_NAME_ABSTRACT_APPLICATION_CONTEXT_DELEGATOR =
383                            "weblogic.spring.monitoring.utils." +
384                                    "AbstractApplicationContextDelegator";
385    
386            private static final String _CLASS_NAME_JAVA_SESSION_SERIALIZER =
387                    "com.caucho.server.session.JavaSessionSerializer";
388    
389            private static final String _CLASS_NAME_REFLECTION_ANNOTATED_TYPE =
390                    "com.caucho.config.reflect.ReflectionAnnotatedType";
391    
392            private static final String _CLASS_NAME_SECURE_ACTION =
393                    "org.apache.felix.framework.util.SecureAction";
394    
395            private static Log _log = LogFactoryUtil.getLog(BaseReflectChecker.class);
396    
397    }