From 0a90384a9c7d840e88d9636271e8393a514647a0 Mon Sep 17 00:00:00 2001 From: Leif Johansson Date: Tue, 28 Jul 2009 10:34:52 +0200 Subject: Import shibboleth ds 1.1.0 --- .../shibboleth/wayf/DiscoveryServiceHandler.html | 1016 ++++++++++++++++++++ 1 file changed, 1016 insertions(+) create mode 100644 doc/src-xref/edu/internet2/middleware/shibboleth/wayf/DiscoveryServiceHandler.html (limited to 'doc/src-xref/edu/internet2/middleware/shibboleth/wayf/DiscoveryServiceHandler.html') diff --git a/doc/src-xref/edu/internet2/middleware/shibboleth/wayf/DiscoveryServiceHandler.html b/doc/src-xref/edu/internet2/middleware/shibboleth/wayf/DiscoveryServiceHandler.html new file mode 100644 index 0000000..9f4e4ed --- /dev/null +++ b/doc/src-xref/edu/internet2/middleware/shibboleth/wayf/DiscoveryServiceHandler.html @@ -0,0 +1,1016 @@ + + + + +DiscoveryServiceHandler xref + + + +
View Javadoc
+
+1   /**
+2    * Copyright [2006] [University Corporation for Advanced Internet Development, Inc.]
+3    *
+4    * Licensed under the Apache License, Version 2.0 (the "License");
+5    * you may not use this file except in compliance with the License.
+6    * You may obtain a copy of the License at
+7    *
+8    * http://www.apache.org/licenses/LICENSE-2.0
+9    *
+10   * Unless required by applicable law or agreed to in writing, software
+11   * distributed under the License is distributed on an "AS IS" BASIS,
+12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+13   * See the License for the specific language governing permissions and
+14   * limitations under the License.
+15   */
+16  package edu.internet2.middleware.shibboleth.wayf;
+17  
+18  import java.io.IOException;
+19  import java.io.UnsupportedEncodingException;
+20  import java.net.MalformedURLException;
+21  import java.net.URL;
+22  import java.net.URLDecoder;
+23  import java.net.URLEncoder;
+24  import java.util.ArrayList;
+25  import java.util.Collection;
+26  import java.util.Comparator;
+27  import java.util.Date;
+28  import java.util.HashSet;
+29  import java.util.Hashtable;
+30  import java.util.List;
+31  import java.util.Locale;
+32  import java.util.Map;
+33  import java.util.Set;
+34  import java.util.TreeSet;
+35  
+36  import javax.servlet.RequestDispatcher;
+37  import javax.servlet.ServletException;
+38  import javax.servlet.http.HttpServletRequest;
+39  import javax.servlet.http.HttpServletResponse;
+40  
+41  import org.opensaml.saml2.common.Extensions;
+42  import org.opensaml.saml2.metadata.EntityDescriptor;
+43  import org.opensaml.saml2.metadata.RoleDescriptor;
+44  import org.opensaml.saml2.metadata.SPSSODescriptor;
+45  import org.opensaml.xml.XMLObject;
+46  import org.slf4j.Logger;
+47  import org.slf4j.LoggerFactory;
+48  import org.w3c.dom.Element;
+49  import org.w3c.dom.NodeList;
+50  
+51  import edu.internet2.middleware.shibboleth.common.ShibbolethConfigurationException;
+52  import edu.internet2.middleware.shibboleth.wayf.plugins.Plugin;
+53  import edu.internet2.middleware.shibboleth.wayf.plugins.PluginContext;
+54  import edu.internet2.middleware.shibboleth.wayf.plugins.PluginMetadataParameter;
+55  import edu.internet2.middleware.shibboleth.wayf.plugins.WayfRequestHandled;
+56  
+57  /**
+58    * Specific handler for each version of the Discovery Service. 
+59    */
+60  public class DiscoveryServiceHandler {
+61  
+62      /*
+63       * Protcol parameters - Old.
+64       */
+65      /**
+66       * Shire is the SP Assertion Consumer endpoint.
+67       */
+68      private static final String SHIRE_PARAM_NAME = "shire";
+69      /**
+70       * TargetName is where we are trying to get to.
+71       */
+72      private static final String TARGET_PARAM_NAME = "target";
+73      /**
+74       * time is to do with replay attack.
+75       */
+76      private static final String TIME_PARAM_NAME = "time";
+77      /**
+78       * This is the ID (in the metadata) of the SP.
+79       */
+80      private static final String PROVIDERID_PARAM_NAME = "providerId";
+81      
+82      /*
+83       * Protocol parameters - New
+84       */
+85      /**
+86       * The SP id.
+87       */
+88      private static final String ENTITYID_PARAM_NAME = "entityID";
+89      /**
+90       * Where to send the request back to.
+91       */
+92      private static final String RETURN_PARAM_NAME = "return";
+93      /**
+94       * "return" is an invalid attribute, so we use returnX.
+95       */
+96      private static final String RETURN_ATTRIBUTE_NAME = "returnX";
+97      /**
+98       * Alternatively the index of where to send the address back to.
+99       */
+100     private static final String RETURN_INDEX_NAME = "returnIndex";
+101     
+102     /**
+103      * What value to put the ID of the selected metadata into.
+104      */
+105     private static final String RETURNID_PARAM_NAME = "returnIDParam";
+106     
+107     /**
+108      * What returnIDParam defaults to.
+109      */
+110     private static final String RETURNID_DEFAULT_VALUE = "entityID";
+111     /**
+112      * Whether we are allowed to interact.
+113      */
+114     private static final String ISPASSIVE_PARAM_NAME = "isPassive";
+115     
+116     /**
+117      * Whether we understand this or not.
+118      */
+119     private static final String POLICY_PARAM_NAME = "policy";
+120 
+121     /**
+122      * The only policy we know about.
+123      */
+124     private static final String KNOWN_POLICY_NAME 
+125         = "urn:oasis:names:tc:SAML:profiles:SSO:idp-discoveryprotocol:single";
+126     
+127     /**
+128      * Mandatory Serialization constant.
+129      */
+130     private static final  Logger LOG = LoggerFactory.getLogger(DiscoveryServiceHandler.class.getName());
+131 
+132     /**
+133      * The location defines the last part of the URL which distinguished this handler. 
+134      */
+135     private final String location;
+136     
+137     /**
+138      * If isDefault is true then if there is a mismatch then this handler is used.  
+139      */
+140     private final boolean isDefault;
+141     
+142     /**
+143      * Config handles detailed behavior.
+144      */
+145     private final HandlerConfig config;
+146     
+147     /**
+148      * The list of all the metadata providers that this discovery handler believes in.
+149      */
+150     private final List <IdPSiteSet> siteSets;
+151     
+152     /**
+153      * The list of all the plugins that this hanlder has had configured.
+154      */
+155     private final List <Plugin> plugins;
+156     
+157     /**
+158      * Constructor to create and configure the handler.
+159      * @param config - DOM Element with configuration information.
+160      * @param federations - Supplies all known providers which will be included if so configured.
+161      * @param plugins - Supplies all known plugins which will be included if configured in. 
+162      * @param defaultConfig - The default configurations.
+163      * @throws ShibbolethConfigurationException - if we find something odd in the config file. 
+164      */
+165     protected DiscoveryServiceHandler(Element config, 
+166                                       Hashtable <String, IdPSiteSet> federations,
+167                                       Hashtable <String, Plugin> plugins, 
+168                                       HandlerConfig defaultConfig) throws ShibbolethConfigurationException
+169     {
+170         siteSets = new ArrayList <IdPSiteSet>(federations.size());
+171         this.plugins = new ArrayList <Plugin>(plugins.size());
+172 
+173         //
+174         // Collect the Configuration from the XML
+175         //
+176         
+177         this.config = new HandlerConfig(config, defaultConfig);
+178         
+179         location = config.getAttribute("location");
+180         
+181         if (location == null || location.equals("")) {
+182                 
+183                 LOG.error("DiscoveryService must have a location specified");
+184                 throw new ShibbolethConfigurationException("DiscoveryService must have a location specified");  
+185         }
+186         
+187         //
+188         // Is this the default WAYF?
+189         //
+190         
+191         String attribute = config.getAttribute("default");
+192         if (attribute != null && !attribute.equals("")) {
+193                 isDefault = Boolean.valueOf(attribute).booleanValue();
+194         } else {
+195                 isDefault = true;
+196         }
+197         
+198         //
+199         // Which federations (sitesets) do we care about?
+200         //
+201         
+202         NodeList list = config.getElementsByTagName("Federation");
+203                 
+204         for (int i = 0; i < list.getLength(); i++ ) {
+205                     
+206             attribute = ((Element) list.item(i)).getAttribute("identifier");
+207                     
+208                 IdPSiteSet siteset = federations.get(attribute);
+209                 
+210                 if (siteset == null) {
+211                     LOG.error("Handler " + location + ": could not find metadata for <Federation> with identifier " + attribute + ".");
+212                     throw new ShibbolethConfigurationException(
+213                            "Handler " + location + ": could not find metadata for  <Federation> identifier " + attribute + ".");
+214                 }
+215                 
+216                 siteSets.add(siteset);
+217         }
+218 
+219         if (siteSets.size() == 0) {
+220             //
+221             // No Federations explicitly named pick em all
+222             //
+223             siteSets.addAll(federations.values());
+224         }
+225         
+226         //
+227         // Now, which plugins?
+228         //
+229 
+230         list = config.getElementsByTagName("PluginInstance");
+231         
+232         for (int i = 0; i < list.getLength(); i++ ) {
+233                     
+234             attribute = ((Element) list.item(i)).getAttribute("identifier");
+235                     
+236                 Plugin plugin = plugins.get(attribute);
+237                 
+238                 if (plugin == null) {
+239                     LOG.error("Handler " + location + ": could not find plugin for identifier " + attribute);
+240                     throw new ShibbolethConfigurationException(
+241                               "Handler " + location + ": could not find plugin for identifier " + attribute);
+242                 }
+243                 
+244                 this.plugins.add(plugin);
+245         }
+246 
+247         //
+248         // So now tell every IdPSite about every plugin.
+249         //
+250         // Note that there is only one idpsite per metadatafile per WAYF and that the discovery 
+251         // services share them, so the data explosion is only number(IdpSites) * number(Plugins) not
+252         // number(IdpSites) * number(Plugins) * number(DiscoverHandlers)
+253         
+254         for (IdPSiteSet site: siteSets) {
+255             for (Plugin plugin: this.plugins) {
+256                 site.addPlugin(plugin);
+257             }
+258         }
+259     }
+260     
+261     
+262     //
+263     // Standard Beany Methods
+264     //
+265     /**
+266      * The 'Name' of the service. the path used to identify the ServiceHandler.
+267      * @return the path used to identify the ServiceHandler.
+268      */
+269     
+270     protected String getLocation() {
+271         return location;
+272     }
+273 
+274     /**
+275      * Whether this is the default service.
+276      * @return is it?
+277      */
+278     protected boolean isDefault() {
+279         return isDefault;
+280     }
+281     
+282     //
+283     // Now the bits that deal with the user request
+284     //
+285 
+286     public void doGet(HttpServletRequest req, HttpServletResponse res) {
+287         
+288         String policy = req.getParameter(POLICY_PARAM_NAME);
+289         
+290         if (null != policy && !KNOWN_POLICY_NAME.equals(policy)) {
+291             //
+292             // unknown policy
+293             //
+294             LOG.error("Unknown policy " + policy);
+295             handleError(req, res, "Unknown policy " + policy);
+296             return;
+297         }
+298         
+299         //
+300         // Decide how to route the request based on query string
+301         //
+302         String requestType = req.getParameter("action");
+303         
+304         if (requestType == null || requestType.equals("")) {
+305             requestType = "lookup";
+306         }
+307         
+308         try {
+309 
+310             if (requestType.equals("search")) {
+311                     
+312                 String parameter = req.getParameter("string"); 
+313                 if (parameter != null && parameter.equals("")) {
+314                         parameter = null;
+315                 }
+316                 handleLookup(req, res, parameter);
+317                     
+318             } else if (requestType.equals("selection")) {
+319                     
+320                 handleSelection(req, res);
+321             } else {
+322                 handleLookup(req, res, null);
+323             }
+324         } catch (WayfException we) {
+325             LOG.error("Error processing DS request:", we);
+326             handleError(req, res, we.getLocalizedMessage());
+327         } catch (WayfRequestHandled we) {
+328             //
+329             // Yuck - a sucess path involving an exception
+330             //
+331         }
+332 
+333     }
+334         
+335     /**
+336      * When the WAYF user has selected something we look it up, tell the plugins and then dispatch to the Idp.
+337      *  
+338      * @param req - standard J2EE stuff
+339      * @param res - standard J2EE stuff
+340      * @throws WayfRequestHandled - if one of the plugins has done the dispatch
+341      * @throws WayfException - if we had an errors
+342      */
+343     private void handleSelection(HttpServletRequest req, 
+344                                  HttpServletResponse res) throws WayfRequestHandled, WayfException 
+345      {
+346             
+347         String idpName = req.getParameter("origin");
+348         LOG.debug("Processing handle selection: " + idpName);
+349 
+350         String sPName = getSPId(req);
+351 
+352         if (idpName == null || idpName.equals("")) {
+353             handleLookup(req, res, null);
+354             return;
+355         }
+356 
+357         if (getValue(req, SHIRE_PARAM_NAME) == null) {
+358             //
+359             // 2.0 protocol
+360             //
+361             setupReturnAddress(sPName, req);
+362         }
+363         //
+364         // Notify plugins
+365         //
+366         IdPSite site = null; 
+367         
+368         for (Plugin plugin:plugins) {
+369             for (IdPSiteSet idPSiteSet: siteSets) {
+370                 PluginMetadataParameter param = idPSiteSet.paramFor(plugin);
+371                 plugin.selected(req, res, param, idpName);
+372                 if (site == null && idPSiteSet.containsIdP(idpName)) {
+373                     site = idPSiteSet.getSite(idpName);
+374                 }
+375             }
+376         }
+377         
+378         if (site == null) {
+379             handleLookup(req, res, null);
+380         } else {
+381             forwardRequest(req, res, site);
+382         }
+383     }
+384 
+385 
+386     /**
+387      * This sets up the parameter RETURN_ATTRIBUTE_NAME with the return address 
+388      * harvested from the reqest.
+389      * <ul><le>If a "return" parameter is present we check in the metadata for spoofing 
+390      *         and then set up from there </le>
+391      *     <le>If "returnID" is specified we get this from the metadata</le>
+392      *     <le>If nothing is provided we get the default from the metadata (if provided)</le>
+393      *     <le>Otherwise we whine</le>
+394      * </ul>     
+395      * @param spName - the name of the Service provider.
+396      * @param req - The request.
+397      * @throws WayfException - if we spot spoofing or there is no defaumlt 
+398      */
+399     private void setupReturnAddress(String spName, HttpServletRequest req) throws WayfException{
+400         
+401         DiscoveryResponseImpl[] discoveryServices;
+402         Set<XMLObject> objects = new HashSet<XMLObject>();
+403         String defaultName = null;
+404         
+405         for (IdPSiteSet metadataProvider:siteSets) {
+406             
+407             //
+408             // Only do work if the SP makes sense
+409             //
+410 
+411             if (metadataProvider.containsSP(spName)) {
+412                
+413                 //
+414                 // The name makes sense so let's get the entity and from that
+415                 // all of its roles
+416                 //
+417                 
+418                 EntityDescriptor entity = metadataProvider.getEntity(spName);
+419                 List<RoleDescriptor> roles = entity.getRoleDescriptors();
+420                 
+421                 for (RoleDescriptor role:roles) {
+422                     
+423                     //
+424                     // Check every role
+425                     //
+426                     
+427                     if (role instanceof SPSSODescriptor) {
+428                         
+429                         //
+430                         // And grab hold of all the extensions for SPSSO descriptors
+431                         //
+432                         
+433                         Extensions exts = role.getExtensions();
+434                         if (exts != null) {
+435                             objects.addAll(exts.getOrderedChildren());
+436                         }
+437                     }
+438                 }
+439             }
+440         }
+441         
+442         //
+443         // Now, let's strip out everything which isn't a DiscoveryService
+444         //
+445         
+446         discoveryServices = new DiscoveryResponseImpl[objects.size()];
+447         int dsCount = 0;
+448         
+449         for (XMLObject obj:objects) {
+450             if (obj instanceof DiscoveryResponseImpl) {
+451                 DiscoveryResponseImpl ds = (DiscoveryResponseImpl) obj;
+452                 discoveryServices[dsCount++] = ds;
+453                 if (ds.isDefault() || null == defaultName) {
+454                     defaultName = ds.getLocation();
+455                 }
+456             }
+457         }
+458         
+459         //
+460         // Now process the return parameters.  The name is either a parameter
+461         // called RETURN_PARAM_NAME or an attributes called RETURN_ATTRIBUTE_NAME
+462         //
+463         String returnName = req.getParameter(RETURN_PARAM_NAME);
+464         
+465         if (returnName == null || returnName.length() == 0) {
+466             returnName = getValue(req, RETURN_ATTRIBUTE_NAME);
+467         }
+468         
+469         //
+470         // Return index is only ever a parameter
+471         //
+472         
+473         String returnIndex = req.getParameter(RETURN_INDEX_NAME);
+474         
+475         if (returnName != null && returnName.length() != 0) {
+476             //
+477             // Given something so we have to police it.
+478             //
+479             String nameNoParam = returnName;
+480             URL providedReturnURL;
+481             int index = nameNoParam.indexOf('?');
+482             boolean found = false;
+483             
+484             if (index >= 0) {
+485                 nameNoParam = nameNoParam.substring(0,index);
+486             }
+487             
+488             try {
+489                 providedReturnURL = new URL(nameNoParam);                
+490             } catch (MalformedURLException e) {
+491                 throw new WayfException("Couldn't parse provided return name " + nameNoParam, e);
+492             }
+493             
+494             
+495             for (DiscoveryResponseImpl disc: discoveryServices) {
+496                 if (equalsURL(disc, providedReturnURL)) {
+497                     found = true;
+498                     break;
+499                 }
+500             }
+501             if (!found) {
+502                 throw new WayfException("Couldn't find endpoint " + nameNoParam + " in metadata");
+503             }
+504         } else if (returnIndex != null && returnIndex.length() != 0) {
+505             
+506             int index; 
+507             try {
+508                 index = Integer.parseInt(returnIndex);
+509             } catch (NumberFormatException e) {
+510                 throw new WayfException("Couldn't convert " + returnIndex + " into an index");
+511             }
+512             //
+513             // So look throught to find the endpoint with the correct index
+514             //
+515 
+516             boolean found = false;
+517             
+518             for (DiscoveryResponseImpl disc: discoveryServices) {
+519                 if (index  == disc.getIndex()) {
+520                     found = true;
+521                     returnName = disc.getLocation();
+522                     break;
+523                 }
+524             }
+525             if (!found) {
+526                 throw new WayfException("Couldn't not find endpoint " + returnIndex + "in metadata");
+527             }
+528         } else {
+529             //
+530             // No name, not index, so we want the default
+531             //
+532             returnName = defaultName;
+533         }
+534         //
+535         // So by now returnName has the correct value, either harvested from or
+536         // policed against the metadata
+537         //
+538         req.setAttribute(RETURN_ATTRIBUTE_NAME, returnName);
+539     }
+540 
+541     /**
+542      * Helper function to see whather the provided endpoint in the metadata matches the 
+543      * provided return URL in the request.
+544      * 
+545      * @param discovery
+546      * @param providedName
+547      * @return
+548      */
+549     private static boolean equalsURL(DiscoveryResponseImpl discovery, URL providedName) {
+550         
+551         //
+552         // Nothing provided - no match
+553         //
+554         if (null == discovery) {
+555             return false;
+556         }
+557         
+558         URL discoveryName;
+559         try {
+560             discoveryName = new URL(discovery.getLocation());
+561         } catch (MalformedURLException e) {
+562             //
+563             // Something bad happened.  Log it (it is only of interest to the sysadmin, not to the user)
+564             //
+565             LOG.warn("Found invalid discovery end point : " + discovery.getLocation(), e);
+566             return false;
+567         }
+568         
+569         return providedName.equals(discoveryName);
+570         
+571     }
+572 
+573     /**
+574      * Displays a Discovery Service selection page, having first consulted the plugins as needed.
+575      * @param req Describes the request
+576      * @param res Describes the response
+577      * @param searchName What are we looking for?
+578      * 
+579      * @throws WayfRequestHandled if a plugin has dealt with the request
+580      * @throws WayfException in case of an error.
+581      */
+582     private void handleLookup(HttpServletRequest req, 
+583                               HttpServletResponse res, 
+584                               String searchName) throws WayfException, WayfRequestHandled {
+585         
+586         String shire = getValue(req, SHIRE_PARAM_NAME);
+587         String providerId = getSPId(req);
+588         boolean twoZeroProtocol = (shire == null);
+589         boolean isPassive = (twoZeroProtocol && 
+590                              "true".equalsIgnoreCase(getValue(req, ISPASSIVE_PARAM_NAME)));
+591 
+592         Collection <IdPSiteSetEntry> siteLists = null;
+593         Collection<IdPSite> searchResults = null;
+594         
+595         if (config.getProvideListOfLists()) {
+596             siteLists = new ArrayList <IdPSiteSetEntry>(siteSets.size());
+597         }
+598 
+599         Collection <IdPSite> sites = null;
+600         Comparator<IdPSite> comparator = new IdPSite.Compare(req);
+601        
+602         if (config.getProvideList()) {
+603             sites = new TreeSet<IdPSite>(comparator);
+604         }
+605 
+606         if (searchName != null && !searchName.equals("")) {
+607             searchResults = new TreeSet<IdPSite>(comparator);
+608         }
+609 
+610         LOG.debug("Processing Idp Lookup for : " + providerId);
+611 
+612         //
+613         // Iterate over all the sitesets and if they know about the SP pass them to the plugins
+614         // and then add them too the list
+615         //
+616 
+617         PluginContext[] ctx = new PluginContext[plugins.size()];
+618         List<IdPSite> hintList = new ArrayList<IdPSite>();
+619         
+620         if (twoZeroProtocol) {
+621             setupReturnAddress(providerId, req);
+622         }
+623         //
+624         // By having siteLists and sites as parameters we only iterate over 
+625         // the metadata arrays once.
+626         //
+627         try {   
+628             for (IdPSiteSet metadataProvider:siteSets) {
+629                 
+630                 //
+631                 // Only do work if the SP makes sense
+632                 //
+633 
+634                 if (metadataProvider.containsSP(providerId) || !config.getLookupSp()) {
+635 
+636                     Collection <IdPSite> search = null;
+637                     
+638                     if (searchResults != null) {
+639                         search = new TreeSet<IdPSite>(comparator);
+640                     }
+641 
+642                     Map <String, IdPSite> theseSites = metadataProvider.getIdPSites(searchName, config, search);
+643                     
+644                     //
+645                     // Consult the plugins
+646                     //
+647                     for (int i = 0; i < plugins.size(); i++) {
+648                             
+649                         Plugin plugin = plugins.get(i);
+650                         
+651                         if (searchResults == null) {
+652                             //
+653                             // This was a search
+654                             //
+655                             ctx[i] = plugin.lookup(req, 
+656                                                    res, 
+657                                                    metadataProvider.paramFor(plugin), 
+658                                                    theseSites, 
+659                                                    ctx[i], 
+660                                                    hintList);
+661                         } else {
+662                             ctx[i] = plugin.search(req, 
+663                                                    res, 
+664                                                    metadataProvider.paramFor(plugin), 
+665                                                    searchName, 
+666                                                    theseSites, 
+667                                                    ctx[i], 
+668                                                    searchResults, 
+669                                                    hintList);
+670                         }
+671                     }
+672                     
+673                     if (null == theseSites || theseSites.isEmpty()) {
+674                         continue;
+675                     }
+676                     
+677                     //
+678                         
+679                     // Accumulate any per-metadata provider information
+680                     // 
+681             
+682                     Collection<IdPSite> values = new TreeSet<IdPSite>(comparator);
+683                     if (null != theseSites) {
+684                         values.addAll(theseSites.values());
+685                     }
+686                     
+687                     if (siteLists != null) {
+688                         siteLists.add(new IdPSiteSetEntry(metadataProvider,values));
+689                     }
+690                             
+691                     if (sites != null) {
+692                         sites.addAll(values);
+693                     }
+694                     
+695                     if (searchResults != null) {
+696                         searchResults.addAll(search);
+697                     }
+698                 }
+699             }
+700             
+701             if (isPassive) {
+702                 //
+703                 // No GUI intervention.
+704                 //
+705                 if (0 != hintList.size()) {
+706                     //
+707                     // We found a candidate, hand it back
+708                     //
+709                     forwardRequest(req, res, hintList.get(0));
+710                 } else {
+711                     forwardRequest(req, res, null);
+712                 }   
+713                 return;
+714             }
+715             
+716             //
+717             // Now set up all the funky stuff that the JSP needs.  Firstly the protocol
+718             // specific parameters which will come back to us
+719             //
+720             
+721             if (twoZeroProtocol) {
+722                 //
+723                 // The return address was set up in setupReturnAddress
+724                 //
+725                 String returnString = (String) req.getAttribute(RETURN_ATTRIBUTE_NAME);
+726                 if (null == returnString || 0 == returnString.length()) {
+727                     throw new WayfException("Parameter " + RETURN_PARAM_NAME + " not supplied");
+728                 }
+729 
+730                 String returnId = getValue(req, RETURNID_PARAM_NAME);
+731                 if (null == returnId || 0 == returnId.length()) {
+732                     returnId = RETURNID_DEFAULT_VALUE;
+733                 }
+734                 //
+735                 // Return *means* something so we cannot use it as an attribute
+736                 //
+737                 req.setAttribute(RETURN_ATTRIBUTE_NAME, returnString);
+738                 req.setAttribute(RETURNID_PARAM_NAME, returnId);
+739                 req.setAttribute(ENTITYID_PARAM_NAME, providerId);
+740                 
+741             } else {
+742                 String target = getValue(req, TARGET_PARAM_NAME);
+743                 if (null == target || 0 == target.length()) {
+744                     throw new WayfException("Could not extract target from provided parameters");
+745                 }
+746                 req.setAttribute(SHIRE_PARAM_NAME, shire);
+747                 req.setAttribute(TARGET_PARAM_NAME, target);
+748                 req.setAttribute(PROVIDERID_PARAM_NAME, providerId);
+749                 //
+750                 // Time is in unix format
+751                 //
+752                 req.setAttribute("time", new Long(new Date().getTime() / 1000).toString()); 
+753                 
+754             }
+755             
+756             //
+757             // Setup the stuff that the GUI wants.  
+758             //
+759                 
+760             setDisplayLanguage(sites, req);
+761             req.setAttribute("sites", sites);
+762             if (null != siteLists) {
+763                 for (IdPSiteSetEntry siteSetEntry:siteLists) {
+764                     setDisplayLanguage(siteSetEntry.getSites(), req);
+765                 }
+766             }
+767                 
+768             req.setAttribute("siteLists", siteLists);
+769             req.setAttribute("requestURL", req.getRequestURI().toString());
+770 
+771             if (searchResults != null) {
+772                 if (searchResults.size() != 0) {
+773                     setDisplayLanguage(searchResults, req);
+774                     req.setAttribute("searchresults", searchResults);
+775                 } else {
+776                     req.setAttribute("searchResultsEmpty", "true");
+777                 }
+778             }
+779 
+780             if (hintList.size() > 0) {
+781                 setDisplayLanguage(hintList, req);
+782                 req.setAttribute("cookieList", hintList);
+783             }
+784 
+785             LOG.debug("Displaying WAYF selection page.");
+786             RequestDispatcher rd = req.getRequestDispatcher(config.getJspFile());
+787 
+788             //
+789             // And off to the jsp
+790             //
+791             rd.forward(req, res);
+792         } catch (IOException ioe) {
+793             LOG.error("Problem displaying WAYF UI.\n" +  ioe.getMessage());
+794             throw new WayfException("Problem displaying WAYF UI", ioe);
+795         } catch (ServletException se) {
+796             LOG.error("Problem displaying WAYF UI.\n" +  se.getMessage());
+797             throw new WayfException("Problem displaying WAYF UI", se);
+798         }
+799     }
+800 
+801     /**
+802      * Prior to display we set the display language from the
+803      * browser. There is probably a proper way to do this using
+804      * jsp, but I want to keep the API between JSP and java the same 1.3->2.0
+805      * @param sites - the sites we need to impact
+806      * @param req - from whiuch we get the locale
+807      */
+808     private void setDisplayLanguage(Collection<IdPSite> sites, HttpServletRequest req) {
+809         
+810         if (null == sites) {
+811             return;
+812         }
+813         Locale locale = req.getLocale();
+814         if (null == locale) {
+815             Locale.getDefault();
+816         }
+817         String lang = locale.getLanguage();
+818 
+819         for (IdPSite site : sites) {
+820             site.setDisplayLanguage(lang);
+821         }
+822     }
+823 
+824 
+825     /**
+826      * Uses an HTTP Status 307 redirect to forward the user to the IdP or the SP.
+827      * 
+828      * @param req request under consideration
+829      * @param res response under construction
+830      * @param site The Idp
+831      * @throws WayfException if bad things happen.
+832      */
+833     public static void forwardRequest(HttpServletRequest req, HttpServletResponse res, IdPSite site)
+834                     throws WayfException {
+835 
+836         String shire = getValue(req, SHIRE_PARAM_NAME);
+837         String providerId = getSPId(req);
+838         boolean twoZeroProtocol = (shire == null);
+839 
+840         if (!twoZeroProtocol) {
+841             String handleService = site.getAddressForWAYF(); 
+842             if (handleService != null ) {
+843 
+844                 String target = getValue(req, TARGET_PARAM_NAME);
+845                 if (null == target || 0 == target.length()) {
+846                     throw new WayfException("Could not extract target from provided parameters");
+847                 }
+848 
+849                 LOG.info("Redirecting to selected Handle Service: " + handleService);
+850                 try {
+851                     StringBuffer buffer = new StringBuffer(handleService +  
+852                        "?" + TARGET_PARAM_NAME + "=");
+853                     buffer.append(URLEncoder.encode(target, "UTF-8"));
+854                     buffer.append("&" + SHIRE_PARAM_NAME + "=");
+855                     buffer.append(URLEncoder.encode(shire, "UTF-8"));
+856                     buffer.append("&" + PROVIDERID_PARAM_NAME + "=");
+857                     buffer.append(URLEncoder.encode(providerId, "UTF-8"));
+858                          
+859                     //
+860                     // Time is as per U**X
+861                     //
+862                     buffer.append("&" +  TIME_PARAM_NAME + "=");
+863                     buffer.append(new Long(new Date().getTime() / 1000).toString());
+864                     res.sendRedirect(buffer.toString());
+865                 } catch (IOException ioe) {
+866                     //
+867                     // That failed.  
+868                     //
+869                     throw new WayfException("Error forwarding to IdP: \n" + ioe.getMessage());
+870                 }
+871             } else {
+872                 String s = "Error finding to IdP: " + site.getDisplayName(req); 
+873                 LOG.error(s);
+874                 throw new WayfException(s);
+875             }
+876         } else {
+877             String returnUrl = (String) req.getAttribute(RETURN_ATTRIBUTE_NAME);
+878             
+879             if (null == returnUrl || 0 == returnUrl.length()) {
+880                 throw new WayfException("Could not find return parameter");
+881             }
+882             try {
+883                 returnUrl = URLDecoder.decode(returnUrl, "UTF-8");
+884             } catch (UnsupportedEncodingException e) {
+885                 throw new WayfException("Did not understand parameter ", e);
+886             }
+887             String redirect;
+888             if (site != null) {
+889                 StringBuffer buffer = new StringBuffer(returnUrl);
+890                 //
+891                 // If we were given anybody to lookup, construct the URL
+892                 //
+893                 String returnParam = getValue(req, RETURNID_PARAM_NAME);
+894                 if (null == returnParam || 0 == returnParam.length()) {
+895                     returnParam = RETURNID_DEFAULT_VALUE;
+896                 }              
+897                 //
+898                 // Do we add a '?' or a '&' for the parameters
+899                 //
+900 
+901                 if (returnUrl.indexOf('?') >= 0) {
+902                     //
+903                     // there is a parameter already.  Add a '&'
+904                     //
+905                     buffer.append("&" + returnParam + "=");
+906                 } else {
+907                     //
+908                     // No parameter.  Use ?
+909                     //
+910                     buffer.append("?" + returnParam + "=");
+911                 }
+912                 buffer.append(site.getName());
+913                 redirect =  buffer.toString();
+914             } else {
+915                 //
+916                 // Just send it back
+917                 //
+918                 redirect = returnUrl;
+919             }
+920             
+921             LOG.debug("Dispatching to " + redirect);
+922             
+923             try {
+924                 res.sendRedirect(redirect);
+925             } catch (IOException ioe) {
+926                 //
+927                 // That failed.  
+928                 //
+929                 throw new WayfException("Error forwarding back to Sp: \n" + ioe.getMessage());
+930             }         
+931         }
+932     }
+933 
+934     /**
+935      * Handles all "recoverable" errors in WAYF processing by logging the error and forwarding the user to an
+936      * appropriate error page.
+937      * 
+938      * @param req request under consideration
+939      * @param res response under construction
+940      * @param message - what so say
+941      */
+942     private void handleError(HttpServletRequest req, HttpServletResponse res, String message) {
+943 
+944         LOG.debug("Displaying WAYF error page.");
+945         req.setAttribute("errorText", message);
+946         req.setAttribute("requestURL", req.getRequestURI().toString());
+947         RequestDispatcher rd = req.getRequestDispatcher(config.getErrorJspFile());
+948 
+949         try {
+950             rd.forward(req, res);
+951         } catch (IOException ioe) {
+952             LOG.error("Problem trying to display WAYF error page: " + ioe.toString());
+953         } catch (ServletException se) {
+954             LOG.error("Problem trying to display WAYF error page: " + se.toString());
+955         }
+956     }
+957 
+958     /**
+959      * Gets the value for the parameter either from the parameter or from jsp.
+960      * @param req - the request.
+961      * @param name - the name of the parameter.
+962      * @return - result
+963      */
+964     private static String getValue(HttpServletRequest req, String name) {
+965 
+966         
+967         String value = req.getParameter(name); 
+968         if (value != null) {
+969             return value;
+970         }
+971         return (String) req.getAttribute(name);
+972     }
+973 
+974     private static String getSPId(HttpServletRequest req) throws WayfException {
+975 
+976         //
+977         // Try first with 2.0 version
+978         //
+979         String param = req.getParameter(ENTITYID_PARAM_NAME);
+980         if (param != null && !(param.length() == 0)) {
+981             return param;
+982         } 
+983         
+984         param = (String) req.getAttribute(ENTITYID_PARAM_NAME);
+985         if (param != null && !(param.length() == 0)) {
+986             return param;
+987         }       
+988         //
+989         // So Try with 1.3 version
+990         //
+991         param = req.getParameter(PROVIDERID_PARAM_NAME);
+992         if (param != null && !(param.length() == 0)) {
+993             return param;
+994         } 
+995         
+996         param = (String) req.getAttribute(PROVIDERID_PARAM_NAME);
+997         if (param != null && !(param.length() == 0)) {
+998             return param;
+999         } 
+1000         throw new WayfException("Could not locate SP identifier in parameters");
+1001     }   
+1002 }
+
+
+ + -- cgit v1.1