001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.server.security;
030:
031: import com.caucho.config.Config;
032: import com.caucho.config.ConfigException;
033: import com.caucho.config.types.InitParam;
034:
035: import javax.annotation.PostConstruct;
036: import javax.security.auth.Subject;
037: import javax.security.auth.callback.Callback;
038: import javax.security.auth.callback.CallbackHandler;
039: import javax.security.auth.callback.NameCallback;
040: import javax.security.auth.callback.PasswordCallback;
041: import javax.security.auth.callback.UnsupportedCallbackException;
042: import javax.security.auth.login.LoginException;
043: import javax.security.auth.spi.LoginModule;
044: import javax.servlet.ServletContext;
045: import javax.servlet.ServletException;
046: import javax.servlet.http.HttpServletRequest;
047: import javax.servlet.http.HttpServletResponse;
048: import java.io.IOException;
049: import java.lang.reflect.Method;
050: import java.security.Principal;
051: import java.util.HashMap;
052: import java.util.Iterator;
053: import java.util.Set;
054: import java.util.logging.*;
055:
056: /**
057: * The JAAS authenticator uses an existing JAAS LoginModule. Applications
058: * which have existing JAAS modules can use the JaasAuthenticator to
059: * log users in based on the old login.
060: *
061: * <code><pre>
062: * <authenticator url="jaas:">
063: * <init login-module="example.MyLogin"/>
064: * </authenticator>
065: */
066: public class JaasAuthenticator extends AbstractAuthenticator {
067: private static final Logger log = Logger
068: .getLogger(JaasAuthenticator.class.getName());
069:
070: private Class _loginModuleClass;
071:
072: private HashMap<String, String> _options = new HashMap<String, String>();
073:
074: public JaasAuthenticator() {
075: setPasswordDigest(null);
076: }
077:
078: /**
079: * Sets the JAAS spi login module class.
080: */
081: public void setLoginModule(Class loginModuleClass)
082: throws ConfigException {
083: _loginModuleClass = loginModuleClass;
084:
085: Config.checkCanInstantiate(loginModuleClass);
086:
087: if (!LoginModule.class.isAssignableFrom(loginModuleClass))
088: throw new ConfigException(
089: L
090: .l(
091: "'{0}' must implement javax.security.auth.spi.LoginModule",
092: loginModuleClass.getName()));
093: }
094:
095: public void setInitParam(InitParam init) {
096: _options.putAll(init.getParameters());
097: }
098:
099: public void setOptions(InitParam init) {
100: _options.putAll(init.getParameters());
101: }
102:
103: /**
104: * Initialize the authenticator.
105: */
106: @PostConstruct
107: public synchronized void init() throws ServletException {
108: super .init();
109:
110: if (_loginModuleClass == null)
111: throw new ServletException(L
112: .l("JaasAuthenticator requires login-module"));
113: }
114:
115: /**
116: * Authenticate (login) the user.
117: */
118: protected Principal loginImpl(HttpServletRequest request,
119: HttpServletResponse response, ServletContext application,
120: String userName, String password) throws ServletException {
121: try {
122: LoginModule login = (LoginModule) _loginModuleClass
123: .newInstance();
124: Subject subject = new Subject();
125:
126: HashMap<String, String> state = new HashMap<String, String>();
127:
128: state.put("javax.security.auth.login.name", userName);
129: state.put("javax.security.auth.login.password", password);
130:
131: login.initialize(subject, new Handler(userName, password),
132: state, _options);
133:
134: try {
135: login.login();
136: } catch (Exception e) {
137: login.abort();
138: }
139:
140: login.commit();
141:
142: Set principals = subject.getPrincipals();
143:
144: if (principals == null || principals.size() == 0)
145: return null;
146:
147: Iterator iter = principals.iterator();
148: if (iter.hasNext())
149: return (Principal) iter.next();
150:
151: return null;
152: } catch (LoginException e) {
153: log.log(Level.FINE, e.toString(), e);
154:
155: return null;
156: } catch (RuntimeException e) {
157: throw e;
158: } catch (Exception e) {
159: throw new RuntimeException(e);
160: }
161: }
162:
163: /**
164: * Returns true if the user plays the named role.
165: *
166: * @param request the servlet request
167: * @param user the user to test
168: * @param role the role to test
169: */
170: public boolean isUserInRole(HttpServletRequest request,
171: HttpServletResponse response, ServletContext application,
172: Principal principal, String role) throws ServletException {
173: if (principal == null)
174: return false;
175:
176: if (principal instanceof RolePrincipal)
177: return ((RolePrincipal) principal).isUserInRole(role);
178: else
179: return "user".equals(role);
180: }
181:
182: static class Handler implements CallbackHandler {
183: private String _userName;
184: private String _password;
185:
186: Handler(String userName, String password) {
187: _userName = userName;
188: _password = password;
189: }
190:
191: public void handle(Callback[] callbacks) throws IOException,
192: UnsupportedCallbackException {
193: for (int i = 0; i < callbacks.length; i++) {
194: Callback cb = callbacks[i];
195:
196: if (cb instanceof NameCallback) {
197: NameCallback name = (NameCallback) cb;
198:
199: name.setName(_userName);
200: } else if (cb instanceof PasswordCallback) {
201: PasswordCallback password = (PasswordCallback) cb;
202:
203: password.setPassword(_password.toCharArray());
204: }
205: }
206: }
207: }
208: }
|