View Javadoc

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  	private static final Log log = LogFactory.getLog(PersistenceBrokerSSOProvider.class);
76  	
77  	/*
78  	 * Cache for sites and Proxy sites
79  	 */
80  	private Hashtable mapSite = new Hashtable();
81  	private Hashtable clientProxy = new Hashtable();
82  	
83      private String USER_PATH = "/user/";
84      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         super(repositoryPath);
97      }
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 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
108 		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     	String proxyID = fullPath + "_" + SSOSite;
114     	
115     	// Get the site
116     	SSOSite ssoSite = getSSOSiteObject(SSOSite);
117 		
118 		if ( ssoSite != null)
119 		{
120 			SSOSite[] sites = new SSOSite[1];
121 			sites[0] = ssoSite;
122 			
123 			return this.getContentFromURL(proxyID, url, sites, bRefresh);
124 		}
125 		else
126 		{
127 			// Site doesn't exist -- log an error but continue
128 			String msg = "SSO component -- useSSO can't retrive SSO credential because SSOSite [" + SSOSite + "] doesn't exist";
129 			log.error(msg);
130 			SSOSite[] sites = new SSOSite[0];
131 			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 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
143 		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     	String proxyID = fullPath;
150     	
151     	Collection sites = this.getSitesForPrincipal(fullPath);
152     	
153     	if (sites == null)
154     	{
155     		String msg = "SSO Component useSSO -- Couldn't find any SSO sites for user ["+fullPath+"]";
156     		log.error(msg);
157     		throw new SSOException(msg);
158     	}
159     	
160     	// Load all the sites
161     	int siteSize = sites.size();
162     	int siteIndex =0;
163     	SSOSite[] ssoSites = new SSOSite[siteSize];
164     	
165     	Iterator itSites = sites.iterator();
166     	while(itSites.hasNext())
167     	{
168     		SSOSite ssoSite = (SSOSite)itSites.next();
169     		if (ssoSite != null)
170     		{
171     			ssoSites[siteIndex] = ssoSite;
172     			siteIndex++;
173     		}
174     	}
175     	
176     	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     	SSOPrincipal ssoPrincipal = this.getSSOPrincipal(fullPath);
188     	
189     	// For each remote user we'll get the cookie
190     	Vector temp = new Vector();
191     	
192     	Iterator itRemotePrincipal = ssoPrincipal.getRemotePrincipals().iterator();
193     	while (itRemotePrincipal.hasNext())
194     	{
195     		InternalUserPrincipal rp  = (InternalUserPrincipal)itRemotePrincipal.next();
196     		if (rp != null)
197     		{
198     			temp.add(rp.getFullPath());
199     		}
200     	}
201     	
202     	if (temp.size() > 0)
203     	{
204     	
205 	        Criteria filter = new Criteria();   
206 	        filter.addIn("remotePrincipals.fullPath", temp);
207 	         
208 	        QueryByCriteria query = QueryFactory.newQuery(SSOCookieImpl.class, filter);
209 	        return getPersistenceBrokerTemplate().getCollectionByQuery(query);
210     	}
211     	else
212     	{
213     		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 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(user, UserPrincipal.class);
227 		String fullPath = principal.getFullPath();
228 		
229 		// Call into API
230 		return this.getCookiesForUser(fullPath);
231     }
232     
233 
234     public void setRealmForSite(String site, String realm) throws SSOException
235     {
236     	SSOSite ssoSite = getSSOSiteObject(site);
237 		
238 		if ( ssoSite != null)
239 		{
240 			try
241 			{
242 				ssoSite.setRealm(realm);
243 				getPersistenceBrokerTemplate().store(ssoSite);
244 			}
245 			catch (Exception e)
246 			{
247 				throw new SSOException("Failed to set the realm for site [" + site + "] Error" +e );
248 			}
249 		}
250     }
251     
252     public String getRealmForSite(String site) throws SSOException
253     {
254     	SSOSite ssoSite = getSSOSiteObject(site);
255 		
256 		if ( ssoSite != null)
257 		{
258 			return ssoSite.getRealm();
259 		}
260 		
261 		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     	Criteria filter = new Criteria();       
273         filter.addEqualTo("principals.fullPath", fullPath);
274         
275         QueryByCriteria query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
276         return getPersistenceBrokerTemplate().getCollectionByQuery(query); 
277     }
278     
279 	public Iterator getSites(String filter)
280     {
281         Criteria queryCriteria = new Criteria();
282         Query query = QueryFactory.newQuery(SSOSiteImpl.class, queryCriteria);
283         Collection c = getPersistenceBrokerTemplate().getCollectionByQuery(query);
284         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         Principal principal = null;
299         String name = null;
300         
301         // Group or User
302         if (fullPath.indexOf("/group/") > -1 )
303         {
304             name = fullPath.substring(GROUP_PATH.length());
305             principal = new GroupPrincipalImpl(name);
306         }
307         else
308         {
309             name = fullPath.substring(USER_PATH.length());
310             principal = new UserPrincipalImpl(name);
311         }
312  
313         // Create Subject
314         Set principals = new HashSet();
315         principals.add(principal);
316         Subject subject = new Subject(true, principals, new HashSet(), new HashSet());	
317         
318         // Call into the API
319         addCredentialsForSite(subject, remoteUser, site, pwd);
320     }
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         Principal principal = null;
332         String name = null;
333         
334         // Group or User
335         if (fullPath.indexOf("/group/") > -1 )
336         {
337             name = fullPath.substring(GROUP_PATH.length());
338             principal = new GroupPrincipalImpl(name);
339         }
340         else
341         {
342             name = fullPath.substring(USER_PATH.length());
343             principal = new UserPrincipalImpl(name);
344         }
345  
346         // Create Subject
347         Set principals = new HashSet();
348         principals.add(principal);
349         Subject subject = new Subject(true, principals, new HashSet(), new HashSet());	
350     
351         // Call into the API
352         this.removeCredentialsForSite(subject,site);
353     }
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         return site;
365     }
366     
367     /***
368      * getSiteName
369      */
370     public String getSiteName(String site)
371     {
372         SSOSite ssoSite = getSSOSiteObject(site);
373 		
374 		if ( ssoSite != null)
375 		{
376 			return ssoSite.getName();
377 		}
378 		else
379 		{
380 		    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 		SSOSite ssoSite = getSSOSiteObject(site);
390 		
391 		if ( ssoSite == null)
392 		{
393 			return false;	// no entry for site
394 		}
395 		
396 		// Get the principal from the subject
397 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
398 		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 		Collection remoteForSite		= ssoSite.getRemotePrincipals();
403 		Collection principalsForSite	= ssoSite.getPrincipals();	// Users
404 		
405 		// If any of them don't exist just return
406 		if (principalsForSite == null || remoteForSite== null )
407 		    return false;	// no entry
408 		
409 		Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
410 		
411 		if ( remoteForPrincipals == null)
412 		    return false;	// no entry
413 		
414 		// Get remote Principal that matches the site and the principal
415 		if (findRemoteMatch(remoteForPrincipals, remoteForSite) == null )
416 		{
417 		    return false;	// No entry
418 		}
419 		else
420 		{
421 		    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 		SSOSite ssoSite = getSSOSiteObject(site);
433 		
434 		if ( ssoSite == null)
435 			throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);	// no entry for site
436 		
437 		// Get the principal from the subject
438 		BasePrincipal principal = (BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class);
439 		String fullPath = principal.getFullPath();
440 		
441 		// Filter the credentials for the given principals
442 		SSOContext context = getCredential(ssoSite, fullPath);	
443 		
444 		if ( context == null)
445 			throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);	// no entry for site
446 		
447 		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 		SSOSite ssoSite = getSSOSiteObject(site);
459 		if (ssoSite == null)
460 		{
461 			// Create a new site
462 			ssoSite = new SSOSiteImpl();
463 			ssoSite.setSiteURL(site);
464 			ssoSite.setName(site);
465 			ssoSite.setCertificateRequired(false);
466 			ssoSite.setAllowUserSet(true);
467 			// By default we use ChallengeResponse Authentication
468 			ssoSite.setChallengeResponseAuthentication(true);
469 			ssoSite.setFormAuthentication(false);
470 			
471 			// Store the site so that we get a valid SSOSiteID
472 			try
473 	         {
474 	             getPersistenceBrokerTemplate().store(ssoSite);
475 	          }
476 	         catch (Exception e)
477 	         {
478 	         	e.printStackTrace();
479 	            throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
480 	         }
481 		}
482 		
483 		// Get the Principal information (logged in user)
484 		String fullPath = ((BasePrincipal)SecurityHelper.getBestPrincipal(subject, UserPrincipal.class)).getFullPath();
485 		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 		SSOPrincipal principal = this.getPrincipalForSite(ssoSite, fullPath);
489 		
490 		if (principal == null )
491 		{
492 		    principal = getSSOPrincipal(fullPath);
493 		    ssoSite.addPrincipal(principal);
494 		}
495 		else
496 		{
497 		    // Check if the entry the user likes to update exists already
498 		    Collection remoteForSite = ssoSite.getRemotePrincipals();
499 		    Collection principalsForSite = ssoSite.getPrincipals();
500 		    
501 		    if ( remoteForSite != null && principalsForSite != null)
502 		    {
503 		        Collection remoteForPrincipals = this.getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
504 		        if ( remoteForPrincipals != null)
505 		        {
506 			        if (findRemoteMatch(remoteForPrincipals, remoteForSite) != null )
507 			        {
508 			            // Entry exists can't to an add has to call update
509 			            throw new SSOException(SSOException.REMOTE_PRINCIPAL_EXISTS_CALL_UPDATE);
510 			        }
511 		        }
512 		    }
513 		}
514 		
515 		if (principal == null)
516 			throw new SSOException(SSOException.FAILED_ADDING_PRINCIPAL_TO_MAPPING_TABLE_FOR_SITE);
517 		
518 		// Create a remote principal and credentials
519 		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 		if ( fullPath.indexOf("/group/") > -1)
527 		    remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/group/"+  principalName + "/" + remoteUser);
528 		else
529 		    remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/user/"+ principalName + "/" + remoteUser);
530 		
531 		// New credential object for remote principal
532 		 InternalCredentialImpl credential = 
533             new InternalCredentialImpl(remotePrincipal.getPrincipalId(),
534             		this.scramble(pwd), 0, DefaultPasswordCredentialImpl.class.getName());
535 		 
536 		 if ( remotePrincipal.getCredentials() == null)
537 		 	remotePrincipal.setCredentials(new ArrayList(0));
538 		 
539 		remotePrincipal.getCredentials().add( credential);
540 		
541 		// Add it to Principals remotePrincipals list
542 		principal.addRemotePrincipal(remotePrincipal);
543 
544 		// Update the site remotePrincipals list
545 		ssoSite.getRemotePrincipals().add(remotePrincipal);
546 		
547 		 	
548 		// Update database and reset cache
549 		 try
550          {
551              getPersistenceBrokerTemplate().store(ssoSite);
552              
553              // Persist Principal/Remote
554      		getPersistenceBrokerTemplate().store(principal);
555           }
556          catch (Exception e)
557          {
558          	e.printStackTrace();
559             throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
560          }
561          
562          // Add to site
563          this.mapSite.put(site, ssoSite);
564 	}
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 		InternalUserPrincipal remotePrincipal = null;
574 		//Get the site
575 		SSOSite ssoSite = getSSOSiteObject(site);
576 		if (ssoSite == null)
577 		{
578 			throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
579 		}
580 		
581 		// Get the Principal information
582 		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 			Collection principalsForSite = ssoSite.getPrincipals();
588 			Collection remoteForSite = ssoSite.getRemotePrincipals();
589 			
590 			// If any of them don't exist just return
591 			if (principalsForSite == null || remoteForSite== null )
592 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
593 			
594 			Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
595 			
596 			if ( remoteForPrincipals == null)
597 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
598 			
599 			// Get remote Principal that matches the site and the principal
600 			if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
601 			{
602 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
603 			}
604 
605 			// Update assocation tables
606 			ssoSite.getRemotePrincipals().remove(remotePrincipal);
607 			
608 			if (remoteForPrincipals.remove(remotePrincipal) == true)
609 			
610 			// Update the site
611 			getPersistenceBrokerTemplate().store(ssoSite);
612 
613 			// delete the remote Principal from the SECURITY_PRINCIPAL table
614 		    getPersistenceBrokerTemplate().delete(remotePrincipal);
615 		    
616 						
617 		}
618 		catch(SSOException ssoex)
619 		{
620 			throw new SSOException(ssoex);
621 		}
622 		catch (Exception e)
623         {
624         	e.printStackTrace();
625            throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
626         }
627 								
628 		// Update database
629 		 try
630          {
631              getPersistenceBrokerTemplate().store(ssoSite);
632           }
633          catch (Exception e)
634          {
635          	e.printStackTrace();
636             throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
637          }
638          
639 	}
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 			InternalUserPrincipal remotePrincipal = null;
656 			
657 			//Get the site
658 			SSOSite ssoSite = getSSOSiteObject(site);
659 			if (ssoSite == null)
660 			{
661 				throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
662 			}
663 			
664 			// Get the Principal information
665 			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 			Collection principalsForSite	= ssoSite.getPrincipals();
669 			Collection remoteForSite		= ssoSite.getRemotePrincipals();
670 			
671 			// If any of them don't exist just return
672 			if (principalsForSite == null || remoteForSite== null )
673 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
674 			
675 			Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
676 			
677 			if ( remoteForPrincipals == null)
678 			    throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
679 			
680 			// Get remote Principal that matches the site and the principal
681 			if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
682 			{
683 			    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 			InternalCredential credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
690 					
691 			// New credential object
692 			 if ( credential != null) 
693 				// Remove credential and principal from mapping
694 				 credential.setValue(this.scramble(pwd));
695 			
696 			// Update database and reset cache
697 			 try
698 			 {
699 			     getPersistenceBrokerTemplate().store(credential);
700 			  }
701 			 catch (Exception e)
702 			 {
703 			 	e.printStackTrace();
704 			    throw new SSOException(SSOException.FAILED_STORING_SITE_INFO_IN_DB + e.toString() );
705 			 }			 
706 	    }
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 		SSOSite ssoSite = null;
722 		
723 		//Check if the site is in the map
724 		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 		    Criteria filter = new Criteria();       
730 		    filter.addEqualTo("siteURL", site);
731 		    
732 		    QueryByCriteria query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
733 		    Collection ssoSiteCollection = getPersistenceBrokerTemplate().getCollectionByQuery(query);                    
734 		    
735 		    if ( ssoSiteCollection != null && ssoSiteCollection.isEmpty() != true)
736 		    {
737 		    	Iterator itSite = ssoSiteCollection.iterator();
738 		    	// Get the site from the collection. There should be only one entry (uniqueness)
739 		    	if (itSite.hasNext())
740 			    {
741 				    	ssoSite = (SSOSite) itSite.next();
742 			    }
743 		    	
744 		    	// Add it to the map
745 		    	mapSite.put(site, ssoSite);
746 		    }
747 		    else
748 		    {
749 		    	// No entry for this site
750 		    	return null;
751 		    }
752 		}
753 		else
754 		{
755 			ssoSite = (SSOSite)mapSite.get(site);
756 		}
757 		
758 		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 		InternalCredential credential = null;
768 		InternalUserPrincipal remotePrincipal = null;
769 		//	Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
770 		Collection principalsForSite = ssoSite.getPrincipals();
771 		Collection remoteForSite = ssoSite.getRemotePrincipals();
772 		
773 		// If any of them don't exist just return
774 		if ( principalsForSite == null  || remoteForSite== null )
775 		    return null;	// no entry
776 		
777 		Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(principalsForSite, fullPath);
778 				
779 		if ( remoteForPrincipals == null)
780 		    return null;	// no entry
781 		
782 		// Get remote Principal that matches the site and the principal
783 		if ((remotePrincipal = findRemoteMatch(remoteForPrincipals, remoteForSite)) == null )
784 		{
785 		    return null;	// No entry
786 		}
787 		else
788 		{
789 		    // Has an entry
790 			if ( remotePrincipal.getCredentials() != null)
791 				credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
792 			
793 			// Error checking  -- should have a credential at this point
794 			if ( credential == null)
795 			{
796 //				System.out.println("Warning: Remote User " + remotePrincipal.getFullPath() + " doesn't have a credential");
797 				return null; 
798 			}
799 		}
800 		
801 		//	Create new context
802 		String name = stripPrincipalName(remotePrincipal.getFullPath());
803 		
804 		SSOContext context = new SSOContextImpl(credential.getPrincipalId(), name, this.unscramble(credential.getValue()));
805 		
806 		return context;
807 	}
808 	
809     private String stripPrincipalName(String fullPath)
810     {
811         String name;
812         int ix = fullPath.lastIndexOf('/');
813         if ( ix != -1)
814             name = fullPath.substring(ix + 1);
815         else
816             name = new String(fullPath);
817         
818         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 		SSOPrincipal principal = null;
856 		Collection principalsForSite = ssoSite.getPrincipals();
857 		
858 		if ( principalsForSite != null)
859 		{
860 			Iterator itPrincipals = principalsForSite.iterator();
861 			while (itPrincipals.hasNext() && principal == null)
862 			{
863 				SSOPrincipal tmp  = (SSOPrincipal)itPrincipals.next();
864 				if ( 		 tmp != null 
865 				       && tmp.getFullPath().compareToIgnoreCase(fullPath) == 0 )
866 					principal = tmp;	// Found existing entry
867 			}
868 		}
869 		
870 		return principal;
871 	}
872 	
873 	private SSOPrincipal getSSOPrincipal(String fullPath)
874 	{
875 	    // FInd if the principal exists in the SECURITY_PRINCIPAL table
876 	    SSOPrincipal principal = null;
877 	    
878 		Criteria filter = new Criteria();       
879 	    filter.addEqualTo("fullPath", fullPath);
880 	    
881 	    QueryByCriteria query = QueryFactory.newQuery(SSOPrincipalImpl.class, filter);
882 	    Collection principals = getPersistenceBrokerTemplate().getCollectionByQuery(query);                    
883 	    
884 	    if ( principals != null && principals.isEmpty() != true)
885 	    {
886 	    	Iterator itPrincipals = principals.iterator();
887 	    	// Get the site from the collection. There should be only one entry (uniqueness)
888 	    	if (itPrincipals.hasNext())
889 		    {
890 	    		principal = (SSOPrincipal) itPrincipals.next();
891 		    }
892 	    }
893 	    
894 		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 	    Iterator itRemoteForPrincipals = remoteForPrincipals.iterator();
947 	    while ( itRemoteForPrincipals.hasNext())
948 	    {
949 	        InternalUserPrincipal remoteForPrincipal = (InternalUserPrincipal)itRemoteForPrincipals.next();
950 	        
951 	        // Find a match in the site list
952 	        Iterator itRemoteForSite = remoteForSite.iterator();
953 		    while ( itRemoteForSite.hasNext())
954 		    {
955 		        InternalUserPrincipal tmp = (InternalUserPrincipal)itRemoteForSite.next();
956 		        
957 		        if ( tmp.getPrincipalId() == remoteForPrincipal.getPrincipalId() )
958 		            return remoteForPrincipal;
959 		    }
960 	    }
961 	    // No match found
962 	    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 	    if (principalsForSite != null )
973 	    {
974 		    Iterator itPrincipalsForSite = principalsForSite.iterator();
975 		    while (itPrincipalsForSite.hasNext())
976 		    {
977 		        String principalFullPath = null;
978 		        SSOPrincipal principal = (SSOPrincipal)itPrincipalsForSite.next();
979 		        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 		        if ( principalFullPath.indexOf("/group/") == -1)
986 		        {
987 		            // USER
988 		            if ( principalFullPath.compareToIgnoreCase(fullPath) == 0)
989 		                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 		            if ( principalFullPath.compareToIgnoreCase(fullPath) == 0)
998 		                return principal.getRemotePrincipals();
999 		            
1000 		            /* Expand the Group and find a match */
1001 			        InternalGroupPrincipal  groupPrincipal = getGroupPrincipals(principalFullPath);
1002 			        
1003 			        // Found Group that matches the name
1004 			        if (groupPrincipal != null)
1005 		            {
1006 			            Collection usersInGroup = groupPrincipal.getUserPrincipals();
1007 			            Iterator itUsers = usersInGroup.iterator();
1008 		                while (itUsers.hasNext())
1009 		                {
1010 		                    InternalUserPrincipal user = (InternalUserPrincipal)itUsers.next();
1011 		                    if (user.getFullPath().compareToIgnoreCase(fullPath) == 0)
1012 		                    {
1013 		                        // User is member of the group
1014 		                        return principal.getRemotePrincipals();
1015 		                    }
1016 		                }
1017 		            }
1018 		        }  
1019 		    }
1020 	    }
1021 	    
1022 	    // No match found
1023 	    return null;
1024 	}
1025     
1026     public SSOSite getSite(String siteUrl)
1027     {
1028         Criteria filter = new Criteria();
1029         filter.addEqualTo("url", siteUrl);
1030         Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
1031         SSOSite site = (SSOSite) getPersistenceBrokerTemplate().getObjectByQuery(query);
1032         return site;       
1033     }
1034     
1035     public void updateSite(SSOSite site)
1036     throws SSOException
1037     {
1038         try
1039         {
1040             getPersistenceBrokerTemplate().store(site);
1041             this.mapSite.put(site.getName(), site);                        
1042         }
1043         catch (Exception e)
1044         {
1045             String msg = "Unable to remove SSO Site: " + site.getName();
1046             logger.error(msg, e);
1047             throw new SSOException(msg, e);
1048         }        
1049     }
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             SSOSite ssoSite = new SSOSiteImpl();
1066             ssoSite.setSiteURL(siteUrl);
1067             ssoSite.setName(siteName);
1068             ssoSite.setCertificateRequired(false);
1069             ssoSite.setAllowUserSet(true);
1070             ssoSite.setRealm(realm);
1071             ssoSite.setFormAuthentication(true);
1072             ssoSite.setFormUserField(userField);
1073             ssoSite.setFormPwdField(pwdField);
1074             getPersistenceBrokerTemplate().store(ssoSite);
1075             this.mapSite.put(siteName, ssoSite);            
1076         }
1077         catch (Exception e)
1078         {
1079             String msg = "Unable to add SSO Site: " + siteName;
1080             logger.error(msg, e);
1081             throw new SSOException(msg, e);
1082         }  
1083     }
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             SSOSite ssoSite = new SSOSiteImpl();
1098             ssoSite.setSiteURL(siteUrl);
1099             ssoSite.setName(siteName);
1100             ssoSite.setCertificateRequired(false);
1101             ssoSite.setAllowUserSet(true);
1102             ssoSite.setRealm(realm);
1103             ssoSite.setChallengeResponseAuthentication(true);
1104              getPersistenceBrokerTemplate().store(ssoSite);
1105             this.mapSite.put(siteName, ssoSite);            
1106         }
1107         catch (Exception e)
1108         {
1109             String msg = "Unable to add SSO Site: " + siteName;
1110             logger.error(msg, e);
1111             throw new SSOException(msg, e);
1112         }  
1113     }
1114     
1115     public void addSite(String siteName, String siteUrl)
1116     throws SSOException
1117     {
1118         try
1119         {
1120             SSOSite ssoSite = new SSOSiteImpl();
1121             ssoSite.setSiteURL(siteUrl);
1122             ssoSite.setName(siteName);
1123             ssoSite.setCertificateRequired(false);
1124             ssoSite.setAllowUserSet(true);            
1125             getPersistenceBrokerTemplate().store(ssoSite);
1126             this.mapSite.put(siteName, ssoSite);            
1127         }
1128         catch (Exception e)
1129         {
1130             String msg = "Unable to remove SSO Site: " + siteName;
1131             logger.error(msg, e);
1132             throw new SSOException(msg, e);
1133         }                
1134     }
1135     
1136     public void removeSite(SSOSite site)
1137     throws SSOException
1138     {
1139         try
1140         {
1141             getPersistenceBrokerTemplate().delete(site);
1142             this.mapSite.remove(site);
1143 
1144         }
1145         catch (Exception e)
1146         {
1147             String msg = "Unable to remove SSO Site: " + site.getName();
1148             logger.error(msg, e);
1149             throw new SSOException(msg, e);
1150         }        
1151     }
1152         
1153     public List getPrincipalsForSite(SSOSite site)
1154     {
1155         List list = new ArrayList();
1156         Iterator principals = site.getRemotePrincipals().iterator();
1157         while (principals.hasNext())
1158         {
1159             InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)principals.next();
1160             Iterator creds = remotePrincipal.getCredentials().iterator();
1161             while (creds.hasNext())
1162             {
1163                 InternalCredential cred = (InternalCredential) creds.next();
1164                 SSOContext context = new SSOContextImpl(remotePrincipal.getPrincipalId(), 
1165                                                 stripPrincipalName(remotePrincipal.getFullPath()), 
1166                                                 cred.getValue(), 
1167                                                 stripPortalPrincipalName(remotePrincipal.getFullPath()));
1168                 list.add(context);
1169             }
1170         }
1171         return list;
1172     }
1173 
1174     
1175     private String stripPortalPrincipalName(String fullPath)
1176     {
1177         StringTokenizer tokenizer = new StringTokenizer(fullPath, "/");
1178         while (tokenizer.hasMoreTokens())
1179         {
1180             String token = tokenizer.nextToken();
1181             if (token.equals("user") || token.equals("group"))
1182             {
1183                  if (tokenizer.hasMoreTokens())
1184                 {
1185                     return tokenizer.nextToken();
1186                 }
1187             }
1188         }
1189         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         Criteria filter = new Criteria();
1196         filter.addEqualTo("fullPath", principalFullPath);
1197         Query query = QueryFactory.newQuery(InternalGroupPrincipalImpl.class, filter);
1198         InternalGroupPrincipal group = (InternalGroupPrincipal) getPersistenceBrokerTemplate().getObjectByQuery(query);
1199         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     	URL urlObj = null;
1216     	
1217     	// Result Buffer
1218     	//BufferedInputStream bis = null;
1219     	String resultPage;
1220     	
1221     	String strErrorMessage = "SSO Component Error. Failed to get content for URL " + destUrl;
1222     	
1223     	try
1224     	{
1225     		urlObj = new URL(destUrl);
1226     	}
1227     	catch (MalformedURLException e)
1228     	{
1229     		String msg = ("Error -- Malformed URL [" + destUrl +"] for SSO authenticated destination");
1230     		log.error(msg);
1231     		throw new SSOException(msg, e);
1232     	}
1233     	
1234     	/* 
1235     	 * Setup HTTPClient
1236     	 * Check if an HTTP Client already exists for the given /user/site
1237     	 */
1238     	HttpClient client = (HttpClient)this.clientProxy.get(proxyID);
1239     	GetMethod get = null;
1240     	
1241     	if (bRefresh == true || client == null)
1242     	{
1243     		if (log.isInfoEnabled())
1244     			log.info("SSO Component -- Create new HTTP Client object for Principal/URL [" + proxyID+ "]");
1245     		
1246 	    	client = new HttpClient();
1247 	    	client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
1248 	    	
1249 	    	int numberOfSites = sites.length;
1250 	    	
1251 	    	// Do all the logins for the site
1252 	    	for (int i=0; i<numberOfSites; i++)
1253 	    	{
1254 	    		SSOSite site = sites[i];
1255 	    		
1256 	    		if (site != null)
1257 	    		{
1258 	    			Iterator itRemotePrincipals = site.getRemotePrincipals().iterator();
1259 	    			while (itRemotePrincipals.hasNext() )
1260 	    			{
1261 	    				InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next();
1262 	            		if (remotePrincipal != null)
1263 	            		{
1264 	            			InternalCredential credential = null;
1265 	            			if ( remotePrincipal.getCredentials() != null)
1266 	            				credential = (InternalCredential)remotePrincipal.getCredentials().iterator().next();
1267 	            			
1268 	            			if (credential != null)
1269 	            			{
1270 	            				if (log.isInfoEnabled())
1271 	            					log.info("SSOComponent -- Remote Principal ["+stripPrincipalName(remotePrincipal.getFullPath())+"] has credential ["+this.unscramble(credential.getValue())+ "]");
1272 	            				
1273 	            				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 	            				StringBuffer siteURL = new StringBuffer(site.getSiteURL());
1281 		       					
1282 		        				// Check if it's form based or ChallengeResponse
1283 	        					if (site.isFormAuthentication())
1284 	        					{
1285 	        						siteURL.append("?").append(site.getFormUserField()).append("=").append(stripPrincipalName(remotePrincipal.getFullPath())).append("&").append(site.getFormPwdField()).append("=").append(this.unscramble(credential.getValue()));
1286 	        					}
1287 	            				
1288 	            				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 	            	            get.setDoAuthentication( true );
1296 	            	            try {
1297 	            	                // execute the GET
1298 	            	                int status = client.executeMethod( get );
1299 	            	                
1300 	            	                if (log.isInfoEnabled() )
1301 	            	                		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 	            	                if( destUrl.compareTo(site.getSiteURL()) == 0 && numberOfSites == 1)
1309 	            	                {
1310 	            	                	if (log.isInfoEnabled() )
1311 	            	                		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 	            	            			resultPage = get.getResponseBodyAsString();
1317 	            	            		//}
1318 	            	            		//catch(IOException ioe)
1319 	            	            		//{
1320 	            	            		//	log.error(strErrorMessage, ioe);
1321 	            	            		//	throw new SSOException (strErrorMessage, ioe);	
1322 	            	            		//}
1323 
1324 	            	            		get.releaseConnection();
1325 	            	            		
1326 	            	            		//	Add the client object to the cache
1327 	            	        	    	this.clientProxy.put(proxyID, client);
1328 	            	            		
1329 	            	            		//return bis;
1330 	            	        	    	return resultPage;
1331 	            	                }
1332 	            	        
1333 		            			} catch (Exception e) {
1334 		                        	log.error("Exception while authentication. Error: " +e);	                        
1335 		                        }
1336 		            			
1337 		            			get.releaseConnection();
1338 	             			}
1339 	            		}
1340 	    			}
1341 	    		}   		
1342 	    	}
1343 	    	
1344 	    	// Add the client object to the cache
1345 	    	this.clientProxy.put(proxyID, client);
1346     	}
1347     	else
1348     	{
1349     		if (log.isInfoEnabled())
1350     			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 		get = new GetMethod(destUrl);
1355 		try {
1356             // execute the GET
1357             int status = client.executeMethod( get );
1358             
1359             log.info("Accessing site [" + destUrl + "]. HTTP Status [" +status+ "]" );
1360     
1361 		} catch (Exception e) {
1362         	log.error("Exception while authentication. Error: " +e);	                        
1363         }
1364 		
1365 		
1366 		try
1367 		{
1368 			//bis = new BufferedInputStream(get.getResponseBodyAsStream());
1369 			resultPage = get.getResponseBodyAsString();
1370 		}
1371 		catch(IOException ioe)
1372 		{
1373 			log.error(strErrorMessage, ioe);
1374 			throw new SSOException (strErrorMessage, ioe);
1375         }
1376 		catch (Exception e)
1377 		{
1378 			log.error(strErrorMessage, e);
1379 			throw new SSOException (strErrorMessage, e);
1380 			
1381 		}
1382         finally
1383         {
1384             get.releaseConnection();
1385         }
1386 		
1387 		//return bis;
1388 		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     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     	String xored = new String(xor(pwd.toCharArray(), scrambler));
1406         byte[] bytes = Base64.encodeBase64(xored.getBytes());
1407         String scrambled = new String(bytes);
1408         return scrambled;
1409     }
1410     
1411     private String unscramble(String pwd)
1412     {
1413     	byte[] bytes = pwd.getBytes();
1414         bytes = Base64.decodeBase64(bytes);
1415         String chars = new String(bytes);
1416         String unscrambled = new String(xor(chars.toCharArray(), scrambler));
1417         return unscrambled;
1418     }
1419     
1420     private char[] xor(char[] a, char[]b)
1421     {
1422     	int len = Math.min(a.length, b.length);
1423     	char[] result = new char[len];
1424     	for(int i=0; i<len;i++)
1425     	{
1426     		result[i] = (char) (a[i] ^ b[i]);
1427     	}
1428     	return result;
1429     }
1430 }