001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.resource.security;
023:
024: import java.security.acl.Group;
025: import java.security.Principal;
026: import java.util.Map;
027: import java.util.Set;
028: import javax.resource.spi.security.PasswordCredential;
029: import javax.security.auth.Subject;
030: import javax.security.auth.callback.CallbackHandler;
031: import javax.security.auth.login.LoginException;
032:
033: import org.jboss.security.SimplePrincipal;
034: import org.jboss.security.RunAsIdentity;
035: import org.jboss.logging.Logger;
036:
037: /**
038: * A simple login module that simply associates the principal making the
039: * connection request with the actual EIS connection requirements.
040: *
041: * The type of Principal class used is
042: * <code>org.jboss.security.SimplePrincipal.</code>
043: * <p>
044: *
045: * @see org.jboss.resource.security.ConfiguredIdentityLoginModule
046: *
047: * @author Scott.Stark@jboss.org
048: * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
049: * @author <a href="mailto:dan.bunker@pbs.proquest.com">Dan Bunker</a>
050: * @version $Revision: 57189 $
051: */
052: public class CallerIdentityLoginModule extends
053: AbstractPasswordCredentialLoginModule {
054: /**
055: * Class logger
056: */
057: private static final Logger log = Logger
058: .getLogger(CallerIdentityLoginModule.class);
059:
060: /**
061: * The default username/principal to use for basic connections
062: */
063: private String userName;
064:
065: /**
066: * The default password to use for basic connections
067: */
068: private char[] password;
069: /** A flag indicating if the run-as principal roles should be added to the subject */
070: private boolean addRunAsRoles;
071: private Set runAsRoles;
072:
073: /**
074: * Default Constructor
075: */
076: public CallerIdentityLoginModule() {
077: }
078:
079: /**
080: * The initialize method sets up some default connection information for
081: * basic connections. This is useful for container initialization connection
082: * use or running the application in a non-secure manner. This method is
083: * called before the login method.
084: *
085: * @param subject
086: * @param handler
087: * @param sharedState
088: * @param options
089: */
090: public void initialize(Subject subject, CallbackHandler handler,
091: Map sharedState, Map options) {
092: super .initialize(subject, handler, sharedState, options);
093:
094: userName = (String) options.get("userName");
095: if (userName == null) {
096: log.debug("No default username supplied.");
097: }
098:
099: String pass = (String) options.get("password");
100: if (pass == null) {
101: log.debug("No default password supplied.");
102: } else {
103: password = pass.toCharArray();
104: }
105:
106: // Check the addRunAsRoles
107: String flag = (String) options.get("addRunAsRoles");
108: addRunAsRoles = Boolean.valueOf(flag).booleanValue();
109:
110: log.debug("got default principal: " + userName + ", username: "
111: + userName + ", password: "
112: + (password == null ? "null" : "****")
113: + " addRunAsRoles: " + addRunAsRoles);
114:
115: }
116:
117: /**
118: * Performs the login association between the caller and the resource for a
119: * 1 to 1 mapping. This acts as a login propagation strategy and is useful
120: * for single-sign on requirements
121: *
122: * @return True if authentication succeeds
123: * @throws LoginException
124: */
125: public boolean login() throws LoginException {
126: log.trace("Caller Association login called");
127:
128: //setup to use the default connection info. This will be overiden if security
129: //associations are found
130: String username = userName;
131:
132: //ask the security association class for the principal info making this request
133: try {
134: Principal user = GetPrincipalInfoAction.getPrincipal();
135: char[] userPassword = GetPrincipalInfoAction
136: .getCredential();
137:
138: if (userPassword != null) {
139: password = userPassword;
140: }
141:
142: if (user != null) {
143: username = user.getName();
144: if (log.isTraceEnabled()) {
145: log.trace("Current Calling principal is: "
146: + username + " ThreadName: "
147: + Thread.currentThread().getName());
148: }
149: // Check for a RunAsIdentity
150: RunAsIdentity runAs = GetPrincipalInfoAction
151: .peekRunAsIdentity();
152: if (runAs != null) {
153: runAsRoles = runAs.getRunAsRoles();
154: }
155: }
156: } catch (Throwable e) {
157: throw new LoginException(
158: "Unable to get the calling principal or its credentials for resource association");
159: }
160:
161: // Update userName so that getIdentity is consistent
162: userName = username;
163: if (super .login() == true) {
164: return true;
165: }
166:
167: // Put the principal name into the sharedState map
168: sharedState.put("javax.security.auth.login.name", username);
169: super .loginOk = true;
170:
171: return true;
172: }
173:
174: public boolean commit() throws LoginException {
175: // Put the principal name into the sharedState map
176: sharedState.put("javax.security.auth.login.name", userName);
177: // Add any run-as roles if addRunAsRoles is true
178: if (addRunAsRoles && runAsRoles != null) {
179: SubjectActions.addRoles(subject, runAsRoles);
180: }
181:
182: // Add the PasswordCredential
183: PasswordCredential cred = new PasswordCredential(userName,
184: password);
185: cred.setManagedConnectionFactory(getMcf());
186: SubjectActions.addCredentials(subject, cred);
187: return super .commit();
188: }
189:
190: protected Principal getIdentity() {
191: log.trace("getIdentity called");
192: Principal principal = new SimplePrincipal(userName);
193: return principal;
194: }
195:
196: protected Group[] getRoleSets() throws LoginException {
197: log.trace("getRoleSets called");
198: return new Group[] {};
199: }
200: }
|