1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server.handler;
20
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23
24 import org.eclipse.jetty.server.handler.ContextHandler.AliasCheck;
25 import org.eclipse.jetty.util.log.Log;
26 import org.eclipse.jetty.util.log.Logger;
27 import org.eclipse.jetty.util.resource.PathResource;
28 import org.eclipse.jetty.util.resource.Resource;
29
30
31
32
33
34
35
36
37
38 public class AllowSymLinkAliasChecker implements AliasCheck
39 {
40 private static final Logger LOG = Log.getLogger(AllowSymLinkAliasChecker.class);
41
42 @Override
43 public boolean check(String uri, Resource resource)
44 {
45
46 if (!(resource instanceof PathResource))
47 return false;
48
49 PathResource pathResource = (PathResource)resource;
50
51 try
52 {
53 Path path = pathResource.getPath();
54 Path alias = pathResource.getAliasPath();
55
56
57 if (Files.isSymbolicLink(path))
58 {
59 alias = path.getParent().resolve(alias);
60 if (LOG.isDebugEnabled())
61 {
62 LOG.debug("path ={}",path);
63 LOG.debug("alias={}",alias);
64 }
65 if (Files.isSameFile(path,alias))
66 {
67 if (LOG.isDebugEnabled())
68 LOG.debug("Allow symlink {} --> {}",resource,pathResource.getAliasPath());
69 return true;
70 }
71 }
72
73
74 boolean linked=true;
75 Path target=path;
76 int loops=0;
77 while (linked)
78 {
79 if (++loops>100)
80 {
81 if (LOG.isDebugEnabled())
82 LOG.debug("Too many symlinks {} --> {}",resource,target);
83 return false;
84 }
85 linked=false;
86 Path d = target.getRoot();
87 for (Path e:target)
88 {
89 Path r=d.resolve(e);
90 d=r;
91
92 while (Files.exists(d) && Files.isSymbolicLink(d))
93 {
94 Path link=Files.readSymbolicLink(d);
95 if (!link.isAbsolute())
96 link=d.getParent().resolve(link);
97 d=link;
98 linked=true;
99 }
100 }
101 target=d;
102 }
103
104 if (pathResource.getAliasPath().equals(target))
105 {
106 if (LOG.isDebugEnabled())
107 LOG.debug("Allow path symlink {} --> {}",resource,target);
108 return true;
109 }
110 }
111 catch(Exception e)
112 {
113 LOG.ignore(e);
114 }
115
116 return false;
117 }
118
119 }