//  ========================================================================
//  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
//  ========================================================================
//  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.
//  ========================================================================

[[serving-aliased-files]]
=== Aliased Files and Symbolic links

Web applciations will often server static content from the file system
provided by the operating system running underneatth the JVM. However
because file systems often implement multiple aliased names for the same
file, then security constraints and other servlet URI space mappings my
inadvertantly be bypassed by aliases.

I key example of this is case insensitivety and 8.3 names implemented by
the Windows File system. If a file within a webapplication called
`/mysecretfile.txt` is protected by a security constraint on the URI
` /mysecretfile.txt`, then a request to `/MySecretFile.TXT` will not
match the URI constraint because URIs are case sensitive, but the
windows file system will report that a file does exist at that name and
it will be served despite the security constraint. Less well known than
case insensitivity is that windows files systems also support
http://en.wikipedia.org/wiki/8.3_filename[8.3 filenames] for
compatibility with legacy programs. Thus a request to a URI like
`/MYSECR~1.TXT` will again not match the security constraint, but will
be reported as an existing file by the file system and served.

There are many examples of aliases, not just on windows:

* NTFS Alternate stream names like c:\test\file.txt::$DATA:name
* OpenVMS support file versionig so that `/mysecret.txt;N` refers to
version N of `
      /mysecret.txt` and is essentially an alias.
* The clearcase software configuration management system provides a file
system where @@ in a file name is an alias to a specific version.
* The unix files system supports `/./foo.txt` as and alias for
`/foo.txt`
* Many JVM implementations incorrectly assume the null character is a
string terminator, so that a file name resulting from `/foobar.txt%00`
is an alias for `/foobar.txt`
* Unix symbolic links and hard links are a form of aliases that allow
the same file or directory to have multiple names.

In addition, it is not just URI security constraints that can be
bypassed. For example the mapping of the URI pattern `*.jsp` to the JSP
Servlet may be bypassed by an a request to an alias like `
  /foobar.jsp%00`, thus rather than execute the JSP, the source code of
the JSP is returned by the file system.

==== Good Security Practise

Part of the problem with aliases is that the standard web application
security model is to allow all requests except the ones that are
specifically denied by security constraints. A best practise for
security is to deny all requests and to permit only those that are
specifically identified as allowable. While it is possible to design web
application security constraints in this style, it can be difficult in
all circumstances and it is not the default. Thus it is important for
Jetty to be able to detect and deny requests to aliased static content.

[[file-alias-detection]]
==== Alias detection

It is impossible for Jetty to know of all the aliases that may be
implemented by the file system running beneath it, thus it does not
attempt to make any specific checks for any know aliases. Instead jetty
detects aliases by using the canonical path of a file. If a file
resource handled by jetty has a canonical name that differs from the
name used to request the resource, then Jetty determines that the
resource is an aliased request and it will not be returned by the
`ServletContext.getResource(String)` method (or similar) and thus will
not be served as static content nor used as the basis of a JSP.

This if Jetty is running on a windows operation system, then a file
called `/MySecret.TXT` will have a canonical name that exactly matches
that case. So while a request to `/mysecret.txt` or ` /MYSECR~1.TXT`
will result in a File Resource that matches the file, the different
canonical name will indicate that those requests are aliases and they
will not be served as static content and instead a 404 response
returned.

Unfortunately this approach denies all aliases, including symbolic
links, which can be useful in assembling complex web applications.

[[file-alias-serving]]
==== Serving Aliases and Symbolic Links

Not all aliases are bad nor should be seen as attempts to subvert
security constraints. Specifically symbolic links can be very useful
when assembling complex web applications, yet by default Jetty will not
serve them. Thus Jetty contexts support an extensible AliasCheck
mechanism to allow aliases resources to be inspected an conditionally
served. In this way, "good" aliases can be detected and served. Jetty
provides several utility implementations of the AliasCheck interface as
nested classes with ContextHandler:

ApproveAliases::
  Approve all aliases (USE WITH CAUTION!).
AllowSymLinkAliasChecker::
  Approve Aliases using the java-7 Files.readSymbolicLink(path) and
  Path.toRealPath(...) APIs to check that alias are valid symbolic
  links.

An application is free to implement its own Alias checking. Alias
Checkers can be installed in a context via the following XML used in a
context deployer file or `WEB-INF/jetty-web.xml`:

[source, xml, subs="{sub-order}"]
----
  <!-- Allow symbolic links  -->
  <Call name="addAliasCheck">
    <Arg><New class="org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker"/></Arg>
  </Call>
      
----
