mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Add tests for s2s code
This commit is contained in:
parent
ceda073766
commit
53209b9ab1
@ -158,7 +158,7 @@
|
|||||||
-record(stream_start, {from :: jid:jid(),
|
-record(stream_start, {from :: jid:jid(),
|
||||||
to :: jid:jid(),
|
to :: jid:jid(),
|
||||||
id = <<>> :: binary(),
|
id = <<>> :: binary(),
|
||||||
version = <<>> :: binary(),
|
version :: {non_neg_integer(),non_neg_integer()},
|
||||||
xmlns = <<>> :: binary(),
|
xmlns = <<>> :: binary(),
|
||||||
stream_xmlns = <<>> :: binary(),
|
stream_xmlns = <<>> :: binary(),
|
||||||
db_xmlns = <<>> :: binary(),
|
db_xmlns = <<>> :: binary(),
|
||||||
|
@ -352,16 +352,16 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
|||||||
S -> S
|
S -> S
|
||||||
end,
|
end,
|
||||||
StreamVersion = case Version of
|
StreamVersion = case Version of
|
||||||
<<"1.0">> -> <<"1.0">>;
|
{1,0} -> {1,0};
|
||||||
_ -> <<"">>
|
_ -> undefined
|
||||||
end,
|
end,
|
||||||
IsBlacklistedIP = is_ip_blacklisted(StateData#state.ip, Lang),
|
IsBlacklistedIP = is_ip_blacklisted(StateData#state.ip, Lang),
|
||||||
case lists:member(Server, ?MYHOSTS) of
|
case lists:member(Server, ?MYHOSTS) of
|
||||||
true when IsBlacklistedIP == false ->
|
true when IsBlacklistedIP == false ->
|
||||||
change_shaper(StateData, jid:make(<<"">>, Server, <<"">>)),
|
change_shaper(StateData, jid:make(<<"">>, Server, <<"">>)),
|
||||||
case StreamVersion of
|
case StreamVersion of
|
||||||
<<"1.0">> ->
|
{1,0} ->
|
||||||
send_header(StateData, Server, <<"1.0">>, ?MYLANG),
|
send_header(StateData, Server, {1,0}, ?MYLANG),
|
||||||
case StateData#state.authenticated of
|
case StateData#state.authenticated of
|
||||||
false ->
|
false ->
|
||||||
TLS = StateData#state.tls,
|
TLS = StateData#state.tls,
|
||||||
@ -490,10 +490,14 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
|||||||
send_header(StateData, ?MYNAME, StreamVersion, ?MYLANG),
|
send_header(StateData, ?MYNAME, StreamVersion, ?MYLANG),
|
||||||
send_element(StateData, xmpp:serr_host_unknown()),
|
send_element(StateData, xmpp:serr_host_unknown()),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
end
|
end;
|
||||||
|
_ ->
|
||||||
|
send_header(StateData, ?MYNAME, {1,0}, ?MYLANG),
|
||||||
|
send_element(StateData, xmpp:serr_invalid_xml()),
|
||||||
|
{stop, normal, StateData}
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Txt = xmpp:format_error(Why),
|
Txt = xmpp:format_error(Why),
|
||||||
send_header(StateData, ?MYNAME, <<"1.0">>, ?MYLANG),
|
send_header(StateData, ?MYNAME, {1,0}, ?MYLANG),
|
||||||
send_element(StateData, xmpp:serr_invalid_xml(Txt, ?MYLANG)),
|
send_element(StateData, xmpp:serr_invalid_xml(Txt, ?MYLANG)),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
end;
|
end;
|
||||||
@ -506,7 +510,7 @@ wait_for_stream({xmlstreamend, _}, StateData) ->
|
|||||||
send_element(StateData, xmpp:serr_not_well_formed()),
|
send_element(StateData, xmpp:serr_not_well_formed()),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_stream({xmlstreamerror, _}, StateData) ->
|
wait_for_stream({xmlstreamerror, _}, StateData) ->
|
||||||
send_header(StateData, ?MYNAME, <<"1.0">>, <<"">>),
|
send_header(StateData, ?MYNAME, {1,0}, <<"">>),
|
||||||
send_element(StateData, xmpp:serr_not_well_formed()),
|
send_element(StateData, xmpp:serr_not_well_formed()),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_stream(closed, StateData) ->
|
wait_for_stream(closed, StateData) ->
|
||||||
@ -1374,7 +1378,7 @@ handle_info({'DOWN', Monitor, _Type, _Object, _Info},
|
|||||||
handle_info(system_shutdown, StateName, StateData) ->
|
handle_info(system_shutdown, StateName, StateData) ->
|
||||||
case StateName of
|
case StateName of
|
||||||
wait_for_stream ->
|
wait_for_stream ->
|
||||||
send_header(StateData, ?MYNAME, <<"1.0">>, <<"en">>),
|
send_header(StateData, ?MYNAME, {1,0}, <<"en">>),
|
||||||
send_element(StateData, xmpp:serr_system_shutdown()),
|
send_element(StateData, xmpp:serr_system_shutdown()),
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
@ -1597,39 +1601,20 @@ send_packet(StateData, Packet) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
-spec send_header(state(), binary(), binary(), binary()) -> ok | {error, any()}.
|
-spec send_header(state(), binary(), binary(), binary()) -> ok | {error, any()}.
|
||||||
send_header(StateData, Server, Version, Lang)
|
|
||||||
when StateData#state.xml_socket ->
|
|
||||||
VersionAttr = case Version of
|
|
||||||
<<"">> -> [];
|
|
||||||
_ -> [{<<"version">>, Version}]
|
|
||||||
end,
|
|
||||||
LangAttr = case Lang of
|
|
||||||
<<"">> -> [];
|
|
||||||
_ -> [{<<"xml:lang">>, Lang}]
|
|
||||||
end,
|
|
||||||
Header = {xmlstreamstart, <<"stream:stream">>,
|
|
||||||
VersionAttr ++
|
|
||||||
LangAttr ++
|
|
||||||
[{<<"xmlns">>, <<"jabber:client">>},
|
|
||||||
{<<"xmlns:stream">>,
|
|
||||||
<<"http://etherx.jabber.org/streams">>},
|
|
||||||
{<<"id">>, StateData#state.streamid},
|
|
||||||
{<<"from">>, Server}]},
|
|
||||||
(StateData#state.sockmod):send_xml(StateData#state.socket,
|
|
||||||
Header);
|
|
||||||
send_header(StateData, Server, Version, Lang) ->
|
send_header(StateData, Server, Version, Lang) ->
|
||||||
VersionStr = case Version of
|
Header = #xmlel{name = Name, attrs = Attrs} =
|
||||||
<<"">> -> <<"">>;
|
xmpp:encode(#stream_start{version = Version,
|
||||||
_ -> [<<" version='">>, Version, <<"'">>]
|
lang = Lang,
|
||||||
end,
|
xmlns = ?NS_CLIENT,
|
||||||
LangStr = case Lang of
|
stream_xmlns = ?NS_STREAM,
|
||||||
<<"">> -> <<"">>;
|
id = StateData#state.streamid,
|
||||||
_ -> [<<" xml:lang='">>, Lang, <<"'">>]
|
from = jid:make(Server)}),
|
||||||
end,
|
if StateData#state.xml_socket ->
|
||||||
Header = io_lib:format(?STREAM_HEADER,
|
(StateData#state.sockmod):send_xml(StateData#state.socket,
|
||||||
[StateData#state.streamid, Server, VersionStr,
|
{xmlstreamstart, Name, Attrs});
|
||||||
LangStr]),
|
true ->
|
||||||
send_text(StateData, iolist_to_binary(Header)).
|
send_text(StateData, fxml:element_to_header(Header))
|
||||||
|
end.
|
||||||
|
|
||||||
-spec send_trailer(state()) -> ok | {error, any()}.
|
-spec send_trailer(state()) -> ok | {error, any()}.
|
||||||
send_trailer(StateData)
|
send_trailer(StateData)
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
remove_connection/2, find_connection/2,
|
remove_connection/2, find_connection/2,
|
||||||
dirty_get_connections/0, allow_host/2,
|
dirty_get_connections/0, allow_host/2,
|
||||||
incoming_s2s_number/0, outgoing_s2s_number/0,
|
incoming_s2s_number/0, outgoing_s2s_number/0,
|
||||||
|
stop_all_connections/0,
|
||||||
clean_temporarily_blocked_table/0,
|
clean_temporarily_blocked_table/0,
|
||||||
list_temporarily_blocked_hosts/0,
|
list_temporarily_blocked_hosts/0,
|
||||||
external_host_overloaded/1, is_temporarly_blocked/1,
|
external_host_overloaded/1, is_temporarly_blocked/1,
|
||||||
@ -480,7 +481,13 @@ get_commands_spec() ->
|
|||||||
"the node",
|
"the node",
|
||||||
policy = admin,
|
policy = admin,
|
||||||
module = ?MODULE, function = outgoing_s2s_number,
|
module = ?MODULE, function = outgoing_s2s_number,
|
||||||
args = [], result = {s2s_outgoing, integer}}].
|
args = [], result = {s2s_outgoing, integer}},
|
||||||
|
#ejabberd_commands{name = stop_all_connections,
|
||||||
|
tags = [s2s],
|
||||||
|
desc = "Stop all outgoing and incoming connections",
|
||||||
|
policy = admin,
|
||||||
|
module = ?MODULE, function = stop_all_connections,
|
||||||
|
args = [], result = {res, rescode}}].
|
||||||
|
|
||||||
incoming_s2s_number() ->
|
incoming_s2s_number() ->
|
||||||
length(supervisor:which_children(ejabberd_s2s_in_sup)).
|
length(supervisor:which_children(ejabberd_s2s_in_sup)).
|
||||||
@ -488,6 +495,15 @@ incoming_s2s_number() ->
|
|||||||
outgoing_s2s_number() ->
|
outgoing_s2s_number() ->
|
||||||
length(supervisor:which_children(ejabberd_s2s_out_sup)).
|
length(supervisor:which_children(ejabberd_s2s_out_sup)).
|
||||||
|
|
||||||
|
stop_all_connections() ->
|
||||||
|
lists:foreach(
|
||||||
|
fun({_Id, Pid, _Type, _Module}) ->
|
||||||
|
exit(Pid, kill)
|
||||||
|
end,
|
||||||
|
supervisor:which_children(ejabberd_s2s_in_sup) ++
|
||||||
|
supervisor:which_children(ejabberd_s2s_out_sup)),
|
||||||
|
mnesia:clear_table(s2s).
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% Update Mnesia tables
|
%%% Update Mnesia tables
|
||||||
|
|
||||||
|
@ -168,21 +168,26 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
|||||||
try xmpp:decode(#xmlel{name = Name, attrs = Attrs}) of
|
try xmpp:decode(#xmlel{name = Name, attrs = Attrs}) of
|
||||||
#stream_start{xmlns = NS_SERVER, stream_xmlns = NS_STREAM}
|
#stream_start{xmlns = NS_SERVER, stream_xmlns = NS_STREAM}
|
||||||
when NS_SERVER /= ?NS_SERVER; NS_STREAM /= ?NS_STREAM ->
|
when NS_SERVER /= ?NS_SERVER; NS_STREAM /= ?NS_STREAM ->
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
send_header(StateData, {1,0}),
|
||||||
send_element(StateData, xmpp:serr_invalid_namespace()),
|
send_element(StateData, xmpp:serr_invalid_namespace()),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
#stream_start{to = #jid{lserver = Server},
|
#stream_start{to = #jid{lserver = Server},
|
||||||
from = #jid{lserver = From},
|
from = From, version = {1,0}}
|
||||||
version = <<"1.0">>}
|
|
||||||
when StateData#state.tls and not StateData#state.authenticated ->
|
when StateData#state.tls and not StateData#state.authenticated ->
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
send_header(StateData, {1,0}),
|
||||||
Auth = if StateData#state.tls_enabled ->
|
Auth = if StateData#state.tls_enabled ->
|
||||||
{Result, Message} =
|
case From of
|
||||||
ejabberd_s2s:check_peer_certificate(
|
#jid{} ->
|
||||||
StateData#state.sockmod,
|
{Result, Message} =
|
||||||
StateData#state.socket,
|
ejabberd_s2s:check_peer_certificate(
|
||||||
From),
|
StateData#state.sockmod,
|
||||||
{Result, From, Message};
|
StateData#state.socket,
|
||||||
|
From#jid.lserver),
|
||||||
|
{Result, From#jid.lserver, Message};
|
||||||
|
undefined ->
|
||||||
|
{error, <<"(unknown)">>,
|
||||||
|
<<"Got no valid 'from' attribute">>}
|
||||||
|
end;
|
||||||
true ->
|
true ->
|
||||||
{no_verify, <<"(unknown)">>, <<"TLS not (yet) enabled">>}
|
{no_verify, <<"(unknown)">>, <<"TLS not (yet) enabled">>}
|
||||||
end,
|
end,
|
||||||
@ -225,8 +230,8 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
|||||||
NewStateData#state{server = Server}}
|
NewStateData#state{server = Server}}
|
||||||
end;
|
end;
|
||||||
#stream_start{to = #jid{lserver = Server},
|
#stream_start{to = #jid{lserver = Server},
|
||||||
version = <<"1.0">>} when StateData#state.authenticated ->
|
version = {1,0}} when StateData#state.authenticated ->
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
send_header(StateData, {1,0}),
|
||||||
send_element(StateData,
|
send_element(StateData,
|
||||||
#stream_features{
|
#stream_features{
|
||||||
sub_els = ejabberd_hooks:run_fold(
|
sub_els = ejabberd_hooks:run_fold(
|
||||||
@ -236,24 +241,28 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
|||||||
#stream_start{db_xmlns = ?NS_SERVER_DIALBACK}
|
#stream_start{db_xmlns = ?NS_SERVER_DIALBACK}
|
||||||
when (StateData#state.tls_required and StateData#state.tls_enabled)
|
when (StateData#state.tls_required and StateData#state.tls_enabled)
|
||||||
or (not StateData#state.tls_required) ->
|
or (not StateData#state.tls_required) ->
|
||||||
send_header(StateData, <<"">>),
|
send_header(StateData, undefined),
|
||||||
{next_state, stream_established, StateData};
|
{next_state, stream_established, StateData};
|
||||||
#stream_start{} ->
|
#stream_start{} ->
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
send_header(StateData, {1,0}),
|
||||||
send_element(StateData, xmpp:serr_undefined_condition()),
|
send_element(StateData, xmpp:serr_undefined_condition()),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData};
|
||||||
|
_ ->
|
||||||
|
send_header(StateData, {1,0}),
|
||||||
|
send_element(StateData, xmpp:serr_invalid_xml()),
|
||||||
|
{stop, normal, StateData}
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Txt = xmpp:format_error(Why),
|
Txt = xmpp:format_error(Why),
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
send_header(StateData, {1,0}),
|
||||||
send_element(StateData, xmpp:serr_not_well_formed(Txt, ?MYLANG)),
|
send_element(StateData, xmpp:serr_invalid_xml(Txt, ?MYLANG)),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
end;
|
end;
|
||||||
wait_for_stream({xmlstreamerror, _}, StateData) ->
|
wait_for_stream({xmlstreamerror, _}, StateData) ->
|
||||||
send_header(StateData, <<"">>),
|
send_header(StateData, {1,0}),
|
||||||
send_element(StateData, xmpp:serr_not_well_formed()),
|
send_element(StateData, xmpp:serr_not_well_formed()),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_stream(timeout, StateData) ->
|
wait_for_stream(timeout, StateData) ->
|
||||||
send_header(StateData, <<"">>),
|
send_header(StateData, {1,0}),
|
||||||
send_element(StateData, xmpp:serr_connection_timeout()),
|
send_element(StateData, xmpp:serr_connection_timeout()),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
wait_for_stream(closed, StateData) ->
|
wait_for_stream(closed, StateData) ->
|
||||||
@ -277,13 +286,21 @@ wait_for_feature_request(#starttls{},
|
|||||||
StateData#state.tls_options,
|
StateData#state.tls_options,
|
||||||
{certfile, CertFile})
|
{certfile, CertFile})
|
||||||
end,
|
end,
|
||||||
|
TLSOpts2 = case ejabberd_config:get_option(
|
||||||
|
{s2s_cafile, StateData#state.server},
|
||||||
|
fun iolist_to_binary/1) of
|
||||||
|
undefined -> TLSOpts1;
|
||||||
|
CAFile ->
|
||||||
|
lists:keystore(cafile, 1, TLSOpts1,
|
||||||
|
{cafile, CAFile})
|
||||||
|
end,
|
||||||
TLSOpts = case ejabberd_config:get_option(
|
TLSOpts = case ejabberd_config:get_option(
|
||||||
{s2s_tls_compression, StateData#state.server},
|
{s2s_tls_compression, StateData#state.server},
|
||||||
fun(true) -> true;
|
fun(true) -> true;
|
||||||
(false) -> false
|
(false) -> false
|
||||||
end, false) of
|
end, false) of
|
||||||
true -> lists:delete(compression_none, TLSOpts1);
|
true -> lists:delete(compression_none, TLSOpts2);
|
||||||
false -> [compression_none | TLSOpts1]
|
false -> [compression_none | TLSOpts2]
|
||||||
end,
|
end,
|
||||||
TLSSocket = (StateData#state.sockmod):starttls(
|
TLSSocket = (StateData#state.sockmod):starttls(
|
||||||
Socket, TLSOpts,
|
Socket, TLSOpts,
|
||||||
@ -293,8 +310,7 @@ wait_for_feature_request(#starttls{},
|
|||||||
StateData#state{socket = TLSSocket, streamid = new_id(),
|
StateData#state{socket = TLSSocket, streamid = new_id(),
|
||||||
tls_enabled = true, tls_options = TLSOpts}};
|
tls_enabled = true, tls_options = TLSOpts}};
|
||||||
_ ->
|
_ ->
|
||||||
Txt = <<"Unsupported TLS transport">>,
|
send_element(StateData, #starttls_failure{}),
|
||||||
send_element(StateData, xmpp:serr_policy_violation(Txt, ?MYLANG)),
|
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
end;
|
end;
|
||||||
wait_for_feature_request(#sasl_auth{mechanism = Mech},
|
wait_for_feature_request(#sasl_auth{mechanism = Mech},
|
||||||
@ -313,7 +329,10 @@ wait_for_feature_request(#sasl_auth{mechanism = Mech},
|
|||||||
StateData#state{streamid = new_id(),
|
StateData#state{streamid = new_id(),
|
||||||
authenticated = true}};
|
authenticated = true}};
|
||||||
true ->
|
true ->
|
||||||
send_element(StateData, #sasl_failure{}),
|
Txt = xmpp:mk_text(<<"Denied by ACL">>, ?MYLANG),
|
||||||
|
send_element(StateData,
|
||||||
|
#sasl_failure{reason = 'not-authorized',
|
||||||
|
text = Txt}),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
@ -495,7 +514,7 @@ handle_info({send_text, Text}, StateName, StateData) ->
|
|||||||
handle_info({timeout, Timer, _}, StateName,
|
handle_info({timeout, Timer, _}, StateName,
|
||||||
#state{timer = Timer} = StateData) ->
|
#state{timer = Timer} = StateData) ->
|
||||||
if StateName == wait_for_stream ->
|
if StateName == wait_for_stream ->
|
||||||
send_header(StateData, <<"">>);
|
send_header(StateData, undefined);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
@ -555,15 +574,15 @@ send_error(StateData, Stanza, Error) ->
|
|||||||
send_trailer(StateData) ->
|
send_trailer(StateData) ->
|
||||||
send_text(StateData, <<"</stream:stream>">>).
|
send_text(StateData, <<"</stream:stream>">>).
|
||||||
|
|
||||||
-spec send_header(state(), binary()) -> ok.
|
-spec send_header(state(), undefined | {integer(), integer()}) -> ok.
|
||||||
send_header(StateData, Version) ->
|
send_header(StateData, Version) ->
|
||||||
send_text(StateData,
|
Header = xmpp:encode(
|
||||||
<<"<?xml version='1.0'?><stream:stream "
|
#stream_start{xmlns = ?NS_SERVER,
|
||||||
"xmlns:stream='http://etherx.jabber.org/stream"
|
stream_xmlns = ?NS_STREAM,
|
||||||
"s' xmlns='jabber:server' xmlns:db='jabber:ser"
|
db_xmlns = ?NS_SERVER_DIALBACK,
|
||||||
"ver:dialback' id='",
|
id = StateData#state.streamid,
|
||||||
(StateData#state.streamid)/binary, "'", Version/binary,
|
version = Version}),
|
||||||
">">>).
|
send_text(StateData, fxml:element_to_header(Header)).
|
||||||
|
|
||||||
-spec change_shaper(state(), binary(), jid()) -> ok.
|
-spec change_shaper(state(), binary(), jid()) -> ok.
|
||||||
change_shaper(StateData, Host, JID) ->
|
change_shaper(StateData, Host, JID) ->
|
||||||
@ -606,9 +625,14 @@ fsm_limit_opts(Opts) ->
|
|||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec decode_element(xmlel(), state_name(), state()) -> fsm_transition().
|
-spec decode_element(xmlel() | xmpp_element(), state_name(), state()) -> fsm_transition().
|
||||||
decode_element(#xmlel{} = El, StateName, StateData) ->
|
decode_element(#xmlel{} = El, StateName, StateData) ->
|
||||||
try xmpp:decode(El) of
|
Opts = if StateName == stream_established ->
|
||||||
|
[ignore_els];
|
||||||
|
true ->
|
||||||
|
[]
|
||||||
|
end,
|
||||||
|
try xmpp:decode(El, Opts) of
|
||||||
Pkt -> ?MODULE:StateName(Pkt, StateData)
|
Pkt -> ?MODULE:StateName(Pkt, StateData)
|
||||||
catch error:{xmpp_codec, Why} ->
|
catch error:{xmpp_codec, Why} ->
|
||||||
case xmpp:is_stanza(El) of
|
case xmpp:is_stanza(El) of
|
||||||
@ -620,12 +644,15 @@ decode_element(#xmlel{} = El, StateName, StateData) ->
|
|||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
{next_state, StateName, StateData}
|
{next_state, StateName, StateData}
|
||||||
end.
|
end;
|
||||||
|
decode_element(Pkt, StateName, StateData) ->
|
||||||
|
?MODULE:StateName(Pkt, StateData).
|
||||||
|
|
||||||
opt_type(domain_certfile) -> fun iolist_to_binary/1;
|
opt_type(domain_certfile) -> fun iolist_to_binary/1;
|
||||||
opt_type(max_fsm_queue) ->
|
opt_type(max_fsm_queue) ->
|
||||||
fun (I) when is_integer(I), I > 0 -> I end;
|
fun (I) when is_integer(I), I > 0 -> I end;
|
||||||
opt_type(s2s_certfile) -> fun iolist_to_binary/1;
|
opt_type(s2s_certfile) -> fun iolist_to_binary/1;
|
||||||
|
opt_type(s2s_cafile) -> fun iolist_to_binary/1;
|
||||||
opt_type(s2s_ciphers) -> fun iolist_to_binary/1;
|
opt_type(s2s_ciphers) -> fun iolist_to_binary/1;
|
||||||
opt_type(s2s_dhfile) -> fun iolist_to_binary/1;
|
opt_type(s2s_dhfile) -> fun iolist_to_binary/1;
|
||||||
opt_type(s2s_protocol_options) ->
|
opt_type(s2s_protocol_options) ->
|
||||||
@ -647,6 +674,6 @@ opt_type(s2s_use_starttls) ->
|
|||||||
(required_trusted) -> required_trusted
|
(required_trusted) -> required_trusted
|
||||||
end;
|
end;
|
||||||
opt_type(_) ->
|
opt_type(_) ->
|
||||||
[domain_certfile, max_fsm_queue, s2s_certfile,
|
[domain_certfile, max_fsm_queue, s2s_certfile, s2s_cafile,
|
||||||
s2s_ciphers, s2s_dhfile, s2s_protocol_options,
|
s2s_ciphers, s2s_dhfile, s2s_protocol_options,
|
||||||
s2s_tls_compression, s2s_use_starttls].
|
s2s_tls_compression, s2s_use_starttls].
|
||||||
|
@ -106,12 +106,6 @@
|
|||||||
%% Specified in miliseconds. Default value is 5 minutes.
|
%% Specified in miliseconds. Default value is 5 minutes.
|
||||||
-define(MAX_RETRY_DELAY, 300000).
|
-define(MAX_RETRY_DELAY, 300000).
|
||||||
|
|
||||||
-define(STREAM_HEADER,
|
|
||||||
<<"<?xml version='1.0'?><stream:stream "
|
|
||||||
"xmlns:stream='http://etherx.jabber.org/stream"
|
|
||||||
"s' xmlns='jabber:server' xmlns:db='jabber:ser"
|
|
||||||
"ver:dialback' from='~s' to='~s'~s>">>).
|
|
||||||
|
|
||||||
-define(SOCKET_DEFAULT_RESULT, {error, badarg}).
|
-define(SOCKET_DEFAULT_RESULT, {error, badarg}).
|
||||||
|
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
@ -228,9 +222,8 @@ open_socket(init, StateData) ->
|
|||||||
?SOCKET_DEFAULT_RESULT, AddrList)
|
?SOCKET_DEFAULT_RESULT, AddrList)
|
||||||
of
|
of
|
||||||
{ok, Socket} ->
|
{ok, Socket} ->
|
||||||
Version = if StateData#state.use_v10 ->
|
Version = if StateData#state.use_v10 -> {1,0};
|
||||||
<<" version='1.0'">>;
|
true -> undefined
|
||||||
true -> <<"">>
|
|
||||||
end,
|
end,
|
||||||
NewStateData = StateData#state{socket = Socket,
|
NewStateData = StateData#state{socket = Socket,
|
||||||
tls_enabled = false,
|
tls_enabled = false,
|
||||||
@ -318,11 +311,10 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData0) ->
|
|||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
#stream_start{xmlns = NS_SERVER, stream_xmlns = NS_STREAM}
|
#stream_start{xmlns = NS_SERVER, stream_xmlns = NS_STREAM}
|
||||||
when NS_SERVER /= ?NS_SERVER; NS_STREAM /= ?NS_STREAM ->
|
when NS_SERVER /= ?NS_SERVER; NS_STREAM /= ?NS_STREAM ->
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
|
||||||
send_element(StateData, xmpp:serr_invalid_namespace()),
|
send_element(StateData, xmpp:serr_invalid_namespace()),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
#stream_start{db_xmlns = ?NS_SERVER_DIALBACK, id = ID,
|
#stream_start{db_xmlns = ?NS_SERVER_DIALBACK, id = ID,
|
||||||
version = V} when V /= <<"1.0">> ->
|
version = V} when V /= {1,0} ->
|
||||||
send_db_request(StateData#state{remote_streamid = ID});
|
send_db_request(StateData#state{remote_streamid = ID});
|
||||||
#stream_start{db_xmlns = ?NS_SERVER_DIALBACK, id = ID}
|
#stream_start{db_xmlns = ?NS_SERVER_DIALBACK, id = ID}
|
||||||
when StateData#state.use_v10 ->
|
when StateData#state.use_v10 ->
|
||||||
@ -337,13 +329,14 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData0) ->
|
|||||||
StateData#state{db_enabled = false, remote_streamid = ID},
|
StateData#state{db_enabled = false, remote_streamid = ID},
|
||||||
?FSMTIMEOUT};
|
?FSMTIMEOUT};
|
||||||
#stream_start{} ->
|
#stream_start{} ->
|
||||||
send_header(StateData, <<"">>),
|
|
||||||
send_element(StateData, xmpp:serr_invalid_namespace()),
|
send_element(StateData, xmpp:serr_invalid_namespace()),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData};
|
||||||
|
_ ->
|
||||||
|
send_element(StateData, xmpp:serr_invalid_xml()),
|
||||||
|
{stop, normal, StateData}
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Txt = xmpp:format_error(Why),
|
Txt = xmpp:format_error(Why),
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
send_element(StateData, xmpp:serr_invalid_xml(Txt, ?MYLANG)),
|
||||||
send_element(StateData, xmpp:serr_not_well_formed(Txt, ?MYLANG)),
|
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
end;
|
end;
|
||||||
wait_for_stream(Event, StateData) ->
|
wait_for_stream(Event, StateData) ->
|
||||||
@ -469,7 +462,7 @@ wait_for_auth_result({xmlstreamelement, El}, StateData) ->
|
|||||||
wait_for_auth_result(#sasl_success{}, StateData) ->
|
wait_for_auth_result(#sasl_success{}, StateData) ->
|
||||||
?DEBUG("auth: ~p", [{StateData#state.myname, StateData#state.server}]),
|
?DEBUG("auth: ~p", [{StateData#state.myname, StateData#state.server}]),
|
||||||
ejabberd_socket:reset_stream(StateData#state.socket),
|
ejabberd_socket:reset_stream(StateData#state.socket),
|
||||||
send_header(StateData, <<" version='1.0'">>),
|
send_header(StateData, {1,0}),
|
||||||
{next_state, wait_for_stream,
|
{next_state, wait_for_stream,
|
||||||
StateData#state{streamid = new_id(), authenticated = true},
|
StateData#state{streamid = new_id(), authenticated = true},
|
||||||
?FSMTIMEOUT};
|
?FSMTIMEOUT};
|
||||||
@ -500,7 +493,7 @@ wait_for_starttls_proceed(#starttls_proceed{}, StateData) ->
|
|||||||
streamid = new_id(),
|
streamid = new_id(),
|
||||||
tls_enabled = true,
|
tls_enabled = true,
|
||||||
tls_options = TLSOpts},
|
tls_options = TLSOpts},
|
||||||
send_header(NewStateData, <<" version='1.0'">>),
|
send_header(NewStateData, {1,0}),
|
||||||
{next_state, wait_for_stream, NewStateData, ?FSMTIMEOUT};
|
{next_state, wait_for_stream, NewStateData, ?FSMTIMEOUT};
|
||||||
wait_for_starttls_proceed(Event, StateData) ->
|
wait_for_starttls_proceed(Event, StateData) ->
|
||||||
handle_unexpected_event(Event, wait_for_starttls_proceed, StateData).
|
handle_unexpected_event(Event, wait_for_starttls_proceed, StateData).
|
||||||
@ -567,7 +560,8 @@ handle_unexpected_event(Event, StateName, StateData) ->
|
|||||||
{xmlstreamend, _} ->
|
{xmlstreamend, _} ->
|
||||||
?INFO_MSG("Closing s2s connection ~s -> ~s in state ~s: "
|
?INFO_MSG("Closing s2s connection ~s -> ~s in state ~s: "
|
||||||
"XML stream closed by peer",
|
"XML stream closed by peer",
|
||||||
[StateData#state.myname, StateData#state.server]),
|
[StateData#state.myname, StateData#state.server,
|
||||||
|
StateName]),
|
||||||
{stop, normal, StateData};
|
{stop, normal, StateData};
|
||||||
timeout ->
|
timeout ->
|
||||||
send_element(StateData, xmpp:serr_connection_timeout()),
|
send_element(StateData, xmpp:serr_connection_timeout()),
|
||||||
@ -741,6 +735,7 @@ print_state(State) -> State.
|
|||||||
|
|
||||||
-spec send_text(state(), iodata()) -> ok.
|
-spec send_text(state(), iodata()) -> ok.
|
||||||
send_text(StateData, Text) ->
|
send_text(StateData, Text) ->
|
||||||
|
?DEBUG("Send Text on stream = ~s", [Text]),
|
||||||
ejabberd_socket:send(StateData#state.socket, Text).
|
ejabberd_socket:send(StateData#state.socket, Text).
|
||||||
|
|
||||||
-spec send_element(state(), xmpp_element()) -> ok.
|
-spec send_element(state(), xmpp_element()) -> ok.
|
||||||
@ -748,15 +743,16 @@ send_element(StateData, El) ->
|
|||||||
El1 = fix_ns(xmpp:encode(El)),
|
El1 = fix_ns(xmpp:encode(El)),
|
||||||
send_text(StateData, fxml:element_to_binary(El1)).
|
send_text(StateData, fxml:element_to_binary(El1)).
|
||||||
|
|
||||||
-spec send_header(state(), binary()) -> ok.
|
-spec send_header(state(), undefined | {integer(), integer()}) -> ok.
|
||||||
send_header(StateData, Version) ->
|
send_header(StateData, Version) ->
|
||||||
Txt = io_lib:format(
|
Header = xmpp:encode(
|
||||||
"<?xml version='1.0'?><stream:stream "
|
#stream_start{xmlns = ?NS_SERVER,
|
||||||
"xmlns:stream='http://etherx.jabber.org/stream"
|
stream_xmlns = ?NS_STREAM,
|
||||||
"s' xmlns='jabber:server' xmlns:db='jabber:ser"
|
db_xmlns = ?NS_SERVER_DIALBACK,
|
||||||
"ver:dialback' from='~s' to='~s'~s>",
|
from = jid:make(StateData#state.myname),
|
||||||
[StateData#state.myname, StateData#state.server, Version]),
|
to = jid:make(StateData#state.server),
|
||||||
send_text(StateData, Txt).
|
version = Version}),
|
||||||
|
send_text(StateData, fxml:element_to_header(Header)).
|
||||||
|
|
||||||
-spec send_trailer(state()) -> ok.
|
-spec send_trailer(state()) -> ok.
|
||||||
send_trailer(StateData) ->
|
send_trailer(StateData) ->
|
||||||
|
@ -149,6 +149,10 @@ wait_for_stream({xmlstreamstart, Name, Attrs}, StateData) ->
|
|||||||
#stream_start{} ->
|
#stream_start{} ->
|
||||||
send_header(StateData, ?MYNAME),
|
send_header(StateData, ?MYNAME),
|
||||||
send_element(StateData, xmpp:serr_improper_addressing()),
|
send_element(StateData, xmpp:serr_improper_addressing()),
|
||||||
|
{stop, normal, StateData};
|
||||||
|
_ ->
|
||||||
|
send_header(StateData, ?MYNAME),
|
||||||
|
send_element(StateData, xmpp:serr_invalid_xml()),
|
||||||
{stop, normal, StateData}
|
{stop, normal, StateData}
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Txt = xmpp:format_error(Why),
|
Txt = xmpp:format_error(Why),
|
||||||
@ -319,13 +323,12 @@ send_error(StateData, Stanza, Error) ->
|
|||||||
|
|
||||||
-spec send_header(state(), binary()) -> ok.
|
-spec send_header(state(), binary()) -> ok.
|
||||||
send_header(StateData, Host) ->
|
send_header(StateData, Host) ->
|
||||||
send_text(StateData,
|
Header = xmpp:encode(
|
||||||
io_lib:format(
|
#stream_start{xmlns = ?NS_COMPONENT,
|
||||||
<<"<?xml version='1.0'?><stream:stream "
|
stream_xmlns = ?NS_STREAM,
|
||||||
"xmlns:stream='http://etherx.jabber.org/stream"
|
from = jid:make(Host),
|
||||||
"s' xmlns='jabber:component:accept' id='~s' "
|
id = StateData#state.streamid}),
|
||||||
"from='~s'>">>,
|
send_text(StateData, fxml:element_to_header(Header)).
|
||||||
[StateData#state.streamid, fxml:crypt(Host)])).
|
|
||||||
|
|
||||||
-spec send_trailer(state()) -> ok.
|
-spec send_trailer(state()) -> ok.
|
||||||
send_trailer(StateData) ->
|
send_trailer(StateData) ->
|
||||||
|
@ -3955,6 +3955,14 @@ pp(upload_slot, 3) -> [get, put, xmlns];
|
|||||||
pp(thumbnail, 4) -> [uri, 'media-type', width, height];
|
pp(thumbnail, 4) -> [uri, 'media-type', width, height];
|
||||||
pp(_, _) -> no.
|
pp(_, _) -> no.
|
||||||
|
|
||||||
|
enc_version({Maj, Min}) ->
|
||||||
|
<<(integer_to_binary(Maj))/binary, $.,
|
||||||
|
(integer_to_binary(Min))/binary>>.
|
||||||
|
|
||||||
|
dec_version(S) ->
|
||||||
|
[Major, Minor] = binary:split(S, <<$.>>),
|
||||||
|
{binary_to_integer(Major), binary_to_integer(Minor)}.
|
||||||
|
|
||||||
enc_host_port(Host) when is_binary(Host) -> Host;
|
enc_host_port(Host) when is_binary(Host) -> Host;
|
||||||
enc_host_port({{_, _, _, _, _, _, _, _} = IPv6,
|
enc_host_port({{_, _, _, _, _, _, _, _} = IPv6,
|
||||||
Port}) ->
|
Port}) ->
|
||||||
@ -5284,13 +5292,20 @@ encode_stream_start_attr_xmlns(_val, _acc) ->
|
|||||||
|
|
||||||
decode_stream_start_attr_version(__TopXMLNS,
|
decode_stream_start_attr_version(__TopXMLNS,
|
||||||
undefined) ->
|
undefined) ->
|
||||||
<<>>;
|
undefined;
|
||||||
decode_stream_start_attr_version(__TopXMLNS, _val) ->
|
decode_stream_start_attr_version(__TopXMLNS, _val) ->
|
||||||
_val.
|
case catch dec_version(_val) of
|
||||||
|
{'EXIT', _} ->
|
||||||
|
erlang:error({xmpp_codec,
|
||||||
|
{bad_attr_value, <<"version">>, <<"stream:stream">>,
|
||||||
|
__TopXMLNS}});
|
||||||
|
_res -> _res
|
||||||
|
end.
|
||||||
|
|
||||||
encode_stream_start_attr_version(<<>>, _acc) -> _acc;
|
encode_stream_start_attr_version(undefined, _acc) ->
|
||||||
|
_acc;
|
||||||
encode_stream_start_attr_version(_val, _acc) ->
|
encode_stream_start_attr_version(_val, _acc) ->
|
||||||
[{<<"version">>, _val} | _acc].
|
[{<<"version">>, enc_version(_val)} | _acc].
|
||||||
|
|
||||||
decode_stream_start_attr_id(__TopXMLNS, undefined) ->
|
decode_stream_start_attr_id(__TopXMLNS, undefined) ->
|
||||||
<<>>;
|
<<>>;
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
make_iq_result/1, start_event_relay/0,
|
make_iq_result/1, start_event_relay/0,
|
||||||
stop_event_relay/1, put_event/2, get_event/1,
|
stop_event_relay/1, put_event/2, get_event/1,
|
||||||
bind/1, auth/1, auth/2, open_session/1, open_session/2,
|
bind/1, auth/1, auth/2, open_session/1, open_session/2,
|
||||||
zlib/1, starttls/1, close_socket/1, init_stream/1,
|
zlib/1, starttls/1, starttls/2, close_socket/1, init_stream/1,
|
||||||
auth_legacy/2, auth_legacy/3]).
|
auth_legacy/2, auth_legacy/3, tcp_connect/1, send_text/2]).
|
||||||
|
|
||||||
-include("suite.hrl").
|
-include("suite.hrl").
|
||||||
|
|
||||||
suite() ->
|
suite() ->
|
||||||
[{timetrap, {seconds,10}}].
|
[{timetrap, {seconds,30}}].
|
||||||
|
|
||||||
init_per_suite(Config) ->
|
init_per_suite(Config) ->
|
||||||
NewConfig = init_config(Config),
|
NewConfig = init_config(Config),
|
||||||
@ -36,6 +36,10 @@ init_per_suite(Config) ->
|
|||||||
LDIFFile = filename:join([DataDir, "ejabberd.ldif"]),
|
LDIFFile = filename:join([DataDir, "ejabberd.ldif"]),
|
||||||
{ok, _} = file:copy(ExtAuthScript, filename:join([CWD, "extauth.py"])),
|
{ok, _} = file:copy(ExtAuthScript, filename:join([CWD, "extauth.py"])),
|
||||||
{ok, _} = ldap_srv:start(LDIFFile),
|
{ok, _} = ldap_srv:start(LDIFFile),
|
||||||
|
inet_db:add_host({127,0,0,1}, [binary_to_list(?S2S_VHOST),
|
||||||
|
binary_to_list(?MNESIA_VHOST)]),
|
||||||
|
inet_db:set_domain(binary_to_list(randoms:get_string())),
|
||||||
|
inet_db:set_lookup([file, native]),
|
||||||
start_ejabberd(NewConfig),
|
start_ejabberd(NewConfig),
|
||||||
NewConfig.
|
NewConfig.
|
||||||
|
|
||||||
@ -125,6 +129,16 @@ do_init_per_group(riak, Config) ->
|
|||||||
Err ->
|
Err ->
|
||||||
{skip, {riak_not_available, Err}}
|
{skip, {riak_not_available, Err}}
|
||||||
end;
|
end;
|
||||||
|
do_init_per_group(s2s, Config) ->
|
||||||
|
ejabberd_config:add_option(s2s_use_starttls, required_trusted),
|
||||||
|
ejabberd_config:add_option(domain_certfile, "cert.pem"),
|
||||||
|
Port = ?config(s2s_port, Config),
|
||||||
|
set_opt(server, ?COMMON_VHOST,
|
||||||
|
set_opt(xmlns, ?NS_SERVER,
|
||||||
|
set_opt(type, server,
|
||||||
|
set_opt(server_port, Port,
|
||||||
|
set_opt(stream_from, ?S2S_VHOST,
|
||||||
|
set_opt(lang, <<"">>, Config))))));
|
||||||
do_init_per_group(component, Config) ->
|
do_init_per_group(component, Config) ->
|
||||||
Server = ?config(server, Config),
|
Server = ?config(server, Config),
|
||||||
Port = ?config(component_port, Config),
|
Port = ?config(component_port, Config),
|
||||||
@ -132,7 +146,7 @@ do_init_per_group(component, Config) ->
|
|||||||
set_opt(server, <<"component.", Server/binary>>,
|
set_opt(server, <<"component.", Server/binary>>,
|
||||||
set_opt(type, component,
|
set_opt(type, component,
|
||||||
set_opt(server_port, Port,
|
set_opt(server_port, Port,
|
||||||
set_opt(stream_version, <<"">>,
|
set_opt(stream_version, undefined,
|
||||||
set_opt(lang, <<"">>, Config))))));
|
set_opt(lang, <<"">>, Config))))));
|
||||||
do_init_per_group(_GroupName, Config) ->
|
do_init_per_group(_GroupName, Config) ->
|
||||||
Pid = start_event_relay(),
|
Pid = start_event_relay(),
|
||||||
@ -158,6 +172,8 @@ end_per_group(riak, _Config) ->
|
|||||||
ok;
|
ok;
|
||||||
end_per_group(component, _Config) ->
|
end_per_group(component, _Config) ->
|
||||||
ok;
|
ok;
|
||||||
|
end_per_group(s2s, _Config) ->
|
||||||
|
ejabberd_config:add_option(s2s_use_starttls, false);
|
||||||
end_per_group(_GroupName, Config) ->
|
end_per_group(_GroupName, Config) ->
|
||||||
stop_event_relay(Config),
|
stop_event_relay(Config),
|
||||||
ok.
|
ok.
|
||||||
@ -215,7 +231,7 @@ init_per_testcase(TestCase, OrigConfig) ->
|
|||||||
"test_connect" ++ _ ->
|
"test_connect" ++ _ ->
|
||||||
Config;
|
Config;
|
||||||
"test_legacy_auth" ++ _ ->
|
"test_legacy_auth" ++ _ ->
|
||||||
init_stream(set_opt(stream_version, <<"">>, Config));
|
init_stream(set_opt(stream_version, undefined, Config));
|
||||||
"test_auth" ++ _ ->
|
"test_auth" ++ _ ->
|
||||||
connect(Config);
|
connect(Config);
|
||||||
"test_starttls" ++ _ ->
|
"test_starttls" ++ _ ->
|
||||||
@ -244,6 +260,8 @@ init_per_testcase(TestCase, OrigConfig) ->
|
|||||||
Password = ?config(password, Config),
|
Password = ?config(password, Config),
|
||||||
ejabberd_auth:try_register(User, Server, Password),
|
ejabberd_auth:try_register(User, Server, Password),
|
||||||
open_session(bind(auth(connect(Config))));
|
open_session(bind(auth(connect(Config))));
|
||||||
|
_ when TestGroup == s2s_tests ->
|
||||||
|
auth(connect(starttls(connect(Config))));
|
||||||
_ ->
|
_ ->
|
||||||
open_session(bind(auth(connect(Config))))
|
open_session(bind(auth(connect(Config))))
|
||||||
end.
|
end.
|
||||||
@ -262,6 +280,7 @@ legacy_auth_tests() ->
|
|||||||
no_db_tests() ->
|
no_db_tests() ->
|
||||||
[{generic, [parallel],
|
[{generic, [parallel],
|
||||||
[test_connect_bad_xml,
|
[test_connect_bad_xml,
|
||||||
|
test_connect_unexpected_xml,
|
||||||
test_connect_unknown_ns,
|
test_connect_unknown_ns,
|
||||||
test_connect_bad_xmlns,
|
test_connect_bad_xmlns,
|
||||||
test_connect_bad_ns_stream,
|
test_connect_bad_ns_stream,
|
||||||
@ -286,7 +305,12 @@ no_db_tests() ->
|
|||||||
time,
|
time,
|
||||||
stats,
|
stats,
|
||||||
disco]},
|
disco]},
|
||||||
{presence, [sequence], [presence]},
|
{presence_and_s2s, [sequence],
|
||||||
|
[presence,
|
||||||
|
s2s_dialback,
|
||||||
|
s2s_optional,
|
||||||
|
s2s_required,
|
||||||
|
s2s_required_trusted]},
|
||||||
{sm, [sequence],
|
{sm, [sequence],
|
||||||
[sm,
|
[sm,
|
||||||
sm_resume,
|
sm_resume,
|
||||||
@ -433,18 +457,39 @@ extauth_tests() ->
|
|||||||
test_unregister]}].
|
test_unregister]}].
|
||||||
|
|
||||||
component_tests() ->
|
component_tests() ->
|
||||||
[{component_tests, [sequence],
|
[{component_connect, [parallel],
|
||||||
[test_connect_bad_xml,
|
[test_connect_bad_xml,
|
||||||
|
test_connect_unexpected_xml,
|
||||||
test_connect_unknown_ns,
|
test_connect_unknown_ns,
|
||||||
test_connect_bad_xmlns,
|
test_connect_bad_xmlns,
|
||||||
test_connect_bad_ns_stream,
|
test_connect_bad_ns_stream,
|
||||||
test_connect_missing_to,
|
test_connect_missing_to,
|
||||||
test_connect,
|
test_connect,
|
||||||
test_auth,
|
test_auth,
|
||||||
test_auth_fail,
|
test_auth_fail]},
|
||||||
component_missing_address,
|
{component_tests, [sequence],
|
||||||
component_invalid_from,
|
[test_missing_address,
|
||||||
component_send,
|
test_invalid_from,
|
||||||
|
test_component_send,
|
||||||
|
bad_nonza,
|
||||||
|
codec_failure]}].
|
||||||
|
|
||||||
|
s2s_tests() ->
|
||||||
|
[{s2s_connect, [parallel],
|
||||||
|
[test_connect_bad_xml,
|
||||||
|
test_connect_unexpected_xml,
|
||||||
|
test_connect_unknown_ns,
|
||||||
|
test_connect_bad_xmlns,
|
||||||
|
test_connect_bad_ns_stream,
|
||||||
|
test_connect,
|
||||||
|
test_connect_s2s_starttls_required,
|
||||||
|
test_starttls,
|
||||||
|
test_connect_missing_from,
|
||||||
|
test_connect_s2s_unauthenticated_iq,
|
||||||
|
test_auth_starttls]},
|
||||||
|
{s2s_tests, [sequence],
|
||||||
|
[test_missing_address,
|
||||||
|
test_invalid_from,
|
||||||
bad_nonza,
|
bad_nonza,
|
||||||
codec_failure]}].
|
codec_failure]}].
|
||||||
|
|
||||||
@ -453,6 +498,7 @@ groups() ->
|
|||||||
{extauth, [sequence], extauth_tests()},
|
{extauth, [sequence], extauth_tests()},
|
||||||
{no_db, [sequence], no_db_tests()},
|
{no_db, [sequence], no_db_tests()},
|
||||||
{component, [sequence], component_tests()},
|
{component, [sequence], component_tests()},
|
||||||
|
{s2s, [sequence], s2s_tests()},
|
||||||
{mnesia, [sequence], db_tests(mnesia)},
|
{mnesia, [sequence], db_tests(mnesia)},
|
||||||
{redis, [sequence], db_tests(redis)},
|
{redis, [sequence], db_tests(redis)},
|
||||||
{mysql, [sequence], db_tests(mysql)},
|
{mysql, [sequence], db_tests(mysql)},
|
||||||
@ -461,16 +507,17 @@ groups() ->
|
|||||||
{riak, [sequence], db_tests(riak)}].
|
{riak, [sequence], db_tests(riak)}].
|
||||||
|
|
||||||
all() ->
|
all() ->
|
||||||
[{group, component},
|
[{group, ldap},
|
||||||
%%{group, ldap},
|
|
||||||
{group, no_db},
|
{group, no_db},
|
||||||
{group, mnesia},
|
{group, mnesia},
|
||||||
%%{group, redis},
|
{group, redis},
|
||||||
%%{group, mysql},
|
{group, mysql},
|
||||||
%%{group, pgsql},
|
{group, pgsql},
|
||||||
%%{group, sqlite},
|
{group, sqlite},
|
||||||
%%{group, extauth},
|
{group, extauth},
|
||||||
%%{group, riak},
|
{group, riak},
|
||||||
|
{group, component},
|
||||||
|
{group, s2s},
|
||||||
stop_ejabberd].
|
stop_ejabberd].
|
||||||
|
|
||||||
stop_ejabberd(Config) ->
|
stop_ejabberd(Config) ->
|
||||||
@ -480,11 +527,23 @@ stop_ejabberd(Config) ->
|
|||||||
Config.
|
Config.
|
||||||
|
|
||||||
test_connect_bad_xml(Config) ->
|
test_connect_bad_xml(Config) ->
|
||||||
Config0 = init_stream(set_opt(xmlns, <<"'">>, Config)),
|
Config0 = tcp_connect(Config),
|
||||||
|
send_text(Config0, <<"<'/>">>),
|
||||||
|
Version = ?config(stream_version, Config0),
|
||||||
|
?recv1(#stream_start{version = Version}),
|
||||||
?recv1(#stream_error{reason = 'not-well-formed'}),
|
?recv1(#stream_error{reason = 'not-well-formed'}),
|
||||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||||
close_socket(Config0).
|
close_socket(Config0).
|
||||||
|
|
||||||
|
test_connect_unexpected_xml(Config) ->
|
||||||
|
Config0 = tcp_connect(Config),
|
||||||
|
send(Config0, #caps{}),
|
||||||
|
Version = ?config(stream_version, Config0),
|
||||||
|
?recv1(#stream_start{version = Version}),
|
||||||
|
?recv1(#stream_error{reason = 'invalid-xml'}),
|
||||||
|
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||||
|
close_socket(Config0).
|
||||||
|
|
||||||
test_connect_unknown_ns(Config) ->
|
test_connect_unknown_ns(Config) ->
|
||||||
Config0 = init_stream(set_opt(xmlns, <<"wrong">>, Config)),
|
Config0 = init_stream(set_opt(xmlns, <<"wrong">>, Config)),
|
||||||
?recv1(#stream_error{reason = 'invalid-xml'}),
|
?recv1(#stream_error{reason = 'invalid-xml'}),
|
||||||
@ -492,7 +551,11 @@ test_connect_unknown_ns(Config) ->
|
|||||||
close_socket(Config0).
|
close_socket(Config0).
|
||||||
|
|
||||||
test_connect_bad_xmlns(Config) ->
|
test_connect_bad_xmlns(Config) ->
|
||||||
Config0 = init_stream(set_opt(xmlns, ?NS_SERVER, Config)),
|
NS = case ?config(type, Config) of
|
||||||
|
client -> ?NS_SERVER;
|
||||||
|
_ -> ?NS_CLIENT
|
||||||
|
end,
|
||||||
|
Config0 = init_stream(set_opt(xmlns, NS, Config)),
|
||||||
?recv1(#stream_error{reason = 'invalid-namespace'}),
|
?recv1(#stream_error{reason = 'invalid-namespace'}),
|
||||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||||
close_socket(Config0).
|
close_socket(Config0).
|
||||||
@ -521,19 +584,32 @@ test_connect_missing_to(Config) ->
|
|||||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||||
close_socket(Config0).
|
close_socket(Config0).
|
||||||
|
|
||||||
|
test_connect_missing_from(Config) ->
|
||||||
|
Config1 = starttls(connect(Config)),
|
||||||
|
Config2 = set_opt(stream_from, <<"">>, Config1),
|
||||||
|
Config3 = init_stream(Config2),
|
||||||
|
?recv1(#stream_error{reason = 'policy-violation'}),
|
||||||
|
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||||
|
close_socket(Config3).
|
||||||
|
|
||||||
test_connect(Config) ->
|
test_connect(Config) ->
|
||||||
disconnect(connect(Config)).
|
disconnect(connect(Config)).
|
||||||
|
|
||||||
test_component_connect(Config) ->
|
test_connect_s2s_starttls_required(Config) ->
|
||||||
disconnect(component_connect(Config)).
|
Config1 = connect(Config),
|
||||||
|
send(Config1, #caps{}),
|
||||||
|
?recv1(#stream_error{reason = 'policy-violation'}),
|
||||||
|
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||||
|
close_socket(Config1).
|
||||||
|
|
||||||
component_connect(Config) ->
|
test_connect_s2s_unauthenticated_iq(Config) ->
|
||||||
init_stream(Config).
|
Config1 = connect(starttls(connect(Config))),
|
||||||
|
unauthenticated_iq(Config1).
|
||||||
|
|
||||||
test_starttls(Config) ->
|
test_starttls(Config) ->
|
||||||
case ?config(starttls, Config) of
|
case ?config(starttls, Config) of
|
||||||
true ->
|
true ->
|
||||||
disconnect(starttls(Config));
|
disconnect(connect(starttls(Config)));
|
||||||
_ ->
|
_ ->
|
||||||
{skipped, 'starttls_not_available'}
|
{skipped, 'starttls_not_available'}
|
||||||
end.
|
end.
|
||||||
@ -597,8 +673,11 @@ unauthenticated_stanza(Config) ->
|
|||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
unauthenticated_iq(Config) ->
|
unauthenticated_iq(Config) ->
|
||||||
|
From = my_jid(Config),
|
||||||
|
To = server_jid(Config),
|
||||||
#iq{type = error} =
|
#iq{type = error} =
|
||||||
send_recv(Config, #iq{type = get, sub_els = [#disco_info{}]}),
|
send_recv(Config, #iq{type = get, from = From, to = To,
|
||||||
|
sub_els = [#disco_info{}]}),
|
||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
bad_nonza(Config) ->
|
bad_nonza(Config) ->
|
||||||
@ -613,23 +692,57 @@ invalid_from(Config) ->
|
|||||||
?recv1({xmlstreamend, <<"stream:stream">>}),
|
?recv1({xmlstreamend, <<"stream:stream">>}),
|
||||||
close_socket(Config).
|
close_socket(Config).
|
||||||
|
|
||||||
component_missing_address(Config) ->
|
test_missing_address(Config) ->
|
||||||
Server = server_jid(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, from = Server}),
|
||||||
#iq{type = error} = send_recv(Config, #iq{type = get, to = Server}),
|
#iq{type = error} = send_recv(Config, #iq{type = get, to = Server}),
|
||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
component_invalid_from(Config) ->
|
test_invalid_from(Config) ->
|
||||||
From = jid:make(randoms:get_string()),
|
From = jid:make(randoms:get_string()),
|
||||||
To = jid:make(randoms:get_string()),
|
To = jid:make(randoms:get_string()),
|
||||||
#iq{type = error} =
|
#iq{type = error} =
|
||||||
send_recv(Config, #iq{type = get, from = From, to = To}),
|
send_recv(Config, #iq{type = get, from = From, to = To}),
|
||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
component_send(Config) ->
|
test_component_send(Config) ->
|
||||||
JID = my_jid(Config),
|
To = jid:make(?COMMON_VHOST),
|
||||||
send(Config, #message{from = JID, to = JID}),
|
From = server_jid(Config),
|
||||||
#message{from = JID, to = JID} = recv(),
|
#iq{type = result, from = To, to = From} =
|
||||||
|
send_recv(Config, #iq{type = get, to = To, from = From,
|
||||||
|
sub_els = [#ping{}]}),
|
||||||
|
disconnect(Config).
|
||||||
|
|
||||||
|
s2s_dialback(Config) ->
|
||||||
|
ejabberd_s2s:stop_all_connections(),
|
||||||
|
ejabberd_config:add_option(s2s_use_starttls, false),
|
||||||
|
ejabberd_config:add_option(domain_certfile, "self-signed-cert.pem"),
|
||||||
|
s2s_ping(Config).
|
||||||
|
|
||||||
|
s2s_optional(Config) ->
|
||||||
|
ejabberd_s2s:stop_all_connections(),
|
||||||
|
ejabberd_config:add_option(s2s_use_starttls, optional),
|
||||||
|
ejabberd_config:add_option(domain_certfile, "self-signed-cert.pem"),
|
||||||
|
s2s_ping(Config).
|
||||||
|
|
||||||
|
s2s_required(Config) ->
|
||||||
|
ejabberd_s2s:stop_all_connections(),
|
||||||
|
ejabberd_config:add_option(s2s_use_starttls, required),
|
||||||
|
ejabberd_config:add_option(domain_certfile, "self-signed-cert.pem"),
|
||||||
|
s2s_ping(Config).
|
||||||
|
|
||||||
|
s2s_required_trusted(Config) ->
|
||||||
|
ejabberd_s2s:stop_all_connections(),
|
||||||
|
ejabberd_config:add_option(s2s_use_starttls, required),
|
||||||
|
ejabberd_config:add_option(domain_certfile, "cert.pem"),
|
||||||
|
s2s_ping(Config).
|
||||||
|
|
||||||
|
s2s_ping(Config) ->
|
||||||
|
From = my_jid(Config),
|
||||||
|
To = jid:make(?MNESIA_VHOST),
|
||||||
|
ID = randoms:get_string(),
|
||||||
|
ejabberd_s2s:route(From, To, #iq{id = ID, type = get, sub_els = [#ping{}]}),
|
||||||
|
?recv1(#iq{type = result, id = ID, sub_els = []}),
|
||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
auth_md5(Config) ->
|
auth_md5(Config) ->
|
||||||
@ -674,6 +787,9 @@ test_legacy_auth_fail(Config0) ->
|
|||||||
test_auth(Config) ->
|
test_auth(Config) ->
|
||||||
disconnect(auth(Config)).
|
disconnect(auth(Config)).
|
||||||
|
|
||||||
|
test_auth_starttls(Config) ->
|
||||||
|
disconnect(auth(connect(starttls(Config)))).
|
||||||
|
|
||||||
test_auth_fail(Config0) ->
|
test_auth_fail(Config0) ->
|
||||||
Config = set_opt(user, <<"wrong">>,
|
Config = set_opt(user, <<"wrong">>,
|
||||||
set_opt(password, <<"wrong">>, Config0)),
|
set_opt(password, <<"wrong">>, Config0)),
|
||||||
@ -1895,7 +2011,6 @@ announce_slave(Config) ->
|
|||||||
|
|
||||||
flex_offline_master(Config) ->
|
flex_offline_master(Config) ->
|
||||||
Peer = ?config(slave, Config),
|
Peer = ?config(slave, Config),
|
||||||
ct:log("hooks = ~p", [ets:tab2list(hooks)]),
|
|
||||||
LPeer = jid:remove_resource(Peer),
|
LPeer = jid:remove_resource(Peer),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(I) ->
|
fun(I) ->
|
||||||
|
27
test/ejabberd_SUITE_data/ca.key
Normal file
27
test/ejabberd_SUITE_data/ca.key
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAxGSSFSDTbBTk2GwkORLCXoBdYq5YxwPfen8bK+8WjxRb9Thp
|
||||||
|
FsHYfImtDQV0qvcZyWnjUFxRh7Dyw7A2X690nplCdzZ9Gl+5yzzlRefHborMSnNY
|
||||||
|
rnTqx3vs9qiac0A5bzdjMY7XN3VuVwz0XWY6rAiL/7OxunCNUnQz+oswDx7cj1W4
|
||||||
|
bb9pFzBvW5TjaAiziyzS3IxvTc7kYQYJEa99vIlDZ+Ov9rHtiF/5CZ8kHc457B3s
|
||||||
|
uc9hHxO2t0EzmBiqg7wpksJjoJeXaJvT9sKSgW6LXkjBCm/7jm1ElPq+7FCph0qp
|
||||||
|
uIsxMtu15exLKQaSRLcc+tyNkWIZGQ371D2+7wIDAQABAoIBACzcNCozV1fm5ecx
|
||||||
|
vIx05oUjmTFDVfAPyGp4wkIk2OhR5Dd9bTPPj53S7P5+coni67cAQvZGQDFYj/t3
|
||||||
|
MtRkhaT8qRwGDEmL+CqefFidewabGdMfye//sOlkO1qUZMNStkvbQQM+95Ypcszb
|
||||||
|
nq3+/gPx59i+uSg3MXDWLlFand217d8oU4JxmCxHc9ezhkpWsdReiAukWTud+q/5
|
||||||
|
DzyPetaP09z8Ua/YNXuI6IdsvObYxOSCI1hPPuMSQGM4hQiqkHPqPNBIJDwfM9wk
|
||||||
|
WzGom5M7nGitrKynJHdS2VRzsZwFL3Hg0yBXnSY1o8er5A6i5//dS2ISSEN9xHjz
|
||||||
|
9PRRCbECgYEA+yVmv8i5uBLuz/Oeu/iOcX9ZNHfNowuIpInWVyfVhURIc1OwP1Sy
|
||||||
|
uj5Qst2IY+Hm4IVq0sNg3cZdEk+K6RMyc/Qgd7GoYeJNKH1v0RbA6E1zEzqm8Xv+
|
||||||
|
jA3dd7RLb5NTwFv11Qh0BDZfw2e8pCmN4oDp+n8fo7RE3NQGaLb77QsCgYEAyDBE
|
||||||
|
FoYVwXhGaKnhDT1AqM3hkOGBqheJJIxkNUnyMhlU/AxmWtfvTtw7MCP+311bz4Ma
|
||||||
|
h6yUfaEiHQJs2wkPyIaZ8CbbVyP7bXWMZzA/Rnk4dQWZ/VjRYvEzIvmz9di3w5j6
|
||||||
|
P1fWX0QODqcY2CvHyMmPLIysbC0cjVDA4ZpDvC0CgYEAlqvrpuevtCV3rL7F3pPS
|
||||||
|
MXlrdTTi5AyJX91qAEPfr+I1bSsqM/SGfYHhPE34A6SFtPGWEvgwZx0YvWGHPynL
|
||||||
|
PRGbYPPuxzrTe5U1vkVeWoAMp96qRXpUToYK9kPudfP3bRI+vB4kLFrKvRrBa+Oa
|
||||||
|
QeeBeE1IGBiQr8NsTOpq3d0CgYB9R+d0iRlYaKL3oUjcdjbe7Wl6uAXjorMLEmks
|
||||||
|
CEjwHXZX/pKXy4dSPPU1nXFF7DEm3o9d1R1gudSVfw0MztD313TDHC4sjLIuwF/L
|
||||||
|
vB/9RKOWaJkEOe9gEj7EZqy+8I+gcz45IglguUBq3xvnPQ7ck3dsk+TcFidGMQFk
|
||||||
|
rpwxSQKBgQDbdzOJagPep0HVJPkOmF1X4idb1rnQUuMi59I3k6lFTXAaypy6nU69
|
||||||
|
aAUgv7UY4i3XglEhbztk/o51W4/fJ1N8UzbXlBur/pJD8GN2h52ea77CbpOAmDSm
|
||||||
|
Bjjoj92wmYGfBRf7DwJQDgqxvpa0s1cwtYjNf0RmbDPzBsfzrKLKbQ==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
22
test/ejabberd_SUITE_data/ca.pem
Normal file
22
test/ejabberd_SUITE_data/ca.pem
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDtTCCAp2gAwIBAgIJAKI8WTrCnPXzMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||||
|
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
|
||||||
|
aWRnaXRzIFB0eSBMdGQwHhcNMTUwNDE1MTQxNTI0WhcNNDIwODMxMTQxNTI0WjBF
|
||||||
|
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
|
||||||
|
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||||
|
CgKCAQEAxGSSFSDTbBTk2GwkORLCXoBdYq5YxwPfen8bK+8WjxRb9ThpFsHYfImt
|
||||||
|
DQV0qvcZyWnjUFxRh7Dyw7A2X690nplCdzZ9Gl+5yzzlRefHborMSnNYrnTqx3vs
|
||||||
|
9qiac0A5bzdjMY7XN3VuVwz0XWY6rAiL/7OxunCNUnQz+oswDx7cj1W4bb9pFzBv
|
||||||
|
W5TjaAiziyzS3IxvTc7kYQYJEa99vIlDZ+Ov9rHtiF/5CZ8kHc457B3suc9hHxO2
|
||||||
|
t0EzmBiqg7wpksJjoJeXaJvT9sKSgW6LXkjBCm/7jm1ElPq+7FCph0qpuIsxMtu1
|
||||||
|
5exLKQaSRLcc+tyNkWIZGQ371D2+7wIDAQABo4GnMIGkMB0GA1UdDgQWBBTQ9mbL
|
||||||
|
xyIyE3pDyrNMsC36DRHp+TB1BgNVHSMEbjBsgBTQ9mbLxyIyE3pDyrNMsC36DRHp
|
||||||
|
+aFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
|
||||||
|
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAKI8WTrCnPXzMAwGA1UdEwQF
|
||||||
|
MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGyAi//UQaUhy8RLGc33T36Ni6TnRgpz
|
||||||
|
1xu2aahMe0YfPUZsZwwCP6dK+6fSw7OsRqyXZNZJntlur30yMMDlvjXmV6UDzeS4
|
||||||
|
/HGd/hr0LqruYpmvOKmvT/y8VkmBqsGlcaRNhSJGDzMHAVEQ0hzAJe3Emw5R753p
|
||||||
|
iVRbxPqiOVt4U/gjwtrVumSt1v9O4buWo1lTp0jxK1L6K8YWmETLuxyS3IG+i9Ij
|
||||||
|
DDNyU/UxyocP/mcscUAoV9MJX56exwPC93rPxOlwJT5e5ZMRGnwwUt017dPUrKbA
|
||||||
|
u+24S8uJCKN2w0OzsrqzC6lvxOf0JRfNxxxGr1KZYyEGT7ps1jhTebA=
|
||||||
|
-----END CERTIFICATE-----
|
@ -1,52 +1,54 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIGbDCCBVSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET
|
MIIEmTCCA4GgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET
|
||||||
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
|
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
|
||||||
dHkgTHRkMB4XDTE2MDUyNDE3NDIyNVoXDTQzMTAxMDE3NDIyNVowVjELMAkGA1UE
|
dHkgTHRkMB4XDTE2MDkyMzA3MDMyNFoXDTQ0MDIwOTA3MDMyNFowVjELMAkGA1UE
|
||||||
BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
|
BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
|
||||||
ZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAxMGYWN0aXZlMIGfMA0GCSqGSIb3DQEBAQUA
|
ZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAxMGYWN0aXZlMIIBIjANBgkqhkiG9w0BAQEF
|
||||||
A4GNADCBiQKBgQC+GTA1D1+yiXgLqUhJXkSj3hj5FiqlBAfJT/8OSXYifY4M4HYv
|
AAOCAQ8AMIIBCgKCAQEAselBnOh089g/VN7gH1m43Vo67kSqh8QRnXZxfjpzt3oP
|
||||||
VQrqER2Fs7jdCaeoGWDvwfK/UOV0b1ROnf+T/2bXFs8EOeqjOz4xG2oexNKVrYj9
|
Dl5nd04eNey4ezoSBo7o1hKhj/m5KLxmy1kN+xssyutgzto1FZu8GC2jDyLvByNL
|
||||||
ICYAgmSh6Hf2cZJM/YCAISje93Xl2J2w/N7oFC1ZXasPoBIZv3Fgg7hTtQIDAQAB
|
h0Z3XLmzdzBzBjosCtllJtzHlVL08SPuuOId5hToiiT8h3ElgNI4L6w+eLzhZIk5
|
||||||
o4ID2DCCA9QwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l
|
Rj1WojGa+pnaTEgoOaZPcNrkOj81o1tgnbLXN7HY3hJKnRp78DmPySq82cRhvfNr
|
||||||
cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFEynWiCoZK4tLDk3KM1wMsbrz9Ug
|
ePCs6BJr3y7yYJk0nG+EOaj5BK95YSJondZ8fOZuCigJPMogEaSw0SGsSUiQrPsd
|
||||||
MB8GA1UdIwQYMBaAFND2ZsvHIjITekPKs0ywLfoNEen5MDMGA1UdHwQsMCowKKAm
|
+3vZQ+3ctOimnhW7cF3fAM79g+zDdv9N9E3D+inhyQIDAQABo4IBgTCCAX0wCQYD
|
||||||
oCSGImh0dHA6Ly9sb2NhbGhvc3Q6NTI4MC9kYXRhL2NybC5kZXIwNgYIKwYBBQUH
|
VR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlm
|
||||||
AQEEKjAoMCYGCCsGAQUFBzABhhpodHRwOi8vbG9jYWxob3N0OjUyODAvb2NzcDAL
|
aWNhdGUwHQYDVR0OBBYEFJgip1fThIyZu9J+YNz3XKDkOcMKMB8GA1UdIwQYMBaA
|
||||||
BgNVHQ8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwkwggLIBgNVHREEggK/MIIC
|
FND2ZsvHIjITekPKs0ywLfoNEen5MDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9s
|
||||||
u6A4BggrBgEFBQcIBaAsDCp0ZXN0X3NpbmdsZSEjJCVeKigpYH4rLTtfPVtde318
|
b2NhbGhvc3Q6NTI4MC9kYXRhL2NybC5kZXIwNgYIKwYBBQUHAQEEKjAoMCYGCCsG
|
||||||
XEBsb2NhbGhvc3SgPwYIKwYBBQUHCAWgMwwxdGVzdF9zaW5nbGUhIyQlXiooKWB+
|
AQUFBzABhhpodHRwOi8vbG9jYWxob3N0OjUyODAvb2NzcDALBgNVHQ8EBAMCBeAw
|
||||||
Ky07Xz1bXXt9fFxAbW5lc2lhLmxvY2FsaG9zdKA+BggrBgEFBQcIBaAyDDB0ZXN0
|
JwYDVR0lBCAwHgYIKwYBBQUHAwkGCCsGAQUFBwMBBggrBgEFBQcDAjBfBgNVHREE
|
||||||
X3NpbmdsZSEjJCVeKigpYH4rLTtfPVtde318XEBteXNxbC5sb2NhbGhvc3SgPgYI
|
WDBWoBcGCCsGAQUFBwgFoAsMCWxvY2FsaG9zdKAbBggrBgEFBQcIBaAPDA1zMnMu
|
||||||
KwYBBQUHCAWgMgwwdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcGdz
|
bG9jYWxob3N0oB4GCCsGAQUFBwgFoBIMEG1uZXNpYS5sb2NhbGhvc3QwDQYJKoZI
|
||||||
cWwubG9jYWxob3N0oD8GCCsGAQUFBwgFoDMMMXRlc3Rfc2luZ2xlISMkJV4qKClg
|
hvcNAQEFBQADggEBAEwHeECqeEJIz0VFA0OZ0w9+3rfZPX9K59rbJNNnKVATPhk5
|
||||||
fistO189W117fXxcQHNxbGl0ZS5sb2NhbGhvc3SgQAYIKwYBBQUHCAWgNAwydGVz
|
g5NFpXy1mFTV/3MWjDS1QRbgoXzOYR64S87oez4l3jyDz3YxklyjbbiN3QKaUq5h
|
||||||
dF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAZXh0YXV0aC5sb2NhbGhvc3Sg
|
284Ze6CiRqxIi6V2bhjjp3voMSP8BQ72bX9uAWjqQl7Z16wYuCzV4QzVZRD5p0c1
|
||||||
PQYIKwYBBQUHCAWgMQwvdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxA
|
y45WZ6J+sU1GTwEGh0vXZBlDMeTb+53smjEoCxET1ecJmStAvJi+UHiLn63Z3Yzz
|
||||||
bGRhcC5sb2NhbGhvc3SgPQYIKwYBBQUHCAWgMQwvdGVzdF9zaW5nbGUhIyQlXioo
|
CTfdAZ/mj+ytaNLVsgrULXrmZAeo064HVqeyLWL8ZBoM0zLs6u14OQOeDCCB62cj
|
||||||
KWB+Ky07Xz1bXXt9fFxAcDFkYi5sb2NhbGhvc3SgPQYIKwYBBQUHCAWgMQwvdGVz
|
UXb9npKmIdfsWvdii6emCVQqKBQmHnlUMCh56tE=
|
||||||
dF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcmlhay5sb2NhbGhvc3SgPgYI
|
|
||||||
KwYBBQUHCAWgMgwwdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcmVk
|
|
||||||
aXMubG9jYWxob3N0oD4GCCsGAQUFBwgFoDIMMHRlc3Rfc2luZ2xlISMkJV4qKClg
|
|
||||||
fistO189W117fXxcQG1zc3FsLmxvY2FsaG9zdDANBgkqhkiG9w0BAQUFAAOCAQEA
|
|
||||||
et4jpmpwlE+2bw+/iqCt7sfU/5nPmQ8YtgMB+32wf7DINNJgkwOdkYJpzhlMXKrh
|
|
||||||
/bn8+Ybmq6MbK0r2R91Uu858xQf8VKExQm44qaGSyL5Ug3jsAWb3GLZSaWQo37e9
|
|
||||||
QdDeP8XijCEyr3rum19tRIdiImsRAxJqwfaE4pUSgfCEQMkvb+6//8HSf9RRPToD
|
|
||||||
o6eAg8QerEtTfxerEdW/0K1ozOrzSrQembWOu+JjvANRl+p59j+1YOWHzS/yQeZl
|
|
||||||
K3sjFoCvXPvocRnUznvT+TSdy3ORJSjwfEcP5Crim70amZZ6NeMAxfby9wwmmX0x
|
|
||||||
zkwPCSUXliXke6T88Olj7Q==
|
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
MIICXAIBAAKBgQC+GTA1D1+yiXgLqUhJXkSj3hj5FiqlBAfJT/8OSXYifY4M4HYv
|
MIIEpAIBAAKCAQEAselBnOh089g/VN7gH1m43Vo67kSqh8QRnXZxfjpzt3oPDl5n
|
||||||
VQrqER2Fs7jdCaeoGWDvwfK/UOV0b1ROnf+T/2bXFs8EOeqjOz4xG2oexNKVrYj9
|
d04eNey4ezoSBo7o1hKhj/m5KLxmy1kN+xssyutgzto1FZu8GC2jDyLvByNLh0Z3
|
||||||
ICYAgmSh6Hf2cZJM/YCAISje93Xl2J2w/N7oFC1ZXasPoBIZv3Fgg7hTtQIDAQAB
|
XLmzdzBzBjosCtllJtzHlVL08SPuuOId5hToiiT8h3ElgNI4L6w+eLzhZIk5Rj1W
|
||||||
AoGALddtJJ58eVVlOYqs/+RXsRyR8R9DUV/TcNx1qUBV2KNmafyHA4sCgsd10xQv
|
ojGa+pnaTEgoOaZPcNrkOj81o1tgnbLXN7HY3hJKnRp78DmPySq82cRhvfNrePCs
|
||||||
9D2rzIGyOp8OpswfSSC/t+WqB9+ezSruzMuX6IURdHZbX6aWWX6maICtPKEEkCmI
|
6BJr3y7yYJk0nG+EOaj5BK95YSJondZ8fOZuCigJPMogEaSw0SGsSUiQrPsd+3vZ
|
||||||
gaLxE/ojuOXnTEBTkVuVWtuFL9PsK/WGi/FIDzJbwqTWJ4ECQQDy9DrBAQM96B6u
|
Q+3ctOimnhW7cF3fAM79g+zDdv9N9E3D+inhyQIDAQABAoIBAQCWIyxVx+36YgGA
|
||||||
G4XpFzBsfgJZoS+NaMdCwK+/jgcEpI6oxobK8tuGB6drp5jNSuQ905W9n8XjA6Xq
|
E927VzIkyqJ0tMncbOAYq/228oj4yy6th4l1Kx1fkHdWtnjDxBJFpc9l+u4ArI1r
|
||||||
x8/GH9I5AkEAyE5g05HhMlxBWCq+P70pBDIamdHJcPQVL8+6NXkT+mTqqZxxkUy4
|
Cao8wIAadmxp48dshtJC7TBv86EXuvdgH11XiPcknGRVWv4T4cX099gN8cX3QcWR
|
||||||
nMfTh5zE6WfmqYNtrmNBDxXUyaoRSBydXQJACnFnCR7DBekxUGiMc/10LmWoMjQU
|
jHCC3B4phnD9s8RcZAs6X/cQWQU0mxiHodYJefSXDyRIx9wimXmmW83ZqcsFftXS
|
||||||
eC6Vyg/APiqbsJ5mJ2kJKDYSK4uurZjxn3lloCa1HAZ/GgfxHMtj6e86OQJAetq3
|
MI0+jflmRTf07M4gALVL0LlaBkg2FMoNiaKYPTbubcrEMUgTDsoDsjX3Fi43qLdF
|
||||||
wIwE12KGIZF1xpo6gfxJHHbzWngaVozN5OYyPq2O0CDH9xpbUK2vK8oXbCDx9J5L
|
QTq+lF7HrHQ1EQlngCJupka9JxwZc3Fae6XYlDQvSDPcRxzWJoOuVBPtheGeoU3c
|
||||||
s13lFV+Kd3X7y4LhcQJBAKSFg7ht33l8Sa0TdUkY6Tl1NBMCCLf+np+HYrAbQZux
|
PAry9KihAoGBAN8HCb0k4bMN06WZjSzClKhb6eFw4GMbVpDAOwPDl2N+9+pwrGxE
|
||||||
2NtR6nj2YqeOpEe1ibWZm8tj3dzlTm1FCOIpa+pm114=
|
ztekrM+VdXVScIj23g6wKd6fPqK6EYuEEu3Hre82e9ApqjJ34p1UcOs9Vs4N3VDy
|
||||||
|
HJnWhEytsc9c03O5nhsK1YAXoGHEPmCYGsg2UA171LDcarnO1WDmpKkNAoGBAMw2
|
||||||
|
sTCC/LBwgsuPZL5fR10wQ1sr1fIheSL+VK10jSRDwNXT2Y4wdCpQXQ6XNi+n98n5
|
||||||
|
VvKaE6PxFqjnKCrUUty8X5+fzVcTKpBYVICceEzpVY9FrKbeY1shMnOBRTCkaQwz
|
||||||
|
8CoEbbQz6SH5s4qW7M8iJdUJ0RulaFDfpmangTStAoGBALMkMxVjZ4rsI0GT2grG
|
||||||
|
7KNi2LTFducEUX8JeR2n4JUBql78S/LXPhGGa2x9z5ACPPQ23tyLccYowSXyMR+Q
|
||||||
|
YafuyO4pJEBrBxNsqnDXH7BEX9I43rkjEAgdf70bk4RNOmdtA+sSw7UUxTVibPwn
|
||||||
|
kPOadKiv+4JoOa2vzkL8X+yNAoGAbU85OUZkC+2tlViEDILjqDYVV8/3DUxtkxWg
|
||||||
|
LdidVDQQHGTxpvK4u42Ywh6empPGRw54RBPFP5PlFTPmhEZytEUAymi3eUyBFBKz
|
||||||
|
6MPYgRLFAZPB/vA7LqRuZPVlG8xljmqeu17zeenveIg4Wo6+44Dbz1UZ4TqAxAlz
|
||||||
|
AK/YsWECgYAPuZnIo9fWJtUAIe5IA2LIqcN0rj3PsZ/tL6eaMXqKZgCYwTvVUGbT
|
||||||
|
XD4O352t+yLM8v2hJGHrIPuHooN2dCadYuzoBvVFsRTZjGpBlAZ+EJ5WfDYFL0qf
|
||||||
|
68O2KZNXaSS8ZARlp9g3C8AFiakm/uWhtSfwx09uSBHJgld1V3GAoA==
|
||||||
-----END RSA PRIVATE KEY-----
|
-----END RSA PRIVATE KEY-----
|
||||||
|
@ -409,6 +409,7 @@ acl:
|
|||||||
user_regexp: ""
|
user_regexp: ""
|
||||||
define_macro:
|
define_macro:
|
||||||
CERTFILE: "cert.pem"
|
CERTFILE: "cert.pem"
|
||||||
|
CAFILE: "ca.pem"
|
||||||
language: "en"
|
language: "en"
|
||||||
listen:
|
listen:
|
||||||
-
|
-
|
||||||
@ -450,6 +451,10 @@ Welcome to this XMPP server."
|
|||||||
mod_time: []
|
mod_time: []
|
||||||
mod_version: []
|
mod_version: []
|
||||||
registration_timeout: infinity
|
registration_timeout: infinity
|
||||||
|
route_subdomains: s2s
|
||||||
|
domain_certfile: CERTFILE
|
||||||
|
s2s_use_starttls: false
|
||||||
|
s2s_cafile: CAFILE
|
||||||
shaper:
|
shaper:
|
||||||
fast: 50000
|
fast: 50000
|
||||||
normal: 1000
|
normal: 1000
|
||||||
|
@ -7,7 +7,10 @@ def read():
|
|||||||
cmd = pkt[0]
|
cmd = pkt[0]
|
||||||
args_num = len(pkt) - 1
|
args_num = len(pkt) - 1
|
||||||
if cmd == 'auth' and args_num >= 3:
|
if cmd == 'auth' and args_num >= 3:
|
||||||
write(True)
|
if pkt[1] == "wrong":
|
||||||
|
write(False)
|
||||||
|
else:
|
||||||
|
write(True)
|
||||||
elif cmd == 'isuser' and args_num == 2:
|
elif cmd == 'isuser' and args_num == 2:
|
||||||
write(True)
|
write(True)
|
||||||
elif cmd == 'setpass' and args_num >= 3:
|
elif cmd == 'setpass' and args_num >= 3:
|
||||||
|
18
test/ejabberd_SUITE_data/gencerts.sh
Executable file
18
test/ejabberd_SUITE_data/gencerts.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Update openssl.cnf if needed (in particular section [alt_names])
|
||||||
|
|
||||||
|
rm -rf ssl
|
||||||
|
mkdir -p ssl/newcerts
|
||||||
|
touch ssl/index.txt
|
||||||
|
echo 01 > ssl/serial
|
||||||
|
echo 1000 > ssl/crlnumber
|
||||||
|
openssl genrsa -out ssl/client.key
|
||||||
|
openssl req -new -key ssl/client.key -out ssl/client.csr -config openssl.cnf -batch -subj /C=AU/ST=Some-State/O=Internet\ Widgits\ Pty\ Ltd/CN=active
|
||||||
|
openssl ca -keyfile ca.key -cert ca.pem -in ssl/client.csr -out ssl/client.crt -config openssl.cnf -days 10000 -batch -notext
|
||||||
|
openssl req -new -key ssl/client.key -out ssl/self-signed-client.csr -batch -subj /C=AU/ST=Some-State/O=Internet\ Widgits\ Pty\ Ltd/CN=active
|
||||||
|
openssl x509 -req -in ssl/self-signed-client.csr -signkey ssl/client.key -out ssl/self-signed-client.crt -days 10000
|
||||||
|
cat ssl/client.crt > cert.pem
|
||||||
|
cat ssl/self-signed-client.crt > self-signed-cert.pem
|
||||||
|
cat ssl/client.key >> cert.pem
|
||||||
|
cat ssl/client.key >> self-signed-cert.pem
|
||||||
|
rm -rf ssl
|
323
test/ejabberd_SUITE_data/openssl.cnf
Normal file
323
test/ejabberd_SUITE_data/openssl.cnf
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
#
|
||||||
|
# OpenSSL example configuration file.
|
||||||
|
# This is mostly being used for generation of certificate requests.
|
||||||
|
#
|
||||||
|
|
||||||
|
# This definition stops the following lines choking if HOME isn't
|
||||||
|
# defined.
|
||||||
|
HOME = .
|
||||||
|
RANDFILE = $ENV::HOME/.rnd
|
||||||
|
|
||||||
|
# Extra OBJECT IDENTIFIER info:
|
||||||
|
#oid_file = $ENV::HOME/.oid
|
||||||
|
oid_section = new_oids
|
||||||
|
|
||||||
|
# To use this configuration file with the "-extfile" option of the
|
||||||
|
# "openssl x509" utility, name here the section containing the
|
||||||
|
# X.509v3 extensions to use:
|
||||||
|
extensions = v3_req
|
||||||
|
# (Alternatively, use a configuration file that has only
|
||||||
|
# X.509v3 extensions in its main [= default] section.)
|
||||||
|
|
||||||
|
[ new_oids ]
|
||||||
|
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||||
|
# Add a simple OID like this:
|
||||||
|
# testoid1=1.2.3.4
|
||||||
|
# Or use config file substitution like this:
|
||||||
|
# testoid2=${testoid1}.5.6
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ ca ]
|
||||||
|
default_ca = CA_default # The default ca section
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ CA_default ]
|
||||||
|
|
||||||
|
#dir = ./demoCA # Where everything is kept
|
||||||
|
dir = ssl
|
||||||
|
certs = $dir/certs # Where the issued certs are kept
|
||||||
|
crl_dir = $dir/crl # Where the issued crl are kept
|
||||||
|
database = $dir/index.txt # database index file.
|
||||||
|
#unique_subject = no # Set to 'no' to allow creation of
|
||||||
|
# several ctificates with same subject.
|
||||||
|
new_certs_dir = $dir/newcerts # default place for new certs.
|
||||||
|
|
||||||
|
certificate = $dir/cacert.pem # The CA certificate
|
||||||
|
serial = $dir/serial # The current serial number
|
||||||
|
crlnumber = $dir/crlnumber # the current crl number
|
||||||
|
# must be commented out to leave a V1 CRL
|
||||||
|
crl = $dir/crl.pem # The current CRL
|
||||||
|
private_key = $dir/private/cakey.pem# The private key
|
||||||
|
RANDFILE = $dir/private/.rand # private random number file
|
||||||
|
|
||||||
|
x509_extensions = usr_cert # The extentions to add to the cert
|
||||||
|
|
||||||
|
# Comment out the following two lines for the "traditional"
|
||||||
|
# (and highly broken) format.
|
||||||
|
name_opt = ca_default # Subject Name options
|
||||||
|
cert_opt = ca_default # Certificate field options
|
||||||
|
|
||||||
|
# Extension copying option: use with caution.
|
||||||
|
copy_extensions = copy
|
||||||
|
|
||||||
|
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||||
|
# so this is commented out by default to leave a V1 CRL.
|
||||||
|
# crlnumber must also be commented out to leave a V1 CRL.
|
||||||
|
# crl_extensions = crl_ext
|
||||||
|
|
||||||
|
default_days = 365 # how long to certify for
|
||||||
|
default_crl_days= 30 # how long before next CRL
|
||||||
|
default_md = sha1 # which md to use.
|
||||||
|
preserve = no # keep passed DN ordering
|
||||||
|
|
||||||
|
# A few difference way of specifying how similar the request should look
|
||||||
|
# For type CA, the listed attributes must be the same, and the optional
|
||||||
|
# and supplied fields are just that :-)
|
||||||
|
policy = policy_match
|
||||||
|
|
||||||
|
# For the CA policy
|
||||||
|
[ policy_match ]
|
||||||
|
countryName = match
|
||||||
|
stateOrProvinceName = match
|
||||||
|
organizationName = match
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = optional
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
# For the 'anything' policy
|
||||||
|
# At this point in time, you must list all acceptable 'object'
|
||||||
|
# types.
|
||||||
|
[ policy_anything ]
|
||||||
|
countryName = optional
|
||||||
|
stateOrProvinceName = optional
|
||||||
|
localityName = optional
|
||||||
|
organizationName = optional
|
||||||
|
organizationalUnitName = optional
|
||||||
|
commonName = optional
|
||||||
|
emailAddress = optional
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
[ req ]
|
||||||
|
default_bits = 1024
|
||||||
|
default_keyfile = privkey.pem
|
||||||
|
distinguished_name = req_distinguished_name
|
||||||
|
attributes = req_attributes
|
||||||
|
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
||||||
|
|
||||||
|
# Passwords for private keys if not present they will be prompted for
|
||||||
|
# input_password = secret
|
||||||
|
# output_password = secret
|
||||||
|
|
||||||
|
# This sets a mask for permitted string types. There are several options.
|
||||||
|
# default: PrintableString, T61String, BMPString.
|
||||||
|
# pkix : PrintableString, BMPString.
|
||||||
|
# utf8only: only UTF8Strings.
|
||||||
|
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||||
|
# MASK:XXXX a literal mask value.
|
||||||
|
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||||
|
# so use this option with caution!
|
||||||
|
string_mask = nombstr
|
||||||
|
|
||||||
|
req_extensions = v3_req # The extensions to add to a certificate request
|
||||||
|
|
||||||
|
[ req_distinguished_name ]
|
||||||
|
countryName = Country Name (2 letter code)
|
||||||
|
countryName_default = AU
|
||||||
|
countryName_min = 2
|
||||||
|
countryName_max = 2
|
||||||
|
|
||||||
|
stateOrProvinceName = State or Province Name (full name)
|
||||||
|
stateOrProvinceName_default = Some-State
|
||||||
|
|
||||||
|
localityName = Locality Name (eg, city)
|
||||||
|
|
||||||
|
0.organizationName = Organization Name (eg, company)
|
||||||
|
0.organizationName_default = Internet Widgits Pty Ltd
|
||||||
|
|
||||||
|
# we can do this but it is not needed normally :-)
|
||||||
|
#1.organizationName = Second Organization Name (eg, company)
|
||||||
|
#1.organizationName_default = World Wide Web Pty Ltd
|
||||||
|
|
||||||
|
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||||
|
#organizationalUnitName_default =
|
||||||
|
|
||||||
|
commonName = Common Name (eg, YOUR name)
|
||||||
|
commonName_max = 64
|
||||||
|
|
||||||
|
emailAddress = Email Address
|
||||||
|
emailAddress_max = 64
|
||||||
|
|
||||||
|
# SET-ex3 = SET extension number 3
|
||||||
|
|
||||||
|
[ req_attributes ]
|
||||||
|
challengePassword = A challenge password
|
||||||
|
challengePassword_min = 4
|
||||||
|
challengePassword_max = 20
|
||||||
|
|
||||||
|
unstructuredName = An optional company name
|
||||||
|
|
||||||
|
[ usr_cert ]
|
||||||
|
|
||||||
|
# These extensions are added when 'ca' signs a request.
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
crlDistributionPoints = URI:http://localhost:5280/data/crl.der
|
||||||
|
authorityInfoAccess = OCSP;URI:http://localhost:5280/ocsp
|
||||||
|
|
||||||
|
[ v3_req ]
|
||||||
|
|
||||||
|
# Extensions to add to a certificate request
|
||||||
|
|
||||||
|
basicConstraints = CA:FALSE
|
||||||
|
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
extendedKeyUsage = OCSPSigning,serverAuth,clientAuth
|
||||||
|
subjectAltName = @alt_names
|
||||||
|
|
||||||
|
[alt_names]
|
||||||
|
otherName.1 = 1.3.6.1.5.5.7.8.5;UTF8:"localhost"
|
||||||
|
otherName.2 = 1.3.6.1.5.5.7.8.5;UTF8:"s2s.localhost"
|
||||||
|
otherName.3 = 1.3.6.1.5.5.7.8.5;UTF8:"mnesia.localhost"
|
||||||
|
|
||||||
|
[ v3_ca ]
|
||||||
|
crlDistributionPoints = URI:http://localhost:5280/data/crl.der
|
||||||
|
|
||||||
|
# Extensions for a typical CA
|
||||||
|
|
||||||
|
|
||||||
|
# PKIX recommendation.
|
||||||
|
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
# This is what PKIX recommends but some broken software chokes on critical
|
||||||
|
# extensions.
|
||||||
|
#basicConstraints = critical,CA:true
|
||||||
|
# So we do this instead.
|
||||||
|
basicConstraints = CA:true
|
||||||
|
|
||||||
|
# Key usage: this is typical for a CA certificate. However since it will
|
||||||
|
# prevent it being used as an test self-signed certificate it is best
|
||||||
|
# left out by default.
|
||||||
|
# keyUsage = cRLSign, keyCertSign
|
||||||
|
|
||||||
|
# Some might want this also
|
||||||
|
# nsCertType = sslCA, emailCA
|
||||||
|
|
||||||
|
# Include email address in subject alt name: another PKIX recommendation
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# Copy issuer details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
# DER hex encoding of an extension: beware experts only!
|
||||||
|
# obj=DER:02:03
|
||||||
|
# Where 'obj' is a standard or added object
|
||||||
|
# You can even override a supported extension:
|
||||||
|
# basicConstraints= critical, DER:30:03:01:01:FF
|
||||||
|
|
||||||
|
[ crl_ext ]
|
||||||
|
|
||||||
|
# CRL extensions.
|
||||||
|
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||||
|
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
authorityKeyIdentifier=keyid:always,issuer:always
|
||||||
|
|
||||||
|
[ proxy_cert_ext ]
|
||||||
|
# These extensions should be added when creating a proxy certificate
|
||||||
|
|
||||||
|
# This goes against PKIX guidelines but some CAs do it and some software
|
||||||
|
# requires this to avoid interpreting an end user certificate as a CA.
|
||||||
|
|
||||||
|
basicConstraints=CA:FALSE
|
||||||
|
|
||||||
|
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||||
|
# the certificate can be used for anything *except* object signing.
|
||||||
|
|
||||||
|
# This is OK for an SSL server.
|
||||||
|
# nsCertType = server
|
||||||
|
|
||||||
|
# For an object signing certificate this would be used.
|
||||||
|
# nsCertType = objsign
|
||||||
|
|
||||||
|
# For normal client use this is typical
|
||||||
|
# nsCertType = client, email
|
||||||
|
|
||||||
|
# and for everything including object signing:
|
||||||
|
# nsCertType = client, email, objsign
|
||||||
|
|
||||||
|
# This is typical in keyUsage for a client certificate.
|
||||||
|
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||||
|
|
||||||
|
# This will be displayed in Netscape's comment listbox.
|
||||||
|
nsComment = "OpenSSL Generated Certificate"
|
||||||
|
|
||||||
|
# PKIX recommendations harmless if included in all certificates.
|
||||||
|
subjectKeyIdentifier=hash
|
||||||
|
authorityKeyIdentifier=keyid,issuer:always
|
||||||
|
|
||||||
|
# This stuff is for subjectAltName and issuerAltname.
|
||||||
|
# Import the email address.
|
||||||
|
# subjectAltName=email:copy
|
||||||
|
# An alternative to produce certificates that aren't
|
||||||
|
# deprecated according to PKIX.
|
||||||
|
# subjectAltName=email:move
|
||||||
|
|
||||||
|
# Copy subject details
|
||||||
|
# issuerAltName=issuer:copy
|
||||||
|
|
||||||
|
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||||
|
#nsBaseUrl
|
||||||
|
#nsRevocationUrl
|
||||||
|
#nsRenewalUrl
|
||||||
|
#nsCaPolicyUrl
|
||||||
|
#nsSslServerName
|
||||||
|
|
||||||
|
# This really needs to be in place for it to be a proxy certificate.
|
||||||
|
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
46
test/ejabberd_SUITE_data/self-signed-cert.pem
Normal file
46
test/ejabberd_SUITE_data/self-signed-cert.pem
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDKDCCAhACCQCsLYnJDV1wHDANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJB
|
||||||
|
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
|
||||||
|
cyBQdHkgTHRkMQ8wDQYDVQQDEwZhY3RpdmUwHhcNMTYwOTIzMDcwMzI0WhcNNDQw
|
||||||
|
MjA5MDcwMzI0WjBWMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEh
|
||||||
|
MB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMQ8wDQYDVQQDEwZhY3Rp
|
||||||
|
dmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx6UGc6HTz2D9U3uAf
|
||||||
|
WbjdWjruRKqHxBGddnF+OnO3eg8OXmd3Th417Lh7OhIGjujWEqGP+bkovGbLWQ37
|
||||||
|
GyzK62DO2jUVm7wYLaMPIu8HI0uHRndcubN3MHMGOiwK2WUm3MeVUvTxI+644h3m
|
||||||
|
FOiKJPyHcSWA0jgvrD54vOFkiTlGPVaiMZr6mdpMSCg5pk9w2uQ6PzWjW2Cdstc3
|
||||||
|
sdjeEkqdGnvwOY/JKrzZxGG982t48KzoEmvfLvJgmTScb4Q5qPkEr3lhImid1nx8
|
||||||
|
5m4KKAk8yiARpLDRIaxJSJCs+x37e9lD7dy06KaeFbtwXd8Azv2D7MN2/030TcP6
|
||||||
|
KeHJAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAEAIFwHpNCVUiivAcfkxcUPKp0nn
|
||||||
|
mhGqkMDRrPA7fOCm0ir1Puz4GQ/G4i+tWejzzFoS6kKQl+sUZAUYJdziftJFFoZ7
|
||||||
|
br3q3Xafc2dWa8SHNcHH6lA1OEk8tXlhkNl+EgSLnRGMhIf0iZL2wGjE8Hlig6cu
|
||||||
|
3h+OpbUijXUmq0XdH+ui3wNgXb7+Tosg/Od+lr0fNjkopsk3t1oiVXD4OQBZdUyq
|
||||||
|
V5XValiZjMFDUUBdxBA+l6/Qj3bFmluz+FXI8UwfbinukqADTJzkMeUjEkvmKZWO
|
||||||
|
tb+EU77NIuvg/k7b1yp4lEmATpdUfcGEuhWNtgeh5AqgMxOhAsJ7zUTA80I=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAselBnOh089g/VN7gH1m43Vo67kSqh8QRnXZxfjpzt3oPDl5n
|
||||||
|
d04eNey4ezoSBo7o1hKhj/m5KLxmy1kN+xssyutgzto1FZu8GC2jDyLvByNLh0Z3
|
||||||
|
XLmzdzBzBjosCtllJtzHlVL08SPuuOId5hToiiT8h3ElgNI4L6w+eLzhZIk5Rj1W
|
||||||
|
ojGa+pnaTEgoOaZPcNrkOj81o1tgnbLXN7HY3hJKnRp78DmPySq82cRhvfNrePCs
|
||||||
|
6BJr3y7yYJk0nG+EOaj5BK95YSJondZ8fOZuCigJPMogEaSw0SGsSUiQrPsd+3vZ
|
||||||
|
Q+3ctOimnhW7cF3fAM79g+zDdv9N9E3D+inhyQIDAQABAoIBAQCWIyxVx+36YgGA
|
||||||
|
E927VzIkyqJ0tMncbOAYq/228oj4yy6th4l1Kx1fkHdWtnjDxBJFpc9l+u4ArI1r
|
||||||
|
Cao8wIAadmxp48dshtJC7TBv86EXuvdgH11XiPcknGRVWv4T4cX099gN8cX3QcWR
|
||||||
|
jHCC3B4phnD9s8RcZAs6X/cQWQU0mxiHodYJefSXDyRIx9wimXmmW83ZqcsFftXS
|
||||||
|
MI0+jflmRTf07M4gALVL0LlaBkg2FMoNiaKYPTbubcrEMUgTDsoDsjX3Fi43qLdF
|
||||||
|
QTq+lF7HrHQ1EQlngCJupka9JxwZc3Fae6XYlDQvSDPcRxzWJoOuVBPtheGeoU3c
|
||||||
|
PAry9KihAoGBAN8HCb0k4bMN06WZjSzClKhb6eFw4GMbVpDAOwPDl2N+9+pwrGxE
|
||||||
|
ztekrM+VdXVScIj23g6wKd6fPqK6EYuEEu3Hre82e9ApqjJ34p1UcOs9Vs4N3VDy
|
||||||
|
HJnWhEytsc9c03O5nhsK1YAXoGHEPmCYGsg2UA171LDcarnO1WDmpKkNAoGBAMw2
|
||||||
|
sTCC/LBwgsuPZL5fR10wQ1sr1fIheSL+VK10jSRDwNXT2Y4wdCpQXQ6XNi+n98n5
|
||||||
|
VvKaE6PxFqjnKCrUUty8X5+fzVcTKpBYVICceEzpVY9FrKbeY1shMnOBRTCkaQwz
|
||||||
|
8CoEbbQz6SH5s4qW7M8iJdUJ0RulaFDfpmangTStAoGBALMkMxVjZ4rsI0GT2grG
|
||||||
|
7KNi2LTFducEUX8JeR2n4JUBql78S/LXPhGGa2x9z5ACPPQ23tyLccYowSXyMR+Q
|
||||||
|
YafuyO4pJEBrBxNsqnDXH7BEX9I43rkjEAgdf70bk4RNOmdtA+sSw7UUxTVibPwn
|
||||||
|
kPOadKiv+4JoOa2vzkL8X+yNAoGAbU85OUZkC+2tlViEDILjqDYVV8/3DUxtkxWg
|
||||||
|
LdidVDQQHGTxpvK4u42Ywh6empPGRw54RBPFP5PlFTPmhEZytEUAymi3eUyBFBKz
|
||||||
|
6MPYgRLFAZPB/vA7LqRuZPVlG8xljmqeu17zeenveIg4Wo6+44Dbz1UZ4TqAxAlz
|
||||||
|
AK/YsWECgYAPuZnIo9fWJtUAIe5IA2LIqcN0rj3PsZ/tL6eaMXqKZgCYwTvVUGbT
|
||||||
|
XD4O352t+yLM8v2hJGHrIPuHooN2dCadYuzoBvVFsRTZjGpBlAZ+EJ5WfDYFL0qf
|
||||||
|
68O2KZNXaSS8ZARlp9g3C8AFiakm/uWhtSfwx09uSBHJgld1V3GAoA==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
143
test/suite.erl
143
test/suite.erl
@ -27,13 +27,18 @@ init_config(Config) ->
|
|||||||
SASLPath = filename:join([PrivDir, "sasl.log"]),
|
SASLPath = filename:join([PrivDir, "sasl.log"]),
|
||||||
MnesiaDir = filename:join([PrivDir, "mnesia"]),
|
MnesiaDir = filename:join([PrivDir, "mnesia"]),
|
||||||
CertFile = filename:join([DataDir, "cert.pem"]),
|
CertFile = filename:join([DataDir, "cert.pem"]),
|
||||||
|
SelfSignedCertFile = filename:join([DataDir, "self-signed-cert.pem"]),
|
||||||
|
CAFile = filename:join([DataDir, "ca.pem"]),
|
||||||
{ok, CWD} = file:get_cwd(),
|
{ok, CWD} = file:get_cwd(),
|
||||||
{ok, _} = file:copy(CertFile, filename:join([CWD, "cert.pem"])),
|
{ok, _} = file:copy(CertFile, filename:join([CWD, "cert.pem"])),
|
||||||
|
{ok, _} = file:copy(SelfSignedCertFile,
|
||||||
|
filename:join([CWD, "self-signed-cert.pem"])),
|
||||||
|
{ok, _} = file:copy(CAFile, filename:join([CWD, "ca.pem"])),
|
||||||
{ok, CfgContentTpl} = file:read_file(ConfigPathTpl),
|
{ok, CfgContentTpl} = file:read_file(ConfigPathTpl),
|
||||||
Password = <<"password!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>,
|
Password = <<"password!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>,
|
||||||
CfgContent = process_config_tpl(CfgContentTpl, [
|
CfgContent = process_config_tpl(CfgContentTpl, [
|
||||||
{c2s_port, 5222},
|
{c2s_port, 5222},
|
||||||
{loglevel, 5},
|
{loglevel, 4},
|
||||||
{s2s_port, 5269},
|
{s2s_port, 5269},
|
||||||
{component_port, 5270},
|
{component_port, 5270},
|
||||||
{web_port, 5280},
|
{web_port, 5280},
|
||||||
@ -62,6 +67,7 @@ init_config(Config) ->
|
|||||||
[{server_port, ct:get_config(c2s_port, 5222)},
|
[{server_port, ct:get_config(c2s_port, 5222)},
|
||||||
{server_host, "localhost"},
|
{server_host, "localhost"},
|
||||||
{component_port, ct:get_config(component_port, 5270)},
|
{component_port, ct:get_config(component_port, 5270)},
|
||||||
|
{s2s_port, ct:get_config(s2s_port, 5269)},
|
||||||
{server, ?COMMON_VHOST},
|
{server, ?COMMON_VHOST},
|
||||||
{user, <<"test_single!#$%^*()`~+-;_=[]{}|\\">>},
|
{user, <<"test_single!#$%^*()`~+-;_=[]{}|\\">>},
|
||||||
{master_nick, <<"master_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
{master_nick, <<"master_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||||
@ -71,11 +77,14 @@ init_config(Config) ->
|
|||||||
{type, client},
|
{type, client},
|
||||||
{xmlns, ?NS_CLIENT},
|
{xmlns, ?NS_CLIENT},
|
||||||
{ns_stream, ?NS_STREAM},
|
{ns_stream, ?NS_STREAM},
|
||||||
{stream_version, <<"1.0">>},
|
{stream_version, {1, 0}},
|
||||||
{stream_id, <<"">>},
|
{stream_id, <<"">>},
|
||||||
|
{stream_from, <<"">>},
|
||||||
|
{db_xmlns, <<"">>},
|
||||||
{mechs, []},
|
{mechs, []},
|
||||||
{lang, <<"en">>},
|
{lang, <<"en">>},
|
||||||
{base_dir, BaseDir},
|
{base_dir, BaseDir},
|
||||||
|
{socket, undefined},
|
||||||
{resource, <<"resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
{resource, <<"resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||||
{master_resource, <<"master_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
{master_resource, <<"master_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||||
{slave_resource, <<"slave_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
{slave_resource, <<"slave_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
|
||||||
@ -130,42 +139,50 @@ process_config_tpl(Content, [{Name, DefaultValue} | Rest]) ->
|
|||||||
process_config_tpl(NewContent, Rest).
|
process_config_tpl(NewContent, Rest).
|
||||||
|
|
||||||
stream_header(Config) ->
|
stream_header(Config) ->
|
||||||
NSStream = ?config(ns_stream, 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
|
To = case ?config(server, Config) of
|
||||||
<<"">> -> <<"">>;
|
<<"">> -> undefined;
|
||||||
Server -> <<"to='", Server/binary, "'">>
|
Server -> jid:make(Server)
|
||||||
end,
|
end,
|
||||||
Version = case ?config(stream_version, Config) of
|
From = case ?config(stream_from, Config) of
|
||||||
<<"">> -> <<"">>;
|
<<"">> -> undefined;
|
||||||
V -> <<"version='", V/binary, "'">>
|
Frm -> jid:make(Frm)
|
||||||
end,
|
end,
|
||||||
io_lib:format("<?xml version='1.0'?><stream:stream "
|
#stream_start{to = To,
|
||||||
"xmlns:stream='~s' xmlns='~s' ~s ~s ~s>",
|
from = From,
|
||||||
[NSStream, XMLNS, To, Version, Lang]).
|
lang = ?config(lang, Config),
|
||||||
|
version = ?config(stream_version, Config),
|
||||||
|
xmlns = ?config(xmlns, Config),
|
||||||
|
db_xmlns = ?config(db_xmlns, Config),
|
||||||
|
stream_xmlns = ?config(ns_stream, Config)}.
|
||||||
|
|
||||||
connect(Config) ->
|
connect(Config) ->
|
||||||
NewConfig = init_stream(Config),
|
NewConfig = init_stream(Config),
|
||||||
case ?config(type, NewConfig) of
|
case ?config(type, NewConfig) of
|
||||||
client -> process_stream_features(NewConfig);
|
client -> process_stream_features(NewConfig);
|
||||||
|
server -> process_stream_features(NewConfig);
|
||||||
component -> NewConfig
|
component -> NewConfig
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
tcp_connect(Config) ->
|
||||||
|
case ?config(socket, Config) of
|
||||||
|
undefined ->
|
||||||
|
{ok, Sock} = ejabberd_socket:connect(
|
||||||
|
?config(server_host, Config),
|
||||||
|
?config(server_port, Config),
|
||||||
|
[binary, {packet, 0}, {active, false}]),
|
||||||
|
set_opt(socket, Sock, Config);
|
||||||
|
_ ->
|
||||||
|
Config
|
||||||
|
end.
|
||||||
|
|
||||||
init_stream(Config) ->
|
init_stream(Config) ->
|
||||||
Version = ?config(stream_version, Config),
|
Version = ?config(stream_version, Config),
|
||||||
{ok, Sock} = ejabberd_socket:connect(
|
NewConfig = tcp_connect(Config),
|
||||||
?config(server_host, Config),
|
send(NewConfig, stream_header(NewConfig)),
|
||||||
?config(server_port, Config),
|
|
||||||
[binary, {packet, 0}, {active, false}]),
|
|
||||||
NewConfig = set_opt(socket, Sock, Config),
|
|
||||||
ok = send_text(NewConfig, stream_header(NewConfig)),
|
|
||||||
XMLNS = case ?config(type, Config) of
|
XMLNS = case ?config(type, Config) of
|
||||||
client -> ?NS_CLIENT;
|
client -> ?NS_CLIENT;
|
||||||
component -> ?NS_COMPONENT
|
component -> ?NS_COMPONENT;
|
||||||
|
server -> ?NS_SERVER
|
||||||
end,
|
end,
|
||||||
#stream_start{id = ID, xmlns = XMLNS, version = Version} = recv(),
|
#stream_start{id = ID, xmlns = XMLNS, version = Version} = recv(),
|
||||||
set_opt(stream_id, ID, NewConfig).
|
set_opt(stream_id, ID, NewConfig).
|
||||||
@ -206,13 +223,24 @@ close_socket(Config) ->
|
|||||||
Config.
|
Config.
|
||||||
|
|
||||||
starttls(Config) ->
|
starttls(Config) ->
|
||||||
|
starttls(Config, false).
|
||||||
|
|
||||||
|
starttls(Config, ShouldFail) ->
|
||||||
send(Config, #starttls{}),
|
send(Config, #starttls{}),
|
||||||
#starttls_proceed{} = recv(),
|
case recv() of
|
||||||
TLSSocket = ejabberd_socket:starttls(
|
#starttls_proceed{} when ShouldFail ->
|
||||||
?config(socket, Config),
|
ct:fail(starttls_should_have_failed);
|
||||||
[{certfile, ?config(certfile, Config)},
|
#starttls_failure{} when ShouldFail ->
|
||||||
connect]),
|
Config;
|
||||||
process_stream_features(init_stream(set_opt(socket, TLSSocket, Config))).
|
#starttls_failure{} ->
|
||||||
|
ct:fail(starttls_failed);
|
||||||
|
#starttls_proceed{} ->
|
||||||
|
TLSSocket = ejabberd_socket:starttls(
|
||||||
|
?config(socket, Config),
|
||||||
|
[{certfile, ?config(certfile, Config)},
|
||||||
|
connect]),
|
||||||
|
set_opt(socket, TLSSocket, Config)
|
||||||
|
end.
|
||||||
|
|
||||||
zlib(Config) ->
|
zlib(Config) ->
|
||||||
send(Config, #compress{methods = [<<"zlib">>]}),
|
send(Config, #compress{methods = [<<"zlib">>]}),
|
||||||
@ -228,14 +256,19 @@ auth(Config, ShouldFail) ->
|
|||||||
Mechs = ?config(mechs, Config),
|
Mechs = ?config(mechs, Config),
|
||||||
HaveMD5 = lists:member(<<"DIGEST-MD5">>, Mechs),
|
HaveMD5 = lists:member(<<"DIGEST-MD5">>, Mechs),
|
||||||
HavePLAIN = lists:member(<<"PLAIN">>, Mechs),
|
HavePLAIN = lists:member(<<"PLAIN">>, Mechs),
|
||||||
|
HaveExternal = lists:member(<<"EXTERNAL">>, Mechs),
|
||||||
if HavePLAIN ->
|
if HavePLAIN ->
|
||||||
auth_SASL(<<"PLAIN">>, Config, ShouldFail);
|
auth_SASL(<<"PLAIN">>, Config, ShouldFail);
|
||||||
HaveMD5 ->
|
HaveMD5 ->
|
||||||
auth_SASL(<<"DIGEST-MD5">>, Config, ShouldFail);
|
auth_SASL(<<"DIGEST-MD5">>, Config, ShouldFail);
|
||||||
|
HaveExternal andalso Type == server ->
|
||||||
|
auth_SASL(<<"EXTERNAL">>, Config, ShouldFail);
|
||||||
Type == client ->
|
Type == client ->
|
||||||
auth_legacy(Config, false, ShouldFail);
|
auth_legacy(Config, false, ShouldFail);
|
||||||
Type == component ->
|
Type == component ->
|
||||||
auth_component(Config, ShouldFail)
|
auth_component(Config, ShouldFail);
|
||||||
|
true ->
|
||||||
|
ct:fail(no_known_sasl_mechanism_available)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
bind(Config) ->
|
bind(Config) ->
|
||||||
@ -341,10 +374,19 @@ wait_auth_SASL_result(Config, ShouldFail) ->
|
|||||||
ct:fail(sasl_auth_should_have_failed);
|
ct:fail(sasl_auth_should_have_failed);
|
||||||
#sasl_success{} ->
|
#sasl_success{} ->
|
||||||
ejabberd_socket:reset_stream(?config(socket, Config)),
|
ejabberd_socket:reset_stream(?config(socket, Config)),
|
||||||
send_text(Config, stream_header(Config)),
|
send(Config, stream_header(Config)),
|
||||||
#stream_start{xmlns = ?NS_CLIENT, version = <<"1.0">>} = recv(),
|
Type = ?config(type, Config),
|
||||||
|
NS = if Type == client -> ?NS_CLIENT;
|
||||||
|
Type == server -> ?NS_SERVER
|
||||||
|
end,
|
||||||
|
#stream_start{xmlns = NS, version = {1,0}} = recv(),
|
||||||
#stream_features{sub_els = Fs} = recv(),
|
#stream_features{sub_els = Fs} = recv(),
|
||||||
#xmpp_session{optional = true} = lists:keyfind(xmpp_session, 1, Fs),
|
if Type == client ->
|
||||||
|
#xmpp_session{optional = true} =
|
||||||
|
lists:keyfind(xmpp_session, 1, Fs);
|
||||||
|
true ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun(#feature_sm{}, ConfigAcc) ->
|
fun(#feature_sm{}, ConfigAcc) ->
|
||||||
set_opt(sm, true, ConfigAcc);
|
set_opt(sm, true, ConfigAcc);
|
||||||
@ -427,7 +469,11 @@ send(State, Pkt) ->
|
|||||||
end,
|
end,
|
||||||
El = xmpp_codec:encode(NewPkt),
|
El = xmpp_codec:encode(NewPkt),
|
||||||
ct:pal("sent: ~p <-~n~s", [El, xmpp_codec:pp(NewPkt)]),
|
ct:pal("sent: ~p <-~n~s", [El, xmpp_codec:pp(NewPkt)]),
|
||||||
ok = send_text(State, fxml:element_to_binary(El)),
|
Data = case NewPkt of
|
||||||
|
#stream_start{} -> fxml:element_to_header(El);
|
||||||
|
_ -> fxml:element_to_binary(El)
|
||||||
|
end,
|
||||||
|
ok = send_text(State, Data),
|
||||||
NewID.
|
NewID.
|
||||||
|
|
||||||
send_recv(State, IQ) ->
|
send_recv(State, IQ) ->
|
||||||
@ -437,6 +483,9 @@ send_recv(State, IQ) ->
|
|||||||
sasl_new(<<"PLAIN">>, User, Server, Password) ->
|
sasl_new(<<"PLAIN">>, User, Server, Password) ->
|
||||||
{<<User/binary, $@, Server/binary, 0, User/binary, 0, Password/binary>>,
|
{<<User/binary, $@, Server/binary, 0, User/binary, 0, Password/binary>>,
|
||||||
fun (_) -> {error, <<"Invalid SASL challenge">>} end};
|
fun (_) -> {error, <<"Invalid SASL challenge">>} end};
|
||||||
|
sasl_new(<<"EXTERNAL">>, _User, _Server, _Password) ->
|
||||||
|
{<<"">>,
|
||||||
|
fun(_) -> ct:fail(sasl_challenge_is_not_expected) end};
|
||||||
sasl_new(<<"DIGEST-MD5">>, User, Server, Password) ->
|
sasl_new(<<"DIGEST-MD5">>, User, Server, Password) ->
|
||||||
{<<"">>,
|
{<<"">>,
|
||||||
fun (ServerIn) ->
|
fun (ServerIn) ->
|
||||||
@ -567,11 +616,21 @@ set_opt(Opt, Val, Config) ->
|
|||||||
|
|
||||||
wait_for_master(Config) ->
|
wait_for_master(Config) ->
|
||||||
put_event(Config, slave_ready),
|
put_event(Config, slave_ready),
|
||||||
master_ready = get_event(Config).
|
case get_event(Config) of
|
||||||
|
master_ready ->
|
||||||
|
ok;
|
||||||
|
Other ->
|
||||||
|
suite:match_failure([Other], [master_ready])
|
||||||
|
end.
|
||||||
|
|
||||||
wait_for_slave(Config) ->
|
wait_for_slave(Config) ->
|
||||||
put_event(Config, master_ready),
|
put_event(Config, master_ready),
|
||||||
slave_ready = get_event(Config).
|
case get_event(Config) of
|
||||||
|
slave_ready ->
|
||||||
|
ok;
|
||||||
|
Other ->
|
||||||
|
suite:match_failure([Other], [slave_ready])
|
||||||
|
end.
|
||||||
|
|
||||||
make_iq_result(#iq{from = From} = IQ) ->
|
make_iq_result(#iq{from = From} = IQ) ->
|
||||||
IQ#iq{type = result, to = From, from = undefined, sub_els = []}.
|
IQ#iq{type = result, to = From, from = undefined, sub_els = []}.
|
||||||
@ -592,6 +651,7 @@ event_relay() ->
|
|||||||
event_relay(Events, Subscribers) ->
|
event_relay(Events, Subscribers) ->
|
||||||
receive
|
receive
|
||||||
{subscribe, From} ->
|
{subscribe, From} ->
|
||||||
|
erlang:monitor(process, From),
|
||||||
From ! {ok, self()},
|
From ! {ok, self()},
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Event) -> From ! {event, Event, self()}
|
fun(Event) -> From ! {event, Event, self()}
|
||||||
@ -605,7 +665,14 @@ event_relay(Events, Subscribers) ->
|
|||||||
(_) ->
|
(_) ->
|
||||||
ok
|
ok
|
||||||
end, Subscribers),
|
end, Subscribers),
|
||||||
event_relay([Event|Events], Subscribers)
|
event_relay([Event|Events], Subscribers);
|
||||||
|
{'DOWN', _MRef, process, Pid, _Info} ->
|
||||||
|
NewSubscribers = lists:delete(Pid, Subscribers),
|
||||||
|
lists:foreach(
|
||||||
|
fun(Subscriber) ->
|
||||||
|
Subscriber ! {event, peer_down, self()}
|
||||||
|
end, NewSubscribers),
|
||||||
|
event_relay(Events, NewSubscribers)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
subscribe_to_events(Config) ->
|
subscribe_to_events(Config) ->
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
-define(LDAP_VHOST, <<"ldap.localhost">>).
|
-define(LDAP_VHOST, <<"ldap.localhost">>).
|
||||||
-define(EXTAUTH_VHOST, <<"extauth.localhost">>).
|
-define(EXTAUTH_VHOST, <<"extauth.localhost">>).
|
||||||
-define(RIAK_VHOST, <<"riak.localhost">>).
|
-define(RIAK_VHOST, <<"riak.localhost">>).
|
||||||
|
-define(S2S_VHOST, <<"s2s.localhost">>).
|
||||||
|
|
||||||
insert(Val, N, Tuple) ->
|
insert(Val, N, Tuple) ->
|
||||||
L = tuple_to_list(Tuple),
|
L = tuple_to_list(Tuple),
|
||||||
|
@ -3215,7 +3215,9 @@
|
|||||||
default = <<"">>},
|
default = <<"">>},
|
||||||
#attr{name = <<"xml:lang">>, label = '$lang',
|
#attr{name = <<"xml:lang">>, label = '$lang',
|
||||||
default = <<"">>},
|
default = <<"">>},
|
||||||
#attr{name = <<"version">>, default = <<"">>},
|
#attr{name = <<"version">>,
|
||||||
|
dec = {dec_version, []},
|
||||||
|
enc = {enc_version, []}},
|
||||||
#attr{name = <<"id">>, default = <<"">>}]}).
|
#attr{name = <<"id">>, default = <<"">>}]}).
|
||||||
|
|
||||||
-xml(bob_data,
|
-xml(bob_data,
|
||||||
@ -3479,6 +3481,14 @@ enc_host_port({Host, Port}) ->
|
|||||||
enc_host_port(Addr) ->
|
enc_host_port(Addr) ->
|
||||||
enc_ip(Addr).
|
enc_ip(Addr).
|
||||||
|
|
||||||
|
-spec dec_version(_) -> {non_neg_integer(), non_neg_integer()}.
|
||||||
|
dec_version(S) ->
|
||||||
|
[Major, Minor] = binary:split(S, <<$.>>),
|
||||||
|
{binary_to_integer(Major), binary_to_integer(Minor)}.
|
||||||
|
|
||||||
|
enc_version({Maj, Min}) ->
|
||||||
|
<<(integer_to_binary(Maj))/binary, $., (integer_to_binary(Min))/binary>>.
|
||||||
|
|
||||||
%% Local Variables:
|
%% Local Variables:
|
||||||
%% mode: erlang
|
%% mode: erlang
|
||||||
%% End:
|
%% End:
|
||||||
|
Loading…
Reference in New Issue
Block a user