All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jakarta.security.jacc.WebUserDataPermission Maven / Gradle / Ivy

/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.security.jacc;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.security.Permission;
import java.util.HashMap;
import java.util.Map;

import jakarta.servlet.http.HttpServletRequest;

/**
 * Class for Jakarta Servlet Web user data permissions. A WebUserDataPermission is a named permission and has actions.
 *
 * 

* The name of a WebUserDataPermission (also referred to as the target name) identifies a Web resource by its context * path relative URL pattern. * * @see Permission * * @author Ron Monzillo * @author Gary Ellison * */ public final class WebUserDataPermission extends Permission { private static final long serialVersionUID = -970193775626385011L; private transient static final String EMPTY_STRING = ""; private transient static final String ESCAPED_COLON = "%3A"; private static String transportKeys[] = { "NONE", "INTEGRAL", "CONFIDENTIAL", }; private static Map transportHash = new HashMap(); static { for (int i = 0; i < transportKeys.length; i++) { transportHash.put(transportKeys[i], i); } } private static int TT_NONE = transportHash.get("NONE"); private static int TT_CONFIDENTIAL = transportHash.get("CONFIDENTIAL"); private transient URLPatternSpec urlPatternSpec; private transient HttpMethodSpec methodSpec; private transient int transportType; private transient int hashCodeValue; /** * The serialized fields of this permission are defined below. Whether or not the serialized fields correspond to actual * (private) fields is an implementation decision. * * @serialField actions String the canonicalized actions string (as returned by getActions). */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("actions", String.class) }; /** * Creates a new WebUserDataPermission with the specified name and actions. * *

* The name contains a URLPatternSpec that identifies the web resources to which the permissions applies. The syntax of * a URLPatternSpec is as follows: * *

     *
     *          URLPatternList ::= URLPattern | URLPatternList colon URLPattern
     *
     *          URLPatternSpec ::= null | URLPattern | URLPattern colon URLPatternList
     *
     * 
* *

* A null URLPatternSpec is translated to the default URLPattern, "/", by the permission constructor. The empty string * is an exact URLPattern, and may occur anywhere in a URLPatternSpec that an exact URLPattern may occur. The first * URLPattern in a URLPatternSpec may be any of the pattern types, exact, path-prefix, extension, or default as defined * in the Jakarta Servlet Specification). When a URLPatternSpec includes a URLPatternList, the patterns of the * URLPatternList identify the resources to which the permission does NOT apply and depend on the pattern type and value * of the first pattern as follows: * *

    *
  • No pattern may exist in the URLPatternList that matches the first pattern. *
  • If the first pattern is a path-prefix pattern, only exact patterns matched by the first pattern and path-prefix * patterns matched by, but different from, the first pattern may occur in the URLPatternList. *
  • If the first pattern is an extension pattern, only exact patterns that are matched by the first pattern and * path-prefix patterns may occur in the URLPatternList. *
  • If the first pattern is the default pattern, "/", any pattern except the default pattern may occur in the * URLPatternList. *
  • If the first pattern is an exact pattern a URLPatternList must not be present in the URLPatternSpec. *
* *

* The actions parameter contains a comma separated list of HTTP methods that may be followed by a transportType * separated from the HTTP method by a colon. * *

     *
     *          ExtensionMethod ::= any token as defined by RFC 2616
     *                  (that is, 1*[any CHAR except CTLs or separators])
     *
     *          HTTPMethod ::= "Get" | "POST" | "PUT" | "DELETE" | "HEAD" |
     *                  "OPTIONS" | "TRACE" | ExtensionMethod
     *
     *          HTTPMethodList ::= HTTPMethod | HTTPMethodList comma HTTPMethod
     *
     *          HTTPMethodExceptionList ::= exclaimationPoint HTTPMethodList
     *
     *          HTTPMethodSpec ::= emptyString | HTTPMethodExceptionList |
     *                  HTTPMethodList
     *
     *          transportType ::= "INTEGRAL" | "CONFIDENTIAL" | "NONE"
     *
     *          actions ::= null | HTTPMethodSpec |
     *                  HTTPMethodSpec colon transportType
     *
     * 
* *

* If duplicates occur in the HTTPMethodSpec they must be eliminated by the permission constructor. * *

* An empty string HTTPMethodSpec is a shorthand for a List containing all the possible HTTP methods. * *

* If the HTTPMethodSpec contains an HTTPMethodExceptionList (i.e., it begins with an exclaimationPoint), the permission * pertains to all methods except those occuring in the exception list. * *

* An actions string without a transportType is a shorthand for a actions string with the value "NONE" as its * TransportType. * *

* A granted permission representing a transportType of "NONE", indicates that the associated resources may be accessed * using any connection type. * * @param name the URLPatternSpec that identifies the application specific web resources to which the permission * pertains. All URLPatterns in the URLPatternSpec are relative to the context path of the deployed web application * module, and the same URLPattern must not occur more than once in a URLPatternSpec. A null URLPatternSpec is * translated to the default URLPattern, "/", by the permission constructor. All colons occuring within the URLPattern * elements of the URLPatternSpec must be represented in escaped encoding as defined in RFC 2396. * @param actions identifies the HTTP methods and transport type to which the permission pertains. If the value passed * through this parameter is null or the empty string, then the permission is constructed with actions corresponding to * all the possible HTTP methods and transportType "NONE". */ public WebUserDataPermission(String name, String actions) { super(name); this.urlPatternSpec = new URLPatternSpec(name); parseActions(actions); } /** * Creates a new WebUserDataPermission with name corresponding to the URLPatternSpec, and actions composed from the * array of HTTP methods and the transport type. * * @param urlPatternSpec the URLPatternSpec that identifies the application specific web resources to which the * permission pertains. All URLPatterns in the URLPatternSpec are relative to the context path of the deployed web * application module, and the same URLPattern must not occur more than once in a URLPatternSpec. A null URLPatternSpec * is translated to the default URLPattern, "/", by the permission constructor. All colons occurring within the * URLPattern elements of the URLPatternSpec must be represented in escaped encoding as defined in RFC 2396. * @param HTTPMethods an array of strings each element of which contains the value of an HTTP method. If the value * passed through this parameter is null or is an array with no elements, then the permission is constructed with * actions corresponding to all the possible HTTP methods. * @param transportType a String whose value is a transportType. If the value passed through this parameter is null, * then the permission is constructed with actions corresponding to transportType "NONE". */ public WebUserDataPermission(String urlPatternSpec, String[] HTTPMethods, String transportType) { super(urlPatternSpec); this.urlPatternSpec = new URLPatternSpec(urlPatternSpec); this.transportType = TT_NONE; if (transportType != null) { Integer bit = transportHash.get(transportType); if (bit == null) { throw new IllegalArgumentException("illegal transport value"); } this.transportType = bit.intValue(); } this.methodSpec = HttpMethodSpec.getSpec(HTTPMethods); } /** * Creates a new WebUserDataPermission from the HttpServletRequest object. * * @param request the HttpServletRequest object corresponding to the Jakarta Servlet operation to which the permission pertains. * The permission name is the substring of the requestURI (HttpServletRequest.getRequestURI()) that begins after the * contextPath (HttpServletRequest.getContextPath()). When the substring operation yields the string "/", the permission * is constructed with the empty string as its name. The constructor must transform all colon characters occurring in the * name to escaped encoding as defined in RFC 2396. The HTTP method component of the permission's actions is as obtained * from HttpServletRequest.getMethod(). The TransportType component of the permission's actions is determined by calling * HttpServletRequest.isSecure(). */ public WebUserDataPermission(HttpServletRequest request) { super(getUriMinusContextPath(request)); this.urlPatternSpec = new URLPatternSpec(super.getName()); this.transportType = request.isSecure() ? TT_CONFIDENTIAL : TT_NONE; this.methodSpec = HttpMethodSpec.getSpec(request.getMethod()); } /** * Checks two WebUserDataPermission objects for equality. WebUserDataPermission objects are equivalent if their * URLPatternSpec and (canonicalized) actions values are equivalent. * *

* The URLPatternSpec of a reference permission is * equivalent to that of an argument permission if their first patterns are equivalent, and the patterns of the * URLPatternList of the reference permission collectively match exactly the same set of patterns as are matched by the * patterns of the URLPatternList of the argument permission. * *

* Two Permission objects, P1 and P2, are equivalent if and only if P1.implies(P2) AND P2.implies(P1). * * @param o the WebUserDataPermission object being tested for equality with this WebUserDataPermission. * @return true if the argument WebUserDataPermission object is equivalent to this WebUserDataPermission. */ @Override public boolean equals(Object o) { if (o == null || !(o instanceof WebUserDataPermission)) { return false; } WebUserDataPermission that = (WebUserDataPermission) o; if (this.transportType != that.transportType) { return false; } if (!this.methodSpec.equals(that.methodSpec)) { return false; } return this.urlPatternSpec.equals(that.urlPatternSpec); } /** * Returns a canonical String representation of the actions of this WebUserDataPermission. * *

* The canonical form of the actions of a WebUserDataPermission is described by the following syntax description. * *

     *
     *          ExtensionMethod ::= any token as defined by RFC 2616
     *                   (that is, 1*[any CHAR except CTLs or separators])
     *
     *          HTTPMethod ::= "GET" | "POST" | "PUT" | "DELETE" | "HEAD" |
     *                   "OPTIONS" | "TRACE" | ExtensionMethod
     *
     *          HTTPMethodList ::= HTTPMethod | HTTPMethodList comma HTTPMethod
     *
     *          HTTPMethodExceptionList ::= exclaimationPoint HTTPMethodList
     *
     *          HTTPMethodSpec ::= emptyString | HTTPMethodExceptionList |
     *                  HTTPMethodList
     *
     *          transportType ::= "INTEGRAL" | "CONFIDENTIAL" | "NONE"
     *
     *          actions ::= null | HTTPMethodList |
     *                  HTTPMethodSpec colon transportType
     *
     * 
* *

* If the permission's HTTP methods correspond to the entire HTTP method set and the permission's transport type is * "INTEGRAL" or "CONFIDENTIAL", the HTTP methods shall be represented in the canonical form by an emptyString * HTTPMethodSpec. If the permission's HTTP methods correspond to the entire HTTP method set, and the permission's * transport type is not "INTEGRAL"or "CONFIDENTIAL", the canonical actions value shall be the null value. * *

* If the permission's methods do not correspond to the entire HTTP method set, duplicates must be eliminated and the * remaining elements must be ordered such that the predefined methods preceed the extension methods, and such that * within each method classification the corresponding methods occur in ascending lexical order. The resulting * (non-emptyString) HTTPMethodSpec must be included in the canonical form, and if the permission's transport type is * not "INTEGRAL" or "CONFIDENTIAL", the canonical actions value must be exactly the resulting HTTPMethodSpec. * * @return a String containing the canonicalized actions of this WebUserDataPermission (or the null value). */ @Override public String getActions() { String methodSpecActions = methodSpec.getActions(); if (transportType == TT_NONE && methodSpecActions == null) { return null; } if (transportType == TT_NONE) { return methodSpecActions; } if (methodSpecActions == null) { return ":" + transportKeys[transportType]; } return methodSpecActions + ":" + transportKeys[transportType]; } /** * Returns the hash code value for this WebUserDataPermission. * *

* The properties of the returned hash code must be as follows: * *

    *
  • During the lifetime of a Java application, the hashCode method shall return the same integer value every time it * is called on a WebUserDataPermission object. The value returned by hashCode for a particular EJBMethod permission * need not remain consistent from one execution of an application to another. *
  • If two WebUserDataPermission objects are equal according to the equals method, then calling the hashCode method * on each of the two Permission objects must produce the same integer result (within an application). *
* * @return the integer hash code value for this object. */ @Override public int hashCode() { if (hashCodeValue == 0) { String hashInput = urlPatternSpec.toString() + " " + methodSpec.hashCode() + ":" + transportType; hashCodeValue = hashInput.hashCode(); } return hashCodeValue; } /** * Determines if the argument Permission is "implied by" this WebUserDataPermission. * *

* For this to be the case all of the following must be true: * *

    *
  • The argument is an instanceof WebUserDataPermission. *
  • The first URLPattern in the name of the argument permission is matched by the first URLPattern in the name of * this permission. *
  • The first URLPattern in the name of the argument permission is NOT matched by any URLPattern in the * URLPatternList of the URLPatternSpec of this permission. *
  • If the first URLPattern in the name of the argument permission matches the first URLPattern in the URLPatternSpec * of this permission, then every URLPattern in the URLPatternList of the URLPatternSpec of this permission is matched * by a URLPattern in the URLPatternList of the argument permission. *
  • The HTTP methods represented by the actions of the argument permission are a subset of the HTTP methods * represented by the actions of this permission. *
  • The transportType in the actions of this permission either corresponds to the value "NONE", or equals the * transportType in the actions of the argument permission. *
* *

* URLPattern matching is performed using the Jakarta Servlet matching rules where two URL patterns match if they are * related as follows: * *

    *
  • their pattern values are String equivalent, or *
  • this pattern is the path-prefix pattern "/*", or *
  • this pattern is a path-prefix pattern (that is, it starts with "/" and ends with "/*") and the argument pattern * starts with the substring of this pattern, minus its last 2 characters, and the next character of the argument * pattern, if there is one, is "/", or *
  • this pattern is an extension pattern (that is, it starts with "*.") and the argument pattern ends with this * pattern, or *
  • the reference pattern is the special default pattern, "/", which matches all argument patterns. *
* *

* All of the comparisons described above are case sensitive. * * @param permission "this" WebUserDataPermission is checked to see if it implies the argument permission. * * @return true if the specified permission is implied by this object, false if not. */ @Override public boolean implies(Permission permission) { if (!(permission instanceof WebUserDataPermission)) { return false; } WebUserDataPermission that = (WebUserDataPermission) permission; if (this.transportType != TT_NONE && this.transportType != that.transportType) { return false; } if (!this.methodSpec.implies(that.methodSpec)) { return false; } return this.urlPatternSpec.implies(that.urlPatternSpec); } // ----------------- Private Methods --------------------- /** * Chops the ContextPath off the front of the requestURI to yield the servletPath + PathInfo. For the special case where * the servletPath + PathInfo is the pattern, "/", this routine returns the empty string. */ private static String getUriMinusContextPath(HttpServletRequest request) { String uri = request.getRequestURI(); if (uri == null) { return EMPTY_STRING; } String contextPath = request.getContextPath(); int contextLength = contextPath == null ? 0 : contextPath.length(); if (contextLength > 0) { uri = uri.substring(contextLength); } if (uri.equals("/")) { return EMPTY_STRING; } // Encode all colons return uri.replaceAll(":", ESCAPED_COLON); } private void parseActions(String actions) { transportType = TT_NONE; if (actions == null || actions.equals("")) { methodSpec = HttpMethodSpec.getSpec((String) null); } else { int colon = actions.indexOf(':'); if (colon < 0) { methodSpec = HttpMethodSpec.getSpec(actions); } else { if (colon == 0) { methodSpec = HttpMethodSpec.getSpec((String) null); } else { methodSpec = HttpMethodSpec.getSpec(actions.substring(0, colon)); } Integer bit = transportHash.get(actions.substring(colon + 1)); if (bit == null) { throw new IllegalArgumentException("illegal transport value"); } transportType = bit.intValue(); } } } /** * readObject reads the serialized fields from the input stream and uses them to restore the permission. This method * need not be implemented if establishing the values of the serialized fields (as is done by defaultReadObject) is * sufficient to initialize the permission. * * @param inputStream The stream from which the fields are read * * @throws ClassNotFoundException If the class of an object couldn't be found * @throws IOException If an I/O error occurs */ private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { parseActions((String) inputStream.readFields().get("actions", null)); urlPatternSpec = new URLPatternSpec(super.getName()); } /** * writeObject is used to establish the values of the serialized fields before they are written to the output stream and * need not be implemented if the values of the serialized fields are always available and up to date. The serialized * fields are written to the output stream in the same form as they would be written by defaultWriteObject. * * @param outputStream The stream to which the serialized fields are written * * @throws IOException If an I/O error occurs while writing to the underlying stream */ private synchronized void writeObject(ObjectOutputStream outputStream) throws IOException { outputStream.putFields().put("actions", this.getActions()); outputStream.writeFields(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy