From 203e119c2cfe2f209a2d3da9d2dcc799ab2d761c Mon Sep 17 00:00:00 2001 From: Maciej Szlosarczyk Date: Mon, 29 Jul 2019 13:23:45 +0300 Subject: [PATCH] Introduce error 2000 When a client sends invalid command to proxy, it should be reported as error 2000 and sent to registry. We should sent them there regardless --- apps/epp_proxy/include/epp_proxy.hrl | 11 ++++++++++ apps/epp_proxy/src/epp_router.erl | 13 ++++++++++-- apps/epp_proxy/src/epp_tcp_worker.erl | 17 ++++++++-------- apps/epp_proxy/src/epp_tls_worker.erl | 17 ++++++++-------- apps/epp_proxy/test/tcp_client_SUITE.erl | 26 +++++++++++++++++++++--- apps/epp_proxy/test/tls_client_SUITE.erl | 26 +++++++++++++++++++++--- 6 files changed, 86 insertions(+), 24 deletions(-) diff --git a/apps/epp_proxy/include/epp_proxy.hrl b/apps/epp_proxy/include/epp_proxy.hrl index 44dc9ea..f1b0b0b 100644 --- a/apps/epp_proxy/include/epp_proxy.hrl +++ b/apps/epp_proxy/include/epp_proxy.hrl @@ -9,3 +9,14 @@ }). -type epp_request() :: #epp_request{}. + + +-define(XMLErrorCode, <<"2001">>). + +-define(XMLErrorMessage, <<"Command syntax error.">>). + +-define(UnknownCommandErrorCode, <<"2000">>). + +-define(UnknownCommandErrorMessage, <<"Unknown command.">>). + +-define(DefaultTimeout, 120000). diff --git a/apps/epp_proxy/src/epp_router.erl b/apps/epp_proxy/src/epp_router.erl index d7a8da7..a6b9777 100644 --- a/apps/epp_proxy/src/epp_router.erl +++ b/apps/epp_proxy/src/epp_router.erl @@ -1,6 +1,7 @@ -module(epp_router). --export([request_method/1, route_request/1]). +-export([is_valid_command/1, request_method/1, + route_request/1]). -define(validCommands, ["hello", "login", "logout", "check", "info", "poll", @@ -9,14 +10,22 @@ %% 47 is the character code -define(forwardSlash, 47). -%% request method: GET for greeting, POST for everything else. +%% request method: GET for greeting and error, POST for everything else. request_method("hello") -> get; request_method(<<"hello">>) -> get; request_method("error") -> get; request_method(<<"error">>) -> get; request_method(_) -> post. +is_valid_command(Command) when is_binary(Command) -> + CommandAsList = binary_to_list(Command), + lists:member(CommandAsList, ?validCommands); +is_valid_command(Command) when is_list(Command) -> + lists:member(Command, ?validCommands); +is_valid_command(_) -> false. + %% Base router +route_request(undefined) -> url_map("error"); route_request(Command) when is_binary(Command) -> List = binary_to_list(Command), url_map(List); route_request(Command) when is_list(Command) -> diff --git a/apps/epp_proxy/src/epp_tcp_worker.erl b/apps/epp_proxy/src/epp_tcp_worker.erl index e04894e..5fb2579 100644 --- a/apps/epp_proxy/src/epp_tcp_worker.erl +++ b/apps/epp_proxy/src/epp_tcp_worker.erl @@ -18,12 +18,6 @@ -record(state, {socket, session_id, headers}). --define(XMLErrorCode, <<"2001">>). - --define(XMLErrorMessage, <<"Command syntax error.">>). - --define(DefaultTimeout, 120000). - %% Initialize process %% Assign an unique session id that will be passed on to http server as a cookie init(Socket) -> @@ -177,8 +171,15 @@ parse_frame(Frame) -> case epp_xml:parse(Frame) of {ok, XMLRecord} -> Command = epp_xml:get_command(XMLRecord), - #valid_frame{command = Command, cl_trid = ClTRID, - raw_frame = Frame}; + case epp_router:is_valid_command(Command) of + true -> + #valid_frame{command = Command, cl_trid = ClTRID, + raw_frame = Frame}; + false -> + #invalid_frame{code = ?UnknownCommandErrorCode, + message = ?UnknownCommandErrorMessage, + cl_trid = ClTRID} + end; {error, _} -> #invalid_frame{code = ?XMLErrorCode, message = ?XMLErrorMessage, cl_trid = ClTRID} diff --git a/apps/epp_proxy/src/epp_tls_worker.erl b/apps/epp_proxy/src/epp_tls_worker.erl index ec80b74..bb3c84d 100644 --- a/apps/epp_proxy/src/epp_tls_worker.erl +++ b/apps/epp_proxy/src/epp_tls_worker.erl @@ -18,12 +18,6 @@ -record(state, {socket, session_id, headers}). --define(XMLErrorCode, <<"2001">>). - --define(XMLErrorMessage, <<"Command syntax error.">>). - --define(DefaultTimeout, 120000). - %% Initialize process %% Assign an unique session id that will be passed on to http server as a cookie init(Socket) -> @@ -197,8 +191,15 @@ parse_frame(Frame) -> case epp_xml:parse(Frame) of {ok, XMLRecord} -> Command = epp_xml:get_command(XMLRecord), - #valid_frame{command = Command, cl_trid = ClTRID, - raw_frame = Frame}; + case epp_router:is_valid_command(Command) of + true -> + #valid_frame{command = Command, cl_trid = ClTRID, + raw_frame = Frame}; + false -> + #invalid_frame{code = ?UnknownCommandErrorCode, + message = ?UnknownCommandErrorMessage, + cl_trid = ClTRID} + end; {error, _} -> #invalid_frame{code = ?XMLErrorCode, message = ?XMLErrorMessage, cl_trid = ClTRID} diff --git a/apps/epp_proxy/test/tcp_client_SUITE.erl b/apps/epp_proxy/test/tcp_client_SUITE.erl index 68cee2c..6853448 100644 --- a/apps/epp_proxy/test/tcp_client_SUITE.erl +++ b/apps/epp_proxy/test/tcp_client_SUITE.erl @@ -11,6 +11,7 @@ valid_command_test_case/1, long_message_test_case/1, invalid_command_test_case/1, + missing_command_test_case/1, error_test_case/1]). all() -> @@ -20,6 +21,7 @@ all() -> valid_command_test_case, long_message_test_case, invalid_command_test_case, + missing_command_test_case, error_test_case]. init_per_suite(Config) -> @@ -133,8 +135,7 @@ long_message_test_case(Config) -> "Command completed successfully; no messages"), ok. -%% Sending an invalid command frame should close the connection. -%% It also crashes the process. +%% Sending an invalid command frame should return a canned response. invalid_command_test_case(Config) -> Options = proplists:get_value(tcp_options, Config), {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000), @@ -150,7 +151,26 @@ invalid_command_test_case(Config) -> "\n" "\n">>, ok = send_data(InvalidCommand, Socket), - {error, closed} = receive_data(Socket), + ErrorResponse = receive_data(Socket), + match_data(ErrorResponse, + "Unknown command."), + ok. + +%% Sending a valid XML without command frame should return a canned response. +missing_command_test_case(Config) -> + Options = proplists:get_value(tcp_options, Config), + {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000), + _Data = receive_data(Socket), + ok = send_data(login_command(), Socket), + _LoginResponse = receive_data(Socket), + InvalidCommand = + <<"\n" + "\n" + "\n">>, + ok = send_data(InvalidCommand, Socket), + ErrorResponse = receive_data(Socket), + match_data(ErrorResponse, + "Unknown command."), ok. error_test_case(Config) -> diff --git a/apps/epp_proxy/test/tls_client_SUITE.erl b/apps/epp_proxy/test/tls_client_SUITE.erl index ae86826..297fffe 100644 --- a/apps/epp_proxy/test/tls_client_SUITE.erl +++ b/apps/epp_proxy/test/tls_client_SUITE.erl @@ -11,6 +11,7 @@ valid_command_test_case/1, long_message_test_case/1, invalid_command_test_case/1, + missing_command_test_case/1, error_test_case/1, revoked_cert_test_case/1]). @@ -21,6 +22,7 @@ all() -> valid_command_test_case, long_message_test_case, invalid_command_test_case, + missing_command_test_case, error_test_case, revoked_cert_test_case]. @@ -142,8 +144,7 @@ long_message_test_case(Config) -> "Command completed successfully; no messages"), ok. -%% Sending an invalid command frame should close the connection. -%% It also crashes the process. +%% Sending an invalid command frame returns a canned response. invalid_command_test_case(Config) -> Options = proplists:get_value(ssl_options, Config), {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000), @@ -159,7 +160,26 @@ invalid_command_test_case(Config) -> "\n" "\n">>, ok = send_data(InvalidCommand, Socket), - {error, closed} = receive_data(Socket), + ErrorResponse = receive_data(Socket), + match_data(ErrorResponse, + "Unknown command."), + ok. + +%% Sending a missing command frame should return a canned response. +missing_command_test_case(Config) -> + Options = proplists:get_value(ssl_options, Config), + {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000), + _Data = receive_data(Socket), + ok = send_data(login_command(), Socket), + _LoginResponse = receive_data(Socket), + InvalidCommand = + <<"\n" + "\n" + "\n">>, + ok = send_data(InvalidCommand, Socket), + ErrorResponse = receive_data(Socket), + match_data(ErrorResponse, + "Unknown command."), ok. error_test_case(Config) ->