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.executor.PortalExecutorManagerUtil;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.messaging.BaseAsyncDestination;
021    import com.liferay.portal.kernel.security.pacl.permission.PortalRuntimePermission;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.Validator;
025    
026    import java.security.Permission;
027    
028    import java.util.Set;
029    import java.util.TreeSet;
030    
031    import sun.reflect.Reflection;
032    
033    /**
034     * @author Brian Wing Shun Chan
035     */
036    public class PortalRuntimeChecker extends BaseChecker {
037    
038            public void afterPropertiesSet() {
039                    initExpandoBridgeClassNames();
040                    initGetBeanPropertyClassNames();
041                    initSearchEngineIds();
042                    initSetBeanPropertyClassNames();
043                    initThreadPoolExecutorNames();
044            }
045    
046            public void checkPermission(Permission permission) {
047                    PortalRuntimePermission portalRuntimePermission =
048                            (PortalRuntimePermission)permission;
049    
050                    String name = portalRuntimePermission.getName();
051                    Object subject = portalRuntimePermission.getSubject();
052                    String property = GetterUtil.getString(
053                            portalRuntimePermission.getProperty());
054    
055                    if (name.equals(PORTAL_RUNTIME_PERMISSION_EXPANDO_BRIDGE)) {
056                            String className = (String)subject;
057    
058                            if (!_expandoBridgeClassNames.contains(className)) {
059                                    throwSecurityException(
060                                            _log, "Attempted to get Expando bridge on " + className);
061                            }
062                    }
063                    else if (name.equals(PORTAL_RUNTIME_PERMISSION_GET_BEAN_PROPERTY)) {
064                            Class<?> clazz = (Class<?>)subject;
065    
066                            if (!hasGetBeanProperty(clazz, property)) {
067                                    if (Validator.isNotNull(property)) {
068                                            throwSecurityException(
069                                                    _log,
070                                                    "Attempted to get bean property " + property + " on " +
071                                                            clazz);
072                                    }
073                                    else {
074                                            throwSecurityException(
075                                                    _log, "Attempted to get bean property on " + clazz);
076                                    }
077                            }
078                    }
079                    else if (name.equals(PORTAL_RUNTIME_PERMISSION_SEARCH_ENGINE)) {
080                            String searchEngineId = (String)subject;
081    
082                            if (!_searchEngineIds.contains(searchEngineId)) {
083                                    throwSecurityException(
084                                            _log, "Attempted to get search engine " + searchEngineId);
085                            }
086                    }
087                    else if (name.equals(PORTAL_RUNTIME_PERMISSION_SET_BEAN_PROPERTY)) {
088                            Class<?> clazz = (Class<?>)subject;
089    
090                            if (!hasSetBeanProperty(clazz, property)) {
091                                    if (Validator.isNotNull(property)) {
092                                            throwSecurityException(
093                                                    _log,
094                                                    "Attempted to set bean property " + property + " on " +
095                                                            clazz);
096                                    }
097                                    else {
098                                            throwSecurityException(
099                                                    _log, "Attempted to set bean property on " + clazz);
100                                    }
101                            }
102                    }
103                    else if (name.equals(PORTAL_RUNTIME_PERMISSION_THREAD_POOL_EXECUTOR)) {
104                            String threadPoolExecutorName = (String)subject;
105    
106                            if (!_threadPoolExecutorNames.contains(threadPoolExecutorName)) {
107                                    throwSecurityException(
108                                            _log,
109                                            "Attempted to modify thread pool executor " +
110                                                    threadPoolExecutorName);
111                            }
112                    }
113            }
114    
115            protected boolean hasGetBeanProperty(Class<?> clazz, String property) {
116                    String className = clazz.getName();
117    
118                    if (_getBeanPropertyClassNames.contains(className)) {
119                            return true;
120                    }
121    
122                    if (Validator.isNotNull(property)) {
123                            if (_getBeanPropertyClassNames.contains(
124                                            className.concat(StringPool.POUND).concat(property))) {
125    
126                                    return true;
127                            }
128                    }
129    
130                    if (clazz == PortalExecutorManagerUtil.class) {
131                            Class<?> callerClass10 = Reflection.getCallerClass(10);
132    
133                            if (callerClass10 == BaseAsyncDestination.class) {
134                                    return true;
135                            }
136                    }
137    
138                    return false;
139            }
140    
141            protected boolean hasSetBeanProperty(Class<?> clazz, String property) {
142                    String className = clazz.getName();
143    
144                    if (_setBeanPropertyClassNames.contains(className)) {
145                            return true;
146                    }
147    
148                    if (Validator.isNotNull(property)) {
149                            if (_setBeanPropertyClassNames.contains(
150                                            className.concat(StringPool.POUND).concat(property))) {
151    
152                                    return true;
153                            }
154                    }
155    
156                    return false;
157            }
158    
159            protected void initExpandoBridgeClassNames() {
160                    _expandoBridgeClassNames = getPropertySet(
161                            "security-manager-expando-bridge");
162    
163                    if (_log.isDebugEnabled()) {
164                            Set<String> classNames = new TreeSet<String>(
165                                    _expandoBridgeClassNames);
166    
167                            for (String className : classNames) {
168                                    _log.debug("Allowing Expando bridge on class " + className);
169                            }
170                    }
171            }
172    
173            protected void initGetBeanPropertyClassNames() {
174                    _getBeanPropertyClassNames = getPropertySet(
175                            "security-manager-get-bean-property");
176    
177                    if (_log.isDebugEnabled()) {
178                            Set<String> classNames = new TreeSet<String>(
179                                    _getBeanPropertyClassNames);
180    
181                            for (String className : classNames) {
182                                    _log.debug("Allowing get bean property on class " + className);
183                            }
184                    }
185            }
186    
187            protected void initSearchEngineIds() {
188                    _searchEngineIds = getPropertySet("security-manager-search-engine-ids");
189    
190                    if (_log.isDebugEnabled()) {
191                            Set<String> searchEngineIds = new TreeSet<String>(_searchEngineIds);
192    
193                            for (String searchEngineId : searchEngineIds) {
194                                    _log.debug("Allowing search engine " + searchEngineId);
195                            }
196                    }
197            }
198    
199            protected void initSetBeanPropertyClassNames() {
200                    _setBeanPropertyClassNames = getPropertySet(
201                            "security-manager-set-bean-property");
202    
203                    if (_log.isDebugEnabled()) {
204                            Set<String> classNames = new TreeSet<String>(
205                                    _setBeanPropertyClassNames);
206    
207                            for (String className : classNames) {
208                                    _log.debug("Allowing set bean property on class " + className);
209                            }
210                    }
211            }
212    
213            protected void initThreadPoolExecutorNames() {
214                    _threadPoolExecutorNames = getPropertySet(
215                            "security-manager-thread-pool-executor-names");
216    
217                    if (_log.isDebugEnabled()) {
218                            Set<String> threadPoolExecutorNames = new TreeSet<String>(
219                                    _threadPoolExecutorNames);
220    
221                            for (String threadPoolExecutorName : threadPoolExecutorNames) {
222                                    _log.debug(
223                                            "Allowing thread pool executor " + threadPoolExecutorName);
224                            }
225                    }
226            }
227    
228            private static Log _log = LogFactoryUtil.getLog(PortalRuntimeChecker.class);
229    
230            private Set<String> _expandoBridgeClassNames;
231            private Set<String> _getBeanPropertyClassNames;
232            private Set<String> _searchEngineIds;
233            private Set<String> _setBeanPropertyClassNames;
234            private Set<String> _threadPoolExecutorNames;
235    
236    }