001: /*
002: * Tomcat: The deployer for the tomcat daemon
003: * Copyright (C) 2007 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * CoadunationRealm.java
020: */
021:
022: // package path
023: package com.rift.coad.daemon.tomcat.security;
024:
025: // java imports
026: import java.io.IOException;
027: import java.security.Principal;
028: import java.util.Set;
029: import java.util.List;
030: import java.util.ArrayList;
031: import java.util.Iterator;
032:
033: // coadunation imports
034: import com.rift.coad.security.BasicPrincipal;
035: import com.rift.coad.lib.security.login.SessionLogin;
036: import com.rift.coad.lib.security.login.handlers.PasswordInfoHandler;
037: import com.rift.coad.lib.security.UserSession;
038: import com.rift.coad.lib.security.RoleManager;
039: import com.rift.coad.lib.security.Role;
040:
041: // logging import
042: import org.apache.log4j.Logger;
043:
044: // tomcat imports
045: import javax.servlet.http.HttpServletResponse;
046: import org.apache.catalina.Realm;
047: import org.apache.catalina.deploy.SecurityConstraint;
048: import org.apache.catalina.deploy.LoginConfig;
049: import org.apache.catalina.connector.Request;
050: import org.apache.catalina.connector.Response;
051: import org.apache.catalina.realm.RealmBase;
052: import org.apache.catalina.realm.Constants;
053: import org.apache.catalina.realm.GenericPrincipal;
054:
055: /**
056: * This object is responsible acting as a Tomcat Realm but authenticating the
057: * calls off of Coadunation.
058: *
059: * @author brett
060: */
061: public class CoadunationRealm extends RealmBase implements Realm {
062:
063: // private member variables
064: protected Logger log = Logger.getLogger(CoadunationRealm.class
065: .getName());
066: private boolean trace = false;
067:
068: /**
069: * Creates a new instance of CoadunationRealm
070: */
071: public CoadunationRealm() {
072: trace = log.isTraceEnabled();
073: }
074:
075: /**
076: * This method returns the name of this realm.
077: */
078: protected String getName() {
079: return this .getClass().getName();
080: }
081:
082: /**
083: * This method returns the password associated with the given username.
084: */
085: protected String getPassword(String username) {
086: String password = null;
087: return password;
088: }
089:
090: /**
091: * This method returns the principal for the requested user
092: */
093: protected Principal getPrincipal(String username) {
094: return new BasicPrincipal(username);
095: }
096:
097: /**
098: * This method is here for debug purposes
099: */
100: public boolean hasResourcePermission(Request request,
101: Response response, SecurityConstraint[] constraints,
102: org.apache.catalina.Context context) throws IOException {
103: if (constraints == null || constraints.length == 0) {
104: return (true);
105: }
106:
107: boolean hasPermission = false;
108: // Specifically allow access to the form login and form error pages
109: // and the "j_security_check" action
110: LoginConfig config = context.getLoginConfig();
111: if ((config != null)
112: && (Constants.FORM_METHOD
113: .equals(config.getAuthMethod()))) {
114: String requestURI = request.getRequestPathMB().toString();
115: String loginPage = config.getLoginPage();
116: if (loginPage.equals(requestURI)) {
117: if (trace)
118: log
119: .trace("Allow access to login page "
120: + loginPage);
121: return (true);
122: }
123: String errorPage = config.getErrorPage();
124: if (errorPage.equals(requestURI)) {
125: if (trace)
126: log
127: .trace("Allow access to error page "
128: + errorPage);
129: return (true);
130: }
131: if (requestURI.endsWith(Constants.FORM_ACTION)) {
132: if (trace)
133: log
134: .trace("Allow access to username/password submission");
135: return (true);
136: }
137: }
138:
139: // Which user principal have we already authenticated?
140: Principal principal = request.getPrincipal();
141: boolean denyfromall = false;
142: for (int i = 0; i < constraints.length; i++) {
143: SecurityConstraint constraint = constraints[i];
144:
145: String roles[];
146: if (constraint.getAllRoles()) {
147: // * means all roles defined in web.xml
148: roles = request.getContext().findSecurityRoles();
149: } else {
150: roles = constraint.findAuthRoles();
151: }
152:
153: if (roles == null) {
154: roles = new String[0];
155: }
156:
157: if (trace)
158: log.trace("Checking roles " + principal);
159:
160: if (roles.length == 0 && !constraint.getAllRoles()) {
161: if (constraint.getAuthConstraint()) {
162: if (trace)
163: log.trace("No roles");
164: hasPermission = false; // No listed roles means no access at all
165: denyfromall = true;
166: } else {
167: if (trace)
168: log.trace("Passing all access");
169: return (true);
170: }
171: } else if (principal == null) {
172: if (trace)
173: log
174: .trace("No user authenticated, cannot grant access");
175: hasPermission = false;
176: } else if (!denyfromall) {
177: for (int j = 0; j < roles.length; j++) {
178: if (hasRole(principal, roles[j])) {
179: hasPermission = true;
180: }
181: if (trace)
182: log.trace("No role found: " + roles[j]);
183: }
184: }
185: }
186:
187: if (allRolesMode != AllRolesMode.STRICT_MODE
188: && hasPermission == false && principal != null) {
189: if (trace) {
190: log.trace("Checking for all roles mode: "
191: + allRolesMode);
192: }
193: // Check for an all roles(role-name="*")
194: for (int i = 0; i < constraints.length; i++) {
195: SecurityConstraint constraint = constraints[i];
196: String roles[];
197: // If the all roles mode exists, sets
198: if (constraint.getAllRoles()) {
199: if (allRolesMode == AllRolesMode.AUTH_ONLY_MODE) {
200: if (trace) {
201: log
202: .trace("Granting access for role-name=*, auth-only");
203: }
204: hasPermission = true;
205: break;
206: }
207:
208: // For AllRolesMode.STRICT_AUTH_ONLY_MODE there must be zero roles
209: roles = request.getContext().findSecurityRoles();
210: if (roles.length == 0
211: && allRolesMode == AllRolesMode.STRICT_AUTH_ONLY_MODE) {
212: if (trace) {
213: log
214: .trace("Granting access for role-name=*, strict auth-only");
215: }
216: hasPermission = true;
217: break;
218: }
219: }
220: }
221: }
222:
223: // Return a "Forbidden" message denying access to this resource
224: if (!hasPermission) {
225: response.sendError(HttpServletResponse.SC_FORBIDDEN, sm
226: .getString("realmBase.forbidden"));
227: }
228: return hasPermission;
229: }
230:
231: /**
232: * Return the Principal associated with the specified username and
233: * credentials, if there is one; otherwise return <code>null</code>.
234: *
235: * @param username Username of the Principal to look up
236: * @param credentials Password or other credentials to use in authenticating
237: * this username
238: */
239: public Principal authenticate(String username, String credentials) {
240: try {
241: SessionLogin sessionLogin = new SessionLogin(
242: new PasswordInfoHandler(username, credentials));
243: sessionLogin.login();
244: UserSession userSession = sessionLogin.getUser();
245:
246: // retrieve the list of roles
247: List roles = new ArrayList();
248: Set systemRoles = RoleManager.getInstance().getRoles();
249: for (Iterator iter = systemRoles.iterator(); iter.hasNext();) {
250: Role role = RoleManager.getInstance().getRole(
251: (String) iter.next());
252: Set rolePrincipals = role.getPrincipals();
253: for (Iterator roleIter = rolePrincipals.iterator(); roleIter
254: .hasNext();) {
255: if (userSession.getPrincipals().contains(
256: roleIter.next())) {
257: roles.add(role.getName());
258: break;
259: }
260: }
261:
262: }
263:
264: // construct the gneric principal object
265: CoadunationGenericPrincipal genericPrincipal = new CoadunationGenericPrincipal(
266: this , username, credentials, roles, userSession);
267:
268: // setup the session
269: log.info("Setup a users session");
270: CoadunationInterceptor.getInstance().pushUser(userSession);
271:
272: // return generic principals
273: return genericPrincipal;
274: } catch (Exception ex) {
275: log.error("Failed to authenticate the user [" + username
276: + "] because :" + ex.getMessage(), ex);
277: }
278:
279: return null;
280: }
281:
282: /**
283: * Return the Principal associated with the specified username and
284: * credentials, if there is one; otherwise return <code>null</code>.
285: *
286: * @param username Username of the Principal to look up
287: * @param credentials Password or other credentials to use in authenticating
288: * this username
289: */
290: public Principal authenticate(String username, byte[] credentials) {
291:
292: return authenticate(username, new String(credentials));
293: }
294: }
|