mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Do additional validation on incoming private group messages
This commit is contained in:
@@ -8,11 +8,11 @@ interface Constants {
|
||||
String KEY_TYPE = "type";
|
||||
String KEY_TIMESTAMP = "timestamp";
|
||||
String KEY_READ = MSG_KEY_READ;
|
||||
String KEY_PARENT_ID = "parentId";
|
||||
String KEY_PARENT_MSG_ID = "parentMsgId";
|
||||
String KEY_NEW_MEMBER_MSG_ID = "newMemberMsgId";
|
||||
String KEY_PREVIOUS_MSG_ID = "previousMsgId";
|
||||
String KEY_AUTHOR_ID = "authorId";
|
||||
String KEY_AUTHOR_NAME = "authorName";
|
||||
String KEY_AUTHOR_PUBLIC_KEY = "authorPublicKey";
|
||||
|
||||
// Messaging Group Metadata
|
||||
String KEY_PREVIOUS_MSG_ID = "previousMsgId";
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_
|
||||
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME;
|
||||
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY;
|
||||
import static org.briarproject.privategroup.Constants.KEY_PARENT_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_NEW_MEMBER_MSG_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_PARENT_MSG_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_PREVIOUS_MSG_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_READ;
|
||||
import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP;
|
||||
import static org.briarproject.privategroup.Constants.KEY_TYPE;
|
||||
@@ -80,6 +82,8 @@ class GroupMessageValidator extends BdfMessageValidator {
|
||||
break;
|
||||
case POST:
|
||||
c = validatePost(m, g, body, member_name, member_public_key);
|
||||
addMessageMetadata(c, member_name, member_public_key,
|
||||
m.getTimestamp());
|
||||
break;
|
||||
default:
|
||||
throw new InvalidMessageException("Unknown Message Type");
|
||||
@@ -141,6 +145,7 @@ class GroupMessageValidator extends BdfMessageValidator {
|
||||
|
||||
// Return the metadata and dependencies
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(KEY_NEW_MEMBER_MSG_ID, new_member_id);
|
||||
return new BdfMessageContext(meta, dependencies);
|
||||
}
|
||||
|
||||
@@ -185,7 +190,8 @@ class GroupMessageValidator extends BdfMessageValidator {
|
||||
|
||||
// Return the metadata and dependencies
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
if (parent_id != null) meta.put(KEY_PARENT_ID, parent_id);
|
||||
if (parent_id != null) meta.put(KEY_PARENT_MSG_ID, parent_id);
|
||||
meta.put(KEY_PREVIOUS_MSG_ID, previous_message_id);
|
||||
return new BdfMessageContext(meta, dependencies);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.briarproject.api.identity.IdentityManager;
|
||||
import org.briarproject.api.privategroup.GroupMessage;
|
||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||
import org.briarproject.api.privategroup.JoinMessageHeader;
|
||||
import org.briarproject.api.privategroup.MessageType;
|
||||
import org.briarproject.api.privategroup.PrivateGroup;
|
||||
import org.briarproject.api.privategroup.PrivateGroupFactory;
|
||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||
@@ -28,6 +29,7 @@ import org.briarproject.clients.BdfIncomingMessageHook;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -45,7 +47,8 @@ import static org.briarproject.api.privategroup.MessageType.POST;
|
||||
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_NAME;
|
||||
import static org.briarproject.privategroup.Constants.KEY_AUTHOR_PUBLIC_KEY;
|
||||
import static org.briarproject.privategroup.Constants.KEY_PARENT_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_NEW_MEMBER_MSG_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_PARENT_MSG_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_PREVIOUS_MSG_ID;
|
||||
import static org.briarproject.privategroup.Constants.KEY_READ;
|
||||
import static org.briarproject.privategroup.Constants.KEY_TIMESTAMP;
|
||||
@@ -100,6 +103,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
throws DbException, FormatException {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(KEY_TYPE, NEW_MEMBER.getInt());
|
||||
addMessageMetadata(meta, m, true);
|
||||
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
|
||||
}
|
||||
|
||||
@@ -166,9 +170,11 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
try {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put(KEY_TYPE, POST.getInt());
|
||||
if (m.getParent() != null) meta.put(KEY_PARENT_ID, m.getParent());
|
||||
if (m.getParent() != null) meta.put(KEY_PARENT_MSG_ID, m.getParent());
|
||||
addMessageMetadata(meta, m, true);
|
||||
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
|
||||
setPreviousMsgId(txn, m.getMessage().getGroupId(),
|
||||
m.getMessage().getId());
|
||||
trackOutgoingMessage(txn, m.getMessage());
|
||||
txn.setComplete();
|
||||
} catch (FormatException e) {
|
||||
@@ -181,6 +187,15 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
m.getMessage().getTimestamp(), m.getMember(), OURSELVES, true);
|
||||
}
|
||||
|
||||
private void addMessageMetadata(BdfDictionary meta, GroupMessage m,
|
||||
boolean read) {
|
||||
meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp());
|
||||
meta.put(KEY_READ, read);
|
||||
meta.put(KEY_AUTHOR_ID, m.getMember().getId());
|
||||
meta.put(KEY_AUTHOR_NAME, m.getMember().getName());
|
||||
meta.put(KEY_AUTHOR_PUBLIC_KEY, m.getMember().getPublicKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrivateGroup getPrivateGroup(GroupId g) throws DbException {
|
||||
PrivateGroup privateGroup;
|
||||
@@ -288,8 +303,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
throws DbException, FormatException {
|
||||
|
||||
MessageId parentId = null;
|
||||
if (meta.containsKey(KEY_PARENT_ID)) {
|
||||
parentId = new MessageId(meta.getRaw(KEY_PARENT_ID));
|
||||
if (meta.containsKey(KEY_PARENT_MSG_ID)) {
|
||||
parentId = new MessageId(meta.getRaw(KEY_PARENT_MSG_ID));
|
||||
}
|
||||
long timestamp = meta.getLong(KEY_TIMESTAMP);
|
||||
|
||||
@@ -318,23 +333,86 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
||||
protected boolean incomingMessage(Transaction txn, Message m, BdfList body,
|
||||
BdfDictionary meta) throws DbException, FormatException {
|
||||
|
||||
trackIncomingMessage(txn, m);
|
||||
|
||||
// TODO POST timestamp must be greater than the timestamps of the parent post, if any, and the member's previous message
|
||||
|
||||
// TODO JOIN timestamp must be equal to the timestamp of the new member message.
|
||||
// TODO JOIN new_member_id must be the identifier of a NEW_MEMBER message with the same member_name and member_public_key
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addMessageMetadata(BdfDictionary meta, GroupMessage m,
|
||||
boolean read) {
|
||||
meta.put(KEY_TIMESTAMP, m.getMessage().getTimestamp());
|
||||
meta.put(KEY_READ, read);
|
||||
meta.put(KEY_AUTHOR_ID, m.getMember().getId());
|
||||
meta.put(KEY_AUTHOR_NAME, m.getMember().getName());
|
||||
meta.put(KEY_AUTHOR_PUBLIC_KEY, m.getMember().getPublicKey());
|
||||
long timestamp = meta.getLong(KEY_TIMESTAMP);
|
||||
MessageType type =
|
||||
MessageType.valueOf(meta.getLong(KEY_TYPE).intValue());
|
||||
switch (type) {
|
||||
case NEW_MEMBER:
|
||||
// don't track incoming message, because it won't show in the UI
|
||||
return true;
|
||||
case JOIN:
|
||||
// new_member_id must be the identifier of a NEW_MEMBER message
|
||||
byte[] newMemberIdBytes =
|
||||
meta.getOptionalRaw(KEY_NEW_MEMBER_MSG_ID);
|
||||
MessageId newMemberId = new MessageId(newMemberIdBytes);
|
||||
BdfDictionary newMemberMeta = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, newMemberId);
|
||||
MessageType newMemberType = MessageType
|
||||
.valueOf(newMemberMeta.getLong(KEY_TYPE).intValue());
|
||||
if (newMemberType != NEW_MEMBER) {
|
||||
// FIXME throw new InvalidMessageException() (#643)
|
||||
db.deleteMessage(txn, m.getId());
|
||||
return false;
|
||||
}
|
||||
// timestamp must be equal to timestamp of NEW_MEMBER message
|
||||
if (timestamp != newMemberMeta.getLong(KEY_TIMESTAMP)) {
|
||||
// FIXME throw new InvalidMessageException() (#643)
|
||||
db.deleteMessage(txn, m.getId());
|
||||
return false;
|
||||
}
|
||||
// NEW_MEMBER must have same member_name and member_public_key
|
||||
if (!Arrays.equals(meta.getRaw(KEY_AUTHOR_ID),
|
||||
newMemberMeta.getRaw(KEY_AUTHOR_ID))) {
|
||||
// FIXME throw new InvalidMessageException() (#643)
|
||||
db.deleteMessage(txn, m.getId());
|
||||
return false;
|
||||
}
|
||||
// TODO add to member list
|
||||
trackIncomingMessage(txn, m);
|
||||
return true;
|
||||
case POST:
|
||||
// timestamp must be greater than the timestamps of parent post
|
||||
byte[] parentIdBytes = meta.getOptionalRaw(KEY_PARENT_MSG_ID);
|
||||
if (parentIdBytes != null) {
|
||||
MessageId parentId = new MessageId(parentIdBytes);
|
||||
BdfDictionary parentMeta = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, parentId);
|
||||
if (timestamp <= parentMeta.getLong(KEY_TIMESTAMP)) {
|
||||
// FIXME throw new InvalidMessageException() (#643)
|
||||
db.deleteMessage(txn, m.getId());
|
||||
return false;
|
||||
}
|
||||
MessageType parentType = MessageType
|
||||
.valueOf(parentMeta.getLong(KEY_TYPE).intValue());
|
||||
if (parentType != POST) {
|
||||
// FIXME throw new InvalidMessageException() (#643)
|
||||
db.deleteMessage(txn, m.getId());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// and the member's previous message
|
||||
byte[] previousMsgIdBytes = meta.getRaw(KEY_PREVIOUS_MSG_ID);
|
||||
MessageId previousMsgId = new MessageId(previousMsgIdBytes);
|
||||
BdfDictionary previousMeta = clientHelper
|
||||
.getMessageMetadataAsDictionary(txn, previousMsgId);
|
||||
if (timestamp <= previousMeta.getLong(KEY_TIMESTAMP)) {
|
||||
// FIXME throw new InvalidMessageException() (#643)
|
||||
db.deleteMessage(txn, m.getId());
|
||||
return false;
|
||||
}
|
||||
// previous message must be from same member
|
||||
if (!Arrays.equals(meta.getRaw(KEY_AUTHOR_ID),
|
||||
previousMeta.getRaw(KEY_AUTHOR_ID))) {
|
||||
// FIXME throw new InvalidMessageException() (#643)
|
||||
db.deleteMessage(txn, m.getId());
|
||||
return false;
|
||||
}
|
||||
trackIncomingMessage(txn, m);
|
||||
return true;
|
||||
default:
|
||||
// the validator should only let valid types pass
|
||||
throw new RuntimeException("Unknown MessageType");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user