mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Add tests for external component
This commit is contained in:
parent
a4ec064455
commit
ceda073766
@ -494,7 +494,7 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
||||
catch _:{xmpp_codec, Why} ->
|
||||
Txt = xmpp:format_error(Why),
|
||||
send_header(StateData, ?MYNAME, <<"1.0">>, ?MYLANG),
|
||||
send_element(StateData, xmpp:serr_not_well_formed(Txt, ?MYLANG)),
|
||||
send_element(StateData, xmpp:serr_invalid_xml(Txt, ?MYLANG)),
|
||||
{stop, normal, StateData}
|
||||
end;
|
||||
wait_for_stream(timeout, StateData) ->
|
||||
|
@ -125,7 +125,12 @@ init([{SockMod, Socket}, Opts]) ->
|
||||
|
||||
wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
||||
try xmpp:decode(#xmlel{name = Name, attrs = Attrs}) of
|
||||
#stream_start{xmlns = ?NS_COMPONENT, to = To} when is_record(To, jid) ->
|
||||
#stream_start{xmlns = NS_COMPONENT, stream_xmlns = NS_STREAM}
|
||||
when NS_COMPONENT /= ?NS_COMPONENT; NS_STREAM /= ?NS_STREAM ->
|
||||
send_header(StateData, ?MYNAME),
|
||||
send_element(StateData, xmpp:serr_invalid_namespace()),
|
||||
{stop, normal, StateData};
|
||||
#stream_start{to = To} when is_record(To, jid) ->
|
||||
Host = To#jid.lserver,
|
||||
send_header(StateData, Host),
|
||||
HostOpts = case dict:is_key(Host, StateData#state.host_opts) of
|
||||
@ -141,13 +146,9 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
||||
end,
|
||||
{next_state, wait_for_handshake,
|
||||
StateData#state{host = Host, host_opts = HostOpts}};
|
||||
#stream_start{xmlns = ?NS_COMPONENT} ->
|
||||
send_header(StateData, ?MYNAME),
|
||||
send_element(StateData, xmpp:serr_improper_addressing()),
|
||||
{stop, normal, StateData};
|
||||
#stream_start{} ->
|
||||
send_header(StateData, ?MYNAME),
|
||||
send_element(StateData, xmpp:serr_invalid_namespace()),
|
||||
send_element(StateData, xmpp:serr_improper_addressing()),
|
||||
{stop, normal, StateData}
|
||||
catch _:{xmpp_codec, Why} ->
|
||||
Txt = xmpp:format_error(Why),
|
||||
@ -203,7 +204,8 @@ stream_established(El, StateData) when ?is_stanza(El) ->
|
||||
To = xmpp:get_to(El),
|
||||
Lang = xmpp:get_lang(El),
|
||||
if From == undefined orelse To == undefined ->
|
||||
send_error(StateData, El, xmpp:err_jid_malformed());
|
||||
Txt = <<"Missing 'from' or 'to' attribute">>,
|
||||
send_error(StateData, El, xmpp:err_jid_malformed(Txt, Lang));
|
||||
true ->
|
||||
FromJID = case StateData#state.check_from of
|
||||
false ->
|
||||
@ -214,19 +216,16 @@ stream_established(El, StateData) when ?is_stanza(El) ->
|
||||
From;
|
||||
_ ->
|
||||
%% The default is the standard behaviour in XEP-0114
|
||||
case From of
|
||||
#jid{lserver = Server} ->
|
||||
Server = From#jid.lserver,
|
||||
case dict:is_key(Server, StateData#state.host_opts) of
|
||||
true -> From;
|
||||
false -> error
|
||||
end;
|
||||
_ -> error
|
||||
end
|
||||
end,
|
||||
if FromJID /= error ->
|
||||
ejabberd_router:route(FromJID, To, El);
|
||||
true ->
|
||||
Txt = <<"Incorrect value of 'from' or 'to' attribute">>,
|
||||
Txt = <<"Improper domain part of 'from' attribute">>,
|
||||
send_error(StateData, El, xmpp:err_not_allowed(Txt, Lang))
|
||||
end
|
||||
end,
|
||||
|
@ -125,6 +125,15 @@ do_init_per_group(riak, Config) ->
|
||||
Err ->
|
||||
{skip, {riak_not_available, Err}}
|
||||
end;
|
||||
do_init_per_group(component, Config) ->
|
||||
Server = ?config(server, Config),
|
||||
Port = ?config(component_port, Config),
|
||||
set_opt(xmlns, ?NS_COMPONENT,
|
||||
set_opt(server, <<"component.", Server/binary>>,
|
||||
set_opt(type, component,
|
||||
set_opt(server_port, Port,
|
||||
set_opt(stream_version, <<"">>,
|
||||
set_opt(lang, <<"">>, Config))))));
|
||||
do_init_per_group(_GroupName, Config) ->
|
||||
Pid = start_event_relay(),
|
||||
set_opt(event_relay, Pid, Config).
|
||||
@ -147,6 +156,8 @@ end_per_group(extauth, _Config) ->
|
||||
ok;
|
||||
end_per_group(riak, _Config) ->
|
||||
ok;
|
||||
end_per_group(component, _Config) ->
|
||||
ok;
|
||||
end_per_group(_GroupName, Config) ->
|
||||
stop_event_relay(Config),
|
||||
ok.
|
||||
@ -252,7 +263,7 @@ no_db_tests() ->
|
||||
[{generic, [parallel],
|
||||
[test_connect_bad_xml,
|
||||
test_connect_unknown_ns,
|
||||
test_connect_bad_ns_client,
|
||||
test_connect_bad_xmlns,
|
||||
test_connect_bad_ns_stream,
|
||||
test_connect_bad_lang,
|
||||
test_connect_bad_to,
|
||||
@ -421,10 +432,27 @@ extauth_tests() ->
|
||||
test_auth_fail,
|
||||
test_unregister]}].
|
||||
|
||||
component_tests() ->
|
||||
[{component_tests, [sequence],
|
||||
[test_connect_bad_xml,
|
||||
test_connect_unknown_ns,
|
||||
test_connect_bad_xmlns,
|
||||
test_connect_bad_ns_stream,
|
||||
test_connect_missing_to,
|
||||
test_connect,
|
||||
test_auth,
|
||||
test_auth_fail,
|
||||
component_missing_address,
|
||||
component_invalid_from,
|
||||
component_send,
|
||||
bad_nonza,
|
||||
codec_failure]}].
|
||||
|
||||
groups() ->
|
||||
[{ldap, [sequence], ldap_tests()},
|
||||
{extauth, [sequence], extauth_tests()},
|
||||
{no_db, [sequence], no_db_tests()},
|
||||
{component, [sequence], component_tests()},
|
||||
{mnesia, [sequence], db_tests(mnesia)},
|
||||
{redis, [sequence], db_tests(redis)},
|
||||
{mysql, [sequence], db_tests(mysql)},
|
||||
@ -433,7 +461,8 @@ groups() ->
|
||||
{riak, [sequence], db_tests(riak)}].
|
||||
|
||||
all() ->
|
||||
[%%{group, ldap},
|
||||
[{group, component},
|
||||
%%{group, ldap},
|
||||
{group, no_db},
|
||||
{group, mnesia},
|
||||
%%{group, redis},
|
||||
@ -451,19 +480,19 @@ stop_ejabberd(Config) ->
|
||||
Config.
|
||||
|
||||
test_connect_bad_xml(Config) ->
|
||||
Config0 = init_stream(set_opt(ns_client, <<"'">>, Config)),
|
||||
Config0 = init_stream(set_opt(xmlns, <<"'">>, Config)),
|
||||
?recv1(#stream_error{reason = 'not-well-formed'}),
|
||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||
close_socket(Config0).
|
||||
|
||||
test_connect_unknown_ns(Config) ->
|
||||
Config0 = init_stream(set_opt(ns_client, <<"wrong">>, Config)),
|
||||
?recv1(#stream_error{reason = 'not-well-formed'}),
|
||||
Config0 = init_stream(set_opt(xmlns, <<"wrong">>, Config)),
|
||||
?recv1(#stream_error{reason = 'invalid-xml'}),
|
||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||
close_socket(Config0).
|
||||
|
||||
test_connect_bad_ns_client(Config) ->
|
||||
Config0 = init_stream(set_opt(ns_client, ?NS_SERVER, Config)),
|
||||
test_connect_bad_xmlns(Config) ->
|
||||
Config0 = init_stream(set_opt(xmlns, ?NS_SERVER, Config)),
|
||||
?recv1(#stream_error{reason = 'invalid-namespace'}),
|
||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||
close_socket(Config0).
|
||||
@ -495,6 +524,12 @@ test_connect_missing_to(Config) ->
|
||||
test_connect(Config) ->
|
||||
disconnect(connect(Config)).
|
||||
|
||||
test_component_connect(Config) ->
|
||||
disconnect(component_connect(Config)).
|
||||
|
||||
component_connect(Config) ->
|
||||
init_stream(Config).
|
||||
|
||||
test_starttls(Config) ->
|
||||
case ?config(starttls, Config) of
|
||||
true ->
|
||||
@ -578,6 +613,25 @@ invalid_from(Config) ->
|
||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||
close_socket(Config).
|
||||
|
||||
component_missing_address(Config) ->
|
||||
Server = server_jid(Config),
|
||||
#iq{type = error} = send_recv(Config, #iq{type = get, from = Server}),
|
||||
#iq{type = error} = send_recv(Config, #iq{type = get, to = Server}),
|
||||
disconnect(Config).
|
||||
|
||||
component_invalid_from(Config) ->
|
||||
From = jid:make(randoms:get_string()),
|
||||
To = jid:make(randoms:get_string()),
|
||||
#iq{type = error} =
|
||||
send_recv(Config, #iq{type = get, from = From, to = To}),
|
||||
disconnect(Config).
|
||||
|
||||
component_send(Config) ->
|
||||
JID = my_jid(Config),
|
||||
send(Config, #message{from = JID, to = JID}),
|
||||
#message{from = JID, to = JID} = recv(),
|
||||
disconnect(Config).
|
||||
|
||||
auth_md5(Config) ->
|
||||
Mechs = ?config(mechs, Config),
|
||||
case lists:member(<<"DIGEST-MD5">>, Mechs) of
|
||||
@ -621,7 +675,8 @@ test_auth(Config) ->
|
||||
disconnect(auth(Config)).
|
||||
|
||||
test_auth_fail(Config0) ->
|
||||
Config = set_opt(user, <<"wrong">>, Config0),
|
||||
Config = set_opt(user, <<"wrong">>,
|
||||
set_opt(password, <<"wrong">>, Config0)),
|
||||
disconnect(auth(Config, _ShouldFail = true)).
|
||||
|
||||
test_bind(Config) ->
|
||||
@ -659,7 +714,9 @@ roster_ver(Config) ->
|
||||
disconnect(Config).
|
||||
|
||||
codec_failure(Config) ->
|
||||
#iq{type = error} = send_recv(Config, #iq{type = wrong}),
|
||||
JID = my_jid(Config),
|
||||
#iq{type = error} =
|
||||
send_recv(Config, #iq{type = wrong, from = JID, to = JID}),
|
||||
disconnect(Config).
|
||||
|
||||
unsupported_query(Config) ->
|
||||
@ -829,13 +886,14 @@ private(Config) ->
|
||||
<<>>)},
|
||||
Storage = #bookmark_storage{conference = [Conference]},
|
||||
StorageXMLOut = xmpp_codec:encode(Storage),
|
||||
WrongEl = #xmlel{name = <<"wrong">>},
|
||||
#iq{type = error} =
|
||||
send_recv(Config, #iq{type = get, sub_els = [#private{}],
|
||||
to = server_jid(Config)}),
|
||||
send_recv(Config, #iq{type = get,
|
||||
sub_els = [#private{xml_els = [WrongEl]}]}),
|
||||
#iq{type = result, sub_els = []} =
|
||||
send_recv(
|
||||
Config, #iq{type = set,
|
||||
sub_els = [#private{xml_els = [StorageXMLOut]}]}),
|
||||
sub_els = [#private{xml_els = [WrongEl, StorageXMLOut]}]}),
|
||||
#iq{type = result,
|
||||
sub_els = [#private{xml_els = [StorageXMLIn]}]} =
|
||||
send_recv(
|
||||
|
@ -428,6 +428,11 @@ listen:
|
||||
port: @@web_port@@
|
||||
module: ejabberd_http
|
||||
captcha: true
|
||||
-
|
||||
port: @@component_port@@
|
||||
module: ejabberd_service
|
||||
password: >-
|
||||
@@password@@
|
||||
loglevel: @@loglevel@@
|
||||
max_fsm_queue: 1000
|
||||
modules:
|
||||
|
@ -30,11 +30,14 @@ init_config(Config) ->
|
||||
{ok, CWD} = file:get_cwd(),
|
||||
{ok, _} = file:copy(CertFile, filename:join([CWD, "cert.pem"])),
|
||||
{ok, CfgContentTpl} = file:read_file(ConfigPathTpl),
|
||||
Password = <<"password!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>,
|
||||
CfgContent = process_config_tpl(CfgContentTpl, [
|
||||
{c2s_port, 5222},
|
||||
{loglevel, 5},
|
||||
{s2s_port, 5269},
|
||||
{component_port, 5270},
|
||||
{web_port, 5280},
|
||||
{password, Password},
|
||||
{mysql_server, <<"localhost">>},
|
||||
{mysql_port, 3306},
|
||||
{mysql_db, <<"ejabberd_test">>},
|
||||
@ -58,13 +61,15 @@ init_config(Config) ->
|
||||
application:set_env(mnesia, dir, MnesiaDir),
|
||||
[{server_port, ct:get_config(c2s_port, 5222)},
|
||||
{server_host, "localhost"},
|
||||
{component_port, ct:get_config(component_port, 5270)},
|
||||
{server, ?COMMON_VHOST},
|
||||
{user, <<"test_single!#$%^*()`~+-;_=[]{}|\\">>},
|
||||
{master_nick, <<"master_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||
{slave_nick, <<"slave_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||
{room_subject, <<"hello, world!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||
{certfile, CertFile},
|
||||
{ns_client, ?NS_CLIENT},
|
||||
{type, client},
|
||||
{xmlns, ?NS_CLIENT},
|
||||
{ns_stream, ?NS_STREAM},
|
||||
{stream_version, <<"1.0">>},
|
||||
{stream_id, <<"">>},
|
||||
@ -74,7 +79,7 @@ init_config(Config) ->
|
||||
{resource, <<"resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||
{master_resource, <<"master_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||
{slave_resource, <<"slave_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||
{password, <<"password!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||
{password, Password},
|
||||
{backends, get_config_backends()}
|
||||
|Config].
|
||||
|
||||
@ -126,20 +131,29 @@ process_config_tpl(Content, [{Name, DefaultValue} | Rest]) ->
|
||||
|
||||
stream_header(Config) ->
|
||||
NSStream = ?config(ns_stream, Config),
|
||||
NSClient = ?config(ns_client, Config),
|
||||
Lang = ?config(lang, Config),
|
||||
XMLNS = ?config(xmlns, Config),
|
||||
Lang = case ?config(lang, Config) of
|
||||
<<"">> -> <<"">>;
|
||||
L -> iolist_to_binary(["xml:lang='", L, "'"])
|
||||
end,
|
||||
To = case ?config(server, Config) of
|
||||
<<"">> -> <<"">>;
|
||||
Server -> <<"to='", Server/binary, "'">>
|
||||
end,
|
||||
Version = ?config(stream_version, Config),
|
||||
Version = case ?config(stream_version, Config) of
|
||||
<<"">> -> <<"">>;
|
||||
V -> <<"version='", V/binary, "'">>
|
||||
end,
|
||||
io_lib:format("<?xml version='1.0'?><stream:stream "
|
||||
"xmlns:stream='~s' xmlns='~s' ~s "
|
||||
"version='~s' xml:lang='~s'>",
|
||||
[NSStream, NSClient, To, Version, Lang]).
|
||||
"xmlns:stream='~s' xmlns='~s' ~s ~s ~s>",
|
||||
[NSStream, XMLNS, To, Version, Lang]).
|
||||
|
||||
connect(Config) ->
|
||||
process_stream_features(init_stream(Config)).
|
||||
NewConfig = init_stream(Config),
|
||||
case ?config(type, NewConfig) of
|
||||
client -> process_stream_features(NewConfig);
|
||||
component -> NewConfig
|
||||
end.
|
||||
|
||||
init_stream(Config) ->
|
||||
Version = ?config(stream_version, Config),
|
||||
@ -149,8 +163,11 @@ init_stream(Config) ->
|
||||
[binary, {packet, 0}, {active, false}]),
|
||||
NewConfig = set_opt(socket, Sock, Config),
|
||||
ok = send_text(NewConfig, stream_header(NewConfig)),
|
||||
#stream_start{id = ID, xmlns = ?NS_CLIENT,
|
||||
version = Version} = recv(),
|
||||
XMLNS = case ?config(type, Config) of
|
||||
client -> ?NS_CLIENT;
|
||||
component -> ?NS_COMPONENT
|
||||
end,
|
||||
#stream_start{id = ID, xmlns = XMLNS, version = Version} = recv(),
|
||||
set_opt(stream_id, ID, NewConfig).
|
||||
|
||||
process_stream_features(Config) ->
|
||||
@ -174,7 +191,11 @@ process_stream_features(Config) ->
|
||||
|
||||
disconnect(Config) ->
|
||||
Socket = ?config(socket, Config),
|
||||
ok = ejabberd_socket:send(Socket, ?STREAM_TRAILER),
|
||||
try
|
||||
ok = send_text(Config, ?STREAM_TRAILER)
|
||||
catch exit:normal ->
|
||||
ok
|
||||
end,
|
||||
{xmlstreamend, <<"stream:stream">>} = recv(),
|
||||
ejabberd_socket:close(Socket),
|
||||
Config.
|
||||
@ -203,6 +224,7 @@ auth(Config) ->
|
||||
auth(Config, false).
|
||||
|
||||
auth(Config, ShouldFail) ->
|
||||
Type = ?config(type, Config),
|
||||
Mechs = ?config(mechs, Config),
|
||||
HaveMD5 = lists:member(<<"DIGEST-MD5">>, Mechs),
|
||||
HavePLAIN = lists:member(<<"PLAIN">>, Mechs),
|
||||
@ -210,16 +232,23 @@ auth(Config, ShouldFail) ->
|
||||
auth_SASL(<<"PLAIN">>, Config, ShouldFail);
|
||||
HaveMD5 ->
|
||||
auth_SASL(<<"DIGEST-MD5">>, Config, ShouldFail);
|
||||
true ->
|
||||
auth_legacy(Config, false, ShouldFail)
|
||||
Type == client ->
|
||||
auth_legacy(Config, false, ShouldFail);
|
||||
Type == component ->
|
||||
auth_component(Config, ShouldFail)
|
||||
end.
|
||||
|
||||
bind(Config) ->
|
||||
case ?config(type, Config) of
|
||||
client ->
|
||||
#iq{type = result, sub_els = [#bind{}]} =
|
||||
send_recv(
|
||||
Config,
|
||||
#iq{type = set,
|
||||
sub_els = [#bind{resource = ?config(resource, Config)}]}),
|
||||
sub_els = [#bind{resource = ?config(resource, Config)}]});
|
||||
component ->
|
||||
ok
|
||||
end,
|
||||
Config.
|
||||
|
||||
open_session(Config) ->
|
||||
@ -279,6 +308,22 @@ auth_legacy(Config, IsDigest, ShouldFail) ->
|
||||
end
|
||||
end.
|
||||
|
||||
auth_component(Config, ShouldFail) ->
|
||||
StreamID = ?config(stream_id, Config),
|
||||
Password = ?config(password, Config),
|
||||
Digest = p1_sha:sha(<<StreamID/binary, Password/binary>>),
|
||||
send(Config, #handshake{data = Digest}),
|
||||
case recv() of
|
||||
#handshake{} when ShouldFail ->
|
||||
ct:fail(component_auth_should_have_failed);
|
||||
#handshake{} ->
|
||||
Config;
|
||||
#stream_error{reason = 'not-authorized'} when ShouldFail ->
|
||||
Config;
|
||||
#stream_error{reason = 'not-authorized'} ->
|
||||
ct:fail(component_auth_failed)
|
||||
end.
|
||||
|
||||
auth_SASL(Mech, Config) ->
|
||||
auth_SASL(Mech, Config, false).
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user