mirror of
https://github.com/processone/ejabberd
synced 2025-10-03 01:39:35 +02:00
Support older Matrix rooms versions starting from version 4
This commit is contained in:
parent
9d1d57cd82
commit
038491d2ec
4 changed files with 210 additions and 33 deletions
|
@ -21,6 +21,13 @@
|
||||||
-record(room_version,
|
-record(room_version,
|
||||||
{id :: binary(),
|
{id :: binary(),
|
||||||
%% use the same field names as in Synapse
|
%% use the same field names as in Synapse
|
||||||
|
enforce_key_validity :: boolean(),
|
||||||
|
special_case_aliases_auth :: boolean(),
|
||||||
|
strict_canonicaljson :: boolean(),
|
||||||
|
limit_notifications_power_levels :: boolean(),
|
||||||
|
knock_join_rule :: boolean(),
|
||||||
|
restricted_join_rule :: boolean(),
|
||||||
|
restricted_join_rule_fix :: boolean(),
|
||||||
knock_restricted_join_rule :: boolean(),
|
knock_restricted_join_rule :: boolean(),
|
||||||
enforce_int_power_levels :: boolean(),
|
enforce_int_power_levels :: boolean(),
|
||||||
implicit_room_creator :: boolean(),
|
implicit_room_creator :: boolean(),
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
handle_info/2, terminate/2, code_change/3,
|
handle_info/2, terminate/2, code_change/3,
|
||||||
depends/2, mod_opt_type/1, mod_options/1, mod_doc/0]).
|
depends/2, mod_opt_type/1, mod_options/1, mod_doc/0]).
|
||||||
-export([parse_auth/1, encode_canonical_json/1,
|
-export([parse_auth/1, encode_canonical_json/1,
|
||||||
|
is_canonical_json/1,
|
||||||
get_id_domain_exn/1,
|
get_id_domain_exn/1,
|
||||||
base64_decode/1, base64_encode/1,
|
base64_decode/1, base64_encode/1,
|
||||||
prune_event/2, get_event_id/2, content_hash/1,
|
prune_event/2, get_event_id/2, content_hash/1,
|
||||||
|
@ -155,8 +156,8 @@ process([<<"federation">>, <<"v2">>, <<"invite">>, RoomID, EventID],
|
||||||
%% TODO: check type and userid
|
%% TODO: check type and userid
|
||||||
Host = ejabberd_config:get_myname(),
|
Host = ejabberd_config:get_myname(),
|
||||||
PrunedEvent = prune_event(Event, RoomVersion),
|
PrunedEvent = prune_event(Event, RoomVersion),
|
||||||
?DEBUG("invite ~p~n", [{RoomID, EventID, Event, RoomVer, catch mod_matrix_gw_s2s:check_signature(Host, PrunedEvent), get_pruned_event_id(PrunedEvent)}]),
|
%?DEBUG("invite ~p~n", [{RoomID, EventID, Event, RoomVer, catch mod_matrix_gw_s2s:check_signature(Host, PrunedEvent, RoomVersion), get_pruned_event_id(PrunedEvent)}]),
|
||||||
case mod_matrix_gw_s2s:check_signature(Host, PrunedEvent) of
|
case mod_matrix_gw_s2s:check_signature(Host, PrunedEvent, RoomVersion) of
|
||||||
true ->
|
true ->
|
||||||
case get_pruned_event_id(PrunedEvent) of
|
case get_pruned_event_id(PrunedEvent) of
|
||||||
EventID ->
|
EventID ->
|
||||||
|
@ -629,9 +630,15 @@ prune_event(#{<<"type">> := Type, <<"content">> := Content} = Event,
|
||||||
Content2 =
|
Content2 =
|
||||||
case Type of
|
case Type of
|
||||||
<<"m.room.member">> ->
|
<<"m.room.member">> ->
|
||||||
C3 = maps:with([<<"membership">>,
|
C3 =
|
||||||
|
case RoomVersion#room_version.restricted_join_rule_fix of
|
||||||
|
true ->
|
||||||
|
maps:with([<<"membership">>,
|
||||||
<<"join_authorised_via_users_server">>],
|
<<"join_authorised_via_users_server">>],
|
||||||
Content),
|
Content);
|
||||||
|
false ->
|
||||||
|
maps:with([<<"membership">>], Content)
|
||||||
|
end,
|
||||||
case RoomVersion#room_version.updated_redaction_rules of
|
case RoomVersion#room_version.updated_redaction_rules of
|
||||||
false ->
|
false ->
|
||||||
C3;
|
C3;
|
||||||
|
@ -653,7 +660,12 @@ prune_event(#{<<"type">> := Type, <<"content">> := Content} = Event,
|
||||||
Content
|
Content
|
||||||
end;
|
end;
|
||||||
<<"m.room.join_rules">> ->
|
<<"m.room.join_rules">> ->
|
||||||
maps:with([<<"join_rule">>, <<"allow">>], Content);
|
case RoomVersion#room_version.restricted_join_rule of
|
||||||
|
false ->
|
||||||
|
maps:with([<<"join_rule">>], Content);
|
||||||
|
true ->
|
||||||
|
maps:with([<<"join_rule">>, <<"allow">>], Content)
|
||||||
|
end;
|
||||||
<<"m.room.power_levels">> ->
|
<<"m.room.power_levels">> ->
|
||||||
case RoomVersion#room_version.updated_redaction_rules of
|
case RoomVersion#room_version.updated_redaction_rules of
|
||||||
false ->
|
false ->
|
||||||
|
@ -677,6 +689,8 @@ prune_event(#{<<"type">> := Type, <<"content">> := Content} = Event,
|
||||||
true ->
|
true ->
|
||||||
maps:with([<<"redacts">>], Content)
|
maps:with([<<"redacts">>], Content)
|
||||||
end;
|
end;
|
||||||
|
<<"m.room.aliases">> when RoomVersion#room_version.special_case_aliases_auth ->
|
||||||
|
maps:with([<<"aliases">>], Content);
|
||||||
_ -> #{}
|
_ -> #{}
|
||||||
end,
|
end,
|
||||||
Event2#{<<"content">> := Content2}.
|
Event2#{<<"content">> := Content2}.
|
||||||
|
@ -716,6 +730,27 @@ sort_json(List) when is_list(List) ->
|
||||||
sort_json(JSON) ->
|
sort_json(JSON) ->
|
||||||
JSON.
|
JSON.
|
||||||
|
|
||||||
|
is_canonical_json(N) when is_integer(N),
|
||||||
|
-16#1FFFFFFFFFFFFF =< N,
|
||||||
|
N =< 16#1FFFFFFFFFFFFF ->
|
||||||
|
true;
|
||||||
|
is_canonical_json(B) when is_binary(B) ->
|
||||||
|
true;
|
||||||
|
is_canonical_json(B) when is_boolean(B) ->
|
||||||
|
true;
|
||||||
|
is_canonical_json(Map) when is_map(Map) ->
|
||||||
|
maps:fold(
|
||||||
|
fun(_K, V, true) ->
|
||||||
|
is_canonical_json(V);
|
||||||
|
(_K, _V, false) ->
|
||||||
|
false
|
||||||
|
end, true, Map);
|
||||||
|
is_canonical_json(List) when is_list(List) ->
|
||||||
|
lists:all(fun is_canonical_json/1, List);
|
||||||
|
is_canonical_json(_) ->
|
||||||
|
false.
|
||||||
|
|
||||||
|
|
||||||
base64_decode(B) ->
|
base64_decode(B) ->
|
||||||
Fixed =
|
Fixed =
|
||||||
case size(B) rem 4 of
|
case size(B) rem 4 of
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
-define(ROOM_MESSAGE, <<"m.room.message">>).
|
-define(ROOM_MESSAGE, <<"m.room.message">>).
|
||||||
-define(ROOM_HISTORY_VISIBILITY, <<"m.room.history_visibility">>).
|
-define(ROOM_HISTORY_VISIBILITY, <<"m.room.history_visibility">>).
|
||||||
-define(ROOM_TOPIC, <<"m.room.topic">>).
|
-define(ROOM_TOPIC, <<"m.room.topic">>).
|
||||||
|
-define(ROOM_ALIASES, <<"m.room.aliases">>).
|
||||||
|
|
||||||
-define(MAX_DEPTH, 16#7FFFFFFFFFFFFFFF).
|
-define(MAX_DEPTH, 16#7FFFFFFFFFFFFFFF).
|
||||||
-define(MAX_TXN_RETRIES, 5).
|
-define(MAX_TXN_RETRIES, 5).
|
||||||
|
@ -650,9 +651,7 @@ handle_event(cast, {join_direct, MatrixServer, RoomID, Sender, UserID}, State, D
|
||||||
Host, get, MatrixServer,
|
Host, get, MatrixServer,
|
||||||
[<<"_matrix">>, <<"federation">>, <<"v1">>, <<"make_join">>,
|
[<<"_matrix">>, <<"federation">>, <<"v1">>, <<"make_join">>,
|
||||||
RoomID, UserID],
|
RoomID, UserID],
|
||||||
[{<<"ver">>, <<"9">>},
|
[{<<"ver">>, V} || V <- supported_versions()],
|
||||||
{<<"ver">>, <<"10">>},
|
|
||||||
{<<"ver">>, <<"11">>}],
|
|
||||||
none,
|
none,
|
||||||
[{timeout, 5000}],
|
[{timeout, 5000}],
|
||||||
[{sync, true},
|
[{sync, true},
|
||||||
|
@ -770,9 +769,7 @@ handle_event(cast, {join, UserJID, Packet}, _State, Data) ->
|
||||||
Host, get, MatrixServer,
|
Host, get, MatrixServer,
|
||||||
[<<"_matrix">>, <<"federation">>, <<"v1">>, <<"make_join">>,
|
[<<"_matrix">>, <<"federation">>, <<"v1">>, <<"make_join">>,
|
||||||
RoomID, UserID],
|
RoomID, UserID],
|
||||||
[{<<"ver">>, <<"9">>},
|
[{<<"ver">>, V} || V <- supported_versions()],
|
||||||
{<<"ver">>, <<"10">>},
|
|
||||||
{<<"ver">>, <<"11">>}],
|
|
||||||
none,
|
none,
|
||||||
[{timeout, 5000}],
|
[{timeout, 5000}],
|
||||||
[{sync, true},
|
[{sync, true},
|
||||||
|
@ -1280,7 +1277,7 @@ check_event_auth(Event, StateMap, Data) ->
|
||||||
<<"ban">> ->
|
<<"ban">> ->
|
||||||
check_event_auth_ban(
|
check_event_auth_ban(
|
||||||
Event, StateMap, Data);
|
Event, StateMap, Data);
|
||||||
<<"knock">> ->
|
<<"knock">> when (Data#data.room_version)#room_version.knock_join_rule ->
|
||||||
check_event_auth_knock(
|
check_event_auth_knock(
|
||||||
Event, StateMap, Data);
|
Event, StateMap, Data);
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -1289,6 +1286,18 @@ check_event_auth(Event, StateMap, Data) ->
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end;
|
end;
|
||||||
|
?ROOM_ALIASES when (Data#data.room_version)#room_version.special_case_aliases_auth ->
|
||||||
|
case Event#event.state_key of
|
||||||
|
undefined ->
|
||||||
|
false;
|
||||||
|
StateKey ->
|
||||||
|
case mod_matrix_gw:get_id_domain_exn(Event#event.sender) of
|
||||||
|
StateKey ->
|
||||||
|
true;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Sender = Event#event.sender,
|
Sender = Event#event.sender,
|
||||||
case maps:find({?ROOM_MEMBER, Sender}, StateMap) of
|
case maps:find({?ROOM_MEMBER, Sender}, StateMap) of
|
||||||
|
@ -1372,8 +1381,11 @@ check_event_auth_join(Event, StateMap, Data) ->
|
||||||
case {JoinRule, SenderMembership} of
|
case {JoinRule, SenderMembership} of
|
||||||
{<<"public">>, _} -> true;
|
{<<"public">>, _} -> true;
|
||||||
{<<"invite">>, <<"invite">>} -> true;
|
{<<"invite">>, <<"invite">>} -> true;
|
||||||
{<<"knock">>, <<"invite">>} -> true;
|
{<<"knock">>, <<"invite">>}
|
||||||
{<<"restricted">>, <<"invite">>} ->
|
when (Data#data.room_version)#room_version.knock_join_rule ->
|
||||||
|
true;
|
||||||
|
{<<"restricted">>, <<"invite">>}
|
||||||
|
when (Data#data.room_version)#room_version.restricted_join_rule ->
|
||||||
%% TODO
|
%% TODO
|
||||||
true;
|
true;
|
||||||
{<<"knock_restricted">>, <<"invite">>}
|
{<<"knock_restricted">>, <<"invite">>}
|
||||||
|
@ -1442,7 +1454,7 @@ check_event_auth_leave(Event, StateMap, Data) ->
|
||||||
case SenderMembership of
|
case SenderMembership of
|
||||||
<<"invite">> -> true;
|
<<"invite">> -> true;
|
||||||
<<"join">> -> true;
|
<<"join">> -> true;
|
||||||
<<"knock">> -> true;
|
<<"knock">> when (Data#data.room_version)#room_version.knock_join_rule -> true;
|
||||||
_ -> false
|
_ -> false
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -1609,6 +1621,13 @@ check_event_auth_power_levels(Event, StateMap, Data) ->
|
||||||
try
|
try
|
||||||
case Event#event.json of
|
case Event#event.json of
|
||||||
#{<<"content">> := NewPL = #{<<"users">> := Users}} when is_map(Users) ->
|
#{<<"content">> := NewPL = #{<<"users">> := Users}} when is_map(Users) ->
|
||||||
|
CheckKeys =
|
||||||
|
case (Data#data.room_version)#room_version.limit_notifications_power_levels of
|
||||||
|
false ->
|
||||||
|
[<<"events">>, <<"users">>];
|
||||||
|
true ->
|
||||||
|
[<<"events">>, <<"users">>, <<"notifications">>]
|
||||||
|
end,
|
||||||
case (Data#data.room_version)#room_version.enforce_int_power_levels of
|
case (Data#data.room_version)#room_version.enforce_int_power_levels of
|
||||||
true ->
|
true ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -1632,7 +1651,7 @@ check_event_auth_power_levels(Event, StateMap, Data) ->
|
||||||
end
|
end
|
||||||
end, [], NewMap)
|
end, [], NewMap)
|
||||||
end,
|
end,
|
||||||
[<<"events">>, <<"users">>, <<"notifications">>]);
|
CheckKeys);
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
|
@ -1677,7 +1696,7 @@ check_event_auth_power_levels(Event, StateMap, Data) ->
|
||||||
end
|
end
|
||||||
end, [], maps:merge(OldMap, NewMap))
|
end, [], maps:merge(OldMap, NewMap))
|
||||||
end,
|
end,
|
||||||
[<<"events">>, <<"users">>, <<"notifications">>]),
|
CheckKeys),
|
||||||
true;
|
true;
|
||||||
_ ->
|
_ ->
|
||||||
true
|
true
|
||||||
|
@ -1772,7 +1791,7 @@ fill_event(JSON, Data) ->
|
||||||
_ -> []
|
_ -> []
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
compute_event_auth_keys(JSON))),
|
compute_event_auth_keys(JSON, Data#data.room_version))),
|
||||||
{JSON#{<<"auth_events">> => AuthEvents,
|
{JSON#{<<"auth_events">> => AuthEvents,
|
||||||
<<"depth">> => Depth2,
|
<<"depth">> => Depth2,
|
||||||
<<"origin">> => MatrixServer,
|
<<"origin">> => MatrixServer,
|
||||||
|
@ -1923,7 +1942,8 @@ get_latest_events(Pid) ->
|
||||||
check_event_signature(Host, Event) ->
|
check_event_signature(Host, Event) ->
|
||||||
PrunedEvent = mod_matrix_gw:prune_event(Event#event.json,
|
PrunedEvent = mod_matrix_gw:prune_event(Event#event.json,
|
||||||
Event#event.room_version),
|
Event#event.room_version),
|
||||||
mod_matrix_gw_s2s:check_signature(Host, PrunedEvent).
|
mod_matrix_gw_s2s:check_signature(Host, PrunedEvent,
|
||||||
|
Event#event.room_version).
|
||||||
|
|
||||||
find_event(Pid, EventID) ->
|
find_event(Pid, EventID) ->
|
||||||
gen_statem:call(Pid, {find_event, EventID}).
|
gen_statem:call(Pid, {find_event, EventID}).
|
||||||
|
@ -2526,8 +2546,85 @@ find_power_level_event(EventID, Data) ->
|
||||||
end, undefined, Event#event.auth_events).
|
end, undefined, Event#event.auth_events).
|
||||||
|
|
||||||
|
|
||||||
|
binary_to_room_version(<<"4">>) ->
|
||||||
|
#room_version{id = <<"4">>,
|
||||||
|
enforce_key_validity = false,
|
||||||
|
special_case_aliases_auth = true,
|
||||||
|
strict_canonicaljson = false,
|
||||||
|
limit_notifications_power_levels = false,
|
||||||
|
knock_join_rule = false,
|
||||||
|
restricted_join_rule = false,
|
||||||
|
restricted_join_rule_fix = false,
|
||||||
|
knock_restricted_join_rule = false,
|
||||||
|
enforce_int_power_levels = false,
|
||||||
|
implicit_room_creator = false,
|
||||||
|
updated_redaction_rules = false
|
||||||
|
};
|
||||||
|
binary_to_room_version(<<"5">>) ->
|
||||||
|
#room_version{id = <<"5">>,
|
||||||
|
enforce_key_validity = true,
|
||||||
|
special_case_aliases_auth = true,
|
||||||
|
strict_canonicaljson = false,
|
||||||
|
limit_notifications_power_levels = false,
|
||||||
|
knock_join_rule = false,
|
||||||
|
restricted_join_rule = false,
|
||||||
|
restricted_join_rule_fix = false,
|
||||||
|
knock_restricted_join_rule = false,
|
||||||
|
enforce_int_power_levels = false,
|
||||||
|
implicit_room_creator = false,
|
||||||
|
updated_redaction_rules = false
|
||||||
|
};
|
||||||
|
binary_to_room_version(<<"6">>) ->
|
||||||
|
#room_version{id = <<"6">>,
|
||||||
|
enforce_key_validity = true,
|
||||||
|
special_case_aliases_auth = false,
|
||||||
|
strict_canonicaljson = true,
|
||||||
|
limit_notifications_power_levels = true,
|
||||||
|
knock_join_rule = false,
|
||||||
|
restricted_join_rule = false,
|
||||||
|
restricted_join_rule_fix = false,
|
||||||
|
knock_restricted_join_rule = false,
|
||||||
|
enforce_int_power_levels = false,
|
||||||
|
implicit_room_creator = false,
|
||||||
|
updated_redaction_rules = false
|
||||||
|
};
|
||||||
|
binary_to_room_version(<<"7">>) ->
|
||||||
|
#room_version{id = <<"7">>,
|
||||||
|
enforce_key_validity = true,
|
||||||
|
special_case_aliases_auth = false,
|
||||||
|
strict_canonicaljson = true,
|
||||||
|
limit_notifications_power_levels = true,
|
||||||
|
knock_join_rule = true,
|
||||||
|
restricted_join_rule = false,
|
||||||
|
restricted_join_rule_fix = false,
|
||||||
|
knock_restricted_join_rule = false,
|
||||||
|
enforce_int_power_levels = false,
|
||||||
|
implicit_room_creator = false,
|
||||||
|
updated_redaction_rules = false
|
||||||
|
};
|
||||||
|
binary_to_room_version(<<"8">>) ->
|
||||||
|
#room_version{id = <<"8">>,
|
||||||
|
enforce_key_validity = true,
|
||||||
|
special_case_aliases_auth = false,
|
||||||
|
strict_canonicaljson = true,
|
||||||
|
limit_notifications_power_levels = true,
|
||||||
|
knock_join_rule = true,
|
||||||
|
restricted_join_rule = true,
|
||||||
|
restricted_join_rule_fix = false,
|
||||||
|
knock_restricted_join_rule = false,
|
||||||
|
enforce_int_power_levels = false,
|
||||||
|
implicit_room_creator = false,
|
||||||
|
updated_redaction_rules = false
|
||||||
|
};
|
||||||
binary_to_room_version(<<"9">>) ->
|
binary_to_room_version(<<"9">>) ->
|
||||||
#room_version{id = <<"9">>,
|
#room_version{id = <<"9">>,
|
||||||
|
enforce_key_validity = true,
|
||||||
|
special_case_aliases_auth = false,
|
||||||
|
strict_canonicaljson = true,
|
||||||
|
limit_notifications_power_levels = true,
|
||||||
|
knock_join_rule = true,
|
||||||
|
restricted_join_rule = true,
|
||||||
|
restricted_join_rule_fix = true,
|
||||||
knock_restricted_join_rule = false,
|
knock_restricted_join_rule = false,
|
||||||
enforce_int_power_levels = false,
|
enforce_int_power_levels = false,
|
||||||
implicit_room_creator = false,
|
implicit_room_creator = false,
|
||||||
|
@ -2535,6 +2632,13 @@ binary_to_room_version(<<"9">>) ->
|
||||||
};
|
};
|
||||||
binary_to_room_version(<<"10">>) ->
|
binary_to_room_version(<<"10">>) ->
|
||||||
#room_version{id = <<"10">>,
|
#room_version{id = <<"10">>,
|
||||||
|
enforce_key_validity = true,
|
||||||
|
special_case_aliases_auth = false,
|
||||||
|
strict_canonicaljson = true,
|
||||||
|
limit_notifications_power_levels = true,
|
||||||
|
knock_join_rule = true,
|
||||||
|
restricted_join_rule = true,
|
||||||
|
restricted_join_rule_fix = true,
|
||||||
knock_restricted_join_rule = true,
|
knock_restricted_join_rule = true,
|
||||||
enforce_int_power_levels = true,
|
enforce_int_power_levels = true,
|
||||||
implicit_room_creator = false,
|
implicit_room_creator = false,
|
||||||
|
@ -2542,6 +2646,13 @@ binary_to_room_version(<<"10">>) ->
|
||||||
};
|
};
|
||||||
binary_to_room_version(<<"11">>) ->
|
binary_to_room_version(<<"11">>) ->
|
||||||
#room_version{id = <<"11">>,
|
#room_version{id = <<"11">>,
|
||||||
|
enforce_key_validity = true,
|
||||||
|
special_case_aliases_auth = false,
|
||||||
|
strict_canonicaljson = true,
|
||||||
|
limit_notifications_power_levels = true,
|
||||||
|
knock_join_rule = true,
|
||||||
|
restricted_join_rule = true,
|
||||||
|
restricted_join_rule_fix = true,
|
||||||
knock_restricted_join_rule = true,
|
knock_restricted_join_rule = true,
|
||||||
enforce_int_power_levels = true,
|
enforce_int_power_levels = true,
|
||||||
implicit_room_creator = true,
|
implicit_room_creator = true,
|
||||||
|
@ -2550,6 +2661,10 @@ binary_to_room_version(<<"11">>) ->
|
||||||
binary_to_room_version(_) ->
|
binary_to_room_version(_) ->
|
||||||
false.
|
false.
|
||||||
|
|
||||||
|
supported_versions() ->
|
||||||
|
[<<"4">>, <<"5">>, <<"6">>, <<"7">>, <<"8">>, <<"9">>,
|
||||||
|
<<"10">>, <<"11">>].
|
||||||
|
|
||||||
json_to_event(#{<<"type">> := Type,
|
json_to_event(#{<<"type">> := Type,
|
||||||
<<"room_id">> := RoomID,
|
<<"room_id">> := RoomID,
|
||||||
<<"depth">> := Depth,
|
<<"depth">> := Depth,
|
||||||
|
@ -2562,6 +2677,17 @@ json_to_event(#{<<"type">> := Type,
|
||||||
is_list(AuthEvents) ->
|
is_list(AuthEvents) ->
|
||||||
StateKey = maps:get(<<"state_key">>, JSON, undefined),
|
StateKey = maps:get(<<"state_key">>, JSON, undefined),
|
||||||
EventID = mod_matrix_gw:get_event_id(JSON, RoomVersion),
|
EventID = mod_matrix_gw:get_event_id(JSON, RoomVersion),
|
||||||
|
case RoomVersion#room_version.strict_canonicaljson of
|
||||||
|
true ->
|
||||||
|
case mod_matrix_gw:is_canonical_json(JSON) of
|
||||||
|
true ->
|
||||||
|
ok;
|
||||||
|
false ->
|
||||||
|
throw(non_canonical_json)
|
||||||
|
end;
|
||||||
|
false ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
#event{id = EventID,
|
#event{id = EventID,
|
||||||
room_version = RoomVersion,
|
room_version = RoomVersion,
|
||||||
room_id = RoomID,
|
room_id = RoomID,
|
||||||
|
@ -3162,12 +3288,13 @@ new_room_id() ->
|
||||||
MatrixServer = mod_matrix_gw_opt:matrix_domain(Host),
|
MatrixServer = mod_matrix_gw_opt:matrix_domain(Host),
|
||||||
<<$!, S/binary, $:, MatrixServer/binary>>.
|
<<$!, S/binary, $:, MatrixServer/binary>>.
|
||||||
|
|
||||||
compute_event_auth_keys(#{<<"type">> := ?ROOM_CREATE}) ->
|
compute_event_auth_keys(#{<<"type">> := ?ROOM_CREATE}, _RoomVersion) ->
|
||||||
[];
|
[];
|
||||||
compute_event_auth_keys(#{<<"type">> := ?ROOM_MEMBER,
|
compute_event_auth_keys(#{<<"type">> := ?ROOM_MEMBER,
|
||||||
<<"sender">> := Sender,
|
<<"sender">> := Sender,
|
||||||
<<"content">> := #{<<"membership">> := Membership} = Content,
|
<<"content">> := #{<<"membership">> := Membership} = Content,
|
||||||
<<"state_key">> := StateKey}) ->
|
<<"state_key">> := StateKey},
|
||||||
|
RoomVersion) ->
|
||||||
Common = [{?ROOM_CREATE, <<"">>},
|
Common = [{?ROOM_CREATE, <<"">>},
|
||||||
{?ROOM_POWER_LEVELS, <<"">>},
|
{?ROOM_POWER_LEVELS, <<"">>},
|
||||||
{?ROOM_MEMBER, Sender},
|
{?ROOM_MEMBER, Sender},
|
||||||
|
@ -3175,7 +3302,8 @@ compute_event_auth_keys(#{<<"type">> := ?ROOM_MEMBER,
|
||||||
case Membership of
|
case Membership of
|
||||||
<<"join">> ->
|
<<"join">> ->
|
||||||
case Content of
|
case Content of
|
||||||
#{<<"join_authorised_via_users_server">> := AuthUser} ->
|
#{<<"join_authorised_via_users_server">> := AuthUser}
|
||||||
|
when RoomVersion#room_version.restricted_join_rule ->
|
||||||
[{?ROOM_MEMBER, AuthUser}, {?ROOM_JOIN_RULES, <<"">>} | Common];
|
[{?ROOM_MEMBER, AuthUser}, {?ROOM_JOIN_RULES, <<"">>} | Common];
|
||||||
_ ->
|
_ ->
|
||||||
[{?ROOM_JOIN_RULES, <<"">>} | Common]
|
[{?ROOM_JOIN_RULES, <<"">>} | Common]
|
||||||
|
@ -3192,7 +3320,7 @@ compute_event_auth_keys(#{<<"type">> := ?ROOM_MEMBER,
|
||||||
_ ->
|
_ ->
|
||||||
Common
|
Common
|
||||||
end;
|
end;
|
||||||
compute_event_auth_keys(#{<<"type">> := _, <<"sender">> := Sender}) ->
|
compute_event_auth_keys(#{<<"type">> := _, <<"sender">> := Sender}, _RoomVersion) ->
|
||||||
[{?ROOM_CREATE, <<"">>},
|
[{?ROOM_CREATE, <<"">>},
|
||||||
{?ROOM_POWER_LEVELS, <<"">>},
|
{?ROOM_POWER_LEVELS, <<"">>},
|
||||||
{?ROOM_MEMBER, Sender}].
|
{?ROOM_MEMBER, Sender}].
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start_link/2, supervisor/1, create_db/0,
|
-export([start_link/2, supervisor/1, create_db/0,
|
||||||
get_connection/2, check_auth/5, check_signature/2,
|
get_connection/2, check_auth/5, check_signature/3,
|
||||||
get_matrix_host_port/2]).
|
get_matrix_host_port/2]).
|
||||||
|
|
||||||
%% gen_statem callbacks
|
%% gen_statem callbacks
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("ejabberd_http.hrl").
|
-include("ejabberd_http.hrl").
|
||||||
-include_lib("kernel/include/inet.hrl").
|
-include_lib("kernel/include/inet.hrl").
|
||||||
|
-include("mod_matrix_gw.hrl").
|
||||||
|
|
||||||
-record(matrix_s2s,
|
-record(matrix_s2s,
|
||||||
{to :: binary(),
|
{to :: binary(),
|
||||||
|
@ -169,18 +170,21 @@ check_auth(Host, MatrixServer, AuthParams, Content, Request) ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
check_signature(Host, JSON) ->
|
check_signature(Host, JSON, RoomVersion) ->
|
||||||
case JSON of
|
case JSON of
|
||||||
#{<<"sender">> := Sender,
|
#{<<"sender">> := Sender,
|
||||||
<<"signatures">> := Sigs} ->
|
<<"signatures">> := Sigs,
|
||||||
|
<<"origin_server_ts">> := OriginServerTS} ->
|
||||||
MatrixServer = mod_matrix_gw:get_id_domain_exn(Sender),
|
MatrixServer = mod_matrix_gw:get_id_domain_exn(Sender),
|
||||||
case Sigs of
|
case Sigs of
|
||||||
#{MatrixServer := #{} = KeySig} ->
|
#{MatrixServer := #{} = KeySig} ->
|
||||||
case maps:next(maps:iterator(KeySig)) of
|
case maps:next(maps:iterator(KeySig)) of
|
||||||
{KeyID, _Sig, _} ->
|
{KeyID, _Sig, _} ->
|
||||||
case catch get_key(Host, MatrixServer, KeyID) of
|
case catch get_key(Host, MatrixServer, KeyID) of
|
||||||
{ok, VerifyKey, _ValidUntil} ->
|
{ok, VerifyKey, ValidUntil} ->
|
||||||
%% TODO: check ValidUntil
|
if
|
||||||
|
not RoomVersion#room_version.enforce_key_validity or
|
||||||
|
OriginServerTS =< ValidUntil ->
|
||||||
case check_signature(JSON, MatrixServer, KeyID, VerifyKey) of
|
case check_signature(JSON, MatrixServer, KeyID, VerifyKey) of
|
||||||
true ->
|
true ->
|
||||||
true;
|
true;
|
||||||
|
@ -188,6 +192,9 @@ check_signature(Host, JSON) ->
|
||||||
?WARNING_MSG("Failed authentication: ~p", [JSON]),
|
?WARNING_MSG("Failed authentication: ~p", [JSON]),
|
||||||
false
|
false
|
||||||
end;
|
end;
|
||||||
|
true ->
|
||||||
|
false
|
||||||
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
end;
|
end;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue