Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ jobs:
if [[ -z "$BRANCH_NAME" || $BRANCH_NAME =~ ^refs/pull/.* ]]; then
continue
fi
(wget -O - "https://github.com/element-hq/synapse/archive/$BRANCH_NAME.tar.gz" \
(wget -O - "https://github.com/famedly/synapse/archive/$BRANCH_NAME.tar.gz" \
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated
| tar -xz --strip-components=1 -C /src/) \
&& echo "Successfully downloaded and extracted $BRANCH_NAME.tar.gz" \
&& break
Expand Down
42 changes: 36 additions & 6 deletions lib/Protocol/Matrix.pm
Original file line number Diff line number Diff line change
Expand Up @@ -266,18 +266,46 @@ my %ALLOWED_CONTENT_BY_TYPE = (

sub redact_event
{
my ( $event ) = @_;
my ( $event, $room_version ) = @_;
$room_version //= 1;

defined( my $type = $event->{type} ) or
croak "Event requires a 'type'";

delete $event->{redacts};
my $old_content = delete $event->{content};
my $old_unsigned = delete $event->{unsigned};
Comment thread
FrenchGithubUser marked this conversation as resolved.

$ALLOWED_KEYS{$_} or delete $event->{$_} for keys %$event;

my $new_content = $event->{content} = {};

# Room version 11+ uses updated redaction rules:
# - m.room.create: entire content property is preserved
# - m.room.power_levels: 'invite' is also preserved
# - m.room.member: 'third_party_invite.signed' is also preserved
# - m.room.redaction: 'redacts' is also preserved
if( defined $room_version and $room_version =~ /\A[0-9]+\z/ and $room_version >= 11 ) {
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated
if( $type eq 'm.room.create' ) {
%$new_content = %{ $old_content // {} };
$event->{unsigned}{age_ts} = $old_unsigned->{age_ts} if exists $old_unsigned->{age_ts};
return;
}
if( $type eq 'm.room.power_levels' ) {
exists $old_content->{invite} and $new_content->{invite} = $old_content->{invite};
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated
}
if( $type eq 'm.room.member' ) {
my $tpi = $old_content->{third_party_invite};
if( ref $tpi eq 'HASH' && exists $tpi->{signed} ) {
$new_content->{third_party_invite} = { signed => $tpi->{signed} };
}
}
if( $type eq 'm.room.redaction' ) {
# In v11, 'redacts' moved into content; preserve content.redacts
exists $old_content->{redacts} and $new_content->{redacts} = $old_content->{redacts};
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated
}
}

if( my $allowed_content_keys = $ALLOWED_CONTENT_BY_TYPE{$type} ) {
exists $old_content->{$_} and $new_content->{$_} = $old_content->{$_} for
@$allowed_content_keys;
Expand All @@ -288,8 +316,8 @@ sub redact_event

sub redacted_event
{
my ( $event ) = @_;
redact_event( $event = { %$event } );
my ( $event, $room_version ) = @_;
redact_event( $event = { %$event }, $room_version );
return $event;
}

Expand All @@ -309,6 +337,7 @@ sub sign_event_json

my $origin = $args{origin} or croak "Require an 'origin'";
my $key_id = $args{key_id} or croak "Require a 'key_id'";
my $room_version = delete $args{room_version};

# 'hashes' records the original unredacted version
{
Expand All @@ -319,7 +348,7 @@ sub sign_event_json
}

# Signature is of redacted version
sign_json( my $signed = redacted_event( $event ), %args );
sign_json( my $signed = redacted_event( $event, $room_version ), %args );

$event->{signatures} = $signed->{signatures};
}
Expand Down Expand Up @@ -349,9 +378,10 @@ sub signed_event_json

sub verify_event_json_signature
{
my ( $event, @args ) = @_;
my ( $event, %args ) = @_;

verify_json_signature( redacted_event( $event ), @args );
my $room_version = delete $args{room_version};
verify_json_signature( redacted_event( $event, $room_version ), %args );
}

=head1 AUTHOR
Expand Down
29 changes: 26 additions & 3 deletions lib/SyTest/Federation/AuthChecks.pm
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ sub auth_check_event
$accepted_events, $event->{auth_events}, "m.room.create"
);

my $room_creator = _creator_for_create_event( $create_event );
return 0 unless defined $room_creator;

{
users => {
$create_event->{content}{creator} => 100,
$room_creator => 100,
},
users_default => 0,

Expand Down Expand Up @@ -86,6 +89,24 @@ sub auth_check_event
return 1;
}

sub _creator_for_create_event
Comment thread
FrenchGithubUser marked this conversation as resolved.
{
my ( $create_event ) = @_;

$create_event or
return undef;

my $room_version = $create_event->{content}{room_version};

# For room version 11+, 'creator' is absent from content, we use sender.
if( defined $room_version and $room_version =~ /\A[0-9]+\z/ and $room_version >= 11 ) {
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated
return $create_event->{sender};
}

# For older room versions, 'creator' must be present explicitly.
return $create_event->{content}{creator};
}

sub auth_check_event_m_room_create
{
my $self = shift;
Expand All @@ -96,7 +117,8 @@ sub auth_check_event_m_room_create
return 0;

# Any m.room.create event is acceptable, provided that the creator matches
return $event->{sender} eq $event->{content}{creator};
my $creator = _creator_for_create_event( $event );
return defined( $creator ) and $event->{sender} eq $creator;
}

sub auth_check_event_m_room_member
Expand All @@ -117,7 +139,8 @@ sub auth_check_event_m_room_member
$accepted_events, $event->{auth_events}, "m.room.create"
);

if( $create_event and $event->{state_key} eq $create_event->{content}{creator} ) {
my $creator = _creator_for_create_event( $create_event );
if( $creator and $event->{state_key} eq $creator ) {
return 1;
}

Expand Down
13 changes: 7 additions & 6 deletions lib/SyTest/Federation/Datastore.pm
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ the C<signatures> key.
sub sign_event
{
my $self = shift;
my ( $event ) = @_;
my ( $event, %args ) = @_;

sign_event_json( $event,
secret_key => $self->secret_key,
origin => $self->server_name,
key_id => $self->key_id,
secret_key => $self->secret_key,
origin => $self->server_name,
key_id => $self->key_id,
room_version => $args{room_version},
);
}

Expand Down Expand Up @@ -204,12 +205,12 @@ sub create_event
$event_id = $self->next_event_id( $event_id_suffix );
$event->{event_id} = $event_id;
}
$self->sign_event( $event );
$self->sign_event( $event, room_version => $room_version );
} else {
die "event with explicit event_id in room v$room_version"
if defined $event_id;

$self->sign_event( $event );
$self->sign_event( $event, room_version => $room_version );
$event_id = id_for_event( $event, $room_version );
}

Expand Down
7 changes: 4 additions & 3 deletions lib/SyTest/Federation/Protocol.pm
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ Calculates the reference hash of an event.

sub hash_event
{
my ( $event ) = @_;
my ( $event, $room_version ) = @_;
$room_version //= 1;
croak "Require an event" unless ref $event eq 'HASH';
my $redacted = redacted_event( $event );
my $redacted = redacted_event( $event, $room_version );
delete $redacted->{signatures};
delete $redacted->{age_ts};
delete $redacted->{unsigned};
Expand Down Expand Up @@ -76,7 +77,7 @@ sub id_for_event
return $event_id;
}

my $event_hash = hash_event( $event );
my $event_hash = hash_event( $event, $room_version );

# room v3 uses the unpadded-base64-encoded hash
if( $room_version eq '3' ) {
Expand Down
11 changes: 7 additions & 4 deletions lib/SyTest/Federation/Room.pm
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,16 @@ sub create_initial_events
$self->room_version eq "1" ? undef : $self->room_version
);

# For room version 11+, 'creator' is absent from content, we use sender.
my $create_content = {
defined( $room_version ) ? ( room_version => $room_version ) : (),
};
$create_content->{creator} = $creator if !defined( $room_version ) || $room_version < 11;
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated
Comment thread
FrenchGithubUser marked this conversation as resolved.
Outdated

$self->create_and_insert_event(
type => "m.room.create",

content => {
creator => $creator,
defined( $room_version ) ? ( room_version => $room_version ) : (),
},
content => $create_content,
sender => $creator,
state_key => "",
);
Expand Down
9 changes: 6 additions & 3 deletions tests/30rooms/01state.pl
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@
$event->{sender} eq $user->user_id or
die "Expected user_id to be ${\$user->user_id}";

assert_json_keys( my $content = $event->{content}, qw( creator ));
$content->{creator} eq $user->user_id or
die "Expected creator to be ${\$user->user_id}";
my $content = $event->{content};
# For room version 11+, 'creator' is absent from content, we use sender.
if( exists $content->{creator} ) {
$content->{creator} eq $user->user_id or
die "Expected creator to be ${\$user->user_id}";
}
Comment thread
FrenchGithubUser marked this conversation as resolved.

return 1;
});
Expand Down