0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package org.apache.jetspeed.sso.impl;
0018:
0019: import java.io.IOException;
0020: import java.net.MalformedURLException;
0021: import java.net.URL;
0022: import java.security.Principal;
0023: import java.util.ArrayList;
0024: import java.util.Collection;
0025: import java.util.HashSet;
0026: import java.util.Hashtable;
0027: import java.util.Iterator;
0028: import java.util.List;
0029: import java.util.Set;
0030: import java.util.StringTokenizer;
0031: import java.util.Vector;
0032:
0033: import javax.security.auth.Subject;
0034:
0035: import org.apache.commons.codec.binary.Base64;
0036: import org.apache.commons.httpclient.HttpClient;
0037: import org.apache.commons.httpclient.UsernamePasswordCredentials;
0038: import org.apache.commons.httpclient.cookie.CookiePolicy;
0039: import org.apache.commons.httpclient.methods.GetMethod;
0040: import org.apache.commons.logging.Log;
0041: import org.apache.commons.logging.LogFactory;
0042: import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport;
0043: import org.apache.jetspeed.security.BasePrincipal;
0044: import org.apache.jetspeed.security.SecurityHelper;
0045: import org.apache.jetspeed.security.UserPrincipal;
0046: import org.apache.jetspeed.security.impl.GroupPrincipalImpl;
0047: import org.apache.jetspeed.security.impl.UserPrincipalImpl;
0048: import org.apache.jetspeed.security.om.InternalCredential;
0049: import org.apache.jetspeed.security.om.InternalGroupPrincipal;
0050: import org.apache.jetspeed.security.om.InternalUserPrincipal;
0051: import org.apache.jetspeed.security.om.impl.InternalCredentialImpl;
0052: import org.apache.jetspeed.security.om.impl.InternalGroupPrincipalImpl;
0053: import org.apache.jetspeed.security.om.impl.InternalUserPrincipalImpl;
0054: import org.apache.jetspeed.security.spi.impl.DefaultPasswordCredentialImpl;
0055: import org.apache.jetspeed.sso.SSOContext;
0056: import org.apache.jetspeed.sso.SSOException;
0057: import org.apache.jetspeed.sso.SSOPrincipal;
0058: import org.apache.jetspeed.sso.SSOProvider;
0059: import org.apache.jetspeed.sso.SSOSite;
0060: import org.apache.ojb.broker.query.Criteria;
0061: import org.apache.ojb.broker.query.Query;
0062: import org.apache.ojb.broker.query.QueryByCriteria;
0063: import org.apache.ojb.broker.query.QueryFactory;
0064:
0065: /**
0066: * <p>Utility component to handle SSO requests</p>
0067: *
0068: * @author <a href="mailto:rogerrut@apache.org">Roger Ruttimann</a>
0069: */
0070: public class PersistenceBrokerSSOProvider extends
0071: InitablePersistenceBrokerDaoSupport implements SSOProvider {
0072: /* Logging */
0073: private static final Log log = LogFactory
0074: .getLog(PersistenceBrokerSSOProvider.class);
0075:
0076: /*
0077: * Cache for sites and Proxy sites
0078: */
0079: private Hashtable mapSite = new Hashtable();
0080: private Hashtable clientProxy = new Hashtable();
0081:
0082: private String USER_PATH = "/user/";
0083: private String GROUP_PATH = "/group/";
0084:
0085: /**
0086: * PersitenceBrokerSSOProvider()
0087: * @param repository Location of repository mapping file. Must be available within the classpath.
0088: * @param prefsFactoryImpl <code>java.util.prefs.PreferencesFactory</code> implementation to use.
0089: * @param enablePropertyManager Whether or not we chould be suing the property manager.
0090: * @throws ClassNotFoundException if the <code>prefsFactoryImpl</code> argument does not reperesent
0091: * a Class that exists in the current classPath.
0092: */
0093: public PersistenceBrokerSSOProvider(String repositoryPath)
0094: throws ClassNotFoundException {
0095: super (repositoryPath);
0096: }
0097:
0098: /*
0099: * (non-Javadoc)
0100: * @see org.apache.jetspeed.sso.SSOProvider#useSSO(java.lang.String, java.lang.String, java.lang.String)
0101: */
0102: public String useSSO(Subject subject, String url, String SSOSite,
0103: boolean bRefresh) throws SSOException {
0104: // Get the principal from the subject
0105: BasePrincipal principal = (BasePrincipal) SecurityHelper
0106: .getBestPrincipal(subject, UserPrincipal.class);
0107: String fullPath = principal.getFullPath();
0108:
0109: /* ProxyID is used for the cache. The http client object will be cached for a
0110: * given user site url combination
0111: */
0112: String proxyID = fullPath + "_" + SSOSite;
0113:
0114: // Get the site
0115: SSOSite ssoSite = getSSOSiteObject(SSOSite);
0116:
0117: if (ssoSite != null) {
0118: SSOSite[] sites = new SSOSite[1];
0119: sites[0] = ssoSite;
0120:
0121: return this
0122: .getContentFromURL(proxyID, url, sites, bRefresh);
0123: } else {
0124: // Site doesn't exist -- log an error but continue
0125: String msg = "SSO component -- useSSO can't retrive SSO credential because SSOSite ["
0126: + SSOSite + "] doesn't exist";
0127: log.error(msg);
0128: SSOSite[] sites = new SSOSite[0];
0129: return this
0130: .getContentFromURL(proxyID, url, sites, bRefresh);
0131: }
0132: }
0133:
0134: /*
0135: * (non-Javadoc)
0136: * @see org.apache.jetspeed.sso.SSOProvider#useSSO(java.lang.String, java.lang.String)
0137: */
0138: public String useSSO(Subject subject, String url, boolean bRefresh)
0139: throws SSOException {
0140: // Get the principal from the subject
0141: BasePrincipal principal = (BasePrincipal) SecurityHelper
0142: .getBestPrincipal(subject, UserPrincipal.class);
0143: String fullPath = principal.getFullPath();
0144:
0145: /* ProxyID is used for the cache. The http client object will be cached for a
0146: * given user
0147: */
0148: String proxyID = fullPath;
0149:
0150: Collection sites = this .getSitesForPrincipal(fullPath);
0151:
0152: if (sites == null) {
0153: String msg = "SSO Component useSSO -- Couldn't find any SSO sites for user ["
0154: + fullPath + "]";
0155: log.error(msg);
0156: throw new SSOException(msg);
0157: }
0158:
0159: // Load all the sites
0160: int siteSize = sites.size();
0161: int siteIndex = 0;
0162: SSOSite[] ssoSites = new SSOSite[siteSize];
0163:
0164: Iterator itSites = sites.iterator();
0165: while (itSites.hasNext()) {
0166: SSOSite ssoSite = (SSOSite) itSites.next();
0167: if (ssoSite != null) {
0168: ssoSites[siteIndex] = ssoSite;
0169: siteIndex++;
0170: }
0171: }
0172:
0173: return this .getContentFromURL(proxyID, url, ssoSites, bRefresh);
0174: }
0175:
0176: /**
0177: * Retrive cookies for an user by User full path
0178: * @param fullPath
0179: * @return
0180: */
0181: public Collection getCookiesForUser(String fullPath) {
0182: // Get the SSO user identified by the fullPath
0183: SSOPrincipal ssoPrincipal = this .getSSOPrincipal(fullPath);
0184:
0185: // For each remote user we'll get the cookie
0186: Vector temp = new Vector();
0187:
0188: Iterator itRemotePrincipal = ssoPrincipal.getRemotePrincipals()
0189: .iterator();
0190: while (itRemotePrincipal.hasNext()) {
0191: InternalUserPrincipal rp = (InternalUserPrincipal) itRemotePrincipal
0192: .next();
0193: if (rp != null) {
0194: temp.add(rp.getFullPath());
0195: }
0196: }
0197:
0198: if (temp.size() > 0) {
0199:
0200: Criteria filter = new Criteria();
0201: filter.addIn("remotePrincipals.fullPath", temp);
0202:
0203: QueryByCriteria query = QueryFactory.newQuery(
0204: SSOCookieImpl.class, filter);
0205: return getPersistenceBrokerTemplate().getCollectionByQuery(
0206: query);
0207: } else {
0208: return null;
0209: }
0210:
0211: }
0212:
0213: /**
0214: * Retrive Cookies by Subject
0215: * @param user
0216: * @return
0217: */
0218: public Collection getCookiesForUser(Subject user) {
0219: // Get the principal from the subject
0220: BasePrincipal principal = (BasePrincipal) SecurityHelper
0221: .getBestPrincipal(user, UserPrincipal.class);
0222: String fullPath = principal.getFullPath();
0223:
0224: // Call into API
0225: return this .getCookiesForUser(fullPath);
0226: }
0227:
0228: public void setRealmForSite(String site, String realm)
0229: throws SSOException {
0230: SSOSite ssoSite = getSSOSiteObject(site);
0231:
0232: if (ssoSite != null) {
0233: try {
0234: ssoSite.setRealm(realm);
0235: getPersistenceBrokerTemplate().store(ssoSite);
0236: } catch (Exception e) {
0237: throw new SSOException(
0238: "Failed to set the realm for site [" + site
0239: + "] Error" + e);
0240: }
0241: }
0242: }
0243:
0244: public String getRealmForSite(String site) throws SSOException {
0245: SSOSite ssoSite = getSSOSiteObject(site);
0246:
0247: if (ssoSite != null) {
0248: return ssoSite.getRealm();
0249: }
0250:
0251: return null;
0252: }
0253:
0254: /**
0255: * Get all SSOSites that the principal has access to
0256: * @param userId
0257: * @return
0258: */
0259: public Collection getSitesForPrincipal(String fullPath) {
0260:
0261: Criteria filter = new Criteria();
0262: filter.addEqualTo("principals.fullPath", fullPath);
0263:
0264: QueryByCriteria query = QueryFactory.newQuery(
0265: SSOSiteImpl.class, filter);
0266: return getPersistenceBrokerTemplate().getCollectionByQuery(
0267: query);
0268: }
0269:
0270: public Iterator getSites(String filter) {
0271: Criteria queryCriteria = new Criteria();
0272: Query query = QueryFactory.newQuery(SSOSiteImpl.class,
0273: queryCriteria);
0274: Collection c = getPersistenceBrokerTemplate()
0275: .getCollectionByQuery(query);
0276: return c.iterator();
0277: }
0278:
0279: /**
0280: * addCredentialsForSite()
0281: * @param fullPath
0282: * @param remoteUser
0283: * @param site
0284: * @param pwd
0285: * @throws SSOException
0286: */
0287: public void addCredentialsForSite(String fullPath,
0288: String remoteUser, String site, String pwd)
0289: throws SSOException {
0290: // Create a Subject for the given path and forward it to the API addCredentialsForSite()
0291: Principal principal = null;
0292: String name = null;
0293:
0294: // Group or User
0295: if (fullPath.indexOf("/group/") > -1) {
0296: name = fullPath.substring(GROUP_PATH.length());
0297: principal = new GroupPrincipalImpl(name);
0298: } else {
0299: name = fullPath.substring(USER_PATH.length());
0300: principal = new UserPrincipalImpl(name);
0301: }
0302:
0303: // Create Subject
0304: Set principals = new HashSet();
0305: principals.add(principal);
0306: Subject subject = new Subject(true, principals, new HashSet(),
0307: new HashSet());
0308:
0309: // Call into the API
0310: addCredentialsForSite(subject, remoteUser, site, pwd);
0311: }
0312:
0313: /**
0314: * removeCredentialsForSite()
0315: * @param fullPath
0316: * @param site
0317: * @throws SSOException
0318: */
0319: public void removeCredentialsForSite(String fullPath, String site)
0320: throws SSOException {
0321: // Create a Subject for the given path and forward it to the API addCredentialsForSite()
0322: Principal principal = null;
0323: String name = null;
0324:
0325: // Group or User
0326: if (fullPath.indexOf("/group/") > -1) {
0327: name = fullPath.substring(GROUP_PATH.length());
0328: principal = new GroupPrincipalImpl(name);
0329: } else {
0330: name = fullPath.substring(USER_PATH.length());
0331: principal = new UserPrincipalImpl(name);
0332: }
0333:
0334: // Create Subject
0335: Set principals = new HashSet();
0336: principals.add(principal);
0337: Subject subject = new Subject(true, principals, new HashSet(),
0338: new HashSet());
0339:
0340: // Call into the API
0341: this .removeCredentialsForSite(subject, site);
0342: }
0343:
0344: /** Retrive site information
0345: *
0346: * getSiteURL
0347: */
0348:
0349: public String getSiteURL(String site) {
0350: // The site is the URL
0351: return site;
0352: }
0353:
0354: /**
0355: * getSiteName
0356: */
0357: public String getSiteName(String site) {
0358: SSOSite ssoSite = getSSOSiteObject(site);
0359:
0360: if (ssoSite != null) {
0361: return ssoSite.getName();
0362: } else {
0363: return null;
0364: }
0365: }
0366:
0367: /* (non-Javadoc)
0368: * @see org.apache.jetspeed.sso.SSOProvider#hasSSOCredentials(javax.security.auth.Subject, java.lang.String)
0369: */
0370: public boolean hasSSOCredentials(Subject subject, String site) {
0371: // Initialization
0372: SSOSite ssoSite = getSSOSiteObject(site);
0373:
0374: if (ssoSite == null) {
0375: return false; // no entry for site
0376: }
0377:
0378: // Get the principal from the subject
0379: BasePrincipal principal = (BasePrincipal) SecurityHelper
0380: .getBestPrincipal(subject, UserPrincipal.class);
0381: String fullPath = principal.getFullPath();
0382:
0383: // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
0384: Collection remoteForSite = ssoSite.getRemotePrincipals();
0385: Collection principalsForSite = ssoSite.getPrincipals(); // Users
0386:
0387: // If any of them don't exist just return
0388: if (principalsForSite == null || remoteForSite == null)
0389: return false; // no entry
0390:
0391: Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(
0392: principalsForSite, fullPath);
0393:
0394: if (remoteForPrincipals == null)
0395: return false; // no entry
0396:
0397: // Get remote Principal that matches the site and the principal
0398: if (findRemoteMatch(remoteForPrincipals, remoteForSite) == null) {
0399: return false; // No entry
0400: } else {
0401: return true; // Has an entry
0402: }
0403: }
0404:
0405: /* (non-Javadoc)
0406: * @see org.apache.jetspeed.sso.SSOProvider#getCredentials(javax.security.auth.Subject, java.lang.String)
0407: */
0408: public SSOContext getCredentials(Subject subject, String site)
0409: throws SSOException {
0410:
0411: // Initialization
0412: SSOSite ssoSite = getSSOSiteObject(site);
0413:
0414: if (ssoSite == null)
0415: throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); // no entry for site
0416:
0417: // Get the principal from the subject
0418: BasePrincipal principal = (BasePrincipal) SecurityHelper
0419: .getBestPrincipal(subject, UserPrincipal.class);
0420: String fullPath = principal.getFullPath();
0421:
0422: // Filter the credentials for the given principals
0423: SSOContext context = getCredential(ssoSite, fullPath);
0424:
0425: if (context == null)
0426: throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE); // no entry for site
0427:
0428: return context;
0429: }
0430:
0431: /* addCredential()
0432: * Adds credentials for a user to the site. If the site doesn't exist it will be created
0433: * @see org.apache.jetspeed.sso.SSOProvider#addCredentialsForSite(javax.security.auth.Subject, java.lang.String, java.lang.String)
0434: */
0435: public void addCredentialsForSite(Subject subject,
0436: String remoteUser, String site, String pwd)
0437: throws SSOException {
0438:
0439: // Check if an entry for the site already exists otherwise create a new one
0440: SSOSite ssoSite = getSSOSiteObject(site);
0441: if (ssoSite == null) {
0442: // Create a new site
0443: ssoSite = new SSOSiteImpl();
0444: ssoSite.setSiteURL(site);
0445: ssoSite.setName(site);
0446: ssoSite.setCertificateRequired(false);
0447: ssoSite.setAllowUserSet(true);
0448: // By default we use ChallengeResponse Authentication
0449: ssoSite.setChallengeResponseAuthentication(true);
0450: ssoSite.setFormAuthentication(false);
0451:
0452: // Store the site so that we get a valid SSOSiteID
0453: try {
0454: getPersistenceBrokerTemplate().store(ssoSite);
0455: } catch (Exception e) {
0456: e.printStackTrace();
0457: throw new SSOException(
0458: SSOException.FAILED_STORING_SITE_INFO_IN_DB
0459: + e.toString());
0460: }
0461: }
0462:
0463: // Get the Principal information (logged in user)
0464: String fullPath = ((BasePrincipal) SecurityHelper
0465: .getBestPrincipal(subject, UserPrincipal.class))
0466: .getFullPath();
0467: String principalName = ((BasePrincipal) SecurityHelper
0468: .getBestPrincipal(subject, UserPrincipal.class))
0469: .getName();
0470:
0471: // Add an entry for the principal to the site if it doesn't exist
0472: SSOPrincipal principal = this .getPrincipalForSite(ssoSite,
0473: fullPath);
0474:
0475: if (principal == null) {
0476: principal = getSSOPrincipal(fullPath);
0477: ssoSite.addPrincipal(principal);
0478: } else {
0479: // Check if the entry the user likes to update exists already
0480: Collection remoteForSite = ssoSite.getRemotePrincipals();
0481: Collection principalsForSite = ssoSite.getPrincipals();
0482:
0483: if (remoteForSite != null && principalsForSite != null) {
0484: Collection remoteForPrincipals = this
0485: .getRemotePrincipalsForPrincipal(
0486: principalsForSite, fullPath);
0487: if (remoteForPrincipals != null) {
0488: if (findRemoteMatch(remoteForPrincipals,
0489: remoteForSite) != null) {
0490: // Entry exists can't to an add has to call update
0491: throw new SSOException(
0492: SSOException.REMOTE_PRINCIPAL_EXISTS_CALL_UPDATE);
0493: }
0494: }
0495: }
0496: }
0497:
0498: if (principal == null)
0499: throw new SSOException(
0500: SSOException.FAILED_ADDING_PRINCIPAL_TO_MAPPING_TABLE_FOR_SITE);
0501:
0502: // Create a remote principal and credentials
0503: InternalUserPrincipalImpl remotePrincipal = new InternalUserPrincipalImpl(
0504: remoteUser);
0505:
0506: /*
0507: * The RemotePrincipal (class InternalUserPrincipal) will have a fullPath that identifies the entry as an SSO credential.
0508: * The entry has to be unique for a site and principal (GROUP -or- USER ) an therefore it needs to be encoded as following:
0509: * The convention for the path is the following: /sso/SiteID/{user|group}/{user name | group name}/remote user name
0510: */
0511: if (fullPath.indexOf("/group/") > -1)
0512: remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId()
0513: + "/group/" + principalName + "/" + remoteUser);
0514: else
0515: remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId()
0516: + "/user/" + principalName + "/" + remoteUser);
0517:
0518: // New credential object for remote principal
0519: InternalCredentialImpl credential = new InternalCredentialImpl(
0520: remotePrincipal.getPrincipalId(), this .scramble(pwd),
0521: 0, DefaultPasswordCredentialImpl.class.getName());
0522:
0523: if (remotePrincipal.getCredentials() == null)
0524: remotePrincipal.setCredentials(new ArrayList(0));
0525:
0526: remotePrincipal.getCredentials().add(credential);
0527:
0528: // Add it to Principals remotePrincipals list
0529: principal.addRemotePrincipal(remotePrincipal);
0530:
0531: // Update the site remotePrincipals list
0532: ssoSite.getRemotePrincipals().add(remotePrincipal);
0533:
0534: // Update database and reset cache
0535: try {
0536: getPersistenceBrokerTemplate().store(ssoSite);
0537:
0538: // Persist Principal/Remote
0539: getPersistenceBrokerTemplate().store(principal);
0540: } catch (Exception e) {
0541: e.printStackTrace();
0542: throw new SSOException(
0543: SSOException.FAILED_STORING_SITE_INFO_IN_DB
0544: + e.toString());
0545: }
0546:
0547: // Add to site
0548: this .mapSite.put(site, ssoSite);
0549: }
0550:
0551: /* (non-Javadoc)
0552: * @see org.apache.jetspeed.sso.SSOProvider#removeCredentialsForSite(javax.security.auth.Subject, java.lang.String)
0553: */
0554: public void removeCredentialsForSite(Subject subject, String site)
0555: throws SSOException {
0556:
0557: // Initailization
0558: InternalUserPrincipal remotePrincipal = null;
0559: //Get the site
0560: SSOSite ssoSite = getSSOSiteObject(site);
0561: if (ssoSite == null) {
0562: throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
0563: }
0564:
0565: // Get the Principal information
0566: String fullPath = ((BasePrincipal) SecurityHelper
0567: .getBestPrincipal(subject, UserPrincipal.class))
0568: .getFullPath();
0569:
0570: try {
0571: // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
0572: Collection principalsForSite = ssoSite.getPrincipals();
0573: Collection remoteForSite = ssoSite.getRemotePrincipals();
0574:
0575: // If any of them don't exist just return
0576: if (principalsForSite == null || remoteForSite == null)
0577: throw new SSOException(
0578: SSOException.NO_CREDENTIALS_FOR_SITE);
0579:
0580: Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(
0581: principalsForSite, fullPath);
0582:
0583: if (remoteForPrincipals == null)
0584: throw new SSOException(
0585: SSOException.NO_CREDENTIALS_FOR_SITE);
0586:
0587: // Get remote Principal that matches the site and the principal
0588: if ((remotePrincipal = findRemoteMatch(remoteForPrincipals,
0589: remoteForSite)) == null) {
0590: throw new SSOException(
0591: SSOException.NO_CREDENTIALS_FOR_SITE);
0592: }
0593:
0594: // Update assocation tables
0595: ssoSite.getRemotePrincipals().remove(remotePrincipal);
0596:
0597: if (remoteForPrincipals.remove(remotePrincipal) == true)
0598:
0599: // Update the site
0600: getPersistenceBrokerTemplate().store(ssoSite);
0601:
0602: // delete the remote Principal from the SECURITY_PRINCIPAL table
0603: getPersistenceBrokerTemplate().delete(remotePrincipal);
0604:
0605: } catch (SSOException ssoex) {
0606: throw new SSOException(ssoex);
0607: } catch (Exception e) {
0608: e.printStackTrace();
0609: // current OJB model implementation isn't 100% correct, make sure no stale/broken state is left behind
0610: mapSite.remove(site);
0611: throw new SSOException(
0612: SSOException.FAILED_STORING_SITE_INFO_IN_DB
0613: + e.toString());
0614: }
0615:
0616: // Update database
0617: try {
0618: getPersistenceBrokerTemplate().store(ssoSite);
0619: } catch (Exception e) {
0620: e.printStackTrace();
0621: throw new SSOException(
0622: SSOException.FAILED_STORING_SITE_INFO_IN_DB
0623: + e.toString());
0624: } finally {
0625: // current OJB model implementation isn't 100% correct, make sure no stale/broken state is left behind
0626: mapSite.remove(site);
0627: }
0628:
0629: }
0630:
0631: /**
0632: * updateCredentialsForSite
0633: * @param subject Current subject
0634: * @param remoteUser remote user login
0635: * @param site URL or description of site
0636: * @param pwd Password for credentail
0637: */
0638: public void updateCredentialsForSite(Subject subject,
0639: String remoteUser, String site, String pwd)
0640: throws SSOException {
0641: // Check if the the current user has a credential for the site
0642:
0643: // Update the credential
0644: // Initailization
0645: InternalUserPrincipal remotePrincipal = null;
0646:
0647: //Get the site
0648: SSOSite ssoSite = getSSOSiteObject(site);
0649: if (ssoSite == null) {
0650: throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
0651: }
0652:
0653: // Get the Principal information
0654: String fullPath = ((BasePrincipal) SecurityHelper
0655: .getBestPrincipal(subject, UserPrincipal.class))
0656: .getFullPath();
0657:
0658: // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
0659: Collection principalsForSite = ssoSite.getPrincipals();
0660: Collection remoteForSite = ssoSite.getRemotePrincipals();
0661:
0662: // If any of them don't exist just return
0663: if (principalsForSite == null || remoteForSite == null)
0664: throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
0665:
0666: Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(
0667: principalsForSite, fullPath);
0668:
0669: if (remoteForPrincipals == null)
0670: throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
0671:
0672: // Get remote Principal that matches the site and the principal
0673: if ((remotePrincipal = findRemoteMatch(remoteForPrincipals,
0674: remoteForSite)) == null) {
0675: throw new SSOException(SSOException.NO_CREDENTIALS_FOR_SITE);
0676: }
0677:
0678: // Update principal information
0679: //remotePrincipal.setFullPath("/sso/" + ssoSite.getSiteId() + "/user/"+ principalName + "/" + remoteUser);
0680:
0681: InternalCredential credential = (InternalCredential) remotePrincipal
0682: .getCredentials().iterator().next();
0683:
0684: // New credential object
0685: if (credential != null)
0686: // Remove credential and principal from mapping
0687: credential.setValue(this .scramble(pwd));
0688:
0689: // Update database and reset cache
0690: try {
0691: getPersistenceBrokerTemplate().store(credential);
0692: } catch (Exception e) {
0693: e.printStackTrace();
0694: throw new SSOException(
0695: SSOException.FAILED_STORING_SITE_INFO_IN_DB
0696: + e.toString());
0697: }
0698: }
0699:
0700: /*
0701: * Helper utilities
0702: *
0703: */
0704:
0705: /*
0706: * getSSOSiteObject
0707: * Obtains the Site information including the credentials for a site (url).
0708: */
0709:
0710: private SSOSite getSSOSiteObject(String site) {
0711: //Initialization
0712: SSOSite ssoSite = null;
0713:
0714: //Check if the site is in the map
0715: if (mapSite.containsKey(site) == false) {
0716: // Go to the database and fetch the information for this site
0717: // Find the MediaType by matching the Mimetype
0718:
0719: Criteria filter = new Criteria();
0720: filter.addEqualTo("siteURL", site);
0721:
0722: QueryByCriteria query = QueryFactory.newQuery(
0723: SSOSiteImpl.class, filter);
0724: Collection ssoSiteCollection = getPersistenceBrokerTemplate()
0725: .getCollectionByQuery(query);
0726:
0727: if (ssoSiteCollection != null
0728: && ssoSiteCollection.isEmpty() != true) {
0729: Iterator itSite = ssoSiteCollection.iterator();
0730: // Get the site from the collection. There should be only one entry (uniqueness)
0731: if (itSite.hasNext()) {
0732: ssoSite = (SSOSite) itSite.next();
0733: }
0734:
0735: // Add it to the map
0736: mapSite.put(site, ssoSite);
0737: } else {
0738: // No entry for this site
0739: return null;
0740: }
0741: } else {
0742: ssoSite = (SSOSite) mapSite.get(site);
0743: }
0744:
0745: return ssoSite;
0746: }
0747:
0748: /*
0749: * getCredential
0750: * returns the credentials for a given user
0751: */
0752: private SSOContext getCredential(SSOSite ssoSite, String fullPath) {
0753: InternalCredential credential = null;
0754: InternalUserPrincipal remotePrincipal = null;
0755: // Get remotePrincipals for Site and match them with the Remote Principal for the Principal attached to site
0756: Collection principalsForSite = ssoSite.getPrincipals();
0757: Collection remoteForSite = ssoSite.getRemotePrincipals();
0758:
0759: // If any of them don't exist just return
0760: if (principalsForSite == null || remoteForSite == null)
0761: return null; // no entry
0762:
0763: Collection remoteForPrincipals = getRemotePrincipalsForPrincipal(
0764: principalsForSite, fullPath);
0765:
0766: if (remoteForPrincipals == null)
0767: return null; // no entry
0768:
0769: // Get remote Principal that matches the site and the principal
0770: if ((remotePrincipal = findRemoteMatch(remoteForPrincipals,
0771: remoteForSite)) == null) {
0772: return null; // No entry
0773: } else {
0774: // Has an entry
0775: if (remotePrincipal.getCredentials() != null)
0776: credential = (InternalCredential) remotePrincipal
0777: .getCredentials().iterator().next();
0778:
0779: // Error checking -- should have a credential at this point
0780: if (credential == null) {
0781: // System.out.println("Warning: Remote User " + remotePrincipal.getFullPath() + " doesn't have a credential");
0782: return null;
0783: }
0784: }
0785:
0786: // Create new context
0787: String name = stripPrincipalName(remotePrincipal.getFullPath());
0788:
0789: SSOContext context = new SSOContextImpl(credential
0790: .getPrincipalId(), name, this .unscramble(credential
0791: .getValue()));
0792:
0793: return context;
0794: }
0795:
0796: private String stripPrincipalName(String fullPath) {
0797: String name;
0798: int ix = fullPath.lastIndexOf('/');
0799: if (ix != -1)
0800: name = fullPath.substring(ix + 1);
0801: else
0802: name = new String(fullPath);
0803:
0804: return name;
0805: }
0806:
0807: /*
0808: * Get a Collection of remote Principals for the logged in principal identified by the full path
0809: *
0810: private Collection getRemotePrincipalsForPrincipal(SSOSite ssoSite, String fullPath)
0811: {
0812: // The site orincipals list contains a list of remote principals for the user
0813: Collection principals = ssoSite.getPrincipals();
0814:
0815: if ( principals == null )
0816: return null; // No principals for this site
0817:
0818: Iterator ixPrincipals = principals.iterator();
0819: while (ixPrincipals.hasNext())
0820: {
0821: SSOPrincipal principal = (SSOPrincipal)ixPrincipals.next();
0822: if ( principal != null
0823: && principal.getFullPath().compareToIgnoreCase(fullPath) == 0 )
0824: {
0825: // Found Principal -- extract remote principals
0826: return principal.getRemotePrincipals();
0827: }
0828: }
0829:
0830: // Principal is not in list
0831: return null;
0832: }
0833: */
0834:
0835: /*
0836: * getPrincipalForSite()
0837: * returns a principal that matches the full path for the site or creates a new entry if it doesn't exist
0838: */
0839: private SSOPrincipal getPrincipalForSite(SSOSite ssoSite,
0840: String fullPath) {
0841: SSOPrincipal principal = null;
0842: Collection principalsForSite = ssoSite.getPrincipals();
0843:
0844: if (principalsForSite != null) {
0845: Iterator itPrincipals = principalsForSite.iterator();
0846: while (itPrincipals.hasNext() && principal == null) {
0847: SSOPrincipal tmp = (SSOPrincipal) itPrincipals.next();
0848: if (tmp != null
0849: && tmp.getFullPath().compareToIgnoreCase(
0850: fullPath) == 0)
0851: principal = tmp; // Found existing entry
0852: }
0853: }
0854:
0855: return principal;
0856: }
0857:
0858: private SSOPrincipal getSSOPrincipal(String fullPath) {
0859: // FInd if the principal exists in the SECURITY_PRINCIPAL table
0860: SSOPrincipal principal = null;
0861:
0862: Criteria filter = new Criteria();
0863: filter.addEqualTo("fullPath", fullPath);
0864:
0865: QueryByCriteria query = QueryFactory.newQuery(
0866: SSOPrincipalImpl.class, filter);
0867: Collection principals = getPersistenceBrokerTemplate()
0868: .getCollectionByQuery(query);
0869:
0870: if (principals != null && principals.isEmpty() != true) {
0871: Iterator itPrincipals = principals.iterator();
0872: // Get the site from the collection. There should be only one entry (uniqueness)
0873: if (itPrincipals.hasNext()) {
0874: principal = (SSOPrincipal) itPrincipals.next();
0875: }
0876: }
0877:
0878: return principal;
0879: }
0880:
0881: /**
0882: * removeRemotePrincipalForPrincipal
0883: * @param site
0884: * @param fullPath
0885: * @return
0886: *
0887: * removes remotePrincipal for a site & principal
0888: *
0889: private InternalUserPrincipal removeRemotePrincipalForPrincipal(SSOSite site, String fullPath) throws SSOException
0890: {
0891: if (site.getPrincipals() != null)
0892: {
0893: Iterator itPrincipals = site.getPrincipals().iterator();
0894: while (itPrincipals.hasNext())
0895: {
0896: SSOPrincipal tmp = (SSOPrincipal)itPrincipals.next();
0897: if (tmp.getFullPath().compareToIgnoreCase(fullPath) == 0)
0898: {
0899: // Found -- get the remotePrincipal
0900: Collection collRemotePrincipals = tmp.getRemotePrincipals() ;
0901: if (collRemotePrincipals != null)
0902: {
0903:
0904: Iterator itRemotePrincipals = collRemotePrincipals.iterator();
0905: if (itRemotePrincipals.hasNext())
0906: {
0907: InternalUserPrincipal remotePrincipal = (InternalUserPrincipal)itRemotePrincipals.next();
0908: // Found remove the object
0909: collRemotePrincipals.remove(remotePrincipal);
0910: return remotePrincipal;
0911: }
0912: }
0913: }
0914: }
0915: }
0916:
0917: throw new SSOException(SSOException.REQUESTED_PRINCIPAL_DOES_NOT_EXIST);
0918: }
0919: */
0920:
0921: /*
0922: *
0923: *
0924: */
0925: private InternalUserPrincipal findRemoteMatch(
0926: Collection remoteForPrincipals, Collection remoteForSite) {
0927: // Iterate over the lists and find match
0928: Iterator itRemoteForPrincipals = remoteForPrincipals.iterator();
0929: while (itRemoteForPrincipals.hasNext()) {
0930: InternalUserPrincipal remoteForPrincipal = (InternalUserPrincipal) itRemoteForPrincipals
0931: .next();
0932:
0933: // Find a match in the site list
0934: Iterator itRemoteForSite = remoteForSite.iterator();
0935: while (itRemoteForSite.hasNext()) {
0936: InternalUserPrincipal tmp = (InternalUserPrincipal) itRemoteForSite
0937: .next();
0938:
0939: if (tmp.getPrincipalId() == remoteForPrincipal
0940: .getPrincipalId())
0941: return remoteForPrincipal;
0942: }
0943: }
0944: // No match found
0945: return null;
0946: }
0947:
0948: /*
0949: * getRemotePrincipalsForPrincipals
0950: * Checks if the user has any remote principals. If the principal is a group expand the group and
0951: * check if the requesting user is a part of the group.
0952: */
0953: private Collection getRemotePrincipalsForPrincipal(
0954: Collection principalsForSite, String fullPath) {
0955: if (principalsForSite != null) {
0956: Iterator itPrincipalsForSite = principalsForSite.iterator();
0957: while (itPrincipalsForSite.hasNext()) {
0958: String principalFullPath = null;
0959: SSOPrincipal principal = (SSOPrincipal) itPrincipalsForSite
0960: .next();
0961: principalFullPath = principal.getFullPath();
0962:
0963: /* If the Principal is for a Group expand the Group and check if the user identified
0964: * by the fullPath is a member of the Group. If the user is a member of the Group
0965: * return the remote Credentials for the current Principal.
0966: */
0967: if (principalFullPath.indexOf("/group/") == -1) {
0968: // USER
0969: if (principalFullPath.compareToIgnoreCase(fullPath) == 0)
0970: return principal.getRemotePrincipals();
0971: } else {
0972: /* GROUP
0973: * If the full path is for a group (delete/add) just return the the list of remotePrincipals
0974: * For a lookup (hasCredentials) the user needs to be mapped against each member of the group
0975: */
0976: if (principalFullPath.compareToIgnoreCase(fullPath) == 0)
0977: return principal.getRemotePrincipals();
0978:
0979: /* Expand the Group and find a match */
0980: InternalGroupPrincipal groupPrincipal = getGroupPrincipals(principalFullPath);
0981:
0982: // Found Group that matches the name
0983: if (groupPrincipal != null) {
0984: Collection usersInGroup = groupPrincipal
0985: .getUserPrincipals();
0986: Iterator itUsers = usersInGroup.iterator();
0987: while (itUsers.hasNext()) {
0988: InternalUserPrincipal user = (InternalUserPrincipal) itUsers
0989: .next();
0990: if (user.getFullPath().compareToIgnoreCase(
0991: fullPath) == 0) {
0992: // User is member of the group
0993: return principal.getRemotePrincipals();
0994: }
0995: }
0996: }
0997: }
0998: }
0999: }
1000:
1001: // No match found
1002: return null;
1003: }
1004:
1005: public SSOSite getSite(String siteUrl) {
1006: Criteria filter = new Criteria();
1007: filter.addEqualTo("url", siteUrl);
1008: Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
1009: SSOSite site = (SSOSite) getPersistenceBrokerTemplate()
1010: .getObjectByQuery(query);
1011: return site;
1012: }
1013:
1014: public void updateSite(SSOSite site) throws SSOException {
1015: try {
1016: getPersistenceBrokerTemplate().store(site);
1017: this .mapSite.put(site.getName(), site);
1018: } catch (Exception e) {
1019: String msg = "Unable to remove SSO Site: " + site.getName();
1020: logger.error(msg, e);
1021: throw new SSOException(msg, e);
1022: }
1023: }
1024:
1025: /**
1026: * Add a new site that uses Form Authentication
1027: * @param siteName
1028: * @param siteUrl
1029: * @param realm
1030: * @param userField
1031: * @param pwdField
1032: * @throws SSOException
1033: */
1034: public void addSiteFormAuthenticated(String siteName,
1035: String siteUrl, String realm, String userField,
1036: String pwdField) throws SSOException {
1037: try {
1038: SSOSite ssoSite = new SSOSiteImpl();
1039: ssoSite.setSiteURL(siteUrl);
1040: ssoSite.setName(siteName);
1041: ssoSite.setCertificateRequired(false);
1042: ssoSite.setAllowUserSet(true);
1043: ssoSite.setRealm(realm);
1044: ssoSite.setFormAuthentication(true);
1045: ssoSite.setFormUserField(userField);
1046: ssoSite.setFormPwdField(pwdField);
1047: getPersistenceBrokerTemplate().store(ssoSite);
1048: this .mapSite.put(siteName, ssoSite);
1049: } catch (Exception e) {
1050: String msg = "Unable to add SSO Site: " + siteName;
1051: logger.error(msg, e);
1052: throw new SSOException(msg, e);
1053: }
1054: }
1055:
1056: /**
1057: * Add a new site that uses ChallengeResponse Authentication
1058: * @param siteName
1059: * @param siteUrl
1060: * @param realm
1061: * @throws SSOException
1062: */
1063: public void addSiteChallengeResponse(String siteName,
1064: String siteUrl, String realm) throws SSOException {
1065: try {
1066: SSOSite ssoSite = new SSOSiteImpl();
1067: ssoSite.setSiteURL(siteUrl);
1068: ssoSite.setName(siteName);
1069: ssoSite.setCertificateRequired(false);
1070: ssoSite.setAllowUserSet(true);
1071: ssoSite.setRealm(realm);
1072: ssoSite.setChallengeResponseAuthentication(true);
1073: getPersistenceBrokerTemplate().store(ssoSite);
1074: this .mapSite.put(siteName, ssoSite);
1075: } catch (Exception e) {
1076: String msg = "Unable to add SSO Site: " + siteName;
1077: logger.error(msg, e);
1078: throw new SSOException(msg, e);
1079: }
1080: }
1081:
1082: public void addSite(String siteName, String siteUrl)
1083: throws SSOException {
1084: try {
1085: SSOSite ssoSite = new SSOSiteImpl();
1086: ssoSite.setSiteURL(siteUrl);
1087: ssoSite.setName(siteName);
1088: ssoSite.setCertificateRequired(false);
1089: ssoSite.setAllowUserSet(true);
1090: getPersistenceBrokerTemplate().store(ssoSite);
1091: this .mapSite.put(siteName, ssoSite);
1092: } catch (Exception e) {
1093: String msg = "Unable to remove SSO Site: " + siteName;
1094: logger.error(msg, e);
1095: throw new SSOException(msg, e);
1096: }
1097: }
1098:
1099: public void removeSite(SSOSite site) throws SSOException {
1100: try {
1101: getPersistenceBrokerTemplate().delete(site);
1102: this .mapSite.remove(site);
1103:
1104: } catch (Exception e) {
1105: String msg = "Unable to remove SSO Site: " + site.getName();
1106: logger.error(msg, e);
1107: throw new SSOException(msg, e);
1108: }
1109: }
1110:
1111: public List getPrincipalsForSite(SSOSite site) {
1112: List list = new ArrayList();
1113: Iterator principals = site.getRemotePrincipals().iterator();
1114: while (principals.hasNext()) {
1115: InternalUserPrincipal remotePrincipal = (InternalUserPrincipal) principals
1116: .next();
1117: Iterator creds = remotePrincipal.getCredentials()
1118: .iterator();
1119: while (creds.hasNext()) {
1120: InternalCredential cred = (InternalCredential) creds
1121: .next();
1122: SSOContext context = new SSOContextImpl(remotePrincipal
1123: .getPrincipalId(),
1124: stripPrincipalName(remotePrincipal
1125: .getFullPath()), cred.getValue(),
1126: stripPortalPrincipalName(remotePrincipal
1127: .getFullPath()));
1128: list.add(context);
1129: }
1130: }
1131: return list;
1132: }
1133:
1134: private String stripPortalPrincipalName(String fullPath) {
1135: StringTokenizer tokenizer = new StringTokenizer(fullPath, "/");
1136: while (tokenizer.hasMoreTokens()) {
1137: String token = tokenizer.nextToken();
1138: if (token.equals("user") || token.equals("group")) {
1139: if (tokenizer.hasMoreTokens()) {
1140: return tokenizer.nextToken();
1141: }
1142: }
1143: }
1144: return fullPath;
1145: }
1146:
1147: private InternalGroupPrincipal getGroupPrincipals(
1148: String principalFullPath) {
1149: // Get to the backend to return the group that matches the full path
1150: Criteria filter = new Criteria();
1151: filter.addEqualTo("fullPath", principalFullPath);
1152: Query query = QueryFactory.newQuery(
1153: InternalGroupPrincipalImpl.class, filter);
1154: InternalGroupPrincipal group = (InternalGroupPrincipal) getPersistenceBrokerTemplate()
1155: .getObjectByQuery(query);
1156: return group;
1157: }
1158:
1159: /*
1160: private SSOSite getSiteForRemoteUser(String fullPath)
1161: {
1162: // Get Site for remote user
1163: Criteria filter = new Criteria();
1164: filter.addEqualTo("remotePrincipals.fullPath", fullPath);
1165: Query query = QueryFactory.newQuery(SSOSiteImpl.class, filter);
1166: return (SSOSite) getPersistenceBrokerTemplate().getObjectByQuery(query);
1167: }
1168: */
1169:
1170: private String getContentFromURL(String proxyID, String destUrl,
1171: SSOSite[] sites, boolean bRefresh) throws SSOException {
1172: URL urlObj = null;
1173:
1174: // Result Buffer
1175: //BufferedInputStream bis = null;
1176: String resultPage;
1177:
1178: String strErrorMessage = "SSO Component Error. Failed to get content for URL "
1179: + destUrl;
1180:
1181: try {
1182: urlObj = new URL(destUrl);
1183: } catch (MalformedURLException e) {
1184: String msg = ("Error -- Malformed URL [" + destUrl + "] for SSO authenticated destination");
1185: log.error(msg);
1186: throw new SSOException(msg, e);
1187: }
1188:
1189: /*
1190: * Setup HTTPClient
1191: * Check if an HTTP Client already exists for the given /user/site
1192: */
1193: HttpClient client = (HttpClient) this .clientProxy.get(proxyID);
1194: GetMethod get = null;
1195:
1196: if (bRefresh == true || client == null) {
1197: if (log.isInfoEnabled())
1198: log
1199: .info("SSO Component -- Create new HTTP Client object for Principal/URL ["
1200: + proxyID + "]");
1201:
1202: client = new HttpClient();
1203: client.getState().setCookiePolicy(
1204: CookiePolicy.COMPATIBILITY);
1205:
1206: int numberOfSites = sites.length;
1207:
1208: // Do all the logins for the site
1209: for (int i = 0; i < numberOfSites; i++) {
1210: SSOSite site = sites[i];
1211:
1212: if (site != null) {
1213: Iterator itRemotePrincipals = site
1214: .getRemotePrincipals().iterator();
1215: while (itRemotePrincipals.hasNext()) {
1216: InternalUserPrincipal remotePrincipal = (InternalUserPrincipal) itRemotePrincipals
1217: .next();
1218: if (remotePrincipal != null) {
1219: InternalCredential credential = null;
1220: if (remotePrincipal.getCredentials() != null)
1221: credential = (InternalCredential) remotePrincipal
1222: .getCredentials().iterator()
1223: .next();
1224:
1225: if (credential != null) {
1226: if (log.isInfoEnabled())
1227: log
1228: .info("SSOComponent -- Remote Principal ["
1229: + stripPrincipalName(remotePrincipal
1230: .getFullPath())
1231: + "] has credential ["
1232: + this
1233: .unscramble(credential
1234: .getValue())
1235: + "]");
1236:
1237: client
1238: .getState()
1239: .setCredentials(
1240: site.getRealm(),
1241: urlObj.getHost(),
1242: new UsernamePasswordCredentials(
1243: stripPrincipalName(remotePrincipal
1244: .getFullPath()),
1245: this
1246: .unscramble(credential
1247: .getValue())));
1248:
1249: // Build URL if it's Form authentication
1250: StringBuffer siteURL = new StringBuffer(
1251: site.getSiteURL());
1252:
1253: // Check if it's form based or ChallengeResponse
1254: if (site.isFormAuthentication()) {
1255: siteURL
1256: .append("?")
1257: .append(
1258: site
1259: .getFormUserField())
1260: .append("=")
1261: .append(
1262: stripPrincipalName(remotePrincipal
1263: .getFullPath()))
1264: .append("&")
1265: .append(
1266: site
1267: .getFormPwdField())
1268: .append("=")
1269: .append(
1270: this
1271: .unscramble(credential
1272: .getValue()));
1273: }
1274:
1275: get = new GetMethod(siteURL.toString());
1276:
1277: // Tell the GET method to automatically handle authentication. The
1278: // method will use any appropriate credentials to handle basic
1279: // authentication requests. Setting this value to false will cause
1280: // any request for authentication to return with a status of 401.
1281: // It will then be up to the client to handle the authentication.
1282: get.setDoAuthentication(true);
1283: try {
1284: // execute the GET
1285: int status = client
1286: .executeMethod(get);
1287:
1288: if (log.isInfoEnabled())
1289: log.info("Accessing site ["
1290: + site.getSiteURL()
1291: + "]. HTTP Status ["
1292: + status + "]");
1293:
1294: /*
1295: * If the destination URL and the SSO url match
1296: * use the authentication process but return immediately
1297: * the result page.
1298: */
1299: if (destUrl.compareTo(site
1300: .getSiteURL()) == 0
1301: && numberOfSites == 1) {
1302: if (log.isInfoEnabled())
1303: log
1304: .info("SSO Component --SSO Site and destination URL match. Go and get the content.");
1305:
1306: //try
1307: //{
1308: //bis = new BufferedInputStream(get.getResponseBodyAsStream());
1309: resultPage = get
1310: .getResponseBodyAsString();
1311: //}
1312: //catch(IOException ioe)
1313: //{
1314: // log.error(strErrorMessage, ioe);
1315: // throw new SSOException (strErrorMessage, ioe);
1316: //}
1317:
1318: get.releaseConnection();
1319:
1320: // Add the client object to the cache
1321: this .clientProxy.put(proxyID,
1322: client);
1323:
1324: //return bis;
1325: return resultPage;
1326: }
1327:
1328: } catch (Exception e) {
1329: log
1330: .error("Exception while authentication. Error: "
1331: + e);
1332: }
1333:
1334: get.releaseConnection();
1335: }
1336: }
1337: }
1338: }
1339: }
1340:
1341: // Add the client object to the cache
1342: this .clientProxy.put(proxyID, client);
1343: } else {
1344: if (log.isInfoEnabled())
1345: log
1346: .info("SSO Component -- Use cached HTTP Client object for Principal/URL ["
1347: + proxyID + "]");
1348: }
1349:
1350: // All the SSO authentication done go to the destination url
1351: get = new GetMethod(destUrl);
1352: try {
1353: // execute the GET
1354: int status = client.executeMethod(get);
1355:
1356: log.info("Accessing site [" + destUrl + "]. HTTP Status ["
1357: + status + "]");
1358:
1359: } catch (Exception e) {
1360: log.error("Exception while authentication. Error: " + e);
1361: }
1362:
1363: try {
1364: //bis = new BufferedInputStream(get.getResponseBodyAsStream());
1365: resultPage = get.getResponseBodyAsString();
1366: } catch (IOException ioe) {
1367: log.error(strErrorMessage, ioe);
1368: throw new SSOException(strErrorMessage, ioe);
1369: } catch (Exception e) {
1370: log.error(strErrorMessage, e);
1371: throw new SSOException(strErrorMessage, e);
1372:
1373: } finally {
1374: get.releaseConnection();
1375: }
1376:
1377: //return bis;
1378: return resultPage;
1379: }
1380:
1381: /*
1382: * Simple encryption decryption routines since the API creates credentials
1383: * together with an user.
1384: * TODO: re-implement when Security API is more flexible
1385: */
1386: static char[] scrambler = "Jestspeed-2 is getting ready for release"
1387: .toCharArray();
1388:
1389: private String scramble(String pwd) {
1390: // xor-ing persistent String values is dangerous because of the (uncommon) way Java encodes UTF-8 0x00 (and some other characters).
1391: // See: http://en.wikipedia.org/wiki/UTF-8#Java
1392: // On some database platforms, like PostgreSQL this can lead to something like:
1393: // org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00
1394: // To prevent this, the resulting xored password is encoded in Base64
1395: String xored = new String(xor(pwd.toCharArray(), scrambler));
1396: byte[] bytes = Base64.encodeBase64(xored.getBytes());
1397: String scrambled = new String(bytes);
1398: return scrambled;
1399: }
1400:
1401: private String unscramble(String pwd) {
1402: byte[] bytes = pwd.getBytes();
1403: bytes = Base64.decodeBase64(bytes);
1404: String chars = new String(bytes);
1405: String unscrambled = new String(xor(chars.toCharArray(),
1406: scrambler));
1407: return unscrambled;
1408: }
1409:
1410: private char[] xor(char[] a, char[] b) {
1411: int len = Math.min(a.length, b.length);
1412: char[] result = new char[len];
1413: for (int i = 0; i < len; i++) {
1414: result[i] = (char) (a[i] ^ b[i]);
1415: }
1416: return result;
1417: }
1418: }
|