Restrict sending messages in a pad chat to editors only

pull/1/head
yflory 6 years ago
parent a2e28e6e25
commit d88dee9a83

@ -12,6 +12,7 @@ define([
var hexToBase64 = Util.hexToBase64; var hexToBase64 = Util.hexToBase64;
var base64ToHex = Util.base64ToHex; var base64ToHex = Util.base64ToHex;
Hash.encodeBase64 = Nacl.util.encodeBase64; Hash.encodeBase64 = Nacl.util.encodeBase64;
Hash.decodeBase64 = Nacl.util.decodeBase64;
// This implementation must match that on the server // This implementation must match that on the server
// it's used for a checksum // it's used for a checksum

@ -26,6 +26,15 @@ define([
return JSON.parse(JSON.stringify(o)); return JSON.parse(JSON.stringify(o));
}; };
var convertToUint8 = function (obj) {
var l = Object.keys(obj).length;
var u = new Uint8Array(l);
for (var i = 0; i<l; i++) {
u[i] = obj[i];
}
return u;
};
// TODO // TODO
// - mute a channel (hide notifications or don't open it?) // - mute a channel (hide notifications or don't open it?)
var createData = Msg.createData = function (proxy, hash) { var createData = Msg.createData = function (proxy, hash) {
@ -234,7 +243,7 @@ define([
return; return;
} }
var decryptedMsg = channel.encryptor.decrypt(parsed0.msg); var decryptedMsg = channel.decrypt(parsed0.msg);
if (decryptedMsg === null) { if (decryptedMsg === null) {
return void console.error("Failed to decrypt message"); return void console.error("Failed to decrypt message");
@ -264,13 +273,14 @@ define([
id: channel.id id: channel.id
}); });
if (channel.readOnly) { return; }
if (parsed[0] !== Types.mapId) { return; } // Don't send your key if it's already an ACK if (parsed[0] !== Types.mapId) { return; } // Don't send your key if it's already an ACK
// Answer with your own key // Answer with your own key
var myData = createData(proxy); var myData = createData(proxy);
delete myData.channel; delete myData.channel;
var rMsg = [Types.mapIdAck, myData, channel.wc.myID]; var rMsg = [Types.mapIdAck, myData, channel.wc.myID];
var rMsgStr = JSON.stringify(rMsg); var rMsgStr = JSON.stringify(rMsg);
var cryptMsg = channel.encryptor.encrypt(rMsgStr); var cryptMsg = channel.encrypt(rMsgStr);
var data = { var data = {
channel: channel.id, channel: channel.id,
msg: cryptMsg msg: cryptMsg
@ -297,7 +307,7 @@ define([
var pushMsg = function (channel, cryptMsg) { var pushMsg = function (channel, cryptMsg) {
var sig = cryptMsg.slice(0, 64); var sig = cryptMsg.slice(0, 64);
if (msgAlreadyKnown(channel, sig)) { return; } if (msgAlreadyKnown(channel, sig)) { return; }
var msg = channel.encryptor.decrypt(cryptMsg); var msg = channel.decrypt(cryptMsg);
var parsedMsg = JSON.parse(msg); var parsedMsg = JSON.parse(msg);
var curvePublic; var curvePublic;
@ -364,11 +374,11 @@ define([
if (!channel) { if (!channel) {
return void console.error('NO_SUCH_CHANNEL'); return void console.error('NO_SUCH_CHANNEL');
} }
if (channel.readOnly) { return; }
var msg = [Types.update, myData.curvePublic, +new Date(), myData]; var msg = [Types.update, myData.curvePublic, +new Date(), myData];
var msgStr = JSON.stringify(msg); var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr); var cryptMsg = channel.encrypt(msgStr);
channel.wc.bcast(cryptMsg).then(function () { channel.wc.bcast(cryptMsg).then(function () {
// TODO send event // TODO send event
//channel.refresh(); //channel.refresh();
@ -465,7 +475,7 @@ define([
if (msg[2] !== 'MSG') { return; } if (msg[2] !== 'MSG') { return; }
try { try {
return { return {
d: JSON.parse(channel.encryptor.decrypt(msg[4])), d: JSON.parse(channel.decrypt(msg[4])),
sig: msg[4].slice(0, 64), sig: msg[4].slice(0, 64),
}; };
} catch (e) { } catch (e) {
@ -573,7 +583,7 @@ define([
var msg = [Types.unfriend, proxy.curvePublic, +new Date()]; var msg = [Types.unfriend, proxy.curvePublic, +new Date()];
var msgStr = JSON.stringify(msg); var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr); var cryptMsg = channel.encrypt(msgStr);
try { try {
channel.wc.bcast(cryptMsg).then(function () { channel.wc.bcast(cryptMsg).then(function () {
@ -602,24 +612,33 @@ define([
isFriendChat: data.isFriendChat, isFriendChat: data.isFriendChat,
isPadChat: data.isPadChat, isPadChat: data.isPadChat,
padChan: data.padChan, padChan: data.padChan,
readOnly: data.readOnly,
sending: false, sending: false,
encryptor: encryptor,
messages: [], messages: [],
userList: [], userList: [],
mapId: {}, mapId: {},
}; };
channel.encrypt = function (msg) {
if (channel.readOnly) { return; }
return encryptor.encrypt(msg);
};
channel.decrypt = data.decrypt || function (msg) {
return encryptor.decrypt(msg);
};
var onJoining = function (peer) { var onJoining = function (peer) {
if (peer === Msg.hk) { return; } if (peer === Msg.hk) { return; }
if (channel.userList.indexOf(peer) !== -1) { return; } if (channel.userList.indexOf(peer) !== -1) { return; }
channel.userList.push(peer); channel.userList.push(peer);
if (channel.readOnly) { return; }
// Join event will be sent once we are able to ID this peer // Join event will be sent once we are able to ID this peer
var myData = createData(proxy); var myData = createData(proxy);
delete myData.channel; delete myData.channel;
var msg = [Types.mapId, myData, channel.wc.myID]; var msg = [Types.mapId, myData, channel.wc.myID];
var msgStr = JSON.stringify(msg); var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr); var cryptMsg = channel.encrypt(msgStr);
var data = { var data = {
channel: channel.id, channel: channel.id,
msg: cryptMsg msg: cryptMsg
@ -693,6 +712,7 @@ define([
var sendMessage = function (id, payload, cb) { var sendMessage = function (id, payload, cb) {
var channel = getChannel(id); var channel = getChannel(id);
if (!channel) { return void cb({error: 'NO_CHANNEL'}); } if (!channel) { return void cb({error: 'NO_CHANNEL'}); }
if (channel.readOnly) { return void cb({error: 'FORBIDDEN'}); }
if (!network.webChannels.some(function (wc) { if (!network.webChannels.some(function (wc) {
if (wc.id === channel.wc.id) { return true; } if (wc.id === channel.wc.id) { return true; }
})) { })) {
@ -706,7 +726,7 @@ define([
msg.push(name); msg.push(name);
} }
var msgStr = JSON.stringify(msg); var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr); var cryptMsg = channel.encrypt(msgStr);
channel.wc.bcast(cryptMsg).then(function () { channel.wc.bcast(cryptMsg).then(function () {
pushMsg(channel, cryptMsg); pushMsg(channel, cryptMsg);
@ -893,20 +913,32 @@ define([
} }
}; };
var validateKeys = {};
messenger.storeValidateKey = function (chan, key) {
validateKeys[chan] = key;
};
var openPadChat = function (data, cb) { var openPadChat = function (data, cb) {
var channel = data.channel; var channel = data.channel;
if (getChannel(channel)) { if (getChannel(channel)) {
emit('PADCHAT_READY', channel); emit('PADCHAT_READY', channel);
return void cb(); return void cb();
} }
var keys = data.secret && data.secret.keys; var secret = data.secret;
var cryptKey = keys.viewKeyStr ? Crypto.b64AddSlashes(keys.viewKeyStr) : data.secret.key; if (secret.keys.cryptKey) {
var encryptor = Crypto.createEncryptor(cryptKey); secret.keys.cryptKey = convertToUint8(secret.keys.cryptKey);
}
var encryptor = Crypto.createEncryptor(secret.keys);
var vKey = (secret.keys && secret.keys.validateKey) || validateKeys[secret.channel];
var chanData = { var chanData = {
padChan: data.secret && data.secret.channel, padChan: data.secret && data.secret.channel,
readOnly: typeof(secret.keys) === "object" && !secret.keys.validateKey,
encryptor: encryptor, encryptor: encryptor,
channel: data.channel, channel: data.channel,
isPadChat: true, isPadChat: true,
decrypt: function (msg) {
return encryptor.decrypt(msg, vKey);
},
//lastKnownHash: friend.lastKnownHash, //lastKnownHash: friend.lastKnownHash,
//owners: [proxy.edPublic, friend.edPublic], //owners: [proxy.edPublic, friend.edPublic],
//isFriendChat: true //isFriendChat: true

@ -995,6 +995,9 @@ define([
var conf = { var conf = {
onReady: function (padData) { onReady: function (padData) {
channel.data = padData || {}; channel.data = padData || {};
if (padData && padData.validateKey && store.messenger) {
store.messenger.storeValidateKey(data.channel, padData.validateKey);
}
postMessage(clientId, "PAD_READY"); postMessage(clientId, "PAD_READY");
}, },
onMessage: function (user, m, validateKey, isCp) { onMessage: function (user, m, validateKey, isCp) {

@ -107,7 +107,6 @@ define([
} }
chan.encryptor = Crypto.createEncryptor(secret.keys);
if (!chan.encryptor) { chan.encryptor = Crypto.createEncryptor(secret.keys); } if (!chan.encryptor) { chan.encryptor = Crypto.createEncryptor(secret.keys); }
wc.on('join', function () { wc.on('join', function () {
@ -117,7 +116,7 @@ define([
ctx.emit('MESSAGE', {leave: true, id: peer}, chan.clients); ctx.emit('MESSAGE', {leave: true, id: peer}, chan.clients);
}); });
wc.on('message', function (cryptMsg) { wc.on('message', function (cryptMsg) {
var msg = chan.encryptor.decrypt(cryptMsg, secret.keys.validateKey); var msg = chan.encryptor.decrypt(cryptMsg, secret.keys && secret.keys.validateKey);
var parsed; var parsed;
try { try {
parsed = JSON.parse(msg); parsed = JSON.parse(msg);

@ -173,9 +173,10 @@ define([
}; };
funcs.openPadChat = function (saveChanges) { funcs.openPadChat = function (saveChanges) {
var md = JSON.parse(JSON.stringify(ctx.metadataMgr.getMetadata())); var md = JSON.parse(JSON.stringify(ctx.metadataMgr.getMetadata()));
var channel = md.chat || Hash.createChannelId(); if (md.chat) { delete md.chat; } // Old channel without signing key
if (!md.chat) { var channel = md.chat2 || Hash.createChannelId();
md.chat = channel; if (!md.chat2) {
md.chat2 = channel;
ctx.metadataMgr.updateMetadata(md); ctx.metadataMgr.updateMetadata(md);
setTimeout(saveChanges); setTimeout(saveChanges);
} }

@ -488,7 +488,7 @@ MessengerUI, Messages) {
show(); show();
}); });
initChat(toolbar, config); initChat(toolbar);
return $container; return $container;
}; };

@ -43,6 +43,7 @@ define([
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
var metadataMgr = common.getMetadataMgr(); var metadataMgr = common.getMetadataMgr();
var origin = metadataMgr.getPrivateData().origin; var origin = metadataMgr.getPrivateData().origin;
var readOnly = metadataMgr.getPrivateData().readOnly;
var isApp = typeof(toolbar) !== "undefined"; var isApp = typeof(toolbar) !== "undefined";
@ -358,7 +359,7 @@ define([
}, function (e) { }, function (e) {
if (e) { if (e) {
// failed to send // failed to send
return void console.error('failed to send'); return void console.error('failed to send', e);
} }
input.value = ''; input.value = '';
sending = false; sending = false;
@ -406,9 +407,9 @@ define([
'data-user': data.isFriendChat && curvePublic 'data-user': data.isFriendChat && curvePublic
}, [ }, [
header, header,
tips, readOnly ? undefined : tips,
messages, messages,
h('div.cp-app-contacts-input', [ readOnly ? undefined : h('div.cp-app-contacts-input', [
input, input,
sendButton, sendButton,
]), ]),

Loading…
Cancel
Save