ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/webresources/AbstractFileResourceSet.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/webresources/AbstractFileResourceSet.java
Status
scanned
Type
file
Name
AbstractFileResourceSet.java
Extension
.java
Programming language
Java
Mime type
text/plain
File type
ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
10240 (10.0 KB)
MD5
7fcdc1159938c296c56156da74e6746a
SHA1
1a6164802f00a5c6d15d2eca2ee2d0838a1ed213
SHA256
f31379d0eab723ebdd7773170d597f5bbb8bbfcfd1cb3726a92dae855444a573
SHA512

      
    
SHA1_git
1a82a9937060a95da1e89c4bcdce105dd71062a4
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
AbstractFileResourceSet.java | 10.0 KB |

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.catalina.webresources; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.apache.catalina.LifecycleException; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.compat.JrePlatform; import org.apache.tomcat.util.http.RequestUtil; public abstract class AbstractFileResourceSet extends AbstractResourceSet { private static final Log log = LogFactory.getLog(AbstractFileResourceSet.class); protected static final String[] EMPTY_STRING_ARRAY = new String[0]; private File fileBase; private String absoluteBase; private String canonicalBase; private boolean readOnly = false; private Boolean allowLinking; protected AbstractFileResourceSet(String internalPath) { setInternalPath(internalPath); } protected final File getFileBase() { return fileBase; } @Override public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } @Override public boolean isReadOnly() { return readOnly; } @Override public void setAllowLinking(boolean allowLinking) { this.allowLinking = Boolean.valueOf(allowLinking); } @Override public boolean getAllowLinking() { if (allowLinking == null) { return getRoot().getAllowLinking(); } return allowLinking.booleanValue(); } protected final File file(String name, boolean mustExist) { if (name.equals("/")) { name = ""; } File file = new File(fileBase, name); // If the requested names ends in '/', the Java File API will return a // matching file if one exists. This isn't what we want as it is not // consistent with the Servlet spec rules for request mapping. if (name.endsWith("/") && file.isFile()) { return null; } // If the file/dir must exist but the identified file/dir can't be read // then signal that the resource was not found if (mustExist && !file.canRead()) { return null; } // If allow linking is enabled, files are not limited to being located // under the fileBase so all further checks are disabled. if (getAllowLinking()) { return file; } // Additional Windows specific checks to handle known problems with // File.getCanonicalPath() and other issues if (JrePlatform.IS_WINDOWS && isInvalidWindowsFilename(name)) { return null; } // Check that this file is located under the WebResourceSet's base String canPath = null; try { canPath = file.getCanonicalPath(); } catch (IOException ignore) { // Ignore } if (canPath == null || !canPath.startsWith(canonicalBase)) { return null; } /* * Ensure that the file is not outside the fileBase. This should not be possible for standard requests (the * request is normalized early in the request processing) but might be possible for some access via the Servlet * API (e.g. RequestDispatcher) therefore these checks are retained as an additional safety measure. * absoluteBase has been normalized so absPath needs to be normalized as well. */ String absPath = normalize(file.getAbsolutePath()); if (absPath == null || absoluteBase.length() > absPath.length()) { return null; } // Remove the fileBase location from the start of the paths since that // was not part of the requested path and the remaining check only // applies to the request path absPath = absPath.substring(absoluteBase.length()); canPath = canPath.substring(canonicalBase.length()); // The remaining request path must start with '/' if it has non-zero length if (!canPath.isEmpty() && canPath.charAt(0) != File.separatorChar) { return null; } // Case sensitivity check // The normalized requested path should be an exact match the equivalent // canonical path. If it is not, possible reasons include: // - case differences on case-insensitive file systems // - Windows removing a trailing ' ' or '.' from the file name // // In all cases, a mismatch here results in the resource not being // found // // absPath is normalized so canPath needs to be normalized as well // Can't normalize canPath earlier as canonicalBase is not normalized if (!canPath.isEmpty()) { canPath = normalize(canPath); } if (!canPath.equals(absPath)) { if (!canPath.equalsIgnoreCase(absPath)) { // Typically means symlinks are in use but being ignored. Given // the symlink was likely created for a reason, log a warning // that it was ignored. logIgnoredSymlink(getRoot().getContext().getName(), absPath, canPath); } return null; } return file; } protected void logIgnoredSymlink(String contextPath, String absPath, String canPath) { // Log issues with configuration files at a higher level if (absPath.startsWith("/META-INF/") || absPath.startsWith("/WEB-INF/")) { log.error(sm.getString("abstractFileResourceSet.canonicalfileCheckFailed", contextPath, absPath, canPath)); } else { log.warn(sm.getString("abstractFileResourceSet.canonicalfileCheckFailed", contextPath, absPath, canPath)); } } private boolean isInvalidWindowsFilename(String name) { final int len = name.length(); if (len == 0) { return false; } // This is consistently ~10 times faster than the equivalent regular expression irrespective of input length. for (int i = 0; i < len; i++) { char c = name.charAt(i); /* * '\"', ':', '<' and '>' are disallowed in Windows file names and there are known problems with these * characters when using File#getCanonicalPath(). * * Control characters (0x00-0x31) are not permitted and tend to be display strangely in log messages and * similar. * * '*', '?' and '|' are also not allowed and, while they are not currently known to cause other * difficulties, they are checked here rather than wasting cycles trying to find an invalid file later. * * The file separators ('/' and '\\') are not allowed in file names but are not excluded here as paths are * passed to this method. * * Note: Characters are listed in ASCII order. */ if (c < 32 || c == '\"' || c == '*' || c == ':' || c == '<' || c == '>' || c == '?' || c == '|') { return true; } } /* * Windows does not allow file names to end in ' ' unless specific low-level APIs are used to create the files * that bypass various checks. File names that end in ' ' are known to cause problems when using * File#getCanonicalPath(). */ return name.charAt(len - 1) == ' '; } /** * Return a context-relative path, beginning with a "/", that represents the canonical version of the specified path * after ".." and "." elements are resolved out. If the specified path attempts to go outside the boundaries of the * current context (i.e. too many ".." path elements are present), return <code>null</code> instead. * * @param path Path to be normalized */ private String normalize(String path) { return RequestUtil.normalize(path, File.separatorChar == '\\'); } @Override public URL getBaseUrl() { try { return getFileBase().toURI().toURL(); } catch (MalformedURLException e) { return null; } } /** * {@inheritDoc} * <p> * This is a NO-OP by default for File based resource sets. */ @Override public void gc() { // NO-OP } // -------------------------------------------------------- Lifecycle methods @Override protected void initInternal() throws LifecycleException { fileBase = new File(getBase(), getInternalPath()); checkType(fileBase); this.absoluteBase = normalize(fileBase.getAbsolutePath()); try { this.canonicalBase = fileBase.getCanonicalPath(); } catch (IOException ioe) { throw new IllegalArgumentException(ioe); } // Need to handle mapping of the file system root as a special case if ("/".equals(this.absoluteBase)) { this.absoluteBase = ""; } if ("/".equals(this.canonicalBase)) { this.canonicalBase = ""; } } protected abstract void checkType(File file); }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
11.0
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9