001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 2004 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: Standard.java 6661 2005-04-28 08:43:27Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.security.realm.web.catalina55;
025:
026: import java.security.Principal;
027: import java.security.cert.X509Certificate;
028: import java.util.ArrayList;
029:
030: import org.apache.catalina.LifecycleException;
031: import org.apache.catalina.realm.GenericPrincipal;
032: import org.apache.catalina.realm.RealmBase;
033:
034: import org.objectweb.jonas.common.Log;
035: import org.objectweb.jonas.security.SecurityService;
036: import org.objectweb.jonas.security.realm.factory.JResource;
037: import org.objectweb.jonas.security.realm.factory.JResourceException;
038: import org.objectweb.jonas.security.realm.principals.User;
039: import org.objectweb.jonas.service.ServiceManager;
040:
041: import org.objectweb.security.context.SecurityContext;
042: import org.objectweb.security.context.SecurityCurrent;
043:
044: import org.objectweb.util.monolog.api.BasicLevel;
045: import org.objectweb.util.monolog.api.Logger;
046:
047: /**
048: * <p>
049: * Implementation of a Realm. (by a wrapper) Use any JOnAS realm by specifying
050: * the resource name
051: *
052: * @author Florent Benoit
053: */
054: public class Standard extends RealmBase {
055:
056: /**
057: * Descriptive information about this Realm implementation.
058: */
059: private static final String NAME = "JRealmCatalina50";
060:
061: /**
062: * Descriptive information about this Realm implementation.
063: */
064: private static final String INFO = "org.objectweb.jonas.security.realm.JRealmCatalina50/1.0";
065:
066: /**
067: * The logger used in JOnAS
068: */
069: private static Logger logger = null;
070:
071: /**
072: * The resource we will use to authenticate users and identify associated
073: * roles.
074: */
075: private JResource jResource = null;
076:
077: /**
078: * The name of the resource
079: */
080: private String resourceName = null;
081:
082: /**
083: * Reference to the JOnAS security service
084: */
085: private SecurityService securityService = null;
086:
087: /**
088: * Return descriptive information about this Realm implementation and the
089: * corresponding version number, in the format
090: * <code><description>/<version></code>.
091: *
092: * @return the info.
093: */
094: public String getInfo() {
095: return INFO;
096: }
097:
098: /**
099: * Return the resource name we will be using.
100: *
101: * @return the resource name.
102: */
103: public String getResourceName() {
104: return resourceName;
105: }
106:
107: /**
108: * Set the resource name we will be using.
109: *
110: * @param resourceName The new resource name
111: */
112: public void setResourceName(String resourceName) {
113: this .resourceName = resourceName;
114:
115: }
116:
117: /**
118: * Return the Principal associated with the specified username and
119: * credentials, if there is one; otherwise return <code>null</code>.
120: *
121: * @param username Username of the Principal to look up
122: * @param credentials Password or other credentials to use in authenticating
123: * this username
124: * @return the principal associated
125: */
126: public Principal authenticate(String username, String credentials) {
127:
128: // No authentication can be made with a null username
129: if (username == null) {
130: if (logger.isLoggable(BasicLevel.DEBUG)) {
131: logger.log(BasicLevel.DEBUG,
132: "No username so no authentication");
133: }
134: return null;
135: }
136:
137: // Does a user with this username exist?
138: User user = null;
139: try {
140: user = jResource.findUser(username);
141: } catch (Exception jre) {
142: // could not retrieve user
143: logger.log(BasicLevel.ERROR, "Can not find the user : "
144: + jre.getMessage());
145: return null;
146: }
147:
148: // User was not found
149: if (user == null) {
150: if (logger.isLoggable(BasicLevel.DEBUG)) {
151: logger.log(BasicLevel.DEBUG, "User " + username
152: + " not found.");
153: }
154: return null;
155: }
156:
157: boolean validated = jResource.isValidUser(user, credentials);
158: if (!validated) {
159: logger.log(BasicLevel.ERROR, "The password for the user "
160: + username + " is not valid");
161: return null;
162: }
163:
164: ArrayList combinedRoles = null;
165: try {
166: combinedRoles = jResource.getArrayListCombinedRoles(user);
167: } catch (JResourceException jre) {
168: logger.log(BasicLevel.ERROR, jre.getMessage());
169: return null;
170: }
171:
172: GenericPrincipal principal = new GenericPrincipal(this , user
173: .getName(), user.getPassword(), combinedRoles);
174: SecurityContext ctx = new SecurityContext(principal.getName(),
175: combinedRoles);
176: SecurityCurrent current = SecurityCurrent.getCurrent();
177: current.setSecurityContext(ctx);
178:
179: return principal;
180: }
181:
182: /**
183: * Return the Principal associated with the specified chain of X509 client
184: * certificates. If there is none, return <code>null</code>.
185: *
186: * @param cert Array of client certificates, with the first one in the array
187: * being the certificate of the client itself.
188: * @return the associated Principal
189: */
190: public Principal authenticate(X509Certificate[] cert) {
191: String dn = cert[0].getSubjectDN().getName();
192: return authenticate(dn, "tomcat");
193: }
194:
195: /**
196: * Return a short name for this Realm implementation.
197: *
198: * @return the name
199: */
200: protected String getName() {
201: return NAME;
202: }
203:
204: /**
205: * Return the password associated with the given principal's user name.
206: *
207: * @param username the given principal's user name.
208: * @return the password associated.
209: */
210: protected String getPassword(String username) {
211: return null;
212: }
213:
214: /**
215: * Return the Principal associated with the given user name.
216: *
217: * @param username the given principal's user name.
218: * @return the Principal associated
219: */
220: protected Principal getPrincipal(String username) {
221: return null;
222: }
223:
224: /**
225: * Prepare for active use of the public methods of this Component.
226: *
227: * @exception LifecycleException if this component detects a fatal error
228: * that prevents it from being started
229: */
230: public synchronized void start() throws LifecycleException {
231:
232: if (logger == null) {
233: logger = Log.getLogger(Log.JONAS_SECURITY_PREFIX);
234: }
235:
236: // Get the Security Service
237: try {
238: securityService = (SecurityService) ServiceManager
239: .getInstance().getSecurityService();
240: } catch (Exception e) {
241: // Can't retrieve Security service
242: throw new LifecycleException(
243: "can't retrieve Security service");
244: }
245:
246: // Get the resource from the security service
247: jResource = securityService.getJResource(resourceName);
248: if (jResource == null) {
249: throw new LifecycleException("Can't retrieve resource '"
250: + resourceName + "' from the security service");
251: }
252:
253: // Perform normal superclass initialization
254: super .start();
255:
256: }
257:
258: /**
259: * Gracefully shut down active use of the public methods of this Component.
260: *
261: * @exception LifecycleException if this component detects a fatal error
262: * that needs to be reported
263: */
264: public synchronized void stop() throws LifecycleException {
265: // Perform normal superclass finalization
266: super .stop();
267:
268: // Release reference to our resource
269: jResource = null;
270: }
271:
272: /**
273: * Log a message on the Logger associated with our Container (if any)
274: *
275: * @param message Message to be logged
276: */
277: protected void log(String message) {
278: if (logger.isLoggable(BasicLevel.DEBUG)) {
279: logger.log(BasicLevel.DEBUG, message);
280: }
281: }
282:
283: }
|