Konstantin, On 4/20/16 8:31 AM, Konstantin Kolinko wrote: > 2016-04-19 22:42 GMT+03:00 Mark Thomas <[email protected]>: >> On 19/04/2016 19:38, Dimitar Valov wrote: >>> All static resources such as index.html will not be found when application >>> is added with <Context path="/" docBase="../../../"/>, for example tomcat >>> is put inside the application's META-INF. >>> >>> I've drilled down that the AbstractFileResourceSet class is responsible for >>> this behaviour, inside the protected final File file(String name, boolean >>> mustExist) method. There absoluteBase and canonicalBase (absolute, unique >>> with resolved symlinks) are used to determine if the file should be >>> accessed based on a case sensitivity check. >>> >>> Everything works fine if the docBase is not just path like ../../.././../ >>> but has an actual directory at the end, like ../../../web-app. However in >>> this edgy case the difference appears since the behaviour of >>> the org.apache.tomcat.util.http.RequestUtil.normalize method has slightly >>> different behavior than the File.getCanonicalPath. >>> >>> System.out.println(RequestUtil.normalize("/base/1/2/3/../../../")); >>> /base/ >>> >>> System.out.println(RequestUtil.normalize("/base/1/2/3/../../..")); >>> /base/1/.. >>> System.out.println(new File("/base/1/2/3/../../../").getCanonicalPath()); >>> /base >>> >>> The added /from RequestUtil breakes the logic inside the file method, since >>> when doing the substring operation inside AbstractFileResourceSet.file >>> method it may or may not have a trailing /. In such situation <whatever >>> path>/index.html substring with the absoluteBase becomes ndex.html. At the >>> end the file method returns from here: >>> >>> if (!canPath.equals(absPath)) // !"index.html".equals("ndex.html") >>> => true >>> return null; >>> >>> The RequestUtil comes from the http packages and follows their conventions >>> when normalizing the path, so an obvious way to fix this is to add and if >>> statement after the normalization >>> inside AbstractFileResourceSet.initInternal. >>> >>> this.absoluteBase = normalize(absolutePath); >>> if (this.absoluteBase.endsWith("/")) { >>> this.absoluteBase = this.absoluteBase.substring(0, >>> this.absoluteBase.length() - 1); >>> } >>> >>> With Java 7 instead of using the RequestUtil for normalization, Path >>> java.nio.file.Path.normalize() can accomplish the correct thing. >>> >>> Do you think that is something that can be fixed? Maybe the above is not >>> the best approach, however it's the least invasive. >> >> We need to be very careful here since this is security sensitive. >> >> Given that normalize handles URIs, there is an argument for slightly >> different handling of trailing '/'. I'm currently of the view (subject >> to the results of some local tests I am running) that if the input ends >> in '/', so should the output. If the input doesn't end in '/' neither >> should the output unless the output is the string "/". >> >> The end result is likely to be that docBase values should not end in "/". >> > > (I have not looked at the context. Just a general comment / review of > r1740134) > > There is a risk of normalizing Windows path of "C:\foo\.." into "C:" > which denotes the current directory on drive C: while the expected > value is the root of the drive, "C:\". > > I have not tested how java.io.File("C:") actually works.
I don't have a Windows machine handy right this minute, but from my previous experience, "C:" means "the current working directory on the C drive, from this process's perspective. For instance: D:\> DIR C:\ ... Program Files Windows ... D:\> DIR C: ... Program Files Windows ... D:\> CD C:\Windows D:\> DIR C: ... System System32 ... So I would think that using "C:" (with no trailing path) from Java would behave the same way: the current working directory *on that drive* would be the one used. I would expect it to work just like "." on *NIX. -chris --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
