1 //
2 // ========================================================================
3 // Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.server.handler;
20
21 import java.io.File;
22 import java.net.URI;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25
26 import org.eclipse.jetty.server.handler.ContextHandler.AliasCheck;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29 import org.eclipse.jetty.util.resource.Resource;
30
31
32 /* ------------------------------------------------------------ */
33 /** Symbolic Link AliasChecker.
34 * <p>An instance of this class can be registered with {@link ContextHandler#addAliasCheck(AliasCheck)}
35 * to check resources that are aliased to other locations. The checker uses the
36 * Java {@link Files#readSymbolicLink(Path)} and {@link Path#toRealPath(java.nio.file.LinkOption...)}
37 * APIs to check if a file is aliased with symbolic links.</p>
38 */
39 public class AllowSymLinkAliasChecker implements AliasCheck
40 {
41 private static final Logger LOG = Log.getLogger(AllowSymLinkAliasChecker.class);
42
43 @Override
44 public boolean check(String path, Resource resource)
45 {
46 try
47 {
48 File file =resource.getFile();
49 if (file==null)
50 return false;
51
52 // If the file exists
53 if (file.exists())
54 {
55 // we can use the real path method to check the symlinks resolve to the alias
56 URI real = file.toPath().toRealPath().toUri();
57 if (real.equals(resource.getAlias()))
58 {
59 LOG.debug("Allow symlink {} --> {}",resource,real);
60 return true;
61 }
62 }
63 else
64 {
65 // file does not exists, so we have to walk the path and links ourselves.
66 Path p = file.toPath().toAbsolutePath();
67 File d = p.getRoot().toFile();
68 for (Path e:p)
69 {
70 d=new File(d,e.toString());
71
72 while (d.exists() && Files.isSymbolicLink(d.toPath()))
73 {
74 Path link=Files.readSymbolicLink(d.toPath());
75 if (!link.isAbsolute())
76 link=link.resolve(d.toPath());
77 d=link.toFile().getAbsoluteFile().getCanonicalFile();
78 }
79 }
80 if (resource.getAlias().equals(d.toURI()))
81 {
82 LOG.debug("Allow symlink {} --> {}",resource,d);
83 return true;
84 }
85 }
86 }
87 catch(Exception e)
88 {
89 e.printStackTrace();
90 LOG.ignore(e);
91 }
92 return false;
93 }
94
95 }