From dfe10daaee512ba39a0b918613f36b989fc90c49 Mon Sep 17 00:00:00 2001 From: Sergei Golovan Date: Sun, 9 Feb 2014 23:06:25 +0400 Subject: lib/inets/src/ftp/ftp.erl: Check the filenames, usernames, passwords etc. for and in them and return error if these offending chars are found. See http://erlang.org/pipermail/erlang-bugs/2014-January/003998.html for details. lib/inets/test/ftp_suite_lib.erl: Added checks for in file and directory names. --- lib/inets/src/ftp/ftp.erl | 142 +++++++++++++++++++++++++++++++++------ lib/inets/test/ftp_suite_lib.erl | 20 ++++++ 2 files changed, 143 insertions(+), 19 deletions(-) (limited to 'lib/inets') diff --git a/lib/inets/src/ftp/ftp.erl b/lib/inets/src/ftp/ftp.erl index 132a384a49..7ca6bae38d 100644 --- a/lib/inets/src/ftp/ftp.erl +++ b/lib/inets/src/ftp/ftp.erl @@ -181,7 +181,12 @@ open(Host, Opts) when is_list(Opts) -> 'ok' | {'error', Reason :: 'euser' | common_reason()}. user(Pid, User, Pass) -> - call(Pid, {user, User, Pass}, atom). + case {is_name_sane(User), is_name_sane(Pass)} of + {true, true} -> + call(Pid, {user, User, Pass}, atom); + _ -> + {error, euser} + end. -spec user(Pid :: pid(), User :: string(), @@ -190,7 +195,12 @@ user(Pid, User, Pass) -> 'ok' | {'error', Reason :: 'euser' | common_reason()}. user(Pid, User, Pass, Acc) -> - call(Pid, {user, User, Pass, Acc}, atom). + case {is_name_sane(User), is_name_sane(Pass), is_name_sane(Acc)} of + {true, true, true} -> + call(Pid, {user, User, Pass, Acc}, atom); + _ -> + {error, euser} + end. %%-------------------------------------------------------------------------- @@ -205,7 +215,12 @@ user(Pid, User, Pass, Acc) -> 'ok' | {'error', Reason :: 'eacct' | common_reason()}. account(Pid, Acc) -> - call(Pid, {account, Acc}, atom). + case is_name_sane(Acc) of + true -> + call(Pid, {account, Acc}, atom); + _ -> + {error, eacct} + end. %%-------------------------------------------------------------------------- @@ -251,7 +266,12 @@ lpwd(Pid) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. cd(Pid, Dir) -> - call(Pid, {cd, Dir}, atom). + case is_name_sane(Dir) of + true -> + call(Pid, {cd, Dir}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -294,7 +314,12 @@ ls(Pid) -> {'error', Reason :: restriction_reason() | common_reason()}. ls(Pid, Dir) -> - call(Pid, {dir, long, Dir}, string). + case is_name_sane(Dir) of + true -> + call(Pid, {dir, long, Dir}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -322,7 +347,12 @@ nlist(Pid) -> {'error', Reason :: restriction_reason() | common_reason()}. nlist(Pid, Dir) -> - call(Pid, {dir, short, Dir}, string). + case is_name_sane(Dir) of + true -> + call(Pid, {dir, short, Dir}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -338,7 +368,12 @@ nlist(Pid, Dir) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. rename(Pid, Old, New) -> - call(Pid, {rename, Old, New}, string). + case {is_name_sane(Old), is_name_sane(New)} of + {true, true} -> + call(Pid, {rename, Old, New}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -354,7 +389,12 @@ rename(Pid, Old, New) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. delete(Pid, File) -> - call(Pid, {delete, File}, string). + case is_name_sane(File) of + true -> + call(Pid, {delete, File}, string); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -369,7 +409,12 @@ delete(Pid, File) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. mkdir(Pid, Dir) -> - call(Pid, {mkdir, Dir}, atom). + case is_name_sane(Dir) of + true -> + call(Pid, {mkdir, Dir}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -384,7 +429,12 @@ mkdir(Pid, Dir) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. rmdir(Pid, Dir) -> - call(Pid, {rmdir, Dir}, atom). + case is_name_sane(Dir) of + true -> + call(Pid, {rmdir, Dir}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -426,7 +476,12 @@ recv(Pid, RemotFileName) -> 'ok' | {'error', Reason :: term()}. recv(Pid, RemotFileName, LocalFileName) -> - call(Pid, {recv, RemotFileName, LocalFileName}, atom). + case is_name_sane(RemotFileName) of + true -> + call(Pid, {recv, RemotFileName, LocalFileName}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -445,7 +500,12 @@ recv(Pid, RemotFileName, LocalFileName) -> {'error', Reason :: restriction_reason() | common_reason()}. recv_bin(Pid, RemoteFile) -> - call(Pid, {recv_bin, RemoteFile}, bin). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {recv_bin, RemoteFile}, bin); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -462,7 +522,12 @@ recv_bin(Pid, RemoteFile) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. recv_chunk_start(Pid, RemoteFile) -> - call(Pid, {recv_chunk_start, RemoteFile}, atom). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {recv_chunk_start, RemoteFile}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -510,7 +575,12 @@ send(Pid, LocalFileName) -> shortage_reason()}. send(Pid, LocalFileName, RemotFileName) -> - call(Pid, {send, LocalFileName, RemotFileName}, atom). + case is_name_sane(RemotFileName) of + true -> + call(Pid, {send, LocalFileName, RemotFileName}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -530,7 +600,12 @@ send(Pid, LocalFileName, RemotFileName) -> shortage_reason()}. send_bin(Pid, Bin, RemoteFile) when is_binary(Bin) -> - call(Pid, {send_bin, Bin, RemoteFile}, atom); + case is_name_sane(RemoteFile) of + true -> + call(Pid, {send_bin, Bin, RemoteFile}, atom); + _ -> + {error, efnamena} + end; send_bin(_Pid, _Bin, _RemoteFile) -> {error, enotbinary}. @@ -548,7 +623,12 @@ send_bin(_Pid, _Bin, _RemoteFile) -> 'ok' | {'error', Reason :: restriction_reason() | common_reason()}. send_chunk_start(Pid, RemoteFile) -> - call(Pid, {send_chunk_start, RemoteFile}, atom). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {send_chunk_start, RemoteFile}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -564,7 +644,12 @@ send_chunk_start(Pid, RemoteFile) -> 'ok' | {'error', Reason :: term()}. append_chunk_start(Pid, RemoteFile) -> - call(Pid, {append_chunk_start, RemoteFile}, atom). + case is_name_sane(RemoteFile) of + true -> + call(Pid, {append_chunk_start, RemoteFile}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -672,7 +757,12 @@ append(Pid, LocalFileName) -> 'ok' | {'error', Reason :: term()}. append(Pid, LocalFileName, RemotFileName) -> - call(Pid, {append, LocalFileName, RemotFileName}, atom). + case is_name_sane(RemotFileName) of + true -> + call(Pid, {append, LocalFileName, RemotFileName}, atom); + _ -> + {error, efnamena} + end. %%-------------------------------------------------------------------------- @@ -694,7 +784,12 @@ append(Pid, LocalFileName, RemotFileName) -> shortage_reason()}. append_bin(Pid, Bin, RemoteFile) when is_binary(Bin) -> - call(Pid, {append_bin, Bin, RemoteFile}, atom); + case is_name_sane(RemoteFile) of + true -> + call(Pid, {append_bin, Bin, RemoteFile}, atom); + _ -> + {error, efnamena} + end; append_bin(_Pid, _Bin, _RemoteFile) -> {error, enotbinary}. @@ -2209,6 +2304,15 @@ cast(GenServer, Msg) -> mk_cmd(Fmt, Args) -> [io_lib:format(Fmt, Args)| [?CR, ?LF]]. % Deep list ok. +is_name_sane([]) -> + true; +is_name_sane([?CR| _]) -> + false; +is_name_sane([?LF| _]) -> + false; +is_name_sane([_| Rest]) -> + is_name_sane(Rest). + pwd_result(Lines) -> {_, [?DOUBLE_QUOTE | Rest]} = lists:splitwith(fun(?DOUBLE_QUOTE) -> false; (_) -> true end, Lines), diff --git a/lib/inets/test/ftp_suite_lib.erl b/lib/inets/test/ftp_suite_lib.erl index 35f21cc74d..daee1bdcdc 100644 --- a/lib/inets/test/ftp_suite_lib.erl +++ b/lib/inets/test/ftp_suite_lib.erl @@ -1266,6 +1266,8 @@ read_log_6035([]) -> %%-------------------------------------------------------------------- do_user(Pid) -> {error, euser} = ftp:user(Pid, ?BAD_USER, ?FTP_PASS), + {error, euser} = ftp:user(Pid, ?FTP_USER++"\r\nPASS "++?FTP_PASS, ?FTP_PASS), + {error, euser} = ftp:user(Pid, ?FTP_USER, ?FTP_PASS++"\r\nCWD ."), ok = ftp:user(Pid, ?FTP_USER, ?FTP_PASS), ok. @@ -1278,6 +1280,7 @@ do_pwd(Pid) -> do_cd(Pid) -> ok = ftp:cd(Pid, "/pub"), {error, epath} = ftp:cd(Pid, ?BAD_DIR), + {error, efnamena} = ftp:cd(Pid, "/pub\r\nCWD ."), ok. do_lcd(Pid, Dir) -> @@ -1294,11 +1297,14 @@ do_ls(Pid) -> %% directory, but can also be a filename or a group %% of files (including wildcards). {ok, _} = ftp:ls(Pid, "incom*"), + %% but \r\n can't be in the wildcard + {error, efnamena} = ftp:ls(Pid, "incoming\r\nCWD ."), ok. do_nlist(Pid, WildcardSupport) -> {ok, _} = ftp:nlist(Pid), {ok, _} = ftp:nlist(Pid, "incoming"), + {error, efnamena} = ftp:ls(Pid, "incoming\r\nCWD ."), %% neither nlist nor ls operates on a directory %% they operate on a pathname, which *can* be a %% directory, but can also be a filename or a group @@ -1324,6 +1330,8 @@ do_rename(Pid, Config) -> ftp:delete(Pid, NewLFile), % reset ok = ftp:send(Pid, LFile), {error, epath} = ftp:rename(Pid, NewLFile, LFile), + {error, efnamena} = ftp:rename(Pid, NewLFile++"\r\nRNTO "++LFile++"\r\nRNFR "++NewLFile, LFile), + {error, efnamena} = ftp:rename(Pid, NewLFile, LFile++"\r\nCWD ."), ok = ftp:rename(Pid, LFile, NewLFile), ftp:delete(Pid, LFile), % cleanup ftp:delete(Pid, NewLFile), % cleanup @@ -1338,6 +1346,7 @@ do_delete(Pid, Config) -> ok = ftp:cd(Pid, "incoming"), ok = ftp:lcd(Pid, PrivDir), ftp:delete(Pid,LFile), % reset + {error, efnamena} = ftp:delete(Pid,LFile++"\r\nCWD ."), ok = ftp:send(Pid, LFile), ok = ftp:delete(Pid,LFile), ok. @@ -1348,6 +1357,8 @@ do_mkdir(Pid) -> integer_to_list(B) ++ "_" ++ integer_to_list(C), ok = ftp:cd(Pid, "incoming"), {ok, CurrDir} = ftp:pwd(Pid), + {error, efnamena} = ftp:mkdir(Pid, NewDir++"\r\nCWD ."), + {error, efnamena} = ftp:rmdir(Pid, NewDir++"\r\nCWD ."), ok = ftp:mkdir(Pid, NewDir), ok = ftp:cd(Pid, NewDir), ok = ftp:cd(Pid, CurrDir), @@ -1363,6 +1374,7 @@ do_send(Pid, Config) -> ok = file:write_file(AbsLFile, list_to_binary(Contents)), ok = ftp:cd(Pid, "incoming"), ok = ftp:lcd(Pid, PrivDir), + {error, efnamena} = ftp:send(Pid, LFile, RFile++"1\r\nCWD ."), ok = ftp:send(Pid, LFile, RFile), {ok, RFilesString} = ftp:nlist(Pid), RFiles = split(RFilesString), @@ -1392,6 +1404,7 @@ do_append(Pid, Config) -> ftp:delete(Pid, RFile), ftp:delete(Pid, LFile), + {error, efnamena} = ftp:append(Pid, LFile, RFile++"1\r\nCWD ."), ok = ftp:append(Pid, LFile, RFile), ok = ftp:append(Pid, LFile, RFile), ok = ftp:append(Pid, LFile), @@ -1413,6 +1426,7 @@ do_send_bin(Pid, Config) -> Bin = list_to_binary(Contents), ok = ftp:cd(Pid, "incoming"), {error, enotbinary} = ftp:send_bin(Pid, Contents, File), + {error, efnamena} = ftp:send_bin(Pid, Bin, File++"1\r\nCWD ."), ok = ftp:send_bin(Pid, Bin, File), {ok, RFilesString} = ftp:nlist(Pid), RFiles = split(RFilesString), @@ -1426,6 +1440,7 @@ do_append_bin(Pid, Config) -> Bin = list_to_binary(Contents), ok = ftp:cd(Pid, "incoming"), {error, enotbinary} = ftp:append_bin(Pid, Contents, File), + {error, efnamena} = ftp:append_bin(Pid, Bin, File++"1\r\nCWD ."), ok = ftp:append_bin(Pid, Bin, File), ok = ftp:append_bin(Pid, Bin, File), %% Control the contents of the file @@ -1438,6 +1453,7 @@ do_send_chunk(Pid, Config) -> Contents = "ftp_SUITE test ...", Bin = list_to_binary(Contents), ok = ftp:cd(Pid, "incoming"), + {error, efnamena} = ftp:send_chunk_start(Pid, File++"1\r\nCWD ."), ok = ftp:send_chunk_start(Pid, File), {error, echunk} = ftp:cd(Pid, "incoming"), {error, enotbinary} = ftp:send_chunk(Pid, Contents), @@ -1454,6 +1470,7 @@ do_append_chunk(Pid, Config) -> File = ?config(file, Config), Contents = ["ER","LE","RL"], ok = ftp:cd(Pid, "incoming"), + {error, efnamena} = ftp:append_chunk_start(Pid, File++"1\r\nCWD ."), ok = ftp:append_chunk_start(Pid, File), {error, enotbinary} = ftp:append_chunk(Pid, lists:nth(1,Contents)), ok = ftp:append_chunk(Pid,list_to_binary(lists:nth(1,Contents))), @@ -1480,6 +1497,7 @@ do_recv(Pid, Config) -> ok = file:delete(AbsFile), % cleanup test_server:sleep(100), ok = ftp:lcd(Pid, PrivDir), + {error, efnamena} = ftp:recv(Pid, File++"\r\nCWD ."), ok = ftp:recv(Pid, File), {ok, Files} = file:list_dir(PrivDir), true = lists:member(File, Files), @@ -1495,6 +1513,7 @@ do_recv_bin(Pid, Config) -> ok = ftp:cd(Pid, "incoming"), ok = ftp:send_bin(Pid, Bin1, File), test_server:sleep(100), + {error, efnamena} = ftp:recv_bin(Pid, File++"\r\nCWD ."), {ok, Bin2} = ftp:recv_bin(Pid, File), ok = ftp:delete(Pid, File), % cleanup Contents2 = binary_to_list(Bin2), @@ -1520,6 +1539,7 @@ do_recv_chunk(Pid, Config) -> ok = ftp:send_bin(Pid, Bin1, File), test_server:sleep(100), {error, "ftp:recv_chunk_start/2 not called"} = recv_chunk(Pid, <<>>), + {error, efnamena} = ftp:recv_chunk_start(Pid, File++"\r\nCWD ."), ok = ftp:recv_chunk_start(Pid, File), {ok, Contents2} = recv_chunk(Pid, <<>>), ok = ftp:delete(Pid, File), % cleanup -- cgit v1.2.3