View Javadoc

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().toURI()))
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().toURI().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  }