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