fix(communities)_: prevent unsigned `CommunityDescription` persistence
fixes: status-im/status-mobile#21303
This commit is contained in:
parent
9ba44651c7
commit
9294ffc12b
|
@ -3491,6 +3491,17 @@ type CheckAllChannelsPermissionsResponse struct {
|
|||
}
|
||||
|
||||
func (m *Manager) HandleCommunityRequestToJoinResponse(signer *ecdsa.PublicKey, request *protobuf.CommunityRequestToJoinResponse) (*RequestToJoin, error) {
|
||||
if len(request.CommunityDescriptionProtocolMessage) > 0 {
|
||||
description, err := unmarshalCommunityDescriptionMessage(request.CommunityDescriptionProtocolMessage, signer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = m.HandleCommunityDescriptionMessage(signer, description, request.CommunityDescriptionProtocolMessage, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
m.communityLock.Lock(request.CommunityId)
|
||||
defer m.communityLock.Unlock(request.CommunityId)
|
||||
|
||||
|
@ -3501,46 +3512,6 @@ func (m *Manager) HandleCommunityRequestToJoinResponse(signer *ecdsa.PublicKey,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
communityDescriptionBytes, err := proto.Marshal(request.Community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// We need to wrap `request.Community` in an `ApplicationMetadataMessage`
|
||||
// of type `CommunityDescription` because `UpdateCommunityDescription` expects this.
|
||||
//
|
||||
// This is merely for marsheling/unmarsheling, hence we attaching a `Signature`
|
||||
// is not needed.
|
||||
metadataMessage := &protobuf.ApplicationMetadataMessage{
|
||||
Payload: communityDescriptionBytes,
|
||||
Type: protobuf.ApplicationMetadataMessage_COMMUNITY_DESCRIPTION,
|
||||
}
|
||||
|
||||
appMetadataMsg, err := proto.Marshal(metadataMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isControlNodeSigner := common.IsPubKeyEqual(community.ControlNode(), signer)
|
||||
if !isControlNodeSigner {
|
||||
m.logger.Debug("signer is not control node", zap.String("signer", common.PubkeyToHex(signer)), zap.String("controlNode", common.PubkeyToHex(community.ControlNode())))
|
||||
return nil, ErrNotAuthorized
|
||||
}
|
||||
|
||||
_, processedDescription, err := m.preprocessDescription(community.ID(), request.Community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = community.UpdateCommunityDescription(processedDescription, appMetadataMsg, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = m.handleCommunityTokensMetadata(community); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if community.Encrypted() && len(request.Grant) > 0 {
|
||||
_, err = m.HandleCommunityGrant(community, request.Grant, request.Clock)
|
||||
if err != nil && err != ErrGrantOlder && err != ErrGrantExpired {
|
||||
|
@ -3548,19 +3519,12 @@ func (m *Manager) HandleCommunityRequestToJoinResponse(signer *ecdsa.PublicKey,
|
|||
}
|
||||
}
|
||||
|
||||
err = m.persistence.SaveCommunity(community)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if request.Accepted {
|
||||
err = m.markRequestToJoinAsAccepted(&m.identity.PublicKey, community)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
|
||||
err = m.persistence.SetRequestToJoinState(pkString, community.ID(), RequestToJoinStateDeclined)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -2917,6 +2917,26 @@ func (s *MessengerCommunitiesSuite) TestSyncCommunity_RequestToJoin() {
|
|||
s.Equal(aRtj.CustomizationColor, bobRtj.CustomizationColor)
|
||||
}
|
||||
|
||||
func (s *MessengerCommunitiesSuite) TestSyncCommunity_Join() {
|
||||
community, _ := s.createCommunity()
|
||||
s.advertiseCommunityTo(community, s.owner, s.alice)
|
||||
|
||||
alicesOtherDevice := s.createOtherDevice(s.alice)
|
||||
defer TearDownMessenger(&s.Suite, alicesOtherDevice)
|
||||
PairDevices(&s.Suite, alicesOtherDevice, s.alice)
|
||||
|
||||
s.joinCommunity(community, s.owner, s.alice)
|
||||
|
||||
_, err := WaitOnMessengerResponse(alicesOtherDevice, func(response *MessengerResponse) bool {
|
||||
if len(response.Communities()) != 1 {
|
||||
return false
|
||||
}
|
||||
c := response.Communities()[0]
|
||||
return c.IDString() == community.IDString() && c.Joined()
|
||||
}, "community not synced")
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (s *MessengerCommunitiesSuite) TestSyncCommunity_Leave() {
|
||||
// Set Alice's installation metadata
|
||||
aim := &multidevice.InstallationMetadata{
|
||||
|
@ -4661,17 +4681,17 @@ func (s *MessengerCommunitiesSuite) TestAliceDidNotProcessOutdatedCommunityReque
|
|||
s.Require().NoError(err)
|
||||
}
|
||||
|
||||
encryptedDescription, err := community.EncryptedDescription()
|
||||
descriptionMessage, err := community.ToProtocolMessageBytes()
|
||||
s.Require().NoError(err)
|
||||
|
||||
requestToJoinResponse := &protobuf.CommunityRequestToJoinResponse{
|
||||
Clock: community.Clock(),
|
||||
Accepted: true,
|
||||
CommunityId: community.ID(),
|
||||
Community: encryptedDescription,
|
||||
Grant: grant,
|
||||
ProtectedTopicPrivateKey: crypto.FromECDSA(key),
|
||||
Shard: community.Shard().Protobuffer(),
|
||||
Clock: community.Clock(),
|
||||
Accepted: true,
|
||||
CommunityId: community.ID(),
|
||||
Grant: grant,
|
||||
ProtectedTopicPrivateKey: crypto.FromECDSA(key),
|
||||
Shard: community.Shard().Protobuffer(),
|
||||
CommunityDescriptionProtocolMessage: descriptionMessage,
|
||||
}
|
||||
|
||||
// alice handle duplicated request to join response
|
||||
|
|
|
@ -1989,14 +1989,20 @@ func (m *Messenger) acceptRequestToJoinCommunity(requestToJoin *communities.Requ
|
|||
return nil, err
|
||||
}
|
||||
|
||||
descriptionMessage, err := community.ToProtocolMessageBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestToJoinResponseProto := &protobuf.CommunityRequestToJoinResponse{
|
||||
Clock: community.Clock(),
|
||||
Accepted: true,
|
||||
CommunityId: community.ID(),
|
||||
Community: encryptedDescription,
|
||||
Grant: grant,
|
||||
ProtectedTopicPrivateKey: crypto.FromECDSA(key),
|
||||
Shard: community.Shard().Protobuffer(),
|
||||
Clock: community.Clock(),
|
||||
Accepted: true,
|
||||
CommunityId: community.ID(),
|
||||
Community: encryptedDescription, // Deprecated but kept for backward compatibility, to be removed in future
|
||||
Grant: grant,
|
||||
ProtectedTopicPrivateKey: crypto.FromECDSA(key),
|
||||
Shard: community.Shard().Protobuffer(),
|
||||
CommunityDescriptionProtocolMessage: descriptionMessage,
|
||||
}
|
||||
|
||||
// The purpose of this torrent code is to get the 'magnetlink' to populate 'requestToJoinResponseProto.MagnetUri'
|
||||
|
@ -3807,7 +3813,7 @@ func (m *Messenger) handleSyncInstallationCommunity(messageState *ReceivedMessag
|
|||
// This is good to do so that we don't have to queue all the actions done after the handled community description.
|
||||
// `signer` is `communityID` for a community with no owner token and `owner public key` otherwise
|
||||
signer, err := utils.RecoverKey(&amm)
|
||||
if err != nil {
|
||||
if signer == nil || err != nil {
|
||||
logger.Debug("failed to recover community description signer", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1702,7 +1702,7 @@ func (m *Messenger) HandleCommunityRequestToJoinResponse(state *ReceivedMessageS
|
|||
communityShardKey := &protobuf.CommunityShardKey{
|
||||
CommunityId: requestToJoinResponseProto.CommunityId,
|
||||
PrivateKey: requestToJoinResponseProto.ProtectedTopicPrivateKey,
|
||||
Clock: requestToJoinResponseProto.Community.Clock,
|
||||
Clock: community.Clock(),
|
||||
Shard: requestToJoinResponseProto.Shard,
|
||||
}
|
||||
|
||||
|
@ -1767,9 +1767,6 @@ func (m *Messenger) HandleCommunityRequestToJoinResponse(state *ReceivedMessageS
|
|||
|
||||
m.downloadAndImportHistoryArchives(community.ID(), magnetlink, task.CancelChan)
|
||||
}(currentTask)
|
||||
|
||||
clock := requestToJoinResponseProto.Community.ArchiveMagnetlinkClock
|
||||
return m.communitiesManager.UpdateMagnetlinkMessageClock(community.ID(), clock)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -200,13 +200,15 @@ message CommunityUserKicked {
|
|||
|
||||
message CommunityRequestToJoinResponse {
|
||||
uint64 clock = 1;
|
||||
CommunityDescription community = 2;
|
||||
CommunityDescription community = 2 [deprecated = true];
|
||||
bool accepted = 3;
|
||||
bytes grant = 4;
|
||||
bytes community_id = 5;
|
||||
string magnet_uri = 6;
|
||||
bytes protected_topic_private_key = 7;
|
||||
Shard shard = 8;
|
||||
// CommunityDescription protocol message with owner signature
|
||||
bytes community_description_protocol_message = 9;
|
||||
}
|
||||
|
||||
message CommunityRequestToLeave {
|
||||
|
|
Loading…
Reference in New Issue