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  
             // current OJB model implementation isn't 100% correct, make sure no stale/broken state is left behind
 626  0
             mapSite.remove(site);
 627  0
            throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 628  0
         }
 629  
 								
 630  
 		// Update database
 631  
 		 try
 632  
          {
 633  0
              getPersistenceBrokerTemplate().store(ssoSite);
 634  
           }
 635  0
          catch (Exception e)
 636  
          {
 637  0
          	e.printStackTrace();
 638  0
             throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 639  
          }
 640  
          finally
 641  
          {
 642  
              // current OJB model implementation isn't 100% correct, make sure no stale/broken state is left behind
 643  0
              mapSite.remove(site);
 644  0
          }
 645  
          
 646  0
 	}
 647  
 	
 648  
 	/**
 649  
 	 * updateCredentialsForSite
 650  
 	 * @param subject	Current subject
 651  
 	 * @param remoteUser	remote user login
 652  
 	 * @param site		URL or description of site
 653  
 	 * @param pwd	Password for credentail
 654  
 	 */
 655  
 	public void  updateCredentialsForSite(Subject subject, String remoteUser, String site, String pwd)  
 656  
 	    throws SSOException
 657  
 	    {
 658  
 	        // Check if the the current user has a credential for the site
 659  
 		
 660  
 			// Update the credential
 661  
 			//		 Initailization
 662  0
 			InternalUserPrincipal remotePrincipal = null;
 663  
 			
 664  
 			//Get the site
 665  0
 			SSOSite ssoSite = getSSOSiteObject(site);
 666  0
 			if (ssoSite == null)
 667  
 			{
 668  0
 				throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 669  
 			}
 670  
 			
 671  
 			// Get the Principal information
 672  0
 			String fullPath = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getFullPath();
 673  
 			
 674  
 			//	Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
 675  0
 			Collection principalsForSite	= ssoSite.getPrincipals();
 676  0
 			Collection remoteForSite		= ssoSite.getRemotePrincipals();
 677  
 			
 678  
 			// If any of them don't exist just return
 679  0
 			if (principalsForSite == null || remoteForSite== class="keyword">null )
 680  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 681  
 			
 682  0
 			Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
 683  
 			
 684  0
 			if ( remoteForPrincipals == null)
 685  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 686  
 			
 687  
 			// Get remote Principal that matches the site and the principal
 688  0
 			if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
 689  
 			{
 690  0
 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
 691  
 			}
 692  
 						
 693  
 			// Update principal information
 694  
 			//remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/user/"+ principalName + "/" + remoteUser);
 695  
 			
 696  0
 			InternalCredential credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
 697  
 					
 698  
 			// New credential object
 699  0
 			 if ( credential != null) 
 700  
 				// Remove credential and principal from mapping
 701  0
 				 credential.setValue(this.scramble(pwd));
 702  
 			
 703  
 			// Update database and reset cache
 704  
 			 try
 705  
 			 {
 706  0
 			     getPersistenceBrokerTemplate().store(credential);
 707  
 			  }
 708  0
 			 catch (Exception e)
 709  
 			 {
 710  0
 			 	e.printStackTrace();
 711  0
 			    throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
 712  0
 			 }			 
 713  0
 	    }
 714  
 	
 715  
 	/*
 716  
 	 * Helper utilities
 717  
 	 * 
 718  
 	 */
 719  
 	
 720  
 	/*
 721  
 	 * getSSOSiteObject
 722  
 	 * Obtains the Site information including the credentials for a site (url).
 723  
 	 */
 724  
 	
 725  
 	private SSOSite getSSOSiteObject(String site)
 726  
 	{
 727  
 		//Initialization
 728  0
 		SSOSite ssoSite = null;
 729  
 		
 730  
 		//Check if the site is in the map
 731  0
 		if (mapSite.containsKey(site) == false )
 732  
 		{
 733  
 			//	Go to the database and fetch the information for this site
 734  
 			//	Find the MediaType by matching the Mimetype
 735  
 		            
 736  0
 		    Criteria filter = new Criteria();       
 737  0
 		    filter.addEqualTo("siteURL", site);
 738  
 		    
 739  0
 		    QueryByCriteria query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
 740  0
 		    Collection ssoSiteCollection = getPersistenceBrokerTemplate().getCollectionByQuery(query);                    
 741  
 		    
 742  0
 		    if ( ssoSiteCollection != null && ssoSiteCollection.isEmpty() != true)
 743  
 		    {
 744  0
 		    	Iterator itSite = ssoSiteCollection.iterator();
 745  
 		    	// Get the site from the collection. There should be only one entry (uniqueness)
 746  0
 		    	if (itSite.hasNext())
 747  
 			    {
 748  0
 				    	ssoSite = (SSOSite) itSite.next();
 749  
 			    }
 750  
 		    	
 751  
 		    	// Add it to the map
 752  0
 		    	mapSite.put(site, ssoSite);
 753  0
 		    }
 754  
 		    else
 755  
 		    {
 756  
 		    	// No entry for this site
 757  0
 		    	return null;
 758  
 		    }
 759  0
 		}
 760  
 		else
 761  
 		{
 762  0
 			ssoSite = (SSOSite)mapSite.get(site);
 763  
 		}
 764  
 		
 765  0
 		return ssoSite;
 766  
 	}
 767  
 	
 768  
 	/*
 769  
 	 * getCredential
 770  
 	 * returns the credentials for a given user
 771  
 	 */
 772  
 	private SSOContext  getCredential(SSOSite ssoSite, String fullPath)
 773  
 	{
 774  0
 		InternalCredential credential = null;
 775  0
 		InternalUserPrincipal remotePrincipal = null;
 776  
 		//	Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
 777  0
 		Collection principalsForSite = ssoSite.getPrincipals();
 778  0
 		Collection remoteForSite = ssoSite.getRemotePrincipals();
 779  
 		
 780  
 		// If any of them don't exist just return
 781  0
 		if ( principalsForSite == null  || remoteForSite== class="keyword">null )
 782  0
 		    return null;	// no entry
 783  
 		
 784  0
 		Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
 785  
 				
 786  0
 		if ( remoteForPrincipals == null)
 787  0
 		    return null;	// no entry
 788  
 		
 789  
 		// Get remote Principal that matches the site and the principal
 790  0
 		if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
 791  
 		{
 792  0
 		    return null;	// No entry
 793  
 		}
 794  
 		else
 795  
 		{
 796  
 		    // Has an entry
 797  0
 			if ( remotePrincipal.getCredentials() != null)
 798  0
 				credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
 799  
 			
 800  
 			// Error checking  -- should have a credential at this point
 801  0
 			if ( credential == null)
 802  
 			{
 803  
 //				System.out.println("Warning: Remote User " + remotePrincipal.getFullPath() + " doesn't have a credential");
 804  0
 				return null; 
 805  
 			}
 806  
 		}
 807  
 		
 808  
 		//	Create new context
 809  0
 		String name = stripPrincipalName(remotePrincipal.getFullPath());
 810  
 		
 811  0
 		SSOContext context = new SSOContextImpl(credential.getPrincipalId(), name, this.unscramble(credential.getValue()));
 812  
 		
 813  0
 		return context;
 814  
 	}
 815  
 	
 816  
     private String stripPrincipalName(String fullPath)
 817  
     {
 818  
         String name;
 819  0
         int ix = fullPath.lastIndexOf('/');
 820  0
         if ( ix != -1)
 821  0
             name = fullPath.substring(ix + 1);
 822  
         else
 823  0
             name = new String(fullPath);
 824  
         
 825  0
         return name;        
 826  
     }
 827  
 
 828  
 	/*
 829  
 	 * Get a Collection of remote Principals for the logged in principal identified by the full path
 830  
 	 *    
 831  
 	private Collection getRemotePrincipalsForPrincipal(SSOSite ssoSite, String fullPath)
 832  
 	{
 833  
 		// The site orincipals list contains a list of remote principals for the user
 834  
 		Collection principals = ssoSite.getPrincipals();
 835  
 		
 836  
 		if ( principals == null )
 837  
 			return null;	// No principals for this site
 838  
 		
 839  
 		Iterator ixPrincipals = principals.iterator();
 840  
 		while (ixPrincipals.hasNext())
 841  
 		{
 842  
 			SSOPrincipal principal = (SSOPrincipal)ixPrincipals.next();
 843  
 			if (         principal != null 
 844  
 			        && principal.getFullPath().compareToIgnoreCase(fullPath) == 0 )
 845  
 			{
 846  
 				// Found Principal -- extract remote principals 
 847  
 				return principal.getRemotePrincipals();
 848  
 			}
 849  
 		}
 850  
 		
 851  
 		// Principal is not in list
 852  
 		return null;
 853  
 	}
 854  
     */
 855  
 	
 856  
 	/*
 857  
 	 * getPrincipalForSite()
 858  
 	 * returns a principal that matches the full path for the site or creates a new entry if it doesn't exist
 859  
 	 */
 860  
 	private SSOPrincipal getPrincipalForSite(SSOSite ssoSite, String fullPath)
 861  
 	{
 862  0
 		SSOPrincipal principal = null;
 863  0
 		Collection principalsForSite = ssoSite.getPrincipals();
 864  
 		
 865  0
 		if ( principalsForSite != null)
 866  
 		{
 867  0
 			Iterator itPrincipals = principalsForSite.iterator();
 868  0
 			while (itPrincipals.hasNext() && principal == null)
 869  
 			{
 870  0
 				SSOPrincipal tmp  = (SSOPrincipal)itPrincipals.next();
 871  0
 				if ( 		 tmp != null 
 872  
 				       && tmp.getFullPath().compareToIgnoreCase(fullPath) == 0 )
 873  0
 					principal = tmp;	// Found existing entry
 874  0
 			}
 875  
 		}
 876  
 		
 877  0
 		return principal;
 878  
 	}
 879  
 	
 880  
 	private SSOPrincipal getSSOPrincipal(String fullPath)
 881  
 	{
 882  
 	    // FInd if the principal exists in the SECURITY_PRINCIPAL table
 883  0
 	    SSOPrincipal principal = null;
 884  
 	    
 885  0
 		Criteria filter = new Criteria();       
 886  0
 	    filter.addEqualTo("fullPath", fullPath);
 887  
 	    
 888  0
 	    QueryByCriteria query = QueryFactory.newQuery(SSOPrincipalImpl.class, filter);
 889  0
 	    Collection principals = getPersistenceBrokerTemplate().getCollectionByQuery(query);                    
 890  
 	    
 891  0
 	    if ( principals != null && principals.isEmpty() != true)
 892  
 	    {
 893  0
 	    	Iterator itPrincipals = principals.iterator();
 894  
 	    	// Get the site from the collection. There should be only one entry (uniqueness)
 895  0
 	    	if (itPrincipals.hasNext())
 896  
 		    {
 897  0
 	    		principal = (SSOPrincipal) itPrincipals.next();
 898  
 		    }
 899  
 	    }
 900  
 	    
 901  0
 		return principal;		
 902  
 	}
 903  
 	
 904  
 	
 905  
 	
 906  
 	/**
 907  
 	 * removeRemotePrincipalForPrincipal
 908  
 	 * @param site
 909  
 	 * @param fullPath
 910  
 	 * @return
 911  
 	 * 
 912  
 	 * removes remotePrincipal for a site & principal
 913  
 	 *
 914  
 	private InternalUserPrincipal  removeRemotePrincipalForPrincipal(SSOSite site, String fullPath) throws SSOException
 915  
 	{
 916  
 		if (site.getPrincipals() != null)
 917  
 		{
 918  
 			Iterator itPrincipals = site.getPrincipals().iterator();
 919  
 			while (itPrincipals.hasNext())
 920  
 			{
 921  
 				SSOPrincipal tmp = (SSOPrincipal)itPrincipals.next();
 922  
 				if (tmp.getFullPath().compareToIgnoreCase(fullPath) == 0)
 923  
 				{
 924  
 					// Found -- get the remotePrincipal
 925  
 					Collection collRemotePrincipals = tmp.getRemotePrincipals() ;
 926  
 					if (collRemotePrincipals != null)
 927  
 					{
 928  
 					
 929  
 						Iterator itRemotePrincipals = collRemotePrincipals.iterator();
 930  
 						if  (itRemotePrincipals.hasNext())
 931  
 						{
 932  
 							InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next();
 933  
 							// Found remove the object
 934  
 							collRemotePrincipals.remove(remotePrincipal);
 935  
 							return remotePrincipal;
 936  
 						}
 937  
 					}
 938  
 				}
 939  
 			}
 940  
 		}		
 941  
 		
 942  
 		throw new SSOException(SSOException.REQUESTED_PRINCIPAL_DOES_NOT_EXIST);
 943  
 	}
 944  
 	*/
 945  
     
 946  
 	/*
 947  
 	 * 
 948  
 	 * 
 949  
 	 */
 950  
 	private InternalUserPrincipal findRemoteMatch(Collection remoteForPrincipals, Collection remoteForSite)
 951  
 	{
 952  
 	    // Iterate over the lists and find match
 953  0
 	    Iterator itRemoteForPrincipals = remoteForPrincipals.iterator();
 954  0
 	    while ( itRemoteForPrincipals.hasNext())
 955  
 	    {
 956  0
 	        InternalUserPrincipal remoteForPrincipal = (InternalUserPrincipal)itRemoteForPrincipals.next();
 957  
 	        
 958  
 	        // Find a match in the site list
 959  0
 	        Iterator itRemoteForSite = remoteForSite.iterator();
 960  0
 		    while ( itRemoteForSite.hasNext())
 961  
 		    {
 962  0
 		        InternalUserPrincipal tmp = (InternalUserPrincipal)itRemoteForSite.next();
 963  
 		        
 964  0
 		        if ( tmp.getPrincipalId() == remoteForPrincipal.getPrincipalId() )
 965  0
 		            return remoteForPrincipal;
 966  0
 		    }
 967  0
 	    }
 968  
 	    // No match found
 969  0
 	    return null;
 970  
 	}
 971  
 	
 972  
 	/*
 973  
 	 * getRemotePrincipalsForPrincipals
 974  
 	 * Checks if the user has any remote principals. If the principal is a group expand the group and
 975  
 	 * check if the requesting user is a part of the group.
 976  
 	 */
 977  
 	private Collection getRemotePrincipalsForPrincipal(Collection principalsForSite, String fullPath)
 978  
 	{
 979  0
 	    if (principalsForSite != null )
 980  
 	    {
 981  0
 		    Iterator itPrincipalsForSite = principalsForSite.iterator();
 982  0
 		    while (itPrincipalsForSite.hasNext())
 983  
 		    {
 984  0
 		        String principalFullPath = null;
 985  0
 		        SSOPrincipal principal = (SSOPrincipal)itPrincipalsForSite.next();
 986  0
 		        principalFullPath = principal.getFullPath();
 987  
 		        
 988  
 		        /* If the Principal is for a Group expand the Group and check if the user identified
 989  
 		        * by the fullPath is a member of the Group. If the user is a member of the Group
 990  
 		        * return the remote Credentials for the current Principal.
 991  
 		        */
 992  0
 		        if ( principalFullPath.indexOf("/group/") == -1)
 993  
 		        {
 994  
 		            // USER
 995  0
 		            if ( principalFullPath.compareToIgnoreCase(fullPath) == 0)
 996  0
 		                return principal.getRemotePrincipals();
 997  
 		        }
 998  
 		        else
 999  
 		        {
 1000  
 		            /* GROUP 
 1001  
 		             * If the full path is for a group (delete/add) just return the the list of remotePrincipals
 1002  
 		             * For a lookup (hasCredentials) the user needs to be mapped against each member of the group
 1003  
 		            */
 1004  0
 		            if ( principalFullPath.compareToIgnoreCase(fullPath) == 0)
 1005  0
 		                return principal.getRemotePrincipals();
 1006  
 		            
 1007  
 		            /* Expand the Group and find a match */
 1008  0
 			        InternalGroupPrincipal  groupPrincipal = getGroupPrincipals(principalFullPath);
 1009  
 			        
 1010  
 			        // Found Group that matches the name
 1011  0
 			        if (groupPrincipal != null)
 1012  
 		            {
 1013  0
 			            Collection usersInGroup = groupPrincipal.getUserPrincipals();
 1014  0
 			            Iterator itUsers = usersInGroup.iterator();
 1015  0
 		                while (itUsers.hasNext())
 1016  
 		                {
 1017  0
 		                    InternalUserPrincipal user = (InternalUserPrincipal)itUsers.next();
 1018  0
 		                    if (user.getFullPath().compareToIgnoreCase(fullPath) == 0)
 1019  
 		                    {
 1020  
 		                        // User is member of the group
 1021  0
 		                        return principal.getRemotePrincipals();
 1022  
 		                    }
 1023  0
 		                }
 1024  
 		            }
 1025  
 		        }  
 1026  0
 		    }
 1027  
 	    }
 1028  
 	    
 1029  
 	    // No match found
 1030  0
 	    return null;
 1031  
 	}
 1032  
     
 1033  
     public SSOSite getSite(String siteUrl)
 1034  
     {
 1035  0
         Criteria filter = new Criteria();
 1036  0
         filter.addEqualTo("url", siteUrl);
 1037  0
         Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
 1038  0
         SSOSite site = (SSOSite) getPersistenceBrokerTemplate().getObjectByQuery(query);
 1039  0
         return site;       
 1040  
     }
 1041  
     
 1042  
     public void updateSite(SSOSite site)
 1043  
     throws SSOException
 1044  
     {
 1045  
         try
 1046  
         {
 1047  0
             getPersistenceBrokerTemplate().store(site);
 1048  0
             this.mapSite.put(site.getName(), site);                        
 1049  
         }
 1050  0
         catch (Exception e)
 1051  
         {
 1052  0
             String msg = "Unable to remove SSO Site: " + site.getName();
 1053  0
             logger.error(msg, e);
 1054  0
             throw new SSOException(msg, e);
 1055  0
         }        
 1056  0
     }
 1057  
     
 1058  
     /**
 1059  
      * Add a new site that uses Form Authentication
 1060  
      * @param siteName
 1061  
      * @param siteUrl
 1062  
      * @param realm
 1063  
      * @param userField
 1064  
      * @param pwdField
 1065  
      * @throws SSOException
 1066  
      */
 1067  
     public void addSiteFormAuthenticated(String siteName, String siteUrl, String realm, String userField, String pwdField)
 1068  
     throws SSOException
 1069  
     {
 1070  
     	try
 1071  
         {
 1072  0
             SSOSite ssoSite = new SSOSiteImpl();
 1073  0
             ssoSite.setSiteURL(siteUrl);
 1074  0
             ssoSite.setName(siteName);
 1075  0
             ssoSite.setCertificateRequired(false);
 1076  0
             ssoSite.setAllowUserSet(true);
 1077  0
             ssoSite.setRealm(realm);
 1078  0
             ssoSite.setFormAuthentication(true);
 1079  0
             ssoSite.setFormUserField(userField);
 1080  0
             ssoSite.setFormPwdField(pwdField);
 1081  0
             getPersistenceBrokerTemplate().store(ssoSite);
 1082  0
             this.mapSite.put(siteName, ssoSite);            
 1083  
         }
 1084  0
         catch (Exception e)
 1085  
         {
 1086  0
             String msg = "Unable to add SSO Site: " + siteName;
 1087  0
             logger.error(msg, e);
 1088  0
             throw new SSOException(msg, e);
 1089  0
         }  
 1090  0
     }
 1091  
     
 1092  
     /**
 1093  
      * Add a new site that uses ChallengeResponse Authentication
 1094  
      * @param siteName
 1095  
      * @param siteUrl
 1096  
      * @param realm
 1097  
      * @throws SSOException
 1098  
      */
 1099  
     public void addSiteChallengeResponse(String siteName, String siteUrl, String realm)
 1100  
     throws SSOException
 1101  
     {
 1102  
     	try
 1103  
         {
 1104  0
             SSOSite ssoSite = new SSOSiteImpl();
 1105  0
             ssoSite.setSiteURL(siteUrl);
 1106  0
             ssoSite.setName(siteName);
 1107  0
             ssoSite.setCertificateRequired(false);
 1108  0
             ssoSite.setAllowUserSet(true);
 1109  0
             ssoSite.setRealm(realm);
 1110  0
             ssoSite.setChallengeResponseAuthentication(true);
 1111  0
              getPersistenceBrokerTemplate().store(ssoSite);
 1112  0
             this.mapSite.put(siteName, ssoSite);            
 1113  
         }
 1114  0
         catch (Exception e)
 1115  
         {
 1116  0
             String msg = "Unable to add SSO Site: " + siteName;
 1117  0
             logger.error(msg, e);
 1118  0
             throw new SSOException(msg, e);
 1119  0
         }  
 1120  0
     }
 1121  
     
 1122  
     public void addSite(String siteName, String siteUrl)
 1123  
     throws SSOException
 1124  
     {
 1125  
         try
 1126  
         {
 1127  0
             SSOSite ssoSite = new SSOSiteImpl();
 1128  0
             ssoSite.setSiteURL(siteUrl);
 1129  0
             ssoSite.setName(siteName);
 1130  0
             ssoSite.setCertificateRequired(false);
 1131  0
             ssoSite.setAllowUserSet(true);            
 1132  0
             getPersistenceBrokerTemplate().store(ssoSite);
 1133  0
             this.mapSite.put(siteName, ssoSite);            
 1134  
         }
 1135  0
         catch (Exception e)
 1136  
         {
 1137  0
             String msg = "Unable to remove SSO Site: " + siteName;
 1138  0
             logger.error(msg, e);
 1139  0
             throw new SSOException(msg, e);
 1140  0
         }                
 1141  0
     }
 1142  
     
 1143  
     public void removeSite(SSOSite site)
 1144  
     throws SSOException
 1145  
     {
 1146  
         try
 1147  
         {
 1148  0
             getPersistenceBrokerTemplate().delete(site);
 1149  0
             this.mapSite.remove(site);
 1150  
 
 1151  
         }
 1152  0
         catch (Exception e)
 1153  
         {
 1154  0
             String msg = "Unable to remove SSO Site: " + site.getName();
 1155  0
             logger.error(msg, e);
 1156  0
             throw new SSOException(msg, e);
 1157  0
         }        
 1158  0
     }
 1159  
         
 1160  
     public List getPrincipalsForSite(SSOSite site)
 1161  
     {
 1162  0
         List list = new ArrayList();
 1163  0
         Iterator principals = site.getRemotePrincipals().iterator();
 1164  0
         while (principals.hasNext())
 1165  
         {
 1166  0
             InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)principals.next();
 1167  0
             Iterator creds = remotePrincipal.getCredentials().iterator();
 1168  0
             while (creds.hasNext())
 1169  
             {
 1170  0
                 InternalCredential cred = (InternalCredential) creds.next();
 1171  0
                 SSOContext context = new SSOContextImpl(remotePrincipal.getPrincipalId(), 
 1172  
                                                 stripPrincipalName(remotePrincipal.getFullPath()), 
 1173  
                                                 cred.getValue(), 
 1174  
                                                 stripPortalPrincipalName(remotePrincipal.getFullPath()));
 1175  0
                 list.add(context);
 1176  0
             }
 1177  0
         }
 1178  0
         return list;
 1179  
     }
 1180  
 
 1181  
     
 1182  
     private String stripPortalPrincipalName(String fullPath)
 1183  
     {
 1184  0
         StringTokenizer tokenizer = new StringTokenizer(fullPath, "/");
 1185  0
         while (tokenizer.hasMoreTokens())
 1186  
         {
 1187  0
             String token = tokenizer.nextToken();
 1188  0
             if (token.equals("user") || token.equals("group"))
 1189  
             {
 1190  0
                  if (tokenizer.hasMoreTokens())
 1191  
                 {
 1192  0
                     return tokenizer.nextToken();
 1193  
                 }
 1194  
             }
 1195  0
         }
 1196  0
         return fullPath;        
 1197  
     }
 1198  
     
 1199  
     private InternalGroupPrincipal  getGroupPrincipals(String principalFullPath)
 1200  
     {
 1201  
         // Get to the backend to return the group that matches the full path
 1202  0
         Criteria filter = new Criteria();
 1203  0
         filter.addEqualTo("fullPath", principalFullPath);
 1204  0
         Query query = QueryFactory.newQuery(InternalGroupPrincipalImpl.class, filter);
 1205  0
         InternalGroupPrincipal group = (InternalGroupPrincipal) getPersistenceBrokerTemplate().getObjectByQuery(query);
 1206  0
         return group;       
 1207  
     }
 1208  
     
 1209  
     /*
 1210  
     private SSOSite getSiteForRemoteUser(String fullPath)
 1211  
     {
 1212  
     	// Get Site for remote user
 1213  
         Criteria filter = new Criteria();
 1214  
         filter.addEqualTo("remotePrincipals.fullPath", fullPath);
 1215  
         Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
 1216  
         return  (SSOSite) getPersistenceBrokerTemplate().getObjectByQuery(query);
 1217  
     }
 1218  
     */
 1219  
     
 1220  
     private String getContentFromURL(String proxyID, String destUrl, SSOSite[] sites, boolean bRefresh ) throws SSOException
 1221  
     {
 1222  0
     	URL urlObj = null;
 1223  
     	
 1224  
     	// Result Buffer
 1225  
     	//BufferedInputStream bis = null;
 1226  
     	String resultPage;
 1227  
     	
 1228  0
     	String strErrorMessage = "SSO Component Error. Failed to get content for URL " + destUrl;
 1229  
     	
 1230  
     	try
 1231  
     	{
 1232  0
     		urlObj = new URL(destUrl);
 1233  
     	}
 1234  0
     	catch (MalformedURLException e)
 1235  
     	{
 1236  0
     		String msg = ("Error -- Malformed URL [" + destUrl +"] for SSO authenticated destination");
 1237  0
     		log.error(msg);
 1238  0
     		throw new SSOException(msg, e);
 1239  0
     	}
 1240  
     	
 1241  
     	/* 
 1242  
     	 * Setup HTTPClient
 1243  
     	 * Check if an HTTP Client already exists for the given /user/site
 1244  
     	 */
 1245  0
     	HttpClient client = (HttpClient)this.clientProxy.get(proxyID);
 1246  0
     	GetMethod get = null;
 1247  
     	
 1248  0
     	if (bRefresh == true || client == null)
 1249  
     	{
 1250  0
     		if (log.isInfoEnabled())
 1251  0
     			log.info("SSO Component -- Create new HTTP Client object for Principal/URL [" + proxyID+ "]");
 1252  
     		
 1253  0
 	    	client = new HttpClient();
 1254  0
 	    	client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
 1255  
 	    	
 1256  0
 	    	int numberOfSites = sites.length;
 1257  
 	    	
 1258  
 	    	// Do all the logins for the site
 1259  0
 	    	for (int i=0; i<numberOfSites; i++)
 1260  
 	    	{
 1261  0
 	    		SSOSite site = sites[i];
 1262  
 	    		
 1263  0
 	    		if (site != null)
 1264  
 	    		{
 1265  0
 	    			Iterator itRemotePrincipals = site.getRemotePrincipals().iterator();
 1266  0
 	    			while (itRemotePrincipals.hasNext() )
 1267  
 	    			{
 1268  0
 	    				InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next();
 1269  0
 	            		if (remotePrincipal != null)
 1270  
 	            		{
 1271  0
 	            			InternalCredential credential = null;
 1272  0
 	            			if ( remotePrincipal.getCredentials() != null)
 1273  0
 	            				credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
 1274  
 	            			
 1275  0
 	            			if (credential != null)
 1276  
 	            			{
 1277  0
 	            				if (log.isInfoEnabled())
 1278  0
 	            					log.info("SSOComponent -- Remote Principal ["+stripPrincipalName(remotePrincipal.getFullPath())+"] has credential ["+this.unscramble(credential.getValue())+ "]");
 1279  
 	            				
 1280  0
 	            				client.getState().setCredentials(
 1281  
 	            		    			site.getRealm(),
 1282  
 	            		                urlObj.getHost(),
 1283  
 	            		                new UsernamePasswordCredentials(stripPrincipalName(remotePrincipal.getFullPath()),  this.unscramble(credential.getValue()))
 1284  
 	            		            );
 1285  
 	            				
 1286  
 	            				// Build URL if it's Form authentication
 1287  0
 	            				StringBuffer siteURL = new StringBuffer(site.getSiteURL());
 1288  
 		       					
 1289  
 		        				// Check if it's form based or ChallengeResponse
 1290  0
 	        					if (site.isFormAuthentication())
 1291  
 	        					{
 1292  0
 	        						siteURL.append("?").append(site.getFormUserField()).append("=").append(stripPrincipalName(remotePrincipal.getFullPath())).append("&").append(site.getFormPwdField()).append("=").append(this.unscramble(credential.getValue()));
 1293  
 	        					}
 1294  
 	            				
 1295  0
 	            				get = new GetMethod(siteURL.toString());
 1296  
 	
 1297  
 	            	            // Tell the GET method to automatically handle authentication. The
 1298  
 	            	            // method will use any appropriate credentials to handle basic
 1299  
 	            	            // authentication requests.  Setting this value to false will cause
 1300  
 	            	            // any request for authentication to return with a status of 401.
 1301  
 	            	            // It will then be up to the client to handle the authentication.
 1302  0
 	            	            get.setDoAuthentication( true );
 1303  
 	            	            try {
 1304  
 	            	                // execute the GET
 1305  0
 	            	                int status = client.executeMethod( get );
 1306  
 	            	                
 1307  0
 	            	                if (log.isInfoEnabled() )
 1308  0
 	            	                		log.info("Accessing site [" + site.getSiteURL() + "]. HTTP Status [" +status+ "]" );
 1309  
 	            	                
 1310  
 	            	                /*
 1311  
 	            	    	    	 * If the destination URL and the SSO url match
 1312  
 	            	    	    	 * use the authentication process but return immediately
 1313  
 	            	    	    	 * the result page.
 1314  
 	            	    	    	 */
 1315  0
 	            	                if( destUrl.compareTo(site.getSiteURL()) == 0 && numberOfSites == 1)
 1316  
 	            	                {
 1317  0
 	            	                	if (log.isInfoEnabled() )
 1318  0
 	            	                		log.info("SSO Component --SSO Site and destination URL match. Go and get the content." );
 1319  
 	            	                	
 1320  
 	            	                	//try
 1321  
 	            	            		//{
 1322  
 	            	            			//bis = new BufferedInputStream(get.getResponseBodyAsStream());
 1323  0
 	            	            			resultPage = get.getResponseBodyAsString();
 1324  
 	            	            		//}
 1325  
 	            	            		//catch(IOException ioe)
 1326  
 	            	            		//{
 1327  
 	            	            		//	log.error(strErrorMessage, ioe);
 1328  
 	            	            		//	throw new SSOException (strErrorMessage, ioe);	
 1329  
 	            	            		//}
 1330  
 
 1331  0
 	            	            		get.releaseConnection();
 1332  
 	            	            		
 1333  
 	            	            		//	Add the client object to the cache
 1334  0
 	            	        	    	this.clientProxy.put(proxyID, client);
 1335  
 	            	            		
 1336  
 	            	            		//return bis;
 1337  0
 	            	        	    	return resultPage;
 1338  
 	            	                }
 1339  
 	            	        
 1340  0
 		            			} catch (Exception e) {
 1341  0
 		                        	log.error("Exception while authentication. Error: " +e);	                        
 1342  0
 		                        }
 1343  
 		            			
 1344  0
 		            			get.releaseConnection();
 1345  
 	             			}
 1346  
 	            		}
 1347  0
 	    			}
 1348  
 	    		}   		
 1349  
 	    	}
 1350  
 	    	
 1351  
 	    	// Add the client object to the cache
 1352  0
 	    	this.clientProxy.put(proxyID, client);
 1353  0
     	}
 1354  
     	else
 1355  
     	{
 1356  0
     		if (log.isInfoEnabled())
 1357  0
     			log.info("SSO Component -- Use cached HTTP Client object for Principal/URL [" + proxyID+ "]");
 1358  
     	}
 1359  
     	
 1360  
     	// All the SSO authentication done go to the destination url
 1361  0
 		get = new GetMethod(destUrl);
 1362  
 		try {
 1363  
             // execute the GET
 1364  0
             int status = client.executeMethod( get );
 1365  
             
 1366  0
             log.info("Accessing site [" + destUrl + "]. HTTP Status [" +status+ "]" );
 1367  
     
 1368  0
 		} catch (Exception e) {
 1369  0
         	log.error("Exception while authentication. Error: " +e);	                        
 1370  0
         }
 1371  
 		
 1372  
 		
 1373  
 		try
 1374  
 		{
 1375  
 			//bis = new BufferedInputStream(get.getResponseBodyAsStream());
 1376  0
 			resultPage = get.getResponseBodyAsString();
 1377  
 		}
 1378  0
 		catch(IOException ioe)
 1379  
 		{
 1380  0
 			log.error(strErrorMessage, ioe);
 1381  0
 			throw new SSOException (strErrorMessage, ioe);
 1382  
         }
 1383  0
 		catch (Exception e)
 1384  
 		{
 1385  0
 			log.error(strErrorMessage, e);
 1386  0
 			throw new SSOException (strErrorMessage, e);
 1387  
 			
 1388  
 		}
 1389  
         finally
 1390  
         {
 1391  0
             get.releaseConnection();
 1392  0
         }
 1393  
 		
 1394  
 		//return bis;
 1395  0
 		return resultPage;
 1396  
     }
 1397  
     
 1398  
     /*
 1399  
      * Simple encryption decryption routines since the API creates credentials 
 1400  
      * together with an user.
 1401  
      * TODO: re-implement when Security API is more flexible
 1402  
      */
 1403  0
     static char[] scrambler ="Jestspeed-2 is getting ready for release".toCharArray();
 1404  
     
 1405  
     private String scramble(String pwd)
 1406  
     {
 1407  
         // xor-ing persistent String values is dangerous because of the (uncommon) way Java encodes UTF-8 0x00 (and some other characters).
 1408  
         // See: http://en.wikipedia.org/wiki/UTF-8#Java
 1409  
         // On some database platforms, like PostgreSQL this can lead to something like:
 1410  
         //   org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00
 1411  
         // To prevent this, the resulting xored password is encoded in Base64
 1412  0
     	String xored = new String(xor(pwd.toCharArray(), scrambler));
 1413  0
         byte[] bytes = Base64.encodeBase64(xored.getBytes());
 1414  0
         String scrambled = new String(bytes);
 1415  0
         return scrambled;
 1416  
     }
 1417  
     
 1418  
     private String unscramble(String pwd)
 1419  
     {
 1420  0
     	byte[] bytes = pwd.getBytes();
 1421  0
         bytes = Base64.decodeBase64(bytes);
 1422  0
         String chars = new String(bytes);
 1423  0
         String unscrambled = new String(xor(chars.toCharArray(), scrambler));
 1424  0
         return unscrambled;
 1425  
     }
 1426  
     
 1427  
     private char[] xor(class="keyword">char[] a, class="keyword">char[]b)
 1428  
     {
 1429  0
     	int len = Math.min(a.length, b.length);
 1430  0
     	char[] result = new class="keyword">char[len];
 1431  0
     	for(int i=0; i<len;i++)
 1432  
     	{
 1433  0
     		result[i] = (char) (a[i] ^ b[i]);
 1434  
     	}
 1435  0
     	return result;
 1436  
     }
 1437  
 }

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