001
014
015 package com.liferay.portlet;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.portlet.ActionResult;
022 import com.liferay.portal.kernel.portlet.PortletContainer;
023 import com.liferay.portal.kernel.portlet.PortletContainerException;
024 import com.liferay.portal.kernel.portlet.PortletContainerUtil;
025 import com.liferay.portal.kernel.portlet.PortletModeFactory;
026 import com.liferay.portal.kernel.resiliency.spi.SPIUtil;
027 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
028 import com.liferay.portal.kernel.servlet.HttpHeaders;
029 import com.liferay.portal.kernel.servlet.TempAttributesServletRequest;
030 import com.liferay.portal.kernel.struts.LastPath;
031 import com.liferay.portal.kernel.util.ArrayUtil;
032 import com.liferay.portal.kernel.util.GetterUtil;
033 import com.liferay.portal.kernel.util.ParamUtil;
034 import com.liferay.portal.kernel.util.StringUtil;
035 import com.liferay.portal.kernel.util.Validator;
036 import com.liferay.portal.model.Group;
037 import com.liferay.portal.model.Layout;
038 import com.liferay.portal.model.LayoutTypePortlet;
039 import com.liferay.portal.model.Portlet;
040 import com.liferay.portal.security.auth.AuthTokenUtil;
041 import com.liferay.portal.security.auth.PrincipalException;
042 import com.liferay.portal.security.permission.ActionKeys;
043 import com.liferay.portal.security.permission.PermissionChecker;
044 import com.liferay.portal.security.permission.PermissionThreadLocal;
045 import com.liferay.portal.service.permission.GroupPermissionUtil;
046 import com.liferay.portal.service.permission.LayoutPermissionUtil;
047 import com.liferay.portal.service.permission.LayoutPrototypePermissionUtil;
048 import com.liferay.portal.service.permission.LayoutSetPrototypePermissionUtil;
049 import com.liferay.portal.service.permission.OrganizationPermissionUtil;
050 import com.liferay.portal.service.permission.PortletPermissionUtil;
051 import com.liferay.portal.theme.ThemeDisplay;
052 import com.liferay.portal.util.PortalUtil;
053 import com.liferay.portal.util.PortletKeys;
054 import com.liferay.portal.util.PropsValues;
055 import com.liferay.portal.util.WebKeys;
056
057 import java.util.List;
058 import java.util.Map;
059
060 import javax.portlet.Event;
061 import javax.portlet.PortletMode;
062
063 import javax.servlet.RequestDispatcher;
064 import javax.servlet.http.HttpServletRequest;
065 import javax.servlet.http.HttpServletResponse;
066
067
071 @DoPrivileged
072 public class SecurityPortletContainerWrapper implements PortletContainer {
073
074 public static PortletContainer createSecurityPortletContainerWrapper(
075 PortletContainer portletContainer) {
076
077 if (!SPIUtil.isSPI()) {
078 portletContainer = new SecurityPortletContainerWrapper(
079 portletContainer);
080 }
081
082 return portletContainer;
083 }
084
085 public SecurityPortletContainerWrapper(PortletContainer portletContainer) {
086 _portletContainer = portletContainer;
087 }
088
089 @Override
090 public void preparePortlet(HttpServletRequest request, Portlet portlet)
091 throws PortletContainerException {
092
093 _portletContainer.preparePortlet(request, portlet);
094 }
095
096 @Override
097 public ActionResult processAction(
098 HttpServletRequest request, HttpServletResponse response,
099 Portlet portlet)
100 throws PortletContainerException {
101
102 try {
103 HttpServletRequest ownerLayoutRequest =
104 getOwnerLayoutRequestWrapper(request, portlet);
105
106 checkAction(ownerLayoutRequest, portlet);
107
108 return _portletContainer.processAction(request, response, portlet);
109 }
110 catch (PrincipalException pe) {
111 return processActionException(request, response, portlet, pe);
112 }
113 catch (PortletContainerException pce) {
114 throw pce;
115 }
116 catch (Exception e) {
117 throw new PortletContainerException(e);
118 }
119 }
120
121 @Override
122 public List<Event> processEvent(
123 HttpServletRequest request, HttpServletResponse response,
124 Portlet portlet, Layout layout, Event event)
125 throws PortletContainerException {
126
127 return _portletContainer.processEvent(
128 request, response, portlet, layout, event);
129 }
130
131 @Override
132 public void render(
133 HttpServletRequest request, HttpServletResponse response,
134 Portlet portlet)
135 throws PortletContainerException {
136
137 try {
138 checkRender(request, portlet);
139
140 _portletContainer.render(request, response, portlet);
141 }
142 catch (PrincipalException e) {
143 processRenderException(request, response, portlet);
144 }
145 catch (PortletContainerException e) {
146 throw e;
147 }
148 catch (Exception e) {
149 throw new PortletContainerException(e);
150 }
151 }
152
153 @Override
154 public void serveResource(
155 HttpServletRequest request, HttpServletResponse response,
156 Portlet portlet)
157 throws PortletContainerException {
158
159 try {
160 HttpServletRequest ownerLayoutRequest =
161 getOwnerLayoutRequestWrapper(request, portlet);
162
163 checkResource(ownerLayoutRequest, portlet);
164
165 _portletContainer.serveResource(request, response, portlet);
166 }
167 catch (PrincipalException pe) {
168 processServeResourceException(request, response, portlet, pe);
169 }
170 catch (PortletContainerException pce) {
171 throw pce;
172 }
173 catch (Exception e) {
174 throw new PortletContainerException(e);
175 }
176 }
177
178 protected void check(HttpServletRequest request, Portlet portlet)
179 throws Exception {
180
181 if (portlet == null) {
182 return;
183 }
184
185 if (portlet.isUndeployedPortlet()) {
186 throw new PrincipalException();
187 }
188
189 Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
190
191 if (layout.isTypeControlPanel()) {
192 isAccessAllowedToControlPanelPortlet(request, portlet);
193
194 return;
195 }
196
197 if (isAccessAllowedToLayoutPortlet(request, portlet)) {
198 PortalUtil.addPortletDefaultResource(request, portlet);
199
200 if (hasAccessPermission(request, portlet)) {
201 return;
202 }
203 }
204
205 throw new PrincipalException();
206 }
207
208 protected void checkAction(HttpServletRequest request, Portlet portlet)
209 throws Exception {
210
211 checkCSRFProtection(request, portlet);
212
213 check(request, portlet);
214 }
215
216 protected void checkCSRFProtection(
217 HttpServletRequest request, Portlet portlet)
218 throws PortalException {
219
220 if (!PropsValues.AUTH_TOKEN_CHECK_ENABLED) {
221 return;
222 }
223
224 Map<String, String> initParams = portlet.getInitParams();
225
226 boolean checkAuthToken = GetterUtil.getBoolean(
227 initParams.get("check-auth-token"), true);
228
229 if (checkAuthToken) {
230 AuthTokenUtil.check(request);
231 }
232 }
233
234 protected void checkRender(HttpServletRequest request, Portlet portlet)
235 throws Exception {
236
237 check(request, portlet);
238 }
239
240 protected void checkResource(HttpServletRequest request, Portlet portlet)
241 throws Exception {
242
243 check(request, portlet);
244 }
245
246 protected String getOriginalURL(HttpServletRequest request) {
247 LastPath lastPath = (LastPath)request.getAttribute(WebKeys.LAST_PATH);
248
249 if (lastPath == null) {
250 return String.valueOf(request.getRequestURI());
251 }
252
253 String portalURL = PortalUtil.getPortalURL(request);
254
255 return portalURL.concat(
256 lastPath.getContextPath()).concat(lastPath.getPath());
257 }
258
259 protected HttpServletRequest getOwnerLayoutRequestWrapper(
260 HttpServletRequest request, Portlet portlet)
261 throws Exception {
262
263 if (!PropsValues.PORTLET_EVENT_DISTRIBUTION_LAYOUT_SET ||
264 PropsValues.PORTLET_CROSS_LAYOUT_INVOCATION_MODE.equals("render")) {
265
266 return request;
267 }
268
269 Layout ownerLayout = null;
270 LayoutTypePortlet ownerLayoutTypePortlet = null;
271
272 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
273 WebKeys.THEME_DISPLAY);
274
275 Layout requestLayout = (Layout)request.getAttribute(WebKeys.LAYOUT);
276
277 List<LayoutTypePortlet> layoutTypePortlets =
278 PortletContainerUtil.getLayoutTypePortlets(requestLayout);
279
280 for (LayoutTypePortlet layoutTypePortlet : layoutTypePortlets) {
281 if (layoutTypePortlet.hasPortletId(portlet.getPortletId())) {
282 ownerLayoutTypePortlet = layoutTypePortlet;
283
284 ownerLayout = layoutTypePortlet.getLayout();
285
286 break;
287 }
288 }
289
290 if (ownerLayout == null) {
291 return request;
292 }
293
294 Layout currentLayout = themeDisplay.getLayout();
295
296 if (currentLayout.equals(ownerLayout)) {
297 return request;
298 }
299
300 ThemeDisplay themeDisplayClone = (ThemeDisplay)themeDisplay.clone();
301
302 themeDisplayClone.setLayout(ownerLayout);
303 themeDisplayClone.setLayoutTypePortlet(ownerLayoutTypePortlet);
304
305 TempAttributesServletRequest tempAttributesServletRequest =
306 new TempAttributesServletRequest(request);
307
308 tempAttributesServletRequest.setTempAttribute(
309 WebKeys.LAYOUT, ownerLayout);
310 tempAttributesServletRequest.setTempAttribute(
311 WebKeys.THEME_DISPLAY, themeDisplayClone);
312
313 return tempAttributesServletRequest;
314 }
315
316 protected boolean hasAccessPermission(
317 HttpServletRequest request, Portlet portlet)
318 throws PortalException, SystemException {
319
320 PermissionChecker permissionChecker =
321 PermissionThreadLocal.getPermissionChecker();
322
323 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
324 WebKeys.THEME_DISPLAY);
325
326 Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
327
328 PortletMode portletMode = PortletModeFactory.getPortletMode(
329 ParamUtil.getString(request, "p_p_mode"));
330
331 return PortletPermissionUtil.hasAccessPermission(
332 permissionChecker, themeDisplay.getScopeGroupId(), layout, portlet,
333 portletMode);
334 }
335
336 protected void isAccessAllowedToControlPanelPortlet(
337 HttpServletRequest request, Portlet portlet)
338 throws PortalException, SystemException {
339
340 PermissionChecker permissionChecker =
341 PermissionThreadLocal.getPermissionChecker();
342
343 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
344 WebKeys.THEME_DISPLAY);
345
346 if (PortletPermissionUtil.hasControlPanelAccessPermission(
347 permissionChecker, themeDisplay.getScopeGroupId(), portlet)) {
348
349 return;
350 }
351
352 if (isAccessGrantedByRuntimePortlet(request, portlet)) {
353 return;
354 }
355
356 if (isAccessGrantedByPortletAuthenticationToken(request, portlet)) {
357 return;
358 }
359
360 throw new PrincipalException();
361 }
362
363 protected boolean isAccessAllowedToLayoutPortlet(
364 HttpServletRequest request, Portlet portlet)
365 throws PortalException, SystemException {
366
367 if (isAccessGrantedByRuntimePortlet(request, portlet)) {
368 return true;
369 }
370
371 if (isAccessGrantedByPortletOnPage(request, portlet)) {
372 return true;
373 }
374
375 if (isLayoutConfigurationAllowed(request, portlet)) {
376 return true;
377 }
378
379 if (isAccessGrantedByPortletAuthenticationToken(request, portlet)) {
380 return true;
381 }
382
383 return false;
384 }
385
386 protected boolean isAccessGrantedByPortletAuthenticationToken(
387 HttpServletRequest request, Portlet portlet) {
388
389 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
390 WebKeys.THEME_DISPLAY);
391
392 String portletId = portlet.getPortletId();
393
394 if (!portlet.isAddDefaultResource()) {
395 return false;
396 }
397
398 if (!PropsValues.PORTLET_ADD_DEFAULT_RESOURCE_CHECK_ENABLED) {
399 return true;
400 }
401
402 String namespace = PortalUtil.getPortletNamespace(portletId);
403
404 String strutsAction = ParamUtil.getString(
405 request, namespace + "struts_action");
406
407 if (Validator.isNull(strutsAction)) {
408 strutsAction = ParamUtil.getString(request, "struts_action");
409 }
410
411 String requestPortletAuthenticationToken = ParamUtil.getString(
412 request, "p_p_auth");
413
414 if (Validator.isNull(requestPortletAuthenticationToken)) {
415 HttpServletRequest originalRequest =
416 PortalUtil.getOriginalServletRequest(request);
417
418 requestPortletAuthenticationToken = ParamUtil.getString(
419 originalRequest, "p_p_auth");
420 }
421
422 if (AuthTokenUtil.isValidPortletInvocationToken(
423 request, themeDisplay.getPlid(), portletId, strutsAction,
424 requestPortletAuthenticationToken)) {
425
426 return true;
427 }
428
429 return false;
430 }
431
432 protected boolean isAccessGrantedByPortletOnPage(
433 HttpServletRequest request, Portlet portlet)
434 throws PortalException, SystemException {
435
436 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
437 WebKeys.THEME_DISPLAY);
438
439 Layout layout = themeDisplay.getLayout();
440
441 String portletId = portlet.getPortletId();
442
443 if (layout.isTypePanel() &&
444 isPanelSelectedPortlet(themeDisplay, portletId)) {
445
446 return true;
447 }
448
449 LayoutTypePortlet layoutTypePortlet =
450 themeDisplay.getLayoutTypePortlet();
451
452 if ((layoutTypePortlet != null) &&
453 layoutTypePortlet.hasPortletId(portletId)) {
454
455 return true;
456 }
457
458 return false;
459 }
460
461 protected boolean isAccessGrantedByRuntimePortlet(
462 HttpServletRequest request, Portlet portlet) {
463
464 Boolean renderPortletResource = (Boolean)request.getAttribute(
465 WebKeys.RENDER_PORTLET_RESOURCE);
466
467 if (renderPortletResource != null) {
468 boolean runtimePortlet = renderPortletResource.booleanValue();
469
470 if (runtimePortlet) {
471 return true;
472 }
473 }
474
475 return false;
476 }
477
478 protected boolean isLayoutConfigurationAllowed(
479 HttpServletRequest request, Portlet portlet)
480 throws PortalException, SystemException {
481
482 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
483 WebKeys.THEME_DISPLAY);
484
485 if (!themeDisplay.isSignedIn()) {
486 return false;
487 }
488
489 String portletId = portlet.getPortletId();
490
491 if (!portletId.equals(PortletKeys.LAYOUTS_ADMIN)) {
492 return false;
493 }
494
495 PermissionChecker permissionChecker =
496 themeDisplay.getPermissionChecker();
497
498 Layout layout = themeDisplay.getLayout();
499
500 Group group = layout.getGroup();
501
502 if (group.isSite()) {
503 if (LayoutPermissionUtil.contains(
504 permissionChecker, layout, ActionKeys.CUSTOMIZE) ||
505 LayoutPermissionUtil.contains(
506 permissionChecker, layout, ActionKeys.UPDATE)) {
507
508 return true;
509 }
510 }
511
512 if (group.isCompany()) {
513 if (permissionChecker.isCompanyAdmin()) {
514 return true;
515 }
516 }
517 else if (group.isLayoutPrototype()) {
518 long layoutPrototypeId = group.getClassPK();
519
520 if (LayoutPrototypePermissionUtil.contains(
521 permissionChecker, layoutPrototypeId,
522 ActionKeys.UPDATE)) {
523
524 return true;
525 }
526 }
527 else if (group.isLayoutSetPrototype()) {
528 long layoutSetPrototypeId = group.getClassPK();
529
530 if (LayoutSetPrototypePermissionUtil.contains(
531 permissionChecker, layoutSetPrototypeId,
532 ActionKeys.UPDATE)) {
533
534 return true;
535 }
536 }
537 else if (group.isOrganization()) {
538 long organizationId = group.getOrganizationId();
539
540 if (OrganizationPermissionUtil.contains(
541 permissionChecker, organizationId, ActionKeys.UPDATE)) {
542
543 return true;
544 }
545 }
546 else if (group.isUserGroup()) {
547 long scopeGroupId = themeDisplay.getScopeGroupId();
548
549 if (GroupPermissionUtil.contains(
550 permissionChecker, scopeGroupId, ActionKeys.UPDATE)) {
551
552 return true;
553 }
554 }
555 else if (group.isUser()) {
556 return true;
557 }
558
559 return false;
560 }
561
562 protected boolean isPanelSelectedPortlet(
563 ThemeDisplay themeDisplay, String portletId) {
564
565 Layout layout = themeDisplay.getLayout();
566
567 String panelSelectedPortlets = layout.getTypeSettingsProperty(
568 "panelSelectedPortlets");
569
570 if (Validator.isNotNull(panelSelectedPortlets)) {
571 String[] panelSelectedPortletsArray = StringUtil.split(
572 panelSelectedPortlets);
573
574 return ArrayUtil.contains(panelSelectedPortletsArray, portletId);
575 }
576
577 return false;
578 }
579
580 protected ActionResult processActionException(
581 HttpServletRequest request, HttpServletResponse response,
582 Portlet portlet, PrincipalException e) {
583
584 if (_log.isDebugEnabled()) {
585 _log.debug(e);
586 }
587
588 String url = getOriginalURL(request);
589
590 _log.warn(
591 "Reject process action for " + url + " on " +
592 portlet.getPortletId());
593
594 return ActionResult.EMPTY_ACTION_RESULT;
595 }
596
597 protected void processRenderException(
598 HttpServletRequest request, HttpServletResponse response,
599 Portlet portlet)
600 throws PortletContainerException {
601
602 String portletContent = null;
603
604 if (portlet.isShowPortletAccessDenied()) {
605 portletContent = "/html/portal/portlet_access_denied.jsp";
606 }
607
608 try {
609 if (portletContent != null) {
610 RequestDispatcher requestDispatcher =
611 request.getRequestDispatcher(portletContent);
612
613 requestDispatcher.include(request, response);
614 }
615 }
616 catch (Exception ex) {
617 throw new PortletContainerException(ex);
618 }
619 }
620
621 protected void processServeResourceException(
622 HttpServletRequest request, HttpServletResponse response,
623 Portlet portlet, PrincipalException e) {
624
625 if (_log.isDebugEnabled()) {
626 _log.debug(e);
627 }
628
629 String url = getOriginalURL(request);
630
631 response.setHeader(
632 HttpHeaders.CACHE_CONTROL,
633 HttpHeaders.CACHE_CONTROL_NO_CACHE_VALUE);
634
635 response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
636
637 _log.warn(
638 "Reject serveResource for " + url + " on " +
639 portlet.getPortletId());
640 }
641
642 private static Log _log = LogFactoryUtil.getLog(
643 SecurityPortletContainerWrapper.class);
644
645 private PortletContainer _portletContainer;
646
647 }