001: /*
002: * JOSSO: Java Open Single Sign-On
003: *
004: * Copyright 2004-2008, Atricore, Inc.
005: *
006: * This is free software; you can redistribute it and/or modify it
007: * under the terms of the GNU Lesser General Public License as
008: * published by the Free Software Foundation; either version 2.1 of
009: * the License, or (at your option) any later version.
010: *
011: * This software is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this software; if not, write to the Free
018: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
020: */
021:
022: package org.josso.tc55.agent.jaas;
023:
024: import org.apache.catalina.Realm;
025: import org.apache.catalina.realm.GenericPrincipal;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.josso.gateway.SSONameValuePair;
029: import org.josso.gateway.identity.SSOUser;
030:
031: import javax.security.auth.Subject;
032: import java.security.Principal;
033: import java.security.acl.Group;
034: import java.util.ArrayList;
035: import java.util.Enumeration;
036: import java.util.Iterator;
037: import java.util.List;
038:
039: /**
040: * On authentication, Catalina JAAS Realm doesn't return the Principal instances as
041: * built by the Login Modules. It returns a Catalina-specific Principal called GenericPrincipal.
042: * As a consequence all the additional properties that the SSOUser instance carries are lost.
043: * With this class, we'll make Catalina beleive that our SSOUser its actually a GenericPrincipal, so that it
044: * doesn't create a new one.
045: *
046: * @author <a href="mailto:gbrigand@josso.org">Gianluca Brigandi</a>
047: * @version CVS $Id: CatalinaSSOUser.java 508 2008-02-18 13:32:29Z sgonzalez $
048: */
049:
050: public class CatalinaSSOUser extends GenericPrincipal implements
051: SSOUser {
052: private static Log logger = LogFactory
053: .getLog(CatalinaSSOUser.class);
054:
055: private static List _userClasses = new ArrayList();
056: private static List _roleClasses = new ArrayList();
057:
058: static {
059: _userClasses
060: .add("org.josso.gateway.identity.service.BaseUserImpl");
061: _roleClasses
062: .add("org.josso.gateway.identity.service.BaseRoleImpl");
063: }
064:
065: private SSOUser _ssoUser;
066:
067: /**
068: * Construct and return a java.security.Principal instance
069: * representing the authenticated user for the specified Subject. If no
070: * such Principal can be constructed, return null.
071: *
072: * The Principal constructed is *not* GenericPrincipal as in Catalina JAASRealm class,
073: * but CatalinaSSOUser which is a SSOUser.
074: * The Partner Application can access SSOUser-specific properties that are not available
075: * in GenericPrincipal.
076: * The JAASRealm superclass invokes this factory method to build the Catalina-specific
077: * Principal from the Subject filled by the configured JAASLoginModule.
078: *
079: * @param subject The Subject representing the logged in user
080: */
081: public static CatalinaSSOUser newInstance(Realm realm,
082: Subject subject) {
083: // Prepare to scan the Principals for this Subject
084: String password = null; // Will not be carried forward
085: ArrayList roles = new ArrayList();
086: SSOUser ssoUser = null;
087: String username = null;
088:
089: // Scan the Principals for this Subject
090: Iterator principals = subject.getPrincipals().iterator();
091: while (principals.hasNext()) {
092: Principal principal = (Principal) principals.next();
093: // No need to look further - that's our own stuff
094: if (principal instanceof CatalinaSSOUser) {
095: if (logger.isDebugEnabled())
096: logger.debug("Found old CatalinaSSOUser Principal "
097: + principal);
098: return (CatalinaSSOUser) principal;
099: }
100: String principalClass = principal.getClass().getName();
101:
102: if (logger.isDebugEnabled())
103: logger.debug("Principal: " + principalClass + " "
104: + principal);
105:
106: if (_userClasses.contains(principalClass)) {
107: // Override the default - which is the original user, accepted by
108: // the friendly LoginManager
109: username = principal.getName();
110: }
111: if (_roleClasses.contains(principalClass)) {
112: roles.add(principal.getName());
113: }
114: // Same as Jboss - that's a pretty clean solution
115: if ((principal instanceof Group)
116: && "Roles".equals(principal.getName())) {
117: Group grp = (Group) principal;
118: Enumeration en = grp.members();
119: while (en.hasMoreElements()) {
120: Principal roleP = (Principal) en.nextElement();
121: roles.add(roleP.getName());
122: }
123:
124: }
125:
126: // Save the SSOUser principal so that it can be included in the
127: // CatalinaSSOUser Principal
128: if (principal instanceof SSOUser) {
129: ssoUser = (SSOUser) principal;
130: }
131: }
132:
133: if (ssoUser == null) {
134: logger
135: .error("Fatal: Subject does not contain an SSOUser Principal");
136: return null;
137: }
138:
139: // Create the resulting Principal for our authenticated user
140: if (username != null) {
141: return (new CatalinaSSOUser(ssoUser, realm, username,
142: password, roles));
143: } else {
144: return (null);
145: }
146: }
147:
148: /**
149: * Construct a new Principal, associated with the specified Realm, for the
150: * specified username and password.
151: *
152: * @param realm The Realm that owns this Principal
153: * @param name The username of the user represented by this Principal
154: * @param password Credentials used to authenticate this user
155: */
156: private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name,
157: String password) {
158:
159: this (ssoUser, realm, name, password, null);
160: }
161:
162: /**
163: * Construct a new Principal, associated with the specified Realm, for the
164: * specified username and password, with the specified role names
165: * (as Strings).
166: *
167: * @param realm The Realm that owns this principal
168: * @param name The username of the user represented by this Principal
169: * @param password Credentials used to authenticate this user
170: * @param roles List of roles (must be Strings) possessed by this user
171: */
172: private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name,
173: String password, List roles) {
174:
175: super (realm, name, password, roles);
176: _ssoUser = ssoUser;
177:
178: }
179:
180: /**
181: * @deprecated this method always return null
182: * @return always null
183: */
184: public String getSessionId() {
185: return null;
186: }
187:
188: public SSONameValuePair[] getProperties() {
189: return _ssoUser.getProperties();
190: }
191:
192: /**
193: * Return a String representation of this object, which exposes only
194: * information that should be public.
195: */
196: public String toString() {
197: StringBuffer sb = new StringBuffer("CatalinaSSOUser[");
198: sb.append(this .name);
199: sb.append("]");
200: return (sb.toString());
201: }
202:
203: }
|