aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_c2s.erl
diff options
context:
space:
mode:
authorEvgeny Khramtsov <ekhramtsov@process-one.net>2019-06-14 12:33:26 +0300
committerEvgeny Khramtsov <ekhramtsov@process-one.net>2019-06-14 12:33:26 +0300
commita02cff0e780bb735531594c4ece81e8628f79782 (patch)
tree6fe7d8219d14f58183be1741fcea262c216db447 /src/ejabberd_c2s.erl
parentReturn jid_malformed error when sending presence without nick to conference (diff)
Use new configuration validator
Diffstat (limited to '')
-rw-r--r--src/ejabberd_c2s.erl191
1 files changed, 62 insertions, 129 deletions
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 492e2d893..7caa109bb 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -21,15 +21,13 @@
%%%-------------------------------------------------------------------
-module(ejabberd_c2s).
-behaviour(xmpp_stream_in).
--behaviour(ejabberd_config).
-behaviour(ejabberd_listener).
-
+-dialyzer([{no_fail_call, [stop/1, process_closed/2]},
+ {no_return, process_closed/2}]).
-protocol({rfc, 6121}).
%% ejabberd_listener callbacks
-export([start/3, start_link/3, accept/1, listen_opt_type/1, listen_options/0]).
-%% ejabberd_config callbacks
--export([opt_type/1, transform_listen_option/2]).
%% xmpp_stream_in callbacks
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
@@ -109,8 +107,7 @@ resend_presence(Pid, To) ->
close(Ref) ->
xmpp_stream_in:close(Ref).
--spec close(pid(), atom()) -> ok;
- (state(), atom()) -> state().
+-spec close(pid(), atom()) -> ok.
close(Ref, Reason) ->
xmpp_stream_in:close(Ref, Reason).
@@ -319,37 +316,34 @@ tls_options(#{lserver := LServer, tls_options := DefaultOpts,
TLSOpts1 = case {Encrypted, proplists:get_value(certfile, DefaultOpts)} of
{true, CertFile} when CertFile /= undefined -> DefaultOpts;
{_, _} ->
- case get_certfile(LServer) of
- undefined -> DefaultOpts;
- CertFile -> lists:keystore(certfile, 1, DefaultOpts,
- {certfile, CertFile})
+ case ejabberd_pkix:get_certfile(LServer) of
+ error -> DefaultOpts;
+ {ok, CertFile} ->
+ lists:keystore(certfile, 1, DefaultOpts,
+ {certfile, CertFile})
end
end,
- TLSOpts2 = case ejabberd_config:get_option(
- {c2s_ciphers, LServer}) of
+ TLSOpts2 = case ejabberd_option:c2s_ciphers(LServer) of
undefined -> TLSOpts1;
Ciphers -> lists:keystore(ciphers, 1, TLSOpts1,
{ciphers, Ciphers})
end,
- TLSOpts3 = case ejabberd_config:get_option(
- {c2s_protocol_options, LServer}) of
+ TLSOpts3 = case ejabberd_option:c2s_protocol_options(LServer) of
undefined -> TLSOpts2;
ProtoOpts -> lists:keystore(protocol_options, 1, TLSOpts2,
{protocol_options, ProtoOpts})
end,
- TLSOpts4 = case ejabberd_config:get_option(
- {c2s_dhfile, LServer}) of
+ TLSOpts4 = case ejabberd_option:c2s_dhfile(LServer) of
undefined -> TLSOpts3;
DHFile -> lists:keystore(dhfile, 1, TLSOpts3,
{dhfile, DHFile})
end,
- TLSOpts5 = case ejabberd_config:get_option(
- {c2s_cafile, LServer}) of
+ TLSOpts5 = case ejabberd_option:c2s_cafile(LServer) of
undefined -> TLSOpts4;
CAFile -> lists:keystore(cafile, 1, TLSOpts4,
{cafile, CAFile})
end,
- case ejabberd_config:get_option({c2s_tls_compression, LServer}) of
+ case ejabberd_option:c2s_tls_compression(LServer) of
undefined -> TLSOpts5;
false -> [compression_none | TLSOpts5];
true -> lists:delete(compression_none, TLSOpts5)
@@ -376,7 +370,7 @@ authenticated_stream_features(#{lserver := LServer}) ->
sasl_mechanisms(Mechs, #{lserver := LServer} = State) ->
Type = ejabberd_auth:store_type(LServer),
- Mechs1 = ejabberd_config:get_option({disable_sasl_mechanisms, LServer}, []),
+ Mechs1 = ejabberd_option:disable_sasl_mechanisms(LServer),
%% I re-created it from cyrsasl ets magic, but I think it's wrong
%% TODO: need to check before 18.09 release
lists:filter(
@@ -423,9 +417,8 @@ bind(R, #{user := U, server := S, access := Access, lang := Lang,
{error, xmpp:err_conflict(), State};
{accept_resource, Resource} ->
JID = jid:make(U, S, Resource),
- case acl:access_matches(Access,
- #{usr => jid:split(JID), ip => IP},
- LServer) of
+ case acl:match_rule(LServer, Access,
+ #{usr => jid:split(JID), ip => IP}) of
allow ->
State1 = open_session(State#{resource => Resource,
sid => ejabberd_sm:make_sid()}),
@@ -538,14 +531,14 @@ init([State, Opts]) ->
TLSRequired = proplists:get_bool(starttls_required, Opts),
TLSVerify = proplists:get_bool(tls_verify, Opts),
Zlib = proplists:get_bool(zlib, Opts),
- Timeout = ejabberd_config:negotiation_timeout(),
+ Timeout = ejabberd_option:negotiation_timeout(),
State1 = State#{tls_options => TLSOpts2,
tls_required => TLSRequired,
tls_enabled => TLSEnabled,
tls_verify => TLSVerify,
pres_a => ?SETS:new(),
zlib => Zlib,
- lang => ejabberd_config:get_mylang(),
+ lang => ejabberd_option:language(),
server => ejabberd_config:get_myname(),
lserver => ejabberd_config:get_myname(),
access => Access,
@@ -668,36 +661,39 @@ route_probe_reply(_, _) ->
-spec process_presence_out(state(), presence()) -> state().
process_presence_out(#{lserver := LServer, jid := JID,
- lang := Lang, pres_a := PresA} = State,
+ lang := Lang, pres_a := PresA} = State0,
#presence{from = From, to = To, type = Type} = Pres) ->
- if Type == subscribe; Type == subscribed;
- Type == unsubscribe; Type == unsubscribed ->
- Access = gen_mod:get_module_opt(LServer, mod_roster, access),
- MyBareJID = jid:remove_resource(JID),
- case acl:match_rule(LServer, Access, MyBareJID) of
- deny ->
- AccessErrTxt = <<"Access denied by service policy">>,
- AccessErr = xmpp:err_forbidden(AccessErrTxt, Lang),
- send_error(State, Pres, AccessErr);
- allow ->
- ejabberd_hooks:run(roster_out_subscription, LServer, [Pres])
- end;
- true -> ok
- end,
- case privacy_check_packet(State, Pres, out) of
+ State1 =
+ if Type == subscribe; Type == subscribed;
+ Type == unsubscribe; Type == unsubscribed ->
+ Access = mod_roster_opt:access(LServer),
+ MyBareJID = jid:remove_resource(JID),
+ case acl:match_rule(LServer, Access, MyBareJID) of
+ deny ->
+ AccessErrTxt = <<"Access denied by service policy">>,
+ AccessErr = xmpp:err_forbidden(AccessErrTxt, Lang),
+ send_error(State0, Pres, AccessErr);
+ allow ->
+ ejabberd_hooks:run(roster_out_subscription, LServer, [Pres]),
+ State0
+ end;
+ true ->
+ State0
+ end,
+ case privacy_check_packet(State1, Pres, out) of
deny ->
PrivErrTxt = <<"Your active privacy list has denied "
"the routing of this stanza.">>,
PrivErr = xmpp:err_not_acceptable(PrivErrTxt, Lang),
- send_error(State, Pres, PrivErr);
+ send_error(State1, Pres, PrivErr);
allow when Type == subscribe; Type == subscribed;
Type == unsubscribe; Type == unsubscribed ->
BareFrom = jid:remove_resource(From),
ejabberd_router:route(xmpp:set_from_to(Pres, BareFrom, To)),
- State;
+ State1;
allow when Type == error; Type == probe ->
ejabberd_router:route(Pres),
- State;
+ State1;
allow ->
ejabberd_router:route(Pres),
LTo = jid:tolower(To),
@@ -710,12 +706,12 @@ process_presence_out(#{lserver := LServer, jid := JID,
available -> ?SETS:add_element(LTo, PresA);
unavailable -> ?SETS:del_element(LTo, PresA)
end,
- State#{pres_a => A};
+ State1#{pres_a => A};
true ->
- State
+ State1
end;
true ->
- State
+ State1
end
end.
@@ -724,7 +720,7 @@ process_self_presence(#{lserver := LServer, sid := SID,
user := U, server := S, resource := R} = State,
#presence{type = unavailable} = Pres) ->
Status = xmpp:get_text(Pres#presence.status),
- ejabberd_sm:unset_presence(SID, U, S, R, Status),
+ _ = ejabberd_sm:unset_presence(SID, U, S, R, Status),
{Pres1, State1} = ejabberd_hooks:run_fold(
c2s_self_presence, LServer, {Pres, State}, []),
State2 = broadcast_presence_unavailable(State1, Pres1),
@@ -732,7 +728,7 @@ process_self_presence(#{lserver := LServer, sid := SID,
process_self_presence(#{lserver := LServer} = State,
#presence{type = available} = Pres) ->
PreviousPres = maps:get(pres_last, State, undefined),
- update_priority(State, Pres),
+ _ = update_priority(State, Pres),
{Pres1, State1} = ejabberd_hooks:run_fold(
c2s_self_presence, LServer, {Pres, State}, []),
State2 = State1#{pres_last => Pres1,
@@ -867,8 +863,7 @@ get_subscription(#jid{luser = LUser, lserver = LServer}, JID) ->
resource_conflict_action(U, S, R) ->
OptionRaw = case ejabberd_sm:is_existing_resource(U, S, R) of
true ->
- ejabberd_config:get_option(
- {resource_conflict, S}, acceptnew);
+ ejabberd_option:resource_conflict(S);
false ->
acceptnew
end,
@@ -934,9 +929,8 @@ fix_from_to(Pkt, _State) ->
change_shaper(#{shaper := ShaperName, ip := IP, lserver := LServer,
user := U, server := S, resource := R} = State) ->
JID = jid:make(U, S, R),
- Shaper = acl:access_matches(ShaperName,
- #{usr => jid:split(JID), ip => IP},
- LServer),
+ Shaper = ejabberd_shaper:match(LServer, ShaperName,
+ #{usr => jid:split(JID), ip => IP}),
xmpp_stream_in:change_shaper(State, ejabberd_shaper:new(Shaper)).
-spec format_reason(state(), term()) -> binary().
@@ -951,84 +945,24 @@ format_reason(_, {shutdown, _}) ->
format_reason(_, _) ->
<<"internal server error">>.
--spec get_certfile(binary()) -> file:filename_all() | undefined.
-get_certfile(LServer) ->
- case ejabberd_pkix:get_certfile(LServer) of
- {ok, CertFile} ->
- CertFile;
- error ->
- ejabberd_config:get_option(
- {domain_certfile, LServer},
- ejabberd_config:get_option({c2s_certfile, LServer}))
- end.
-
-transform_listen_option(Opt, Opts) ->
- [Opt|Opts].
-
--spec opt_type(atom()) -> fun((any()) -> any()) | [atom()].
-opt_type(c2s_ciphers) -> fun iolist_to_binary/1;
-opt_type(c2s_dhfile) -> fun misc:try_read_file/1;
-opt_type(c2s_cafile) -> fun misc:try_read_file/1;
-opt_type(c2s_protocol_options) ->
- fun (Options) -> str:join(Options, <<"|">>) end;
-opt_type(c2s_tls_compression) ->
- fun (true) -> true;
- (false) -> false
- end;
-opt_type(resource_conflict) ->
- fun (setresource) -> setresource;
- (closeold) -> closeold;
- (closenew) -> closenew;
- (acceptnew) -> acceptnew
- end;
-opt_type(disable_sasl_mechanisms) ->
- fun (V) when is_list(V) ->
- lists:map(fun (M) -> str:to_upper(M) end, V);
- (V) -> [str:to_upper(V)]
- end;
-opt_type(_) ->
- [c2s_ciphers, c2s_cafile, c2s_dhfile,
- c2s_protocol_options, c2s_tls_compression, resource_conflict,
- disable_sasl_mechanisms].
-
-listen_opt_type(certfile = Opt) ->
- fun(S) ->
- ?WARNING_MSG("Listening option '~s' for ~s is deprecated, use "
- "'certfiles' global option instead", [Opt, ?MODULE]),
- {ok, File} = ejabberd_pkix:add_certfile(S),
- File
- end;
-listen_opt_type(starttls) -> fun(B) when is_boolean(B) -> B end;
-listen_opt_type(starttls_required) -> fun(B) when is_boolean(B) -> B end;
-listen_opt_type(tls_verify) -> fun(B) when is_boolean(B) -> B end;
+listen_opt_type(starttls) ->
+ econf:bool();
+listen_opt_type(starttls_required) ->
+ econf:bool();
+listen_opt_type(tls_verify) ->
+ econf:bool();
listen_opt_type(zlib) ->
- fun(true) ->
- ejabberd:start_app(ezlib),
- true;
- (false) ->
- false
- end;
-listen_opt_type(stream_management) ->
- fun(B) when is_boolean(B) ->
- ?ERROR_MSG("Listening option 'stream_management' is ignored: "
- "use mod_stream_mgmt module", []),
- B
- end;
-listen_opt_type(O) ->
- MgmtOpts = mod_stream_mgmt:mod_options(ejabberd_config:get_myname()),
- case lists:keymember(O, 1, MgmtOpts) of
- true ->
- fun(V) ->
- ?ERROR_MSG("Listening option '~s' is ignored: use '~s' "
- "option from mod_stream_mgmt module", [O, O]),
- (mod_stream_mgmt:mod_opt_type(O))(V)
- end
- end.
+ econf:and_then(
+ econf:bool(),
+ fun(false) -> false;
+ (true) ->
+ ejabberd:start_app(ezlib),
+ true
+ end).
listen_options() ->
[{access, all},
{shaper, none},
- {certfile, undefined},
{ciphers, undefined},
{dhfile, undefined},
{cafile, undefined},
@@ -1040,5 +974,4 @@ listen_options() ->
{tls_verify, false},
{zlib, false},
{max_stanza_size, infinity},
- {max_fsm_queue, 5000}|
- mod_stream_mgmt:mod_options(ejabberd_config:get_myname())].
+ {max_fsm_queue, 5000}].