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.server.dispatch.ErrorFilterChain;
032: import com.caucho.server.dispatch.FilterChainBuilder;
033: import com.caucho.server.dispatch.ForwardFilterChain;
034: import com.caucho.server.dispatch.Invocation;
035: import com.caucho.server.webapp.WebApp;
036: import com.caucho.util.L10N;
037:
038: import javax.servlet.FilterChain;
039: import javax.servlet.RequestDispatcher;
040: import javax.servlet.http.HttpServletResponse;
041: import java.util.ArrayList;
042: import java.util.HashMap;
043:
044: /**
045: * Manages security constraint.
046: */
047: public class ConstraintManager extends FilterChainBuilder {
048: private static L10N L = new L10N(ConstraintManager.class);
049:
050: private ArrayList<SecurityConstraint> _constraints = new ArrayList<SecurityConstraint>();
051:
052: public void addConstraint(SecurityConstraint constraint) {
053: _constraints.add(constraint);
054: }
055:
056: public FilterChainBuilder getFilterBuilder() {
057: return this ;
058: /*
059: if (_constraints.size() > 0)
060: return this;
061: else
062: return null;
063: */
064: }
065:
066: /**
067: * Builds a filter chain dynamically based on the invocation.
068: *
069: * @param next the next filter in the chain.
070: * @param invocation the request's invocation.
071: */
072: public FilterChain build(FilterChain next, Invocation invocation) {
073: String uri = invocation.getContextURI();
074:
075: WebApp app = invocation.getWebApp();
076: if (app == null)
077: return next;
078:
079: String lower = uri.toLowerCase();
080:
081: if (lower.startsWith("/web-inf")
082: || lower.startsWith("/meta-inf")) {
083: return new ErrorFilterChain(
084: HttpServletResponse.SC_NOT_FOUND);
085: }
086:
087: ArrayList<AbstractConstraint> constraints;
088: constraints = new ArrayList<AbstractConstraint>();
089:
090: HashMap<String, AbstractConstraint[]> methodMap;
091: methodMap = new HashMap<String, AbstractConstraint[]>();
092:
093: loop: for (int i = 0; i < _constraints.size(); i++) {
094: SecurityConstraint constraint = _constraints.get(i);
095:
096: if (constraint.isMatch(uri)) {
097: AbstractConstraint absConstraint = constraint
098: .getConstraint();
099:
100: if (absConstraint != null) {
101: ArrayList<String> methods = constraint
102: .getMethods(uri);
103:
104: for (int j = 0; methods != null
105: && j < methods.size(); j++) {
106: String method = methods.get(j);
107:
108: AbstractConstraint[] methodList = methodMap
109: .get(method);
110:
111: if (methodList == null)
112: methodList = absConstraint.toArray();
113: // server/12ba - the first constraint matches, following are
114: // ignored
115: /*
116: else {
117:
118: AbstractConstraint []newMethods = absConstraint.toArray();
119:
120: AbstractConstraint []newList;
121:
122: newList = new AbstractConstraint[methodList.length
123: + newMethods.length];
124:
125: System.arraycopy(methodList, 0, newList, 0, methodList.length);
126: System.arraycopy(newMethods, 0, newList,
127: methodList.length, newMethods.length);
128:
129: methodList = newList;
130: }
131: */
132:
133: methodMap.put(method, methodList);
134: }
135:
136: if (methods == null || methods.size() == 0) {
137: AbstractConstraint[] constArray = absConstraint
138: .toArray();
139: for (int k = 0; k < constArray.length; k++)
140: constraints.add(constArray[k]);
141:
142: // server/12ba - the first constraint matches, following are
143: // ignored
144:
145: break loop;
146: }
147: } else {
148: // server/1233
149:
150: break loop;
151: }
152: }
153: }
154:
155: if (uri.endsWith("/j_security_check")
156: && app.getLogin() instanceof FormLogin) {
157: RequestDispatcher disp = app
158: .getNamedDispatcher("j_security_check");
159: if (disp == null)
160: throw new IllegalStateException(L
161: .l("j_security_check is an undefined servlet"));
162:
163: next = new ForwardFilterChain(disp);
164: }
165:
166: if (constraints.size() > 0 || methodMap.size() > 0) {
167: SecurityFilterChain filterChain = new SecurityFilterChain(
168: next);
169: filterChain.setWebApp(invocation.getWebApp());
170: if (methodMap.size() > 0)
171: filterChain.setMethodMap(methodMap);
172: filterChain.setConstraints(constraints);
173:
174: return filterChain;
175: }
176:
177: return next;
178: }
179: }
|