001: /* Copyright 2001 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.security.provider;
007:
008: import org.jasig.portal.security.IOpaqueCredentials;
009: import org.jasig.portal.security.ISecurityContext;
010: import org.jasig.portal.security.PortalSecurityException;
011: import org.apache.commons.logging.Log;
012: import org.apache.commons.logging.LogFactory;
013:
014: /**
015: * <p>This is an implementation of a SecurityContext that performs absolutely
016: * NO validation of the Principal but merely caches the claimed password.
017: * We implement this to provide the illusion of single-signon but it comes
018: * with significant risk. A channel is able to retrieve the originally
019: * validated password of passphrase to perform just-in-time validation but the
020: * means of validation is now COMPLETELY in the hands of the channel. If the
021: * channel utilizes a weak authenticity-checking mechanism and the password is
022: * the same as the one that portal users regard as secure, then unbeknownst to
023: * the user, their "secure" password is being placed in jeopardy. PLEASE use
024: * this SecurityContext implementation sparingly and with your eyes open!</p>
025: *
026: * CacheSecurityContext can be chained together with another context such that
027: * both are required. This allows an authentication provider such as
028: * SimpleLdapSecurityContext to be used to verify the password and
029: * CacheSecurityContext to allow channels access to the password. Example of
030: * security.properties settings to accomplish this:
031: *
032: * root=org.jasig.portal.security.provider.SimpleSecurityContextFactory
033: * root.cache=org.jasig.portal.security.provider.CacheSecurityContextFactory
034: * principalToken.root=userName
035: * credentialToken.root=password
036: *
037: * To ensure that both contexts are exercized the portal property
038: * org.jasig.portal.security.provider.ChainingSecurityContext.stopWhenAuthenticated
039: * must be set to false (by default it is set to true).
040:
041: * @author Andrew Newman, newman@yale.edu
042: * @version $Revision: 34942 $
043: *
044: */
045: class CacheSecurityContext extends ChainingSecurityContext implements
046: ISecurityContext {
047:
048: private static final Log log = LogFactory
049: .getLog(CacheSecurityContext.class);
050:
051: private final int CACHESECURITYAUTHTYPE = 0xFF03;
052: private byte[] cachedcredentials;
053:
054: CacheSecurityContext() {
055: super ();
056: }
057:
058: public int getAuthType() {
059: return this .CACHESECURITYAUTHTYPE;
060: }
061:
062: public synchronized void authenticate()
063: throws PortalSecurityException {
064: this .isauth = false;
065: if (this .myPrincipal.UID != null
066: && this .myOpaqueCredentials.credentialstring != null) {
067: String first_name = null, last_name = null;
068: try {
069: String acct[] = AccountStoreFactory
070: .getAccountStoreImpl()
071: .getUserAccountInformation(this .myPrincipal.UID);
072: if (acct[0] != null) {
073: first_name = acct[1];
074: last_name = acct[2];
075: this .myPrincipal.FullName = first_name + " "
076: + last_name;
077: if (log.isInfoEnabled())
078: log.info("User " + this .myPrincipal.UID
079: + " is authenticated");
080: // Save our credentials so that the parent's authenticate()
081: // method doesn't blow them away.
082: this .cachedcredentials = new byte[this .myOpaqueCredentials.credentialstring.length];
083: System
084: .arraycopy(
085: this .myOpaqueCredentials.credentialstring,
086: 0,
087: this .cachedcredentials,
088: 0,
089: this .myOpaqueCredentials.credentialstring.length);
090: this .isauth = true;
091: } else if (log.isInfoEnabled())
092: log.info("No such user: " + this .myPrincipal.UID);
093: } catch (Exception e) {
094: PortalSecurityException ep = new PortalSecurityException(
095: "SQL Database Error");
096: log.error("SQL database error", e);
097: throw (ep);
098: }
099: } else
100: log
101: .error("Principal or OpaqueCredentials not initialized prior to authenticate");
102: // Ok...we are now ready to authenticate all of our subcontexts.
103: super .authenticate();
104: return;
105: }
106:
107: /**
108: * We need to override this method in order to return a class that implements
109: * the NotSoOpaqueCredentals interface.
110: */
111: public IOpaqueCredentials getOpaqueCredentials() {
112: if (this .isauth) {
113: NotSoOpaqueCredentials oc = new CacheOpaqueCredentials();
114: oc.setCredentials(this .cachedcredentials);
115: return oc;
116: } else
117: return null;
118: }
119:
120: /**
121: * This is a new implementation of an OpaqueCredentials class that
122: * implements the less-opaque NotSoOpaqueCredentials.
123: */
124: private class CacheOpaqueCredentials extends
125: ChainingSecurityContext.ChainingOpaqueCredentials implements
126: NotSoOpaqueCredentials {
127:
128: public String getCredentials() {
129: if (this .credentialstring != null)
130: return new String(this.credentialstring);
131: else
132: return null;
133: }
134: }
135: }
|