mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Improve the cowboy_static consistency across platforms
As a result we explictly reject path_info components that include a forward slash, backward slash or NUL character. This only applies to the [...] part of the path for dir/priv_dir configuration. Also improve the tests so that they work on Windows.
This commit is contained in:
parent
36836594f8
commit
4427108b69
2 changed files with 65 additions and 38 deletions
|
@ -119,35 +119,51 @@ init_dir(Req, Path, HowToAccess, Extra) when is_list(Path) ->
|
|||
init_dir(Req, list_to_binary(Path), HowToAccess, Extra);
|
||||
init_dir(Req, Path, HowToAccess, Extra) ->
|
||||
Dir = fullpath(filename:absname(Path)),
|
||||
PathInfo = cowboy_req:path_info(Req),
|
||||
Filepath = filename:join([Dir|escape_reserved(PathInfo)]),
|
||||
Len = byte_size(Dir),
|
||||
case fullpath(Filepath) of
|
||||
<< Dir:Len/binary, $/, _/binary >> ->
|
||||
init_info(Req, Filepath, HowToAccess, Extra);
|
||||
<< Dir:Len/binary >> ->
|
||||
init_info(Req, Filepath, HowToAccess, Extra);
|
||||
_ ->
|
||||
{cowboy_rest, Req, error}
|
||||
case cowboy_req:path_info(Req) of
|
||||
%% When dir/priv_dir are used and there is no path_info
|
||||
%% this is a configuration error and we abort immediately.
|
||||
undefined ->
|
||||
{ok, cowboy_req:reply(500, Req), error};
|
||||
PathInfo ->
|
||||
case validate_reserved(PathInfo) of
|
||||
error ->
|
||||
{cowboy_rest, Req, error};
|
||||
ok ->
|
||||
Filepath = filename:join([Dir|PathInfo]),
|
||||
Len = byte_size(Dir),
|
||||
case fullpath(Filepath) of
|
||||
<< Dir:Len/binary, $/, _/binary >> ->
|
||||
init_info(Req, Filepath, HowToAccess, Extra);
|
||||
<< Dir:Len/binary >> ->
|
||||
init_info(Req, Filepath, HowToAccess, Extra);
|
||||
_ ->
|
||||
{cowboy_rest, Req, error}
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
escape_reserved([]) -> [];
|
||||
escape_reserved([P|Tail]) -> [escape_reserved(P, <<>>)|escape_reserved(Tail)].
|
||||
validate_reserved([]) ->
|
||||
ok;
|
||||
validate_reserved([P|Tail]) ->
|
||||
case validate_reserved1(P) of
|
||||
ok -> validate_reserved(Tail);
|
||||
error -> error
|
||||
end.
|
||||
|
||||
%% We escape the slash found in path segments because
|
||||
%% a segment corresponds to a directory entry, and
|
||||
%% therefore those slashes are expected to be part of
|
||||
%% the directory name.
|
||||
%%
|
||||
%% Note that on most systems the slash is prohibited
|
||||
%% and cannot appear in filenames, which means the
|
||||
%% requested file will end up being not found.
|
||||
escape_reserved(<<>>, Acc) ->
|
||||
Acc;
|
||||
escape_reserved(<< $/, Rest/bits >>, Acc) ->
|
||||
escape_reserved(Rest, << Acc/binary, $\\, $/ >>);
|
||||
escape_reserved(<< C, Rest/bits >>, Acc) ->
|
||||
escape_reserved(Rest, << Acc/binary, C >>).
|
||||
%% We always reject forward slash, backward slash and NUL as
|
||||
%% those have special meanings across the supported platforms.
|
||||
%% We could support the backward slash on some platforms but
|
||||
%% for the sake of consistency and simplicity we don't.
|
||||
validate_reserved1(<<>>) ->
|
||||
ok;
|
||||
validate_reserved1(<<$/, _/bits>>) ->
|
||||
error;
|
||||
validate_reserved1(<<$\\, _/bits>>) ->
|
||||
error;
|
||||
validate_reserved1(<<0, _/bits>>) ->
|
||||
error;
|
||||
validate_reserved1(<<_, Rest/bits>>) ->
|
||||
validate_reserved1(Rest).
|
||||
|
||||
fullpath(Path) ->
|
||||
fullpath(filename:split(Path), []).
|
||||
|
@ -290,7 +306,7 @@ bad_path_win32_check_test_() ->
|
|||
-endif.
|
||||
|
||||
%% Reject requests that tried to access a file outside
|
||||
%% the target directory.
|
||||
%% the target directory, or used reserved characters.
|
||||
|
||||
-spec malformed_request(Req, State)
|
||||
-> {boolean(), Req, State}.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue