001: /*
002: * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: */
007: package winstone.auth;
008:
009: import java.util.HashSet;
010: import java.util.Set;
011:
012: import javax.servlet.http.HttpServletRequest;
013:
014: import org.w3c.dom.Node;
015:
016: import winstone.Logger;
017: import winstone.Mapping;
018: import winstone.WebAppConfiguration;
019:
020: /**
021: * Models a restriction on a particular set of resources in the webapp.
022: *
023: * @author mailto: <a href="rick_knowles@hotmail.com">Rick Knowles</a>
024: * @version $Id: SecurityConstraint.java,v 1.7 2006/08/10 06:38:30 rickknowles Exp $
025: */
026: public class SecurityConstraint {
027: final String ELEM_DISPLAY_NAME = "display-name";
028: final String ELEM_WEB_RESOURCES = "web-resource-collection";
029: final String ELEM_WEB_RESOURCE_NAME = "web-resource-name";
030: final String ELEM_URL_PATTERN = "url-pattern";
031: final String ELEM_HTTP_METHOD = "http-method";
032: final String ELEM_AUTH_CONSTRAINT = "auth-constraint";
033: final String ELEM_ROLE_NAME = "role-name";
034: final String ELEM_USER_DATA_CONSTRAINT = "user-data-constraint";
035: final String ELEM_TRANSPORT_GUARANTEE = "transport-guarantee";
036: final String GUARANTEE_NONE = "NONE";
037:
038: private String displayName;
039: private String methodSets[];
040: private Mapping urlPatterns[];
041: private String rolesAllowed[];
042: private boolean needsSSL;
043:
044: /**
045: * Constructor
046: */
047: public SecurityConstraint(Node elm, Set rolesAllowed, int counter) {
048: this .needsSSL = false;
049: Set localUrlPatternList = new HashSet();
050: Set localMethodSetList = new HashSet();
051: Set localRolesAllowed = new HashSet();
052:
053: for (int i = 0; i < elm.getChildNodes().getLength(); i++) {
054: Node child = elm.getChildNodes().item(i);
055: if (child.getNodeType() != Node.ELEMENT_NODE)
056: continue;
057: else if (child.getNodeName().equals(ELEM_DISPLAY_NAME))
058: this .displayName = WebAppConfiguration
059: .getTextFromNode(child);
060: else if (child.getNodeName().equals(ELEM_WEB_RESOURCES)) {
061: String methodSet = null;
062:
063: // Parse the element and extract
064: for (int k = 0; k < child.getChildNodes().getLength(); k++) {
065: Node resourceChild = child.getChildNodes().item(k);
066: if (resourceChild.getNodeType() != Node.ELEMENT_NODE)
067: continue;
068: String resourceChildNodeName = resourceChild
069: .getNodeName();
070: if (resourceChildNodeName.equals(ELEM_URL_PATTERN)) {
071: localUrlPatternList
072: .add(Mapping
073: .createFromURL(
074: "Security",
075: WebAppConfiguration
076: .getTextFromNode(resourceChild)));
077: } else if (resourceChildNodeName
078: .equals(ELEM_HTTP_METHOD)) {
079: methodSet = (methodSet == null ? "."
080: : methodSet)
081: + WebAppConfiguration
082: .getTextFromNode(resourceChild)
083: + ".";
084: }
085: }
086: localMethodSetList.add(methodSet == null ? ".ALL."
087: : methodSet);
088: } else if (child.getNodeName().equals(ELEM_AUTH_CONSTRAINT)) {
089: // Parse the element and extract
090: for (int k = 0; k < child.getChildNodes().getLength(); k++) {
091: Node roleChild = child.getChildNodes().item(k);
092: if ((roleChild.getNodeType() != Node.ELEMENT_NODE)
093: || !roleChild.getNodeName().equals(
094: ELEM_ROLE_NAME))
095: continue;
096: String roleName = WebAppConfiguration
097: .getTextFromNode(roleChild);
098: if (roleName.equals("*"))
099: localRolesAllowed.addAll(rolesAllowed);
100: else
101: localRolesAllowed.add(roleName);
102: }
103: } else if (child.getNodeName().equals(
104: ELEM_USER_DATA_CONSTRAINT)) {
105: // Parse the element and extract
106: for (int k = 0; k < child.getChildNodes().getLength(); k++) {
107: Node roleChild = child.getChildNodes().item(k);
108: if ((roleChild.getNodeType() == Node.ELEMENT_NODE)
109: && roleChild.getNodeName().equals(
110: ELEM_TRANSPORT_GUARANTEE))
111: this .needsSSL = !WebAppConfiguration
112: .getTextFromNode(roleChild)
113: .equalsIgnoreCase(GUARANTEE_NONE);
114: }
115: }
116: }
117: this .urlPatterns = (Mapping[]) localUrlPatternList
118: .toArray(new Mapping[0]);
119: this .methodSets = (String[]) localMethodSetList
120: .toArray(new String[0]);
121: this .rolesAllowed = (String[]) localRolesAllowed
122: .toArray(new String[0]);
123:
124: if (this .displayName == null)
125: this .displayName = BaseAuthenticationHandler.AUTH_RESOURCES
126: .getString("SecurityConstraint.DefaultName", ""
127: + counter);
128: }
129:
130: /**
131: * Call this to evaluate the security constraint - is this operation allowed ?
132: */
133: public boolean isAllowed(HttpServletRequest request) {
134: for (int n = 0; n < this .rolesAllowed.length; n++) {
135: if (request.isUserInRole(this .rolesAllowed[n])) {
136: Logger.log(Logger.FULL_DEBUG,
137: BaseAuthenticationHandler.AUTH_RESOURCES,
138: "SecurityConstraint.Passed",
139: new String[] { this .displayName,
140: this .rolesAllowed[n] });
141: return true;
142: }
143: }
144: Logger.log(Logger.FULL_DEBUG,
145: BaseAuthenticationHandler.AUTH_RESOURCES,
146: "SecurityConstraint.Failed", this .displayName);
147: return false;
148: }
149:
150: /**
151: * Call this to evaluate the security constraint - is this constraint applicable to this url ?
152: */
153: public boolean isApplicable(String url, String method) {
154: for (int n = 0; n < this .urlPatterns.length; n++)
155: if (this .urlPatterns[n].match(url, null, null)
156: && methodCheck(method, this .methodSets[n]))
157: return true;
158:
159: return false;
160: }
161:
162: private boolean methodCheck(String protocol, String methodSet) {
163: return methodSet.equals(".ALL.")
164: || (methodSet.indexOf("." + protocol.toUpperCase()
165: + ".") != -1);
166: }
167:
168: public boolean needsSSL() {
169: return this .needsSSL;
170: }
171:
172: public String getName() {
173: return this.displayName;
174: }
175: }
|