001
014
015 package com.liferay.portal.security.auth;
016
017 import com.liferay.portal.kernel.concurrent.ConcurrentHashSet;
018 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
019 import com.liferay.portal.kernel.util.CharPool;
020 import com.liferay.portal.kernel.util.PropsKeys;
021 import com.liferay.portal.kernel.util.SetUtil;
022 import com.liferay.portal.kernel.util.Validator;
023 import com.liferay.portal.model.Portlet;
024 import com.liferay.portal.model.PortletConstants;
025 import com.liferay.portal.service.PortletLocalServiceUtil;
026 import com.liferay.portal.util.PropsValues;
027 import com.liferay.registry.Registry;
028 import com.liferay.registry.RegistryUtil;
029 import com.liferay.registry.ServiceReference;
030 import com.liferay.registry.ServiceRegistration;
031 import com.liferay.registry.ServiceTracker;
032 import com.liferay.registry.ServiceTrackerCustomizer;
033 import com.liferay.registry.collections.StringServiceRegistrationMap;
034 import com.liferay.registry.collections.StringServiceRegistrationMapImpl;
035 import com.liferay.registry.util.StringPlus;
036 import com.liferay.util.Encryptor;
037
038 import java.util.Collections;
039 import java.util.HashMap;
040 import java.util.List;
041 import java.util.Map;
042 import java.util.Set;
043
044
048 @DoPrivileged
049 public class AuthTokenWhitelistImpl implements AuthTokenWhitelist {
050
051 public AuthTokenWhitelistImpl() {
052 resetOriginCSRFWhitelist();
053 resetPortletCSRFWhitelist();
054 resetPortletInvocationWhitelist();
055 resetPortletInvocationWhitelistActions();
056
057 Registry registry = RegistryUtil.getRegistry();
058
059 _serviceTracker = registry.trackServices(
060 registry.getFilter(
061 "(&(" + PropsKeys.AUTH_TOKEN_IGNORE_ACTIONS+"=*)" +
062 "(objectClass=java.lang.Object))"),
063 new AuthTokenIgnoreActionsServiceTrackerCustomizer());
064
065 _serviceTracker.open();
066
067 registerPortalProperty();
068 }
069
070 public void destroy() {
071 for (ServiceRegistration<Object> serviceRegistration :
072 _serviceRegistrations.values()) {
073
074 serviceRegistration.unregister();
075 }
076
077 _serviceTracker.close();
078 }
079
080 @Override
081 public Set<String> getOriginCSRFWhitelist() {
082 return _originCSRFWhitelist;
083 }
084
085 @Override
086 public Set<String> getPortletCSRFWhitelist() {
087 return _portletCSRFWhitelist;
088 }
089
090 @Override
091 public Set<String> getPortletCSRFWhitelistActions() {
092 return _portletCSRFWhitelistActions;
093 }
094
095 @Override
096 public Set<String> getPortletInvocationWhitelist() {
097 return _portletInvocationWhitelist;
098 }
099
100 @Override
101 public Set<String> getPortletInvocationWhitelistActions() {
102 return _portletInvocationWhitelistActions;
103 }
104
105 @Override
106 public boolean isOriginCSRFWhitelisted(long companyId, String origin) {
107 Set<String> whitelist = getOriginCSRFWhitelist();
108
109 for (String whitelistedOrigins : whitelist) {
110 if (origin.startsWith(whitelistedOrigins)) {
111 return true;
112 }
113 }
114
115 return false;
116 }
117
118 @Override
119 public boolean isPortletCSRFWhitelisted(
120 long companyId, String portletId, String strutsAction) {
121
122 String rootPortletId = PortletConstants.getRootPortletId(portletId);
123
124 Set<String> whitelist = getPortletCSRFWhitelist();
125
126 if (whitelist.contains(rootPortletId)) {
127 return true;
128 }
129
130 if (Validator.isNotNull(strutsAction)) {
131 Set<String> whitelistActions = getPortletCSRFWhitelistActions();
132
133 if (whitelistActions.contains(strutsAction) &&
134 isValidStrutsAction(companyId, rootPortletId, strutsAction)) {
135
136 return true;
137 }
138 }
139
140 return false;
141 }
142
143 @Override
144 public boolean isPortletInvocationWhitelisted(
145 long companyId, String portletId, String strutsAction) {
146
147 Set<String> whitelist = getPortletInvocationWhitelist();
148
149 if (whitelist.contains(portletId)) {
150 return true;
151 }
152
153 if (Validator.isNotNull(strutsAction)) {
154 Set<String> whitelistActions =
155 getPortletInvocationWhitelistActions();
156
157 if (whitelistActions.contains(strutsAction) &&
158 isValidStrutsAction(companyId, portletId, strutsAction)) {
159
160 return true;
161 }
162 }
163
164 return false;
165 }
166
167 @Override
168 public boolean isValidSharedSecret(String sharedSecret) {
169 if (Validator.isNull(sharedSecret)) {
170 return false;
171 }
172
173 if (Validator.isNull(PropsValues.AUTH_TOKEN_SHARED_SECRET)) {
174 return false;
175 }
176
177 return sharedSecret.equals(
178 Encryptor.digest(PropsValues.AUTH_TOKEN_SHARED_SECRET));
179 }
180
181 @Override
182 public Set<String> resetOriginCSRFWhitelist() {
183 _originCSRFWhitelist = SetUtil.fromArray(
184 PropsValues.AUTH_TOKEN_IGNORE_ORIGINS);
185 _originCSRFWhitelist = Collections.unmodifiableSet(
186 _originCSRFWhitelist);
187
188 return _originCSRFWhitelist;
189 }
190
191 @Override
192 public Set<String> resetPortletCSRFWhitelist() {
193 _portletCSRFWhitelist = SetUtil.fromArray(
194 PropsValues.AUTH_TOKEN_IGNORE_PORTLETS);
195 _portletCSRFWhitelist = Collections.unmodifiableSet(
196 _portletCSRFWhitelist);
197
198 return _portletCSRFWhitelist;
199 }
200
201 @Override
202 public Set<String> resetPortletInvocationWhitelist() {
203 _portletInvocationWhitelist = SetUtil.fromArray(
204 PropsValues.PORTLET_ADD_DEFAULT_RESOURCE_CHECK_WHITELIST);
205 _portletInvocationWhitelist = Collections.unmodifiableSet(
206 _portletInvocationWhitelist);
207
208 return _portletInvocationWhitelist;
209 }
210
211 @Override
212 public Set<String> resetPortletInvocationWhitelistActions() {
213 _portletInvocationWhitelistActions = SetUtil.fromArray(
214 PropsValues.PORTLET_ADD_DEFAULT_RESOURCE_CHECK_WHITELIST_ACTIONS);
215 _portletInvocationWhitelistActions = Collections.unmodifiableSet(
216 _portletInvocationWhitelistActions);
217
218 return _portletInvocationWhitelistActions;
219 }
220
221 protected boolean isValidStrutsAction(
222 long companyId, String portletId, String strutsAction) {
223
224 try {
225 Portlet portlet = PortletLocalServiceUtil.getPortletById(
226 companyId, portletId);
227
228 if (portlet == null) {
229 return false;
230 }
231
232 String strutsPath = strutsAction.substring(
233 1, strutsAction.lastIndexOf(CharPool.SLASH));
234
235 if (strutsPath.equals(portlet.getStrutsPath()) ||
236 strutsPath.equals(portlet.getParentStrutsPath())) {
237
238 return true;
239 }
240 }
241 catch (Exception e) {
242 }
243
244 return false;
245 }
246
247 protected void registerPortalProperty() {
248 Registry registry = RegistryUtil.getRegistry();
249
250 for (String authTokenIgnoreAction :
251 PropsValues.AUTH_TOKEN_IGNORE_ACTIONS) {
252
253 Map<String, Object> properties = new HashMap<>();
254
255 properties.put(
256 PropsKeys.AUTH_TOKEN_IGNORE_ACTIONS, authTokenIgnoreAction);
257 properties.put("objectClass", Object.class.getName());
258
259 ServiceRegistration<Object> serviceRegistration =
260 registry.registerService(
261 Object.class, new Object(), properties);
262
263 _serviceRegistrations.put(
264 authTokenIgnoreAction, serviceRegistration);
265 }
266 }
267
268 private Set<String> _originCSRFWhitelist;
269 private Set<String> _portletCSRFWhitelist;
270 private final Set<String> _portletCSRFWhitelistActions =
271 new ConcurrentHashSet<>();
272 private Set<String> _portletInvocationWhitelist;
273 private Set<String> _portletInvocationWhitelistActions;
274 private final StringServiceRegistrationMap<Object> _serviceRegistrations =
275 new StringServiceRegistrationMapImpl<>();
276 private final ServiceTracker<Object, Object> _serviceTracker;
277
278 private class AuthTokenIgnoreActionsServiceTrackerCustomizer
279 implements ServiceTrackerCustomizer<Object, Object> {
280
281 @Override
282 public Object addingService(ServiceReference<Object> serviceReference) {
283 List<String> authTokenIgnoreActions = StringPlus.asList(
284 serviceReference.getProperty(
285 PropsKeys.AUTH_TOKEN_IGNORE_ACTIONS));
286
287 _portletCSRFWhitelistActions.addAll(authTokenIgnoreActions);
288
289 Registry registry = RegistryUtil.getRegistry();
290
291 return registry.getService(serviceReference);
292 }
293
294 @Override
295 public void modifiedService(
296 ServiceReference<Object> serviceReference, Object object) {
297
298 removedService(serviceReference, object);
299
300 addingService(serviceReference);
301 }
302
303 @Override
304 public void removedService(
305 ServiceReference<Object> serviceReference, Object object) {
306
307 List<String> authTokenIgnoreActions = StringPlus.asList(
308 serviceReference.getProperty(
309 PropsKeys.AUTH_TOKEN_IGNORE_ACTIONS));
310
311 _portletCSRFWhitelistActions.removeAll(authTokenIgnoreActions);
312
313 Registry registry = RegistryUtil.getRegistry();
314
315 registry.ungetService(serviceReference);
316 }
317
318 }
319
320 }