001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.proxiedcontent; 017 018import java.util.HashMap; 019import java.util.Map; 020 021import org.apache.avalon.framework.parameters.Parameters; 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.cocoon.acting.ServiceableAction; 025import org.apache.cocoon.environment.ObjectModelHelper; 026import org.apache.cocoon.environment.Redirector; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.environment.Session; 029import org.apache.cocoon.environment.SourceResolver; 030import org.jasig.cas.client.proxy.Cas20ProxyRetriever; 031import org.jasig.cas.client.util.AbstractCasFilter; 032import org.jasig.cas.client.validation.Assertion; 033 034import org.ametys.core.authentication.CredentialProvider; 035import org.ametys.core.user.population.UserPopulation; 036import org.ametys.core.user.population.UserPopulationDAO; 037import org.ametys.core.util.SessionAttributeProvider; 038import org.ametys.core.util.URIUtils; 039import org.ametys.plugins.extrausermgt.authentication.cas.AmetysCas20ProxyReceivingTicketValidationFilter; 040import org.ametys.plugins.extrausermgt.authentication.cas.CASCredentialProvider; 041import org.ametys.web.repository.page.ZoneItem; 042 043/** 044 * Get the page url to integrate 045 */ 046public class GetUrlAction extends ServiceableAction 047{ 048 /** The DAO for user populations */ 049 protected UserPopulationDAO _userPopulationDAO; 050 /** The session attribute provider */ 051 protected SessionAttributeProvider _sessionAttributeProvider; 052 053 @Override 054 public void service(ServiceManager smanager) throws ServiceException 055 { 056 super.service(manager); 057 _sessionAttributeProvider = (SessionAttributeProvider) smanager.lookup(SessionAttributeProvider.ROLE); 058 _userPopulationDAO = (UserPopulationDAO) smanager.lookup(UserPopulationDAO.ROLE); 059 } 060 061 @Override 062 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 063 { 064 Map<String, String> result = new HashMap<>(); 065 066 Request request = ObjectModelHelper.getRequest(objectModel); 067 068 String url = request.getParameter("url"); 069 String server = request.getParameter("server"); 070 String isForm = request.getParameter("isForm"); 071 String baseUrl = Utils.normalizeUrl(source); 072 String baseHost = Utils.getRemoteHostFromUrl(baseUrl); 073 String remoteHost; 074 String completeUrl = ""; 075 076 if (url == null) 077 { 078 url = source; 079 } 080 if (server == null) 081 { 082 server = source; 083 } 084 085 url = Utils.normalizeUrl(url); 086 server = Utils.normalizeUrl(server); 087 088 remoteHost = Utils.getRemoteHostFromUrl(url); 089 090 if (baseHost.equals(remoteHost)) 091 { 092 if (isForm != null) 093 { 094 result.put("queryString", "?" + request.getQueryString()); 095 } 096 097 completeUrl = url.substring(0, url.lastIndexOf("/") + 1); 098 099 result.put("url", url); 100 result.put("server", server); 101 result.put("remote-server", remoteHost); 102 result.put("complete-url", completeUrl); 103 ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName()); 104 result.put("zoneitemid", zoneItem.getId()); 105 106 if (zoneItem.getServiceParameters().getValueOrDefault("cas", false)) 107 { 108 _addCasProxyTicketInUrl(request, url, result); 109 } 110 111 return result; 112 } 113 else 114 { 115 getLogger().error("The specified page '" + url + "' is not on the same host than the base page, and therefore could not be proxified."); 116 return null; 117 } 118 } 119 120 private void _addCasProxyTicketInUrl(Request request, String url, Map<String, String> result) 121 { 122 String proxyTicket = null; 123 124 // Case BO: try to get a proxy ticket from the assertion in the current session 125 Session session = request.getSession(false); 126 if (session != null) 127 { 128 Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); 129 if (assertion != null) 130 { 131 proxyTicket = assertion.getPrincipal().getProxyTicketFor(url); 132 } 133 } 134 135 // Case FO request 136 if ("true".equals(request.getHeader("X-Ametys-FO"))) 137 { 138 proxyTicket = _sessionAttributeProvider.getSessionAttribute(AmetysCas20ProxyReceivingTicketValidationFilter.SESSION_ATTRIBUTE_PROXY_GRANTING_TICKET) 139 .filter(String.class::isInstance) 140 .map(String.class::cast) 141 .map(proxyGrantingTicket -> { 142 String populationId = request.getHeader("X-Ametys-FO-Population"); 143 UserPopulation population = _userPopulationDAO.getUserPopulation(populationId); 144 145 if (population != null) 146 { 147 String cpId = request.getHeader("X-Ametys-FO-Credential-Provider"); 148 CredentialProvider credentialProvider = population.getCredentialProvider(cpId); 149 if (credentialProvider instanceof CASCredentialProvider) 150 { 151 String casUrl = (String) credentialProvider.getParameterValues().get(CASCredentialProvider.PARAM_SERVER_URL); 152 return new Cas20ProxyRetriever(casUrl, "UTF-8", null).getProxyTicketIdFor(proxyGrantingTicket, url); 153 } 154 } 155 return null; 156 }) 157 .orElse(null); 158 } 159 160 // If proxy ticket was found, change url and append the ticket 161 if (proxyTicket != null) 162 { 163 StringBuilder urlWithTicket = new StringBuilder(url); 164 urlWithTicket.append(!url.contains("?") ? "?" : "&") 165 .append("ticket=") 166 .append(URIUtils.encodeParameter(proxyTicket)); 167 result.put("url", urlWithTicket.toString()); 168 } 169 else 170 { 171 getLogger().warn(String.format("The application was unable to retrieve a proxy ticket from CAS for target service '%s'", url)); 172 } 173 } 174}