You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Dimitar Valov <di...@gmail.com> on 2016/04/19 20:38:55 UTC

context root with relative path

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.

Best Regards
Dimitar Valov

Re: context root with relative path

Posted by David kerber <dc...@verizon.net>.
On 4/19/2016 4:13 PM, Dimitar Valov wrote:
> Hi Mark,
>
> Yes, it is sensitive, that's why I'm suggesting such simple solution. For
> me the issues comes because of AbstractFileResourceSet::file -> absPath =
> absPath.substring(absoluteBase.length() + 1); and if
> (!canPath.equals(absPath)). This + 1 should account for the /. However we
> cannot count on not having the / at the end of absPath.

Why not explicitly check for the existence of the trailing "\", rather 
than assuming it's (non)existence and just checking the string length?

I think Mark is saying that you have found an inconsistency, and pending 
further testing thinks that there should be changes made so that you get 
back what you supplied to those functions.  I.E., if you gave it a 
trailing "\" as an argument, you'll get one back, and if not, you won't.


>
> I've played with specifying paths that end with / and without, and I think
> that there's no way that the current implementation can be configured
> correctly:
>    * if path like ../../ is used it is normalized to path ending with / =>
> the substring will consume the first character of the filename.
>    * if path like ../.. is used it is normalized to path ending .. (which is
> even worse), but this can be documented out, otherwise a method like
> Path.normalize should be used or implemented.
>    * if path like ../../app or ../../app/ is used everything works
> correctly, but this is bacause StandardContext::fixDocBase takes care to
> delete the last /.
>
> I think that if fixDocBase does something to strings like ../../../ it will
> break the results returned from RequestUtil.normalize, i.e. deleting the
> last / and the normalizing it will produce path ending with /.. which will
> once again not work.
>
> The behaviour of org.apache.tomcat.util.http.RequestUtil is quite similar
> but different from the one getting unique file path (Path.normalize). And
> then if (!canPath.equals(absPath)) is comparing two quite similar things
> ,but not the same  "things". I think that with java.io.File APIs there's
> nothing that can give the needed behaviour (the getCanonicalPath will
> resolve symlinks)
>
> Best Regards,
> Dimitar Valov
>
> On Tue, Apr 19, 2016 at 10:42 PM, Mark Thomas <ma...@apache.org> wrote:
>
>> 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 "/".
>>
>> Mark
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: context root with relative path

Posted by Dimitar Valov <di...@gmail.com>.
Hi Mark,

Yes, it is sensitive, that's why I'm suggesting such simple solution. For
me the issues comes because of AbstractFileResourceSet::file -> absPath =
absPath.substring(absoluteBase.length() + 1); and if
(!canPath.equals(absPath)). This + 1 should account for the /. However we
cannot count on not having the / at the end of absPath.

I've played with specifying paths that end with / and without, and I think
that there's no way that the current implementation can be configured
correctly:
  * if path like ../../ is used it is normalized to path ending with / =>
the substring will consume the first character of the filename.
  * if path like ../.. is used it is normalized to path ending .. (which is
even worse), but this can be documented out, otherwise a method like
Path.normalize should be used or implemented.
  * if path like ../../app or ../../app/ is used everything works
correctly, but this is bacause StandardContext::fixDocBase takes care to
delete the last /.

I think that if fixDocBase does something to strings like ../../../ it will
break the results returned from RequestUtil.normalize, i.e. deleting the
last / and the normalizing it will produce path ending with /.. which will
once again not work.

The behaviour of org.apache.tomcat.util.http.RequestUtil is quite similar
but different from the one getting unique file path (Path.normalize). And
then if (!canPath.equals(absPath)) is comparing two quite similar things
,but not the same  "things". I think that with java.io.File APIs there's
nothing that can give the needed behaviour (the getCanonicalPath will
resolve symlinks)

Best Regards,
Dimitar Valov

On Tue, Apr 19, 2016 at 10:42 PM, Mark Thomas <ma...@apache.org> wrote:

> 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 "/".
>
> Mark
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

RE: context root with relative path

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Dimitar Valov [mailto:dimitar.valov@gmail.com] 
> Subject: Re: context root with relative path

> System.out.println(new File("C:").exists()); prints true, so I guess it
> works okay.

Depends on the definition of "okay"; that only tells us that the C drive's current directory is present.  As Konstantin pointed out, the normalization should have produced "C:\" - which will also pass the exists() test.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: context root with relative path

Posted by David kerber <dc...@verizon.net>.
On 4/20/2016 12:07 PM, Dimitar Valov wrote:
> System.out.println(new File("C:").exists()); prints true, so I guess it
> works okay.

All that means is that it does something.  That doesn't means it's doing 
the correct thing.  That *should* be checking the existence of the 
"current" directory, which is always going to succeed.  The question is, 
is it actually checking for the existence of the root directory?  And 
what does

