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

org.eclipse.jetty.server.SymlinkAllowedResourceAliasChecker Maven / Gradle / Ivy

// 
// ========================================================================
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// 
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// 
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// 
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
// 
package org.eclipse.jetty.server;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

/**
 *  An extension of {@link AllowedResourceAliasChecker} which will allow symlinks alias to arbitrary
 *  targets, so long as the symlink file itself is an allowed resource.
 *
 * @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported.
 */
@Deprecated(since = "2021-05-27")
public class SymlinkAllowedResourceAliasChecker extends AllowedResourceAliasChecker {

    private static final Logger LOG = Log.getLogger(SymlinkAllowedResourceAliasChecker.class);

    /**
     * @param contextHandler the context handler to use.
     */
    public SymlinkAllowedResourceAliasChecker(ContextHandler contextHandler) {
        super(contextHandler);
    }

    @Override
    protected boolean check(String pathInContext, Path path) {
        if (_base == null)
            return false;
        // do not allow any file separation characters in the URI, as we need to know exactly what are the segments
        if (File.separatorChar != '/' && pathInContext.indexOf(File.separatorChar) >= 0)
            return false;
        // Split the URI path into segments, to walk down the resource tree and build the realURI of any symlink found
        // We rebuild the realURI, segment by segment, getting the real name at each step, so that we can distinguish between
        // alias types.  Specifically, so we can allow a symbolic link so long as it's realpath is not protected.
        String[] segments = pathInContext.substring(1).split("/");
        Path fromBase = _base;
        StringBuilder realURI = new StringBuilder();
        try {
            for (String segment : segments) {
                // Add the segment to the path and realURI.
                fromBase = fromBase.resolve(segment);
                realURI.append("/").append(fromBase.toRealPath(NO_FOLLOW_LINKS).getFileName());
                // If the ancestor of the alias is a symlink, then check if the real URI is protected, otherwise allow.
                // This allows symlinks like /other->/WEB-INF and /external->/var/lib/docroot
                // This does not allow symlinks like /WeB-InF->/var/lib/other
                if (Files.isSymbolicLink(fromBase))
                    return !getContextHandler().isProtectedTarget(realURI.toString());
                // If the ancestor is not allowed then do not allow.
                if (!isAllowed(fromBase))
                    return false;
                // TODO as we are building the realURI of the resource, it would be possible to
                // re-check that against security constraints.
            }
        } catch (Throwable t) {
            if (LOG.isDebugEnabled())
                LOG.debug("Failed to check alias", t);
            return false;
        }
        // No symlink found, so must be allowed. Double check it is the right path we checked.
        return isSameFile(fromBase, path);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy