Coverage report

  %line %branch
org.apache.jetspeed.sso.impl.PersistenceBrokerSSOProvider
0% 
0% 

 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.jetspeed.sso.impl;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.net.MalformedURLException;
 21  
 import java.net.URL;
 22  
 import java.security.Principal;
 23  
 import java.util.ArrayList;
 24  
 import java.util.Collection;
 25  
 import java.util.HashSet;
 26  
 import java.util.Hashtable;
 27  
 import java.util.Iterator;
 28  
 import java.util.List;
 29  
 import java.util.Set;
 30  
 import java.util.StringTokenizer;
 31  
 import java.util.Vector;
 32  
 
 33  
 import javax.security.auth.Subject;
 34  
 
 35  
 import org.apache.commons.codec.binary.Base64;
 36  
 import org.apache.commons.httpclient.HttpClient;
 37  
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
 38  
 import org.apache.commons.httpclient.cookie.CookiePolicy;
 39  
 import org.apache.commons.httpclient.methods.GetMethod;
 40  
 import org.apache.commons.logging.Log;
 41  
 import org.apache.commons.logging.LogFactory;
 42  
 import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport;
 43  
 import org.apache.jetspeed.security.BasePrincipal;
 44  
 import org.apache.jetspeed.security.SecurityHelper;
 45  
 import org.apache.jetspeed.security.UserPrincipal;
 46  
 import org.apache.jetspeed.security.impl.GroupPrincipalImpl;
 47  
 import org.apache.jetspeed.security.impl.UserPrincipalImpl;
 48  
 import org.apache.jetspeed.security.om.InternalCredential;
 49  
 import org.apache.jetspeed.security.om.InternalGroupPrincipal;
 50  
 import org.apache.jetspeed.security.om.InternalUserPrincipal;
 51  
 import org.apache.jetspeed.security.om.impl.InternalCredentialImpl;
 52  
 import org.apache.jetspeed.security.om.impl.InternalGroupPrincipalImpl;
 53  
 import org.apache.jetspeed.security.om.impl.InternalUserPrincipalImpl;
 54  
 import org.apache.jetspeed.security.spi.impl.DefaultPasswordCredentialImpl;
 55  
 import org.apache.jetspeed.sso.SSOContext;
 56  
 import org.apache.jetspeed.sso.SSOException;
 57  
 import org.apache.jetspeed.sso.SSOPrincipal;
 58  
 import org.apache.jetspeed.sso.SSOProvider;
 59  
 import org.apache.jetspeed.sso.SSOSite;
 60  
 import org.apache.ojb.broker.query.Criteria;
 61  
 import org.apache.ojb.broker.query.Query;
 62  
 import org.apache.ojb.broker.query.QueryByCriteria;
 63  
 import org.apache.ojb.broker.query.QueryFactory;
 64  
 
 65  
 
 66  
 /**
 67  
 * <p>Utility component to handle SSO requests</p>
 68  
 * 
 69  
 * @author <a href="mailto:rogerrut@apache.org">Roger Ruttimann</a>
 70  
 */
 71  
 public class PersistenceBrokerSSOProvider extends
 72  
 		InitablePersistenceBrokerDaoSupport implements SSOProvider 
 73  
 {	
 74  
 	/* Logging */
 75  0
 	private static final Log log = LogFactory.getLog(PersistenceBrokerSSOProvider.class);
 76  
 	
 77  
 	/*
 78  
 	 * Cache for sites and Proxy sites
 79  
 	 */
 80  0
 	private Hashtable mapSite = new Hashtable();
 81  0
 	private Hashtable clientProxy = new Hashtable();
 82  
 	
 83  0
     private String USER_PATH = "/user/";
 84  0
     private String GROUP_PATH = "/group/";
 85  
 
 86  
   	/**
 87  
      * PersitenceBrokerSSOProvider()
 88  
      * @param repository Location of repository mapping file.  Must be available within the classpath.
 89  
      * @param prefsFactoryImpl <code>java.util.prefs.PreferencesFactory</code> implementation to use.
 90  
      * @param enablePropertyManager  Whether or not we chould be suing the property manager.
 91  
      * @throws ClassNotFoundException if the <code>prefsFactoryImpl</code> argument does not reperesent
 92  
      * a Class that exists in the current classPath.
 93  
      */
 94  
     public PersistenceBrokerSSOProvider(String repositoryPath) throws ClassNotFoundException
 95  
     {
 96  0
        super(repositoryPath);
 97  0
     }
 98  
     
 99  
     
 100  
     /*
 101  
      *  (non-Javadoc)
 102  
      * @see org.apache.jetspeed.sso.SSOProvider#useSSO(java.lang.String, java.lang.String, java.lang.String)
 103  
      */
 104  
     public String useSSO(Subject subject, String url, String SSOSite, boolean bRefresh) throws SSOException
 105  
     {
 106  
     	// Get the principal from the subject
 107  0
 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
 108  0
 		String fullPath = principal.getFullPath();
 109  
 		
 110  
     	/* ProxyID is used for the cache. The http client object will be cached for a
 111  
     	 * given user site url combination
 112  
     	 */
 113  0
     	String proxyID = fullPath + "_" + SSOSite;
 114  
     	
 115  
     	// Get the site
 116  0
     	SSOSite ssoSite = getSSOSiteObject(SSOSite);
 117  
 		
 118  0
 		if ( ssoSite != null)
 119  
 		{
 120  0
 			SSOSite[] sites = new SSOSite[1];
 121  0
 			sites[0] = ssoSite;
 122  
 			
 123  0
 			return this.getContentFromURL(proxyID, url, sites, bRefresh);
 124  
 		}
 125  
 		else
 126  
 		{
 127  
 			// Site doesn't exist -- log an error but continue
 128  0
 			String msg = "SSO component -- useSSO can't retrive SSO credential because SSOSite [" + SSOSite + "] doesn't exist";
 129  0
 			log.error(msg);
 130  0
 			SSOSite[] sites = new SSOSite[0];
 131  0
 			return this.getContentFromURL(proxyID, url, sites, bRefresh);
 132  
 		}
 133  
      }
 134  
     
 135  
     /*
 136  
      *  (non-Javadoc)
 137  
      * @see org.apache.jetspeed.sso.SSOProvider#useSSO(java.lang.String, java.lang.String)
 138  
      */
 139  
     public String useSSO(Subject subject, String url, boolean bRefresh) throws SSOException
 140  
     {
 141  
     	// Get the principal from the subject
 142  0
 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
 143  0
 		String fullPath = principal.getFullPath();
 144  
 
 145  
     	
 146  
     	/* ProxyID is used for the cache. The http client object will be cached for a
 147  
     	 * given user 
 148  
     	 */
 149  0
     	String proxyID = fullPath;
 150  
     	
 151  0
     	Collection sites = this.getSitesForPrincipal(fullPath);
 152  
     	
 153  0
     	if (sites == null)
 154  
     	{
 155  0
     		String msg = "SSO Component useSSO -- Couldn't find any SSO sites for user ["+fullPath+"]";
 156  0
     		log.error(msg);
 157  0
     		throw new SSOException(msg);
 158  
     	}
 159  
     	
 160  
     	// Load all the sites
 161  0
     	int siteSize = sites.size();
 162  0
     	int siteIndex =0;
 163  0
     	SSOSite[] ssoSites = new SSOSite[siteSize];
 164  
     	
 165  0
     	Iterator itSites = sites.iterator();
 166  0
     	while(itSites.hasNext())
 167  
     	{
 168  0
     		SSOSite ssoSite = (SSOSite)itSites.next();
 169  0
     		if (ssoSite != null)
 170  
     		{
 171  0
     			ssoSites[siteIndex] = ssoSite;
 172  0
     			siteIndex++;
 173  
     		}
 174  0
     	}
 175  
     	
 176  0
     	return this.getContentFromURL(proxyID, url, ssoSites, bRefresh);
 177  
     }
 178  
     
 179  
      /**
 180  
      * Retrive cookies for an user by User full path
 181  
      * @param fullPath
 182  
      * @return
 183  
      */
 184  
     public Collection getCookiesForUser(String fullPath)
 185  
     {
 186  
     	// Get the SSO user identified by the fullPath
 187  0
     	SSOPrincipal ssoPrincipal = this.getSSOPrincipal(fullPath);
 188  
     	
 189  
     	// For each remote user we'll get the cookie
 190  0
     	Vector temp = new Vector();
 191  
     	
 192  0
     	Iterator itRemotePrincipal = ssoPrincipal.getRemotePrincipals().iterator();
 193  0
     	while (itRemotePrincipal.hasNext())
 194  
     	{
 195  0
     		InternalUserPrincipal rp  = (InternalUserPrincipal)itRemotePrincipal.next();
 196  0
     		if (rp != null)
 197  
     		{
 198  0
     			temp.add(rp.getFullPath());
 199  
     		}
 200  0
     	}
 201  
     	
 202  0
     	if (temp.size() > 0)
 203  
     	{
 204  
     	
 205  0
 	        Criteria filter = new Criteria();   
 206  0
 	        filter.addIn("remotePrincipals.fullPath", temp);
 207  
 	         
 208  0
 	        QueryByCriteria query = QueryFactory.newQuery(SSOCookieImpl.class, filter);
 209  0
 	        return getPersistenceBrokerTemplate().getCollectionByQuery(query);
 210  
     	}
 211  
     	else
 212  
     	{
 213  0
     		return null;
 214  
     	}
 215  
 
 216  
     }
 217  
     
 218  
     /**
 219  
      * Retrive Cookies by Subject
 220  
      * @param user
 221  
      * @return
 222  
      */
 223  
     public Collection getCookiesForUser(Subject user)
 224  
     {
 225  
     	// Get the principal from the subject
 226  0
 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(user, UserPrincipal.class);
 227  0
 		String fullPath = principal.getFullPath();
 228  
 		
 229  
 		// Call into API
 230  0
 		return this.getCookiesForUser(fullPath);
 231  
     }
 232  
     
 233  
 
 234  
     public void setRealmForSite(String site, String realm) throws SSOException
 235  
     {
 236  0
     	SSOSite ssoSite = getSSOSiteObject(site);
 237  
 		
 238  0
 		if ( ssoSite != null)
 239  
 		{
 240  
 			try
 241  
 			{
 242  0
 				ssoSite.setRealm(realm);
 243  0
 				getPersistenceBrokerTemplate().store(ssoSite);
 244  
 			}
 245  0
 			catch (Exception e)
 246  
 			{
 247  0
 				throw new SSOException("Failed to set the realm for site [" + site + "] Error" +e );
 248  0
 			}
 249  
 		}
 250  0
     }
 251  
     
 252  
     public String getRealmForSite(String site) throws SSOException
 253  
     {
 254  0
     	SSOSite ssoSite = getSSOSiteObject(site);
 255  
 		
 256  0
 		if ( ssoSite != null)
 257  
 		{
 258  0
 			return ssoSite.getRealm();
 259  
 		}
 260  
 		
 261  0
 		return null;
 262  
     }
 263  
     
 264  
     /**
 265  
      * Get all SSOSites that the principal has access to
 266  
      * @param userId
 267  
      * @return
 268  
      */
 269  
     public Collection getSitesForPrincipal(String fullPath)
 270  
     {
 271  
    	
 272  0
     	Criteria filter = new Criteria();       
 273  0
         filter.addEqualTo("principals.fullPath", fullPath);
 274  
         
 275  0
         QueryByCriteria query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
 276  0
         return getPersistenceBrokerTemplate().getCollectionByQuery(query); 
 277  
     }
 278  
     
 279  
 	public Iterator getSites(String filter)
 280  
     {
 281  0
         Criteria queryCriteria = new Criteria();
 282  0
         Query query = QueryFactory.newQuery(SSOSiteImpl.class, queryCriteria);
 283  0
         Collection c = getPersistenceBrokerTemplate().getCollectionByQuery(query);
 284  0
         return c.iterator();        
 285  
     }
 286  
 	
 287  
 	/**
 288  
      * addCredentialsForSite()
 289  
      * @param fullPath
 290  
      * @param remoteUser
 291  
      * @param site
 292  
      * @param pwd
 293  
      * @throws SSOException
 294  
      */
 295  
     public void addCredentialsForSite(String fullPath, String remoteUser, String site, String pwd) throws SSOException
 296  
     {
 297  
         // Create a Subject for the given path and forward it to the API addCredentialsForSite()
 298  0
         Principal principal = null;
 299  0
         String name = null;
 300  
         
 301  
         // Group or User
 302  0
         if (fullPath.indexOf("/group/") > -1 )
 303  
         {
 304  0
             name = fullPath.substring(GROUP_PATH.length());
 305  0
             principal = new GroupPrincipalImpl(name);
 306  
         }
 307  
         else
 308  
         {
 309  0
             name = fullPath.substring(USER_PATH.length());
 310  0
             principal = new UserPrincipalImpl(name);
 311  
         }
 312  
  
 313  
         // Create Subject
 314  0
         Set principals = new HashSet();
 315  0
         principals.add(principal);
 316  0
         Subject subject = new Subject(true, principals, class="keyword">new HashSet(), class="keyword">new HashSet());	
 317  
         
 318  
         // Call into the API
 319  0
         addCredentialsForSite(subject, remoteUser, site, pwd);
 320  0
     }
 321  
     
 322  
     /**
 323  
      * removeCredentialsForSite()
 324  
      * @param fullPath
 325  
      * @param site
 326  
      * @throws SSOException
 327  
      */
 328  
     public void removeCredentialsForSite(String fullPath, String site) throws SSOException
 329  
     {
 330  
         // Create a Subject for the given path and forward it to the API addCredentialsForSite()
 331  0
         Principal principal = null;
 332  0
         String name = null;
 333  
         
 334  
         // Group or User
 335  0
         if (fullPath.indexOf("/group/") > -1 )
 336  
         {
 337  0
             name = fullPath.substring(GROUP_PATH.length());
 338  0
             principal = new GroupPrincipalImpl(name);
 339  
         }
 340  
         else
 341  
         {
 342  0
             name = fullPath.substring(USER_PATH.length());
 343  0
             principal = new UserPrincipalImpl(name);
 344  
         }
 345  
  
 346  
         // Create Subject
 347  0
         Set principals = new HashSet();
 348  0
         principals.add(principal);
 349  0
         Subject subject = new Subject(true, principals, class="keyword">new HashSet(), class="keyword">new HashSet());	
 350  
     
 351  
         // Call into the API
 352  0
         this.removeCredentialsForSite(subject,site);
 353  0
     }
 354  
     
 355  
     
 356  
     /** Retrive site information
 357  
      * 
 358  
      *  getSiteURL
 359  
      */
 360  
     
 361  
     public String getSiteURL(String site)
 362  
     {
 363  
         // The site is the URL
 364  0
         return site;
 365  
     }
 366  
     
 367  
     /**
 368  
      * getSiteName
 369  
      */
 370  
     public String getSiteName(String site)
 371  
     {
 372  0
         SSOSite ssoSite = getSSOSiteObject(site);
 373  
 		
 374  0
 		if ( ssoSite != null)
 375  
 		{
 376  0
 			return ssoSite.getName();
 377  
 		}
 378  
 		else
 379  
 		{
 380  0
 		    return null;
 381  
 		}
 382  
     }
 383  
     
 384  
 	/* (non-Javadoc)
 385  
 	 * @see org.apache.jetspeed.sso.SSOProvider#hasSSOCredentials(javax.security.auth.Subject, java.lang.String)
 386  
 	 */
 387  
 	public boolean hasSSOCredentials(Subject subject, String site) {
 388  
 		// Initialization
 389  0
 		SSOSite ssoSite = getSSOSiteObject(site);
 390  
 		
 391  0
 		if ( ssoSite == null)
 392  
 		{
 393  0
 			return false;	// no entry for site
 394  
 		}
 395  
 		
 396  
 		// Get the principal from the subject
 397  0
 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
 398  0
 		String fullPath = principal.getFullPath();
 399  
 		
 400  
 				
 401  
 		// Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
 402  0
 		Collection remoteForSite		= ssoSite.getRemotePrincipals();
 403  0
 		Collection principalsForSite	= ssoSite.getPrincipals();	// Users
 404  
 		
 405  
 		// If any of them don't exist just return
 406  0
 		if (principalsForSite == null || remoteForSite== class="keyword">null )
 407  0
 		    return false;	// no entry
 408  
 		
 409  0
 		Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
 410  
 		
 411  0
 		if ( remoteForPrincipals == null)
 412  0
 		    return false;	// no entry
 413  
 		
 414  
 		// Get remote Principal that matches the site and the principal
 415  0
 		if (findRemoteMatch(remoteForPrincipals, remoteForSite) == null )
 416  
 		{
 417  0
 		    return false;	// No entry
 418  
 		}
 419  
 		else
 420  
 		{
 421  0
 		    return true;	// Has an entry
 422  
 		}
 423  
 	}
 424  
 
 425  
 	/* (non-Javadoc)
 426  
 	 * @see org.apache.jetspeed.sso.SSOProvider#getCredentials(javax.security.auth.Subject, java.lang.String)
 427  
 	 */
 428  
 	public SSOContext getCredentials(Subject subject, String site)
 429  
 			throws SSOException {
 430  
 		
 431  
 		// Initialization
 432  0
 		SSOSite ssoSite = getSSOSiteObject(site);
 433  
 		
 434  0
 		if ( ssoSite == null)
 435  0
 			throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);	// no entry for site
 436  
 		
 437  
 		// Get the principal from the subject
 438  0
 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
 439  0
 		String fullPath = principal.getFullPath();
 440  
 		
 441  
 		// Filter the credentials for the given principals
 442  0
 		SSOContext context = getCredential(ssoSite, fullPath);	
 443  
 		
 444  0
 		if ( context == null)
 445  0
 			throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);	// no entry for site
 446  
 		
 447  0
 		return context;
 448  
 	}
 449  
 
 450  
 	/* addCredential()
 451  
 		 * Adds credentials for a user to the site. If the site doesn't exist it will be created
 452  
 	 * @see org.apache.jetspeed.sso.SSOProvider#addCredentialsForSite(javax.security.auth.Subject, java.lang.String, java.lang.String)
 453  
 	 */
 454  
 	public void addCredentialsForSite(Subject subject, String remoteUser, String site, String pwd)
 455  
 			throws SSOException {
 456  
 		
 457  
 		// Check if an entry for the site already exists otherwise create a new one
 458  0
 		SSOSite ssoSite = getSSOSiteObject(site);
 459  0
 		if (ssoSite == null)
 460  
 		{
 461  
 			// Create a new site
 462  0
 			ssoSite = new SSOSiteImpl();
 463  0
 			ssoSite.setSiteURL(site);
 464  0
 			ssoSite.setName(site);
 465  0
 			ssoSite.setCertificateRequired(false);
 466  0
 			ssoSite.setAllowUserSet(true);
 467  
 			// By default we use ChallengeResponse Authentication
 468  0
 			ssoSite.setChallengeResponseAuthentication(true);
 469  0
 			ssoSite.setFormAuthentication(false);
 470  
 			
 471  
 			// Store the site so that we get a valid SSOSiteID
 472  
 			try
 473  
 	         {
 474  0
 	             getPersistenceBrokerTemplate().store(ssoSite);
 475  
 	          }
 476  0
 	         catch (Exception e)
 477  
 	         {
 478  0
 	         	e.printStackTrace();
 479  0
 	            throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 480  0
 	         }
 481  
 		}
 482  
 		
 483  
 		// Get the Principal information (logged in user)
 484  0
 		String fullPath = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getFullPath();
 485  0
 		String principalName = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getName();
 486  
 		
 487  
 		// Add an entry for the principal to the site if it doesn't exist
 488  0
 		SSOPrincipal principal = this.getPrincipalForSite(ssoSite, fullPath);
 489  
 		
 490  0
 		if (principal == null )
 491  
 		{
 492  0
 		    principal = getSSOPrincipal(fullPath);
 493  0
 		    ssoSite.addPrincipal(principal);
 494  
 		}
 495  
 		else
 496  
 		{
 497  
 		    // Check if the entry the user likes to update exists already
 498  0
 		    Collection remoteForSite = ssoSite.getRemotePrincipals();
 499  0
 		    Collection principalsForSite = ssoSite.getPrincipals();
 500  
 		    
 501  0
 		    if ( remoteForSite != null && principalsForSite != class="keyword">null)
 502  
 		    {
 503  0
 		        Collection remoteForPrincipals = this.getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
 504  0
 		        if ( remoteForPrincipals != null)
 505  
 		        {
 506  0
 			        if (findRemoteMatch(remoteForPrincipals, remoteForSite) != null )
 507  
 			        {
 508  
 			            // Entry exists can't to an add has to call update
 509  0
 			            throw new SSOException(SSOException.REMOTE_PRINCIPAL_EXISTS_CALL_UPDATE);
 510  
 			        }
 511  
 		        }
 512  
 		    }
 513  
 		}
 514  
 		
 515  0
 		if (principal == null)
 516  0
 			throw new SSOException(SSOException.FAILED_ADDING_PRINCIPAL_TO_MAPPING_TABLE_FOR_SITE);
 517  
 		
 518  
 		// Create a remote principal and credentials
 519  0
 		InternalUserPrincipalImpl remotePrincipal = new InternalUserPrincipalImpl(remoteUser);
 520  
 		
 521  
 		/*
 522  
 		 * The RemotePrincipal (class InternalUserPrincipal) will have a fullPath that identifies the entry as an SSO credential.
 523  
 		 * The entry has to be unique for a site and principal  (GROUP -or- USER ) an therefore it needs to be encoded as following:
 524  
 		 * The convention for the path is the following: /sso/SiteID/{user|group}/{user name | group name}/remote user name
 525  
 		 */
 526  0
 		if ( fullPath.indexOf("/group/") > -1)
 527  0
 		    remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/group/"+  principalName + "/" + remoteUser);
 528  
 		else
 529  0
 		    remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/user/"+ principalName + "/" + remoteUser);
 530  
 		
 531  
 		// New credential object for remote principal
 532  0
 		 InternalCredentialImpl credential = 
 533  
             new InternalCredentialImpl(remotePrincipal.getPrincipalId(),
 534  
             		this.scramble(pwd), 0, DefaultPasswordCredentialImpl.class.getName());
 535  
 		 
 536  0
 		 if ( remotePrincipal.getCredentials() == null)
 537  0
 		 	remotePrincipal.setCredentials(new ArrayList(0));
 538  
 		 
 539  0
 		remotePrincipal.getCredentials().add( credential);
 540  
 		
 541  
 		// Add it to Principals remotePrincipals list
 542  0
 		principal.addRemotePrincipal(remotePrincipal);
 543  
 
 544  
 		// Update the site remotePrincipals list
 545  0
 		ssoSite.getRemotePrincipals().add(remotePrincipal);
 546  
 		
 547  
 		 	
 548  
 		// Update database and reset cache
 549  
 		 try
 550  
          {
 551  0
              getPersistenceBrokerTemplate().store(ssoSite);
 552  
              
 553  
              // Persist Principal/Remote
 554  0
      		getPersistenceBrokerTemplate().store(principal);
 555  
           }
 556  0
          catch (Exception e)
 557  
          {
 558  0
          	e.printStackTrace();
 559  0
             throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 560  0
          }
 561  
          
 562  
          // Add to site
 563  0
          this.mapSite.put(site, ssoSite);
 564  0
 	}
 565  
 
 566  
 	/* (non-Javadoc)
 567  
 	 * @see org.apache.jetspeed.sso.SSOProvider#removeCredentialsForSite(javax.security.auth.Subject, java.lang.String)
 568  
 	 */
 569  
 	public void removeCredentialsForSite(Subject subject, String site)
 570  
 			throws SSOException {
 571  
 		
 572  
 		// Initailization
 573  0
 		InternalUserPrincipal remotePrincipal = null;
 574  
 		//Get the site
 575  0
 		SSOSite ssoSite = getSSOSiteObject(site);
 576  0
 		if (ssoSite == null)
 577  
 		{
 578  0
 			throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 579  
 		}
 580  
 		
 581  
 		// Get the Principal information
 582  0
 		String fullPath = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getFullPath();
 583  
 		
 584  
 		try
 585  
 		{
 586  
 			//	Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
 587  0
 			Collection principalsForSite = ssoSite.getPrincipals();
 588  0
 			Collection remoteForSite = ssoSite.getRemotePrincipals();
 589  
 			
 590  
 			// If any of them don't exist just return
 591  0
 			if (principalsForSite == null || remoteForSite== class="keyword">null )
 592  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 593  
 			
 594  0
 			Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
 595  
 			
 596  0
 			if ( remoteForPrincipals == null)
 597  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 598  
 			
 599  
 			// Get remote Principal that matches the site and the principal
 600  0
 			if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
 601  
 			{
 602  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 603  
 			}
 604  
 
 605  
 			// Update assocation tables
 606  0
 			ssoSite.getRemotePrincipals().remove(remotePrincipal);
 607  
 			
 608  0
 			if (remoteForPrincipals.remove(remotePrincipal) == true)
 609  
 			
 610  
 			// Update the site
 611  0
 			getPersistenceBrokerTemplate().store(ssoSite);
 612  
 
 613  
 			// delete the remote Principal from the SECURITY_PRINCIPAL table
 614  0
 		    getPersistenceBrokerTemplate().delete(remotePrincipal);
 615  
 		    
 616  
 						
 617  
 		}
 618  0
 		catch(SSOException ssoex)
 619  
 		{
 620  0
 			throw new SSOException(ssoex);
 621  
 		}
 622  0
 		catch (Exception e)
 623  
         {
 624  0
         	e.printStackTrace();
 625  0
            throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 626  0
         }
 627  
 								
 628  
 		// Update database
 629  
 		 try
 630  
          {
 631  0
              getPersistenceBrokerTemplate().store(ssoSite);
 632  
           }
 633  0
          catch (Exception e)
 634  
          {
 635  0
          	e.printStackTrace();
 636  0
             throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 637  0
          }
 638  
          
 639  0
 	}
 640  
 	
 641  
 	/**
 642  
 	 * updateCredentialsForSite
 643  
 	 * @param subject	Current subject
 644  
 	 * @param remoteUser	remote user login
 645  
 	 * @param site		URL or description of site
 646  
 	 * @param pwd	Password for credentail
 647  
 	 */
 648  
 	public void  updateCredentialsForSite(Subject subject, String remoteUser, String site, String pwd)  
 649  
 	    throws SSOException
 650  
 	    {
 651  
 	        // Check if the the current user has a credential for the site
 652  
 		
 653  
 			// Update the credential
 654  
 			//		 Initailization
 655  0
 			InternalUserPrincipal remotePrincipal = null;
 656  
 			
 657  
 			//Get the site
 658  0
 			SSOSite ssoSite = getSSOSiteObject(site);
 659  0
 			if (ssoSite == null)
 660  
 			{
 661  0
 				throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 662  
 			}
 663  
 			
 664  
 			// Get the Principal information
 665  0
 			String fullPath = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getFullPath();
 666  
 			
 667  
 			//	Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
 668  0
 			Collection principalsForSite	= ssoSite.getPrincipals();
 669  0
 			Collection remoteForSite		= ssoSite.getRemotePrincipals();
 670  
 			
 671  
 			// If any of them don't exist just return
 672  0
 			if (principalsForSite == null || remoteForSite== class="keyword">null )
 673  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 674  
 			
 675  0
 			Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
 676  
 			
 677  0
 			if ( remoteForPrincipals == null)
 678  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 679  
 			
 680  
 			// Get remote Principal that matches the site and the principal
 681  0
 			if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
 682  
 			{
 683  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 684  
 			}
 685  
 						
 686  
 			// Update principal information
 687  
 			//remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/user/"+ principalName + "/" + remoteUser);
 688  
 			
 689  0
 			InternalCredential credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
 690  
 					
 691  
 			// New credential object
 692  0
 			 if ( credential != null) 
 693  
 				// Remove credential and principal from mapping
 694  0
 				 credential.setValue(this.scramble(pwd));
 695  
 			
 696  
 			// Update database and reset cache
 697  
 			 try
 698  
 			 {
 699  0
 			     getPersistenceBrokerTemplate().store(credential);
 700  
 			  }
 701  0
 			 catch (Exception e)
 702  
 			 {
 703  0
 			 	e.printStackTrace();
 704  0
 			    throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 705  0
 			 }			 
 706  0
 	    }
 707  
 	
 708  
 	/*
 709  
 	 * Helper utilities
 710  
 	 * 
 711  
 	 */
 712  
 	
 713  
 	/*
 714  
 	 * getSSOSiteObject
 715  
 	 * Obtains the Site information including the credentials for a site (url).
 716  
 	 */
 717  
 	
 718  
 	private SSOSite getSSOSiteObject(String site)
 719  
 	{
 720  
 		//Initialization
 721  0
 		SSOSite ssoSite = null;
 722  
 		
 723  
 		//Check if the site is in the map
 724  0
 		if (mapSite.containsKey(site) == false )
 725  
 		{
 726  
 			//	Go to the database and fetch the information for this site
 727  
 			//	Find the MediaType by matching the Mimetype
 728  
 		            
 729  0
 		    Criteria filter = new Criteria();       
 730  0
 		    filter.addEqualTo("siteURL", site);
 731  
 		    
 732  0
 		    QueryByCriteria query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
 733  0
 		    Collection ssoSiteCollection = getPersistenceBrokerTemplate().getCollectionByQuery(query);                    
 734  
 		    
 735  0
 		    if ( ssoSiteCollection != null && ssoSiteCollection.isEmpty() != true)
 736  
 		    {
 737  0
 		    	Iterator itSite = ssoSiteCollection.iterator();
 738  
 		    	// Get the site from the collection. There should be only one entry (uniqueness)
 739  0
 		    	if (itSite.hasNext())
 740  
 			    {
 741  0
 				    	ssoSite = (SSOSite) itSite.next();
 742  
 			    }
 743  
 		    	
 744  
 		    	// Add it to the map
 745  0
 		    	mapSite.put(site, ssoSite);
 746  0
 		    }
 747  
 		    else
 748  
 		    {
 749  
 		    	// No entry for this site
 750  0
 		    	return null;
 751  
 		    }
 752  0
 		}
 753  
 		else
 754  
 		{
 755  0
 			ssoSite = (SSOSite)mapSite.get(site);
 756  
 		}
 757  
 		
 758  0
 		return ssoSite;
 759  
 	}
 760  
 	
 761  
 	/*
 762  
 	 * getCredential
 763  
 	 * returns the credentials for a given user
 764  
 	 */
 765  
 	private SSOContext  getCredential(SSOSite ssoSite, String fullPath)
 766  
 	{
 767  0
 		InternalCredential credential = null;
 768  0
 		InternalUserPrincipal remotePrincipal = null;
 769  
 		//	Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
 770  0
 		Collection principalsForSite = ssoSite.getPrincipals();
 771  0
 		Collection remoteForSite = ssoSite.getRemotePrincipals();
 772  
 		
 773  
 		// If any of them don't exist just return
 774  0
 		if ( principalsForSite == null  || remoteForSite== class="keyword">null )
 775  0
 		    return null;	// no entry
 776  
 		
 777  0
 		Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
 778  
 				
 779  0
 		if ( remoteForPrincipals == null)
 780  0
 		    return null;	// no entry
 781  
 		
 782  
 		// Get remote Principal that matches the site and the principal
 783  0
 		if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
 784  
 		{
 785  0
 		    return null;	// No entry
 786  
 		}
 787  
 		else
 788  
 		{
 789  
 		    // Has an entry
 790  0
 			if ( remotePrincipal.getCredentials() != null)
 791  0
 				credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
 792  
 			
 793  
 			// Error checking  -- should have a credential at this point
 794  0
 			if ( credential == null)
 795  
 			{
 796  
 //				System.out.println("Warning: Remote User " + remotePrincipal.getFullPath() + " doesn't have a credential");
 797  0
 				return null; 
 798  
 			}
 799  
 		}
 800  
 		
 801  
 		//	Create new context
 802  0
 		String name = stripPrincipalName(remotePrincipal.getFullPath());
 803  
 		
 804  0
 		SSOContext context = new SSOContextImpl(credential.getPrincipalId(), name, this.unscramble(credential.getValue()));
 805  
 		
 806  0
 		return context;
 807  
 	}
 808  
 	
 809  
     private String stripPrincipalName(String fullPath)
 810  
     {
 811  
         String name;
 812  0
         int ix = fullPath.lastIndexOf('/');
 813  0
         if ( ix != -1)
 814  0
             name = fullPath.substring(ix + 1);
 815  
         else
 816  0
             name = new String(fullPath);
 817  
         
 818  0
         return name;        
 819  
     }
 820  
 
 821  
 	/*
 822  
 	 * Get a Collection of remote Principals for the logged in principal identified by the full path
 823  
 	 *    
 824  
 	private Collection getRemotePrincipalsForPrincipal(SSOSite ssoSite, String fullPath)
 825  
 	{
 826  
 		// The site orincipals list contains a list of remote principals for the user
 827  
 		Collection principals = ssoSite.getPrincipals();
 828  
 		
 829  
 		if ( principals == null )
 830  
 			return null;	// No principals for this site
 831  
 		
 832  
 		Iterator ixPrincipals = principals.iterator();
 833  
 		while (ixPrincipals.hasNext())
 834  
 		{
 835  
 			SSOPrincipal principal = (SSOPrincipal)ixPrincipals.next();
 836  
 			if (         principal != null 
 837  
 			        && principal.getFullPath().compareToIgnoreCase(fullPath) == 0 )
 838  
 			{
 839  
 				// Found Principal -- extract remote principals 
 840  
 				return principal.getRemotePrincipals();
 841  
 			}
 842  
 		}
 843  
 		
 844  
 		// Principal is not in list
 845  
 		return null;
 846  
 	}
 847  
     */
 848  
 	
 849  
 	/*
 850  
 	 * getPrincipalForSite()
 851  
 	 * returns a principal that matches the full path for the site or creates a new entry if it doesn't exist
 852  
 	 */
 853  
 	private SSOPrincipal getPrincipalForSite(SSOSite ssoSite, String fullPath)
 854  
 	{
 855  0
 		SSOPrincipal principal = null;
 856  0
 		Collection principalsForSite = ssoSite.getPrincipals();
 857  
 		
 858  0
 		if ( principalsForSite != null)
 859  
 		{
 860  0
 			Iterator itPrincipals = principalsForSite.iterator();
 861  0
 			while (itPrincipals.hasNext() && principal == null)
 862  
 			{
 863  0
 				SSOPrincipal tmp  = (SSOPrincipal)itPrincipals.next();
 864  0
 				if ( 		 tmp != null 
 865  
 				       && tmp.getFullPath().compareToIgnoreCase(fullPath) == 0 )
 866  0
 					principal = tmp;	// Found existing entry
 867  0
 			}
 868  
 		}
 869  
 		
 870  0
 		return principal;
 871  
 	}
 872  
 	
 873  
 	private SSOPrincipal getSSOPrincipal(String fullPath)
 874  
 	{
 875  
 	    // FInd if the principal exists in the SECURITY_PRINCIPAL table
 876  0
 	    SSOPrincipal principal = null;
 877  
 	    
 878  0
 		Criteria filter = new Criteria();       
 879  0
 	    filter.addEqualTo("fullPath", fullPath);
 880  
 	    
 881  0
 	    QueryByCriteria query = QueryFactory.newQuery(SSOPrincipalImpl.class, filter);
 882  0
 	    Collection principals = getPersistenceBrokerTemplate().getCollectionByQuery(query);                    
 883  
 	    
 884  0
 	    if ( principals != null && principals.isEmpty() != true)
 885  
 	    {
 886  0
 	    	Iterator itPrincipals = principals.iterator();
 887  
 	    	// Get the site from the collection. There should be only one entry (uniqueness)
 888  0
 	    	if (itPrincipals.hasNext())
 889  
 		    {
 890  0
 	    		principal = (SSOPrincipal) itPrincipals.next();
 891  
 		    }
 892  
 	    }
 893  
 	    
 894  0
 		return principal;		
 895  
 	}
 896  
 	
 897  
 	
 898  
 	
 899  
 	/**
 900  
 	 * removeRemotePrincipalForPrincipal
 901  
 	 * @param site
 902  
 	 * @param fullPath
 903  
 	 * @return
 904  
 	 * 
 905  
 	 * removes remotePrincipal for a site & principal
 906  
 	 *
 907  
 	private InternalUserPrincipal  removeRemotePrincipalForPrincipal(SSOSite site, String fullPath) throws SSOException
 908  
 	{
 909  
 		if (site.getPrincipals() != null)
 910  
 		{
 911  
 			Iterator itPrincipals = site.getPrincipals().iterator();
 912  
 			while (itPrincipals.hasNext())
 913  
 			{
 914  
 				SSOPrincipal tmp = (SSOPrincipal)itPrincipals.next();
 915  
 				if (tmp.getFullPath().compareToIgnoreCase(fullPath) == 0)
 916  
 				{
 917  
 					// Found -- get the remotePrincipal
 918  
 					Collection collRemotePrincipals = tmp.getRemotePrincipals() ;
 919  
 					if (collRemotePrincipals != null)
 920  
 					{
 921  
 					
 922  
 						Iterator itRemotePrincipals = collRemotePrincipals.iterator();
 923  
 						if  (itRemotePrincipals.hasNext())
 924  
 						{
 925  
 							InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next();
 926  
 							// Found remove the object
 927  
 							collRemotePrincipals.remove(remotePrincipal);
 928  
 							return remotePrincipal;
 929  
 						}
 930  
 					}
 931  
 				}
 932  
 			}
 933  
 		}		
 934  
 		
 935  
 		throw new SSOException(SSOException.REQUESTED_PRINCIPAL_DOES_NOT_EXIST);
 936  
 	}
 937  
 	*/
 938  
     
 939  
 	/*
 940  
 	 * 
 941  
 	 * 
 942  
 	 */
 943  
 	private InternalUserPrincipal findRemoteMatch(Collection remoteForPrincipals, Collection remoteForSite)
 944  
 	{
 945  
 	    // Iterate over the lists and find match
 946  0
 	    Iterator itRemoteForPrincipals = remoteForPrincipals.iterator();
 947  0
 	    while ( itRemoteForPrincipals.hasNext())
 948  
 	    {
 949  0
 	        InternalUserPrincipal remoteForPrincipal = (InternalUserPrincipal)itRemoteForPrincipals.next();
 950  
 	        
 951  
 	        // Find a match in the site list
 952  0
 	        Iterator itRemoteForSite = remoteForSite.iterator();
 953  0
 		    while ( itRemoteForSite.hasNext())
 954  
 		    {
 955  0
 		        InternalUserPrincipal tmp = (InternalUserPrincipal)itRemoteForSite.next();
 956  
 		        
 957  0
 		        if ( tmp.getPrincipalId() == remoteForPrincipal.getPrincipalId() )
 958  0
 		            return remoteForPrincipal;
 959  0
 		    }
 960  0
 	    }
 961  
 	    // No match found
 962  0
 	    return null;
 963  
 	}
 964  
 	
 965  
 	/*
 966  
 	 * getRemotePrincipalsForPrincipals
 967  
 	 * Checks if the user has any remote principals. If the principal is a group expand the group and
 968  
 	 * check if the requesting user is a part of the group.
 969  
 	 */
 970  
 	private Collection getRemotePrincipalsForPrincipal(Collection principalsForSite, String fullPath)
 971  
 	{
 972  0
 	    if (principalsForSite != null )
 973  
 	    {
 974  0
 		    Iterator itPrincipalsForSite = principalsForSite.iterator();
 975  0
 		    while (itPrincipalsForSite.hasNext())
 976  
 		    {
 977  0
 		        String principalFullPath = null;
 978  0
 		        SSOPrincipal principal = (SSOPrincipal)itPrincipalsForSite.next();
 979  0
 		        principalFullPath = principal.getFullPath();
 980  
 		        
 981  
 		        /* If the Principal is for a Group expand the Group and check if the user identified
 982  
 		        * by the fullPath is a member of the Group. If the user is a member of the Group
 983  
 		        * return the remote Credentials for the current Principal.
 984  
 		        */
 985  0
 		        if ( principalFullPath.indexOf("/group/") == -1)
 986  
 		        {
 987  
 		            // USER
 988  0
 		            if ( principalFullPath.compareToIgnoreCase(fullPath) == 0)
 989  0
 		                return principal.getRemotePrincipals();
 990  
 		        }
 991  
 		        else
 992  
 		        {
 993  
 		            /* GROUP 
 994  
 		             * If the full path is for a group (delete/add) just return the the list of remotePrincipals
 995  
 		             * For a lookup (hasCredentials) the user needs to be mapped against each member of the group
 996  
 		            */
 997  0
 		            if ( principalFullPath.compareToIgnoreCase(fullPath) == 0)
 998  0
 		                return principal.getRemotePrincipals();
 999  
 		            
 1000  
 		            /* Expand the Group and find a match */
 1001  0
 			        InternalGroupPrincipal  groupPrincipal = getGroupPrincipals(principalFullPath);
 1002  
 			        
 1003  
 			        // Found Group that matches the name
 1004  0
 			        if (groupPrincipal != null)
 1005  
 		            {
 1006  0
 			            Collection usersInGroup = groupPrincipal.getUserPrincipals();
 1007  0
 			            Iterator itUsers = usersInGroup.iterator();
 1008  0
 		                while (itUsers.hasNext())
 1009  
 		                {
 1010  0
 		                    InternalUserPrincipal user = (InternalUserPrincipal)itUsers.next();
 1011  0
 		                    if (user.getFullPath().compareToIgnoreCase(fullPath) == 0)
 1012  
 		                    {
 1013  
 		                        // User is member of the group
 1014  0
 		                        return principal.getRemotePrincipals();
 1015  
 		                    }
 1016  0
 		                }
 1017  
 		            }
 1018  
 		        }  
 1019  0
 		    }
 1020  
 	    }
 1021  
 	    
 1022  
 	    // No match found
 1023  0
 	    return null;
 1024  
 	}
 1025  
     
 1026  
     public SSOSite getSite(String siteUrl)
 1027  
     {
 1028  0
         Criteria filter = new Criteria();
 1029  0
         filter.addEqualTo("url", siteUrl);
 1030  0
         Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
 1031  0
         SSOSite site = (SSOSite) getPersistenceBrokerTemplate().getObjectByQuery(query);
 1032  0
         return site;       
 1033  
     }
 1034  
     
 1035  
     public void updateSite(SSOSite site)
 1036  
     throws SSOException
 1037  
     {
 1038  
         try
 1039  
         {
 1040  0
             getPersistenceBrokerTemplate().store(site);
 1041  0
             this.mapSite.put(site.getName(), site);                        
 1042  
         }
 1043  0
         catch (Exception e)
 1044  
         {
 1045  0
             String msg = "Unable to remove SSO Site: " + site.getName();
 1046  0
             logger.error(msg, e);
 1047  0
             throw new SSOException(msg, e);
 1048  0
         }        
 1049  0
     }
 1050  
     
 1051  
     /**
 1052  
      * Add a new site that uses Form Authentication
 1053  
      * @param siteName
 1054  
      * @param siteUrl
 1055  
      * @param realm
 1056  
      * @param userField
 1057  
      * @param pwdField
 1058  
      * @throws SSOException
 1059  
      */
 1060  
     public void addSiteFormAuthenticated(String siteName, String siteUrl, String realm, String userField, String pwdField)
 1061  
     throws SSOException
 1062  
     {
 1063  
     	try
 1064  
         {
 1065  0
             SSOSite ssoSite = new SSOSiteImpl();
 1066  0
             ssoSite.setSiteURL(siteUrl);
 1067  0
             ssoSite.setName(siteName);
 1068  0
             ssoSite.setCertificateRequired(false);
 1069  0
             ssoSite.setAllowUserSet(true);
 1070  0
             ssoSite.setRealm(realm);
 1071  0
             ssoSite.setFormAuthentication(true);
 1072  0
             ssoSite.setFormUserField(userField);
 1073  0
             ssoSite.setFormPwdField(pwdField);
 1074  0
             getPersistenceBrokerTemplate().store(ssoSite);
 1075  0
             this.mapSite.put(siteName, ssoSite);            
 1076  
         }
 1077  0
         catch (Exception e)
 1078  
         {
 1079  0
             String msg = "Unable to add SSO Site: " + siteName;
 1080  0
             logger.error(msg, e);
 1081  0
             throw new SSOException(msg, e);
 1082  0
         }  
 1083  0
     }
 1084  
     
 1085  
     /**
 1086  
      * Add a new site that uses ChallengeResponse Authentication
 1087  
      * @param siteName
 1088  
      * @param siteUrl
 1089  
      * @param realm
 1090  
      * @throws SSOException
 1091  
      */
 1092  
     public void addSiteChallengeResponse(String siteName, String siteUrl, String realm)
 1093  
     throws SSOException
 1094  
     {
 1095  
     	try
 1096  
         {
 1097  0
             SSOSite ssoSite = new SSOSiteImpl();
 1098  0
             ssoSite.setSiteURL(siteUrl);
 1099  0
             ssoSite.setName(siteName);
 1100  0
             ssoSite.setCertificateRequired(false);
 1101  0
             ssoSite.setAllowUserSet(true);
 1102  0
             ssoSite.setRealm(realm);
 1103  0
             ssoSite.setChallengeResponseAuthentication(true);
 1104  0
              getPersistenceBrokerTemplate().store(ssoSite);
 1105  0
             this.mapSite.put(siteName, ssoSite);            
 1106  
         }
 1107  0
         catch (Exception e)
 1108  
         {
 1109  0
             String msg = "Unable to add SSO Site: " + siteName;
 1110  0
             logger.error(msg, e);
 1111  0
             throw new SSOException(msg, e);
 1112  0
         }  
 1113  0
     }
 1114  
     
 1115  
     public void addSite(String siteName, String siteUrl)
 1116  
     throws SSOException
 1117  
     {
 1118  
         try
 1119  
         {
 1120  0
             SSOSite ssoSite = new SSOSiteImpl();
 1121  0
             ssoSite.setSiteURL(siteUrl);
 1122  0
             ssoSite.setName(siteName);
 1123  0
             ssoSite.setCertificateRequired(false);
 1124  0
             ssoSite.setAllowUserSet(true);            
 1125  0
             getPersistenceBrokerTemplate().store(ssoSite);
 1126  0
             this.mapSite.put(siteName, ssoSite);            
 1127  
         }
 1128  0
         catch (Exception e)
 1129  
         {
 1130  0
             String msg = "Unable to remove SSO Site: " + siteName;
 1131  0
             logger.error(msg, e);
 1132  0
             throw new SSOException(msg, e);
 1133  0
         }                
 1134  0
     }
 1135  
     
 1136  
     public void removeSite(SSOSite site)
 1137  
     throws SSOException
 1138  
     {
 1139  
         try
 1140  
         {
 1141  0
             getPersistenceBrokerTemplate().delete(site);
 1142  0
             this.mapSite.remove(site);
 1143  
 
 1144  
         }
 1145  0
         catch (Exception e)
 1146  
         {
 1147  0
             String msg = "Unable to remove SSO Site: " + site.getName();
 1148  0
             logger.error(msg, e);
 1149  0
             throw new SSOException(msg, e);
 1150  0
         }        
 1151  0
     }
 1152  
         
 1153  
     public List getPrincipalsForSite(SSOSite site)
 1154  
     {
 1155  0
         List list = new ArrayList();
 1156  0
         Iterator principals = site.getRemotePrincipals().iterator();
 1157  0
         while (principals.hasNext())
 1158  
         {
 1159  0
             InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)principals.next();
 1160  0
             Iterator creds = remotePrincipal.getCredentials().iterator();
 1161  0
             while (creds.hasNext())
 1162  
             {
 1163  0
                 InternalCredential cred = (InternalCredential) creds.next();
 1164  0
                 SSOContext context = new SSOContextImpl(remotePrincipal.getPrincipalId(), 
 1165  
                                                 stripPrincipalName(remotePrincipal.getFullPath()), 
 1166  
                                                 cred.getValue(), 
 1167  
                                                 stripPortalPrincipalName(remotePrincipal.getFullPath()));
 1168  0
                 list.add(context);
 1169  0
             }
 1170  0
         }
 1171  0
         return list;
 1172  
     }
 1173  
 
 1174  
     
 1175  
     private String stripPortalPrincipalName(String fullPath)
 1176  
     {
 1177  0
         StringTokenizer tokenizer = new StringTokenizer(fullPath, "/");
 1178  0
         while (tokenizer.hasMoreTokens())
 1179  
         {
 1180  0
             String token = tokenizer.nextToken();
 1181  0
             if (token.equals("user") || token.equals("group"))
 1182  
             {
 1183  0
                  if (tokenizer.hasMoreTokens())
 1184  
                 {
 1185  0
                     return tokenizer.nextToken();
 1186  
                 }
 1187  
             }
 1188  0
         }
 1189  0
         return fullPath;        
 1190  
     }
 1191  
     
 1192  
     private InternalGroupPrincipal  getGroupPrincipals(String principalFullPath)
 1193  
     {
 1194  
         // Get to the backend to return the group that matches the full path
 1195  0
         Criteria filter = new Criteria();
 1196  0
         filter.addEqualTo("fullPath", principalFullPath);
 1197  0
         Query query = QueryFactory.newQuery(InternalGroupPrincipalImpl.class, filter);
 1198  0
         InternalGroupPrincipal group = (InternalGroupPrincipal) getPersistenceBrokerTemplate().getObjectByQuery(query);
 1199  0
         return group;       
 1200  
     }
 1201  
     
 1202  
     /*
 1203  
     private SSOSite getSiteForRemoteUser(String fullPath)
 1204  
     {
 1205  
     	// Get Site for remote user
 1206  
         Criteria filter = new Criteria();
 1207  
         filter.addEqualTo("remotePrincipals.fullPath", fullPath);
 1208  
         Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
 1209  
         return  (SSOSite) getPersistenceBrokerTemplate().getObjectByQuery(query);
 1210  
     }
 1211  
     */
 1212  
     
 1213  
     private String getContentFromURL(String proxyID, String destUrl, SSOSite[] sites, boolean bRefresh ) throws SSOException
 1214  
     {
 1215  0
     	URL urlObj = null;
 1216  
     	
 1217  
     	// Result Buffer
 1218  
     	//BufferedInputStream bis = null;
 1219  
     	String resultPage;
 1220  
     	
 1221  0
     	String strErrorMessage = "SSO Component Error. Failed to get content for URL " + destUrl;
 1222  
     	
 1223  
     	try
 1224  
     	{
 1225  0
     		urlObj = new URL(destUrl);
 1226  
     	}
 1227  0
     	catch (MalformedURLException e)
 1228  
     	{
 1229  0
     		String msg = ("Error -- Malformed URL [" + destUrl +"] for SSO authenticated destination");
 1230  0
     		log.error(msg);
 1231  0
     		throw new SSOException(msg, e);
 1232  0
     	}
 1233  
     	
 1234  
     	/* 
 1235  
     	 * Setup HTTPClient
 1236  
     	 * Check if an HTTP Client already exists for the given /user/site
 1237  
     	 */
 1238  0
     	HttpClient client = (HttpClient)this.clientProxy.get(proxyID);
 1239  0
     	GetMethod get = null;
 1240  
     	
 1241  0
     	if (bRefresh == true || client == null)
 1242  
     	{
 1243  0
     		if (log.isInfoEnabled())
 1244  0
     			log.info("SSO Component -- Create new HTTP Client object for Principal/URL [" + proxyID+ "]");
 1245  
     		
 1246  0
 	    	client = new HttpClient();
 1247  0
 	    	client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
 1248  
 	    	
 1249  0
 	    	int numberOfSites = sites.length;
 1250  
 	    	
 1251  
 	    	// Do all the logins for the site
 1252  0
 	    	for (int i=0; i<numberOfSites; i++)
 1253  
 	    	{
 1254  0
 	    		SSOSite site = sites[i];
 1255  
 	    		
 1256  0
 	    		if (site != null)
 1257  
 	    		{
 1258  0
 	    			Iterator itRemotePrincipals = site.getRemotePrincipals().iterator();
 1259  0
 	    			while (itRemotePrincipals.hasNext() )
 1260  
 	    			{
 1261  0
 	    				InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next();
 1262  0
 	            		if (remotePrincipal != null)
 1263  
 	            		{
 1264  0
 	            			InternalCredential credential = null;
 1265  0
 	            			if ( remotePrincipal.getCredentials() != null)
 1266  0
 	            				credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
 1267  
 	            			
 1268  0
 	            			if (credential != null)
 1269  
 	            			{
 1270  0
 	            				if (log.isInfoEnabled())
 1271  0
 	            					log.info("SSOComponent -- Remote Principal ["+stripPrincipalName(remotePrincipal.getFullPath())+"] has credential ["+this.unscramble(credential.getValue())+ "]");
 1272  
 	            				
 1273  0
 	            				client.getState().setCredentials(
 1274  
 	            		    			site.getRealm(),
 1275  
 	            		                urlObj.getHost(),
 1276  
 	            		                new UsernamePasswordCredentials(stripPrincipalName(remotePrincipal.getFullPath()),  this.unscramble(credential.getValue()))
 1277  
 	            		            );
 1278  
 	            				
 1279  
 	            				// Build URL if it's Form authentication
 1280  0
 	            				StringBuffer siteURL = new StringBuffer(site.getSiteURL());
 1281  
 		       					
 1282  
 		        				// Check if it's form based or ChallengeResponse
 1283  0
 	        					if (site.isFormAuthentication())
 1284  
 	        					{
 1285  0
 	        						siteURL.append("?").append(site.getFormUserField()).append("=").append(stripPrincipalName(remotePrincipal.getFullPath())).append("&").append(site.getFormPwdField()).append("=").append(this.unscramble(credential.getValue()));
 1286  
 	        					}
 1287  
 	            				
 1288  0
 	            				get = new GetMethod(siteURL.toString());
 1289  
 	
 1290  
 	            	            // Tell the GET method to automatically handle authentication. The
 1291  
 	            	            // method will use any appropriate credentials to handle basic
 1292  
 	            	            // authentication requests.  Setting this value to false will cause
 1293  
 	            	            // any request for authentication to return with a status of 401.
 1294  
 	            	            // It will then be up to the client to handle the authentication.
 1295  0
 	            	            get.setDoAuthentication( true );
 1296  
 	            	            try {
 1297  
 	            	                // execute the GET
 1298  0
 	            	                int status = client.executeMethod( get );
 1299  
 	            	                
 1300  0
 	            	                if (log.isInfoEnabled() )
 1301  0
 	            	                		log.info("Accessing site [" + site.getSiteURL() + "]. HTTP Status [" +status+ "]" );
 1302  
 	            	                
 1303  
 	            	                /*
 1304  
 	            	    	    	 * If the destination URL and the SSO url match
 1305  
 	            	    	    	 * use the authentication process but return immediately
 1306  
 	            	    	    	 * the result page.
 1307  
 	            	    	    	 */
 1308  0
 	            	                if( destUrl.compareTo(site.getSiteURL()) == 0 && numberOfSites == 1)
 1309  
 	            	                {
 1310  0
 	            	                	if (log.isInfoEnabled() )
 1311  0
 	            	                		log.info("SSO Component --SSO Site and destination URL match. Go and get the content." );
 1312  
 	            	                	
 1313  
 	            	                	//try
 1314  
 	            	            		//{
 1315  
 	            	            			//bis = new BufferedInputStream(get.getResponseBodyAsStream());
 1316  0
 	            	            			resultPage = get.getResponseBodyAsString();
 1317  
 	            	            		//}
 1318  
 	            	            		//catch(IOException ioe)
 1319  
 	            	            		//{
 1320  
 	            	            		//	log.error(strErrorMessage, ioe);
 1321  
 	            	            		//	throw new SSOException (strErrorMessage, ioe);	
 1322  
 	            	            		//}
 1323  
 
 1324  0
 	            	            		get.releaseConnection();
 1325  
 	            	            		
 1326  
 	            	            		//	Add the client object to the cache
 1327  0
 	            	        	    	this.clientProxy.put(proxyID, client);
 1328  
 	            	            		
 1329  
 	            	            		//return bis;
 1330  0
 	            	        	    	return resultPage;
 1331  
 	            	                }
 1332  
 	            	        
 1333  0
 		            			} catch (Exception e) {
 1334  0
 		                        	log.error("Exception while authentication. Error: " +e);	                        
 1335  0
 		                        }
 1336  
 		            			
 1337  0
 		            			get.releaseConnection();
 1338  
 	             			}
 1339  
 	            		}
 1340  0
 	    			}
 1341  
 	    		}   		
 1342  
 	    	}
 1343  
 	    	
 1344  
 	    	// Add the client object to the cache
 1345  0
 	    	this.clientProxy.put(proxyID, client);
 1346  0
     	}
 1347  
     	else
 1348  
     	{
 1349  0
     		if (log.isInfoEnabled())
 1350  0
     			log.info("SSO Component -- Use cached HTTP Client object for Principal/URL [" + proxyID+ "]");
 1351  
     	}
 1352  
     	
 1353  
     	// All the SSO authentication done go to the destination url
 1354  0
 		get = new GetMethod(destUrl);
 1355  
 		try {
 1356  
             // execute the GET
 1357  0
             int status = client.executeMethod( get );
 1358  
             
 1359  0
             log.info("Accessing site [" + destUrl + "]. HTTP Status [" +status+ "]" );
 1360  
     
 1361  0
 		} catch (Exception e) {
 1362  0
         	log.error("Exception while authentication. Error: " +e);	                        
 1363  0
         }
 1364  
 		
 1365  
 		
 1366  
 		try
 1367  
 		{
 1368  
 			//bis = new BufferedInputStream(get.getResponseBodyAsStream());
 1369  0
 			resultPage = get.getResponseBodyAsString();
 1370  
 		}
 1371  0
 		catch(IOException ioe)
 1372  
 		{
 1373  0
 			log.error(strErrorMessage, ioe);
 1374  0
 			throw new SSOException (strErrorMessage, ioe);
 1375  
         }
 1376  0
 		catch (Exception e)
 1377  
 		{
 1378  0
 			log.error(strErrorMessage, e);
 1379  0
 			throw new SSOException (strErrorMessage, e);
 1380  
 			
 1381  
 		}
 1382  
         finally
 1383  
         {
 1384  0
             get.releaseConnection();
 1385  0
         }
 1386  
 		
 1387  
 		//return bis;
 1388  0
 		return resultPage;
 1389  
     }
 1390  
     
 1391  
     /*
 1392  
      * Simple encryption decryption routines since the API creates credentials 
 1393  
      * together with an user.
 1394  
      * TODO: re-implement when Security API is more flexible
 1395  
      */
 1396  0
     static char[] scrambler ="Jestspeed-2 is getting ready for release".toCharArray();
 1397  
     
 1398  
     private String scramble(String pwd)
 1399  
     {
 1400  
         // xor-ing persistent String values is dangerous because of the (uncommon) way Java encodes UTF-8 0x00 (and some other characters).
 1401  
         // See: http://en.wikipedia.org/wiki/UTF-8#Java
 1402  
         // On some database platforms, like PostgreSQL this can lead to something like:
 1403  
         //   org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00
 1404  
         // To prevent this, the resulting xored password is encoded in Base64
 1405  0
     	String xored = new String(xor(pwd.toCharArray(), scrambler));
 1406  0
         byte[] bytes = Base64.encodeBase64(xored.getBytes());
 1407  0
         String scrambled = new String(bytes);
 1408  0
         return scrambled;
 1409  
     }
 1410  
     
 1411  
     private String unscramble(String pwd)
 1412  
     {
 1413  0
     	byte[] bytes = pwd.getBytes();
 1414  0
         bytes = Base64.decodeBase64(bytes);
 1415  0
         String chars = new String(bytes);
 1416  0
         String unscrambled = new String(xor(chars.toCharArray(), scrambler));
 1417  0
         return unscrambled;
 1418  
     }
 1419  
     
 1420  
     private char[] xor(class="keyword">char[] a, class="keyword">char[]b)
 1421  
     {
 1422  0
     	int len = Math.min(a.length, b.length);
 1423  0
     	char[] result = new class="keyword">char[len];
 1424  0
     	for(int i=0; i<len;i++)
 1425  
     	{
 1426  0
     		result[i] = (char) (a[i] ^ b[i]);
 1427  
     	}
 1428  0
     	return result;
 1429  
     }
 1430  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.