new File("C:\").exists()

give you?  And is it different?



>
> On Wed, Apr 20, 2016 at 3:31 PM, Konstantin Kolinko <kn...@gmail.com>
> wrote:
>
>> 2016-04-19 22:42 GMT+03:00 Mark Thomas <ma...@apache.org>:
>>> 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.
>>
>> Best regards,
>> Konstantin Kolinko
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: context root with relative path

Posted by Dimitar Valov <di...@gmail.com>.
System.out.println(new File("C:").exists()); prints true, so I guess it
works okay.

On Wed, Apr 20, 2016 at 3:31 PM, Konstantin Kolinko <kn...@gmail.com>
wrote:

> 2016-04-19 22:42 GMT+03:00 Mark Thomas <ma...@apache.org>:
> > 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.
>
> Best regards,
> Konstantin Kolinko
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

Re: context root with relative path

Posted by David kerber <dc...@verizon.net>.
On 5/9/2016 11:34 AM, Dimitar Valov wrote:
> Hi,
>
> Have you decided if the proposed fix make since? If the corner case is
> <DRIVE>:/, then it can be handled as well, not to remove the slash in case
> the previous char is :.

IMO, the correct result for this case would most likely be to INCLUDE 
the trailing "/" if the previous character is a ":".  Generally you are 
going to want to end up with "the root of <DRIVE>", not "the default 
directory on <DRIVE>".



>
> Best Regards,
> Dimitar
>
> On Thu, Apr 21, 2016 at 7:12 PM, Leo Donahue <do...@gmail.com> wrote:
>
>> On Apr 21, 2016 10:38 AM, "David kerber" <dc...@verizon.net> wrote:
>>>
>>> On 4/21/2016 11:33 AM, Leo Donahue wrote:
>>>>
>>>> Chris,
>>>>
>>>> On Apr 21, 2016 9:15 AM, "Christopher Schultz" <
>> chris@christopherschultz.net>
>>>> wrote:
>>>>>
>>>>>
>>>>> 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
>>>>>
>>>>> --------------------------------------------------------------
>>>>
>>>>
>>>> On Windows 7 from a command prompt:
>>>>
>>>>> C:\downloads dir c:
>>>>
>>>> Shows contents of downloads
>>>>
>>>>> C:\downloads dir c:\
>>>>
>>>> Shows contents of c drive
>>>
>>>
>>> Yes, that's all well-known on windows.  The question was, how does the
>> Java File object handle it?   Does it give the correct result as above?
>> And going back to the original question, how should these paths be
>> normalized?
>>
>> Let's hope this looks right, pasting code from Android device...
>>
>> *import* java.io.File;
>>
>> *import* java.net.URI;
>>
>> *import* java.net.URISyntaxException;
>>
>> *import* java.util.ArrayList;
>>
>> *import* java.util.List;
>>
>>
>>
>> *public* *class* Demo
>>
>> {
>>
>>     *public* *static* *void* main(String[] args)
>>
>>     {
>>
>>         List<String> paths = *new* ArrayList<String>(2);
>>
>>         paths.add("file:/c:");
>>
>>         paths.add("file:/c:/");
>>
>>
>>
>>         *for* (String x : paths)
>>
>>         {
>>
>>             *try*
>>
>>             {
>>
>>                 URI uri = *new* URI(x);
>>
>>                 File f = *new* File(uri);
>>
>>                 System.*out*.println(f.getAbsolutePath());
>>
>>             }
>>
>>             *catch* (URISyntaxException e)
>>
>>             {
>>
>>                 e.printStackTrace();
>>
>>             }
>>
>>        }
>>
>>     }
>>
>> }
>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: context root with relative path

Posted by Dimitar Valov <di...@gmail.com>.
Hi,

Have you decided if the proposed fix make since? If the corner case is
<DRIVE>:/, then it can be handled as well, not to remove the slash in case
the previous char is :.

Best Regards,
Dimitar

On Thu, Apr 21, 2016 at 7:12 PM, Leo Donahue <do...@gmail.com> wrote:

> On Apr 21, 2016 10:38 AM, "David kerber" <dc...@verizon.net> wrote:
> >
> > On 4/21/2016 11:33 AM, Leo Donahue wrote:
> >>
> >> Chris,
> >>
> >> On Apr 21, 2016 9:15 AM, "Christopher Schultz" <
> chris@christopherschultz.net>
> >> wrote:
> >>>
> >>>
> >>> 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
> >>>
> >>> --------------------------------------------------------------
> >>
> >>
> >> On Windows 7 from a command prompt:
> >>
> >>> C:\downloads dir c:
> >>
> >> Shows contents of downloads
> >>
> >>> C:\downloads dir c:\
> >>
> >> Shows contents of c drive
> >
> >
> > Yes, that's all well-known on windows.  The question was, how does the
> Java File object handle it?   Does it give the correct result as above?
> And going back to the original question, how should these paths be
> normalized?
>
> Let's hope this looks right, pasting code from Android device...
>
> *import* java.io.File;
>
> *import* java.net.URI;
>
> *import* java.net.URISyntaxException;
>
> *import* java.util.ArrayList;
>
> *import* java.util.List;
>
>
>
> *public* *class* Demo
>
> {
>
>     *public* *static* *void* main(String[] args)
>
>     {
>
>         List<String> paths = *new* ArrayList<String>(2);
>
>         paths.add("file:/c:");
>
>         paths.add("file:/c:/");
>
>
>
>         *for* (String x : paths)
>
>         {
>
>             *try*
>
>             {
>
>                 URI uri = *new* URI(x);
>
>                 File f = *new* File(uri);
>
>                 System.*out*.println(f.getAbsolutePath());
>
>             }
>
>             *catch* (URISyntaxException e)
>
>             {
>
>                 e.printStackTrace();
>
>             }
>
>        }
>
>     }
>
> }
>

Re: context root with relative path

Posted by Leo Donahue <do...@gmail.com>.
On Apr 21, 2016 10:38 AM, "David kerber" <dc...@verizon.net> wrote:
>
> On 4/21/2016 11:33 AM, Leo Donahue wrote:
>>
>> Chris,
>>
>> On Apr 21, 2016 9:15 AM, "Christopher Schultz" <
chris@christopherschultz.net>
>> wrote:
>>>
>>>
>>> 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
>>>
>>> --------------------------------------------------------------
>>
>>
>> On Windows 7 from a command prompt:
>>
>>> C:\downloads dir c:
>>
>> Shows contents of downloads
>>
>>> C:\downloads dir c:\
>>
>> Shows contents of c drive
>
>
> Yes, that's all well-known on windows.  The question was, how does the
Java File object handle it?   Does it give the correct result as above?
And going back to the original question, how should these paths be
normalized?

Let's hope this looks right, pasting code from Android device...

*import* java.io.File;

*import* java.net.URI;

*import* java.net.URISyntaxException;

*import* java.util.ArrayList;

*import* java.util.List;



*public* *class* Demo

{

    *public* *static* *void* main(String[] args)

    {

        List<String> paths = *new* ArrayList<String>(2);

        paths.add("file:/c:");

        paths.add("file:/c:/");



        *for* (String x : paths)

        {

            *try*

            {

                URI uri = *new* URI(x);

                File f = *new* File(uri);

                System.*out*.println(f.getAbsolutePath());

            }

            *catch* (URISyntaxException e)

            {

                e.printStackTrace();

            }

       }

    }

}

Re: context root with relative path

Posted by David kerber <dc...@verizon.net>.
On 4/21/2016 11:33 AM, Leo Donahue wrote:
> Chris,
>
> On Apr 21, 2016 9:15 AM, "Christopher Schultz" <ch...@christopherschultz.net>
> wrote:
>>
>> 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
>>
>> --------------------------------------------------------------
>
> On Windows 7 from a command prompt:
>
>> C:\downloads dir c:
> Shows contents of downloads
>
>> C:\downloads dir c:\
> Shows contents of c drive

Yes, that's all well-known on windows.  The question was, how does the 
Java File object handle it?   Does it give the correct result as above? 
  And going back to the original question, how should these paths be 
normalized?



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: context root with relative path

Posted by Leo Donahue <do...@gmail.com>.
Chris,

On Apr 21, 2016 9:15 AM, "Christopher Schultz" <ch...@christopherschultz.net>
wrote:
>
> 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
>
> --------------------------------------------------------------

On Windows 7 from a command prompt:

>C:\downloads dir c:
Shows contents of downloads

>C:\downloads dir c:\
Shows contents of c drive

Leo

Re: context root with relative path

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Konstantin,

On 4/20/16 8:31 AM, Konstantin Kolinko wrote:
> 2016-04-19 22:42 GMT+03:00 Mark Thomas <ma...@apache.org>:
>> 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: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: context root with relative path

Posted by Konstantin Kolinko <kn...@gmail.com>.
2016-04-19 22:42 GMT+03:00 Mark Thomas <ma...@apache.org>:
> 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.

Best regards,
Konstantin Kolinko

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: context root with relative path

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Mark Thomas [mailto:markt@apache.org] 
> Subject: Re: context root with relative path

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.

Not that it's pertinent to the resource retrieval problem, but a path attribute of "/" is never correct ("" might be what is wanted).  But since path attributes on <Context> elements located in META-INF/context.xml are not allowed, it doesn't really matter for this particular issue.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: context root with relative path

Posted by Mark Thomas <ma...@apache.org>.
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 "/".

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org