001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2005 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library 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 library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: JResourceRemoteImpl.java 9787 2006-10-24 12:11:25Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.security.realm.factory;
025:
026: import java.rmi.AccessException;
027: import java.rmi.RemoteException;
028: import java.util.ArrayList;
029:
030: import javax.rmi.PortableRemoteObject;
031: import javax.security.auth.Subject;
032: import javax.security.auth.login.LoginContext;
033: import javax.security.auth.login.LoginException;
034:
035: import org.objectweb.jonas.security.SecurityService;
036: import org.objectweb.jonas.security.auth.JGroup;
037: import org.objectweb.jonas.security.auth.JPrincipal;
038: import org.objectweb.jonas.security.auth.JRole;
039: import org.objectweb.jonas.security.auth.JSubject;
040: import org.objectweb.jonas.security.auth.callback.NoInputCallbackHandler;
041: import org.objectweb.jonas.security.realm.principals.User;
042: import org.objectweb.jonas.service.ServiceManager;
043:
044: /**
045: * This class allow to make authentication on server side even for Client
046: * container or remote applications
047: * @author Florent Benoit
048: */
049: public class JResourceRemoteImpl extends PortableRemoteObject implements
050: JResourceRemote {
051:
052: /**
053: * Security service
054: */
055: private static SecurityService securityService = null;
056:
057: /**
058: * Default constructor
059: * @throws RemoteException if super class cannot export object
060: */
061: public JResourceRemoteImpl() throws RemoteException {
062: super ();
063: }
064:
065: /**
066: * Authenticate a given user
067: * @param principalName name of the user
068: * @param arrayPass password of the user
069: * @param resourceName type of resource to use to register ( memory, jdbc,
070: * ldap)
071: * @throws RemoteException if the authentication failed
072: * @return an authenticated subject if it succeed
073: */
074: public JSubject authenticate(String principalName,
075: char[] arrayPass, String resourceName)
076: throws RemoteException {
077: // Get security service
078: if (securityService == null) {
079: try {
080: securityService = (SecurityService) ServiceManager
081: .getInstance().getSecurityService();
082: } catch (Exception e) {
083: throw createChainedAccessException(
084: "Cannot retrieve security service. Check that the security service is running",
085: e);
086: } catch (Error e) {
087: throw createChainedAccessException(
088: "Cannot retrieve security service. Check that the security service is running",
089: e);
090: }
091: }
092:
093: if (resourceName == null) {
094: throw new AccessException(
095: "The 'resourceName' parameter is required and cannot be null.");
096: }
097:
098: // Get resource
099: JResource jResource = null;
100: try {
101: jResource = securityService.getJResource(resourceName);
102: } catch (Exception e) {
103: throw createChainedAccessException("The resource '"
104: + resourceName + "' is not available.", e);
105: }
106:
107: if (jResource == null) {
108: throw new AccessException("The resource '" + resourceName
109: + "' is not available.");
110: }
111:
112: // Authentication - step 1 (user)
113: User user = null;
114: try {
115: user = jResource.findUser(principalName);
116: } catch (Exception jre) {
117: // could not retrieve user
118: throw createChainedAccessException("Can not find the user",
119: jre);
120: }
121: // User was not found
122: if (user == null) {
123: throw new AccessException("User '" + principalName
124: + "' not found.");
125: }
126:
127: // Authentication - step 2 (password)
128: boolean validated = jResource.isValidUser(user, new String(
129: arrayPass));
130: if (!validated) {
131: throw new AccessException("The password for the user '"
132: + principalName + "' is not valid");
133: }
134:
135: // Authentication - step 3 (roles)
136: ArrayList principalRoles = null;
137: try {
138: principalRoles = jResource.getArrayListCombinedRoles(user);
139: } catch (JResourceException jre) {
140: throw createChainedAccessException(jre.getMessage(), jre);
141: }
142:
143: JGroup group = new JGroup("Roles");
144:
145: // Convert list into array
146: String[] roles = new String[principalRoles.size()];
147: roles = (String[]) principalRoles.toArray(roles);
148: int size = principalRoles.size();
149: for (int i = 0; i < size; i++) {
150: group.addMember(new JRole(roles[i]));
151: }
152:
153: // build object with name and group
154: return new JSubject(new JPrincipal(principalName), group);
155:
156: }
157:
158: /**
159: * Authenticate a given user
160: * @param principalName name of the user
161: * @param arrayPass password of the user
162: * @param entryName the name of the JAAS entry to search in jaas configuration file
163: * @throws RemoteException if the authentication failed
164: * @return an authenticated subject if it succeed
165: */
166: public Subject authenticateJAAS(String principalName,
167: char[] arrayPass, String entryName) throws RemoteException {
168: // entry arg ?
169: if (entryName == null) {
170: throw new AccessException(
171: "The 'entryName' parameter is required and cannot be null.");
172: }
173:
174: // Create a Login context
175: LoginContext loginContext = null;
176: try {
177: loginContext = new LoginContext(entryName,
178: new NoInputCallbackHandler(principalName,
179: new String(arrayPass)));
180: } catch (LoginException e) {
181: throw new AccessException("Login Exception for user '"
182: + principalName + "' : " + e.getMessage());
183: }
184:
185: // Negotiate a login via this LoginContext
186: try {
187: loginContext.login();
188: } catch (LoginException e) {
189: throw new AccessException("Login Exception for user '"
190: + principalName + "' : " + e.getMessage());
191: }
192: return loginContext.getSubject();
193: }
194:
195: /**
196: * Create a AccessException with the given message and set the cause to the
197: * given Exception
198: * @param msg Exception message
199: * @param t Root cause
200: * @return AccessException the chained exception
201: */
202: private static AccessException createChainedAccessException(
203: String msg, Throwable t) {
204: if (t instanceof Exception) {
205: // If this is an Exception subclass, we can directly chain the cause.
206: return new AccessException(msg, (Exception) t);
207: } else {
208: // In the other case, no chaining is possible
209: // We simply put the cause's message in brackets and append
210: // it to the new AccessException
211: String causeMessage = "[inner cause message: "
212: + t.getMessage() + "]";
213: return new AccessException(msg + causeMessage);
214: }
215: }
216:
217: }
|