Skip to content

Commit

Permalink
[NEW] Settings to enable E2E encryption for Private and Direct Rooms …
Browse files Browse the repository at this point in the history
…by default (#16928)
  • Loading branch information
rodrigok authored Mar 20, 2020
1 parent b060e07 commit 12fe0c3
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 129 deletions.
17 changes: 3 additions & 14 deletions app/cas/server/cas_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import url from 'url';

import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { Random } from 'meteor/random';
import { WebApp } from 'meteor/webapp';
import { RoutePolicy } from 'meteor/routepolicy';
import _ from 'underscore';
Expand All @@ -11,8 +10,9 @@ import CAS from 'cas';

import { logger } from './cas_rocketchat';
import { settings } from '../../settings';
import { Rooms, Subscriptions, CredentialTokens } from '../../models';
import { Rooms, CredentialTokens } from '../../models/server';
import { _setRealName } from '../../lib';
import { createRoom } from '../../lib/server/functions/createRoom';

RoutePolicy.declare('/_cas/', 'network');

Expand Down Expand Up @@ -250,18 +250,7 @@ Accounts.registerLoginHandler(function(options) {
if (room_name) {
let room = Rooms.findOneByNameAndType(room_name, 'c');
if (!room) {
room = Rooms.createWithIdTypeAndName(Random.id(), 'c', room_name);
}

if (!Subscriptions.findOneByRoomIdAndUserId(room._id, userId)) {
Subscriptions.createWithRoomAndUser(room, user, {
ts: new Date(),
open: true,
alert: true,
unread: 1,
userMentions: 1,
groupMentions: 0,
});
room = createRoom('c', room_name, user.username);
}
}
});
Expand Down
11 changes: 11 additions & 0 deletions app/e2e/server/beforeCreateRoom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { callbacks } from '../../callbacks/server';
import { settings } from '../../settings/server';

callbacks.add('beforeCreateRoom', ({ type, extraData }) => {
if (
(type === 'd' && settings.get('E2E_Enabled_Default_DirectRooms'))
|| (type === 'p' && settings.get('E2E_Enabled_Default_PrivateRooms'))
) {
extraData.encrypted = true;
}
});
1 change: 1 addition & 0 deletions app/e2e/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { callbacks } from '../../callbacks';
import { Notifications } from '../../notifications';

import './settings';
import './beforeCreateRoom';
import './methods/setUserPublicAndPrivateKeys';
import './methods/getUsersOfRoomWithoutKey';
import './methods/updateGroupKey';
Expand Down
10 changes: 10 additions & 0 deletions app/e2e/server/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,14 @@ settings.addGroup('E2E Encryption', function() {
public: true,
alert: 'E2E_Enable_alert',
});

this.add('E2E_Enabled_Default_DirectRooms', false, {
type: 'boolean',
enableQuery: { _id: 'E2E_Enable', value: true },
});

this.add('E2E_Enabled_Default_PrivateRooms', false, {
type: 'boolean',
enableQuery: { _id: 'E2E_Enable', value: true },
});
});
50 changes: 43 additions & 7 deletions app/lib/server/functions/createDirectRoom.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,81 @@
import { Rooms, Subscriptions } from '../../../models/server';
import { getDefaultSubscriptionPref } from '../../../utils/server';
import { callbacks } from '../../../callbacks/server';

export const createDirectRoom = function(source, target, extraData, options) {
const rid = [source._id, target._id].sort().join('');

Rooms.upsert({ _id: rid }, {
const now = new Date();

const roomUpsertResult = Rooms.upsert({ _id: rid }, {
$set: {
usernames: [source.username, target.username],
},
$setOnInsert: Object.assign({
t: 'd',
usernames: [source.username, target.username],
msgs: 0,
ts: new Date(),
ts: now,
usersCount: 2,
}, extraData),
});

const targetNotificationPref = getDefaultSubscriptionPref(target);

Subscriptions.upsert({ rid, 'u._id': target._id }, {
$setOnInsert: Object.assign({
fname: source.name,
name: source.username,
t: 'd',
open: true,
alert: true,
open: false,
alert: false,
unread: 0,
userMentions: 0,
groupMentions: 0,
customFields: target.customFields,
u: {
_id: target._id,
username: target.username,
},
ts: now,
...targetNotificationPref,
}, options.subscriptionExtra),
});

const sourceNotificationPref = getDefaultSubscriptionPref(source);

Subscriptions.upsert({ rid, 'u._id': source._id }, {
$set: {
ls: now,
open: true,
...target.active === false && {
archived: true,
},
},
$setOnInsert: Object.assign({
fname: target.name,
name: target.username,
t: 'd',
open: true,
alert: true,
alert: false,
unread: 0,
userMentions: 0,
groupMentions: 0,
customFields: source.customFields,
u: {
_id: source._id,
username: source.username,
},
ts: now,
...sourceNotificationPref,
}, options.subscriptionExtra),
});

// If the room is new, run a callback
if (roomUpsertResult.insertedId) {
const insertedRoom = Rooms.findOneById(rid);

callbacks.run('afterCreateDirectRoom', insertedRoom, { from: source, to: target });
}

return {
_id: rid,
t: 'd',
Expand Down
8 changes: 3 additions & 5 deletions app/lib/server/functions/createRoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { getValidRoomName } from '../../../utils';
import { Apps } from '../../../apps/server';
import { createDirectRoom } from './createDirectRoom';

export const createRoom = function(type, name, owner, members, readOnly, extraData = {}, options = {}) {
export const createRoom = function(type, name, owner, members = [], readOnly, extraData = {}, options = {}) {
callbacks.run('beforeCreateRoom', { type, name, owner, members, readOnly, extraData, options });

if (type === 'd') {
return createDirectRoom(members[0], members[1], extraData, options);
}
Expand Down Expand Up @@ -59,10 +61,6 @@ export const createRoom = function(type, name, owner, members, readOnly, extraDa
ro: readOnly === true,
});

if (type === 'd') {
room.usernames = members;
}

if (Apps && Apps.isLoaded()) {
const prevent = Promise.await(Apps.getBridges().getListenerBridge().roomEvent('IPreRoomCreatePrevent', room));
if (prevent) {
Expand Down
18 changes: 3 additions & 15 deletions app/meteor-accounts-saml/server/saml_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ import s from 'underscore.string';

import { SAML } from './saml_utils';
import { settings } from '../../settings/server';
import { Rooms, Subscriptions, CredentialTokens } from '../../models';
import { Users, Rooms, CredentialTokens } from '../../models/server';
import { generateUsernameSuggestion } from '../../lib';
import { _setUsername } from '../../lib/server/functions';
import { Users } from '../../models/server';
import { _setUsername, createRoom } from '../../lib/server/functions';

if (!Accounts.saml) {
Accounts.saml = {
Expand Down Expand Up @@ -419,18 +418,7 @@ Accounts.saml.subscribeToSAMLChannels = function(channels, user) {

let room = Rooms.findOneByNameAndType(roomName, 'c');
if (!room) {
room = Rooms.createWithIdTypeAndName(Random.id(), 'c', roomName);
}

if (!Subscriptions.findOneByRoomIdAndUserId(room._id, user._id)) {
Subscriptions.createWithRoomAndUser(room, user, {
ts: new Date(),
open: true,
alert: true,
unread: 1,
userMentions: 1,
groupMentions: 0,
});
room = createRoom('c', roomName, user.username);
}
}
} catch (err) {
Expand Down
2 changes: 2 additions & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,8 @@
"E2E_Enabled": "E2E Enabled",
"E2E_Enable_alert": "This feature is currently in beta! Please report bugs to github.com/RocketChat/Rocket.Chat/issues and be aware of:<br/>- Encrypted messages of encrypted rooms will not be found by search operations.<br/>- The mobile apps may not support the encypted messages (they are implementing it).<br/>- Bots may not be able to see encrypted messages until they implement support for it.<br/>- Uploads will not be encrypted in this version.",
"E2E_Enable_description": "Enable option to create encrypted groups and be able to change groups and direct messages to be encrypted",
"E2E_Enabled_Default_DirectRooms": "Enable encryption for Direct Rooms by default",
"E2E_Enabled_Default_PrivateRooms": "Enable encryption for Private Rooms by default",
"E2E_Encryption_Password_Change": "Change Encryption Password",
"E2E_Encryption_Password_Explanation": "You can now create encrypted private groups and direct messages. You may also change existing private groups or DMs to encrypted.<br/><br/>This is end to end encryption so the key to encode/decode your messages will not be saved on the server. For that reason you need to store your password somewhere safe. You will be required to enter it on other devices you wish to use e2e encryption on.",
"E2E_password_reveal_text": "You can now create encrypted private groups and direct messages. You may also change existing private groups or DMs to encrypted.<br/><br/>This is end to end encryption so the key to encode/decode your messages will not be saved on the server. For that reason you need to store this password somewhere safe. You will be required to enter it on other devices you wish to use e2e encryption on. <a href=\"https://rocket.chat/docs/user-guides/end-to-end-encryption/\" target=\"_blank\">Learn more here!</a><br/><br/>Your password is: <span style=\"font-weight: bold;\">%s</span><br/><br/>This is an auto generated password, you can setup a new password for your encryption key any time from any browser you have entered the existing password.<br/>This password is only stored on this browser until you store the password and dismiss this message.",
Expand Down
2 changes: 2 additions & 0 deletions packages/rocketchat-i18n/i18n/pt-BR.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,8 @@
"E2E_Enabled": "E2E Enabled",
"E2E_Enable_alert": "Este recurso está atualmente em beta! Relate os erros para github.com/RocketChat/Rocket.Chat/issues e esteja ciente de: <br/>- As mensagens criptografadas de salas criptografadas não serão encontradas pelas operações de pesquisa. <br/>- Os aplicativos para dispositivos móveis talvez não ofereçam suporte às mensagens critografadas (eles estão implementando). <br/>- Os bots talvez não consigam ver as mensagens criptografadas até implementarem o suporte. <br/>- Os uploads não serão criptografados nesta versão.",
"E2E_Enable_description": "Ative a opção para criar grupos criptografados e ser capaz de alterar grupos e mensagens privadas para serem criptografadas",
"E2E_Enabled_Default_DirectRooms": "Ativar criptografia em salas diretas por padrão",
"E2E_Enabled_Default_PrivateRooms": "Ativar criptografia em salas privadas por padrão",
"E2E_Encryption_Password_Explanation": "Agora você pode criar grupos privados criptografados e mensagens diretas. Você também pode alterar os grupos privados ou DMs existentes para criptografados. <br/><br/>Esta é uma criptografia de ponta a ponta, logo a chave para codificar / decodificar suas mensagens não será salva no servidor. Por esse motivo, você precisa armazenar sua senha em algum lugar seguro. Será solicitada a inserção de senha em outros dispositivos nos quais deseja usar a criptografia E2E.",
"E2E_password_reveal_text": "Agora você pode criar grupos privados e mensagens diretas criptografados. Você também pode alterar os grupos privados ou DMs existentes para criptografados. <br/><br/>Esta é uma criptografia de ponta a ponta, logo a chave para codificar / decodificar suas mensagens não será salva no servidor. Por esse motivo, você precisa armazenar sua senha em algum lugar seguro. Será solicitada a inserção de senha em outros dispositivos nos quais deseja usar a criptografia E2E. <a href=\"https://rocket.chat/docs/user-guides/end-to-end-encryption/\" target=\"_blank\">Saiba mais aqui!</a><br/><br/>Sua senha é: <span style=\"font-weight: bold;\">%s</span><br/><br/>Esta é uma senha gerada automaticamente, você pode configurar uma nova senha para sua chave de criptografia a qualquer momento, a partir de qualquer navegador onde utilizou a senha existente. <br/>Esta senha só é armazenada neste navegador até que você armazene a senha e feche esta mensagem.",
"E2E_password_request_text": "Para acessar seus grupos privados e mensagens diretas criptografados , insira sua senha de criptografia. <br/>Você precisa digitar essa senha para codificar / decodificar suas mensagens em todos os clientes que você usa, já que a chave não está armazenada no servidor.",
Expand Down
91 changes: 3 additions & 88 deletions server/methods/createDirectMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ import { check } from 'meteor/check';

import { settings } from '../../app/settings';
import { hasPermission } from '../../app/authorization';
import { Users, Rooms, Subscriptions } from '../../app/models';
import { getDefaultSubscriptionPref } from '../../app/utils';
import { Users } from '../../app/models';
import { RateLimiter } from '../../app/lib';
import { callbacks } from '../../app/callbacks';
import { addUser } from '../../app/federation/server/functions/addUser';
import { createRoom } from '../../app/lib/server';

Meteor.methods({
createDirectMessage(username) {
Expand Down Expand Up @@ -58,91 +57,7 @@ Meteor.methods({
});
}

const rid = [me._id, to._id].sort().join('');

const now = new Date();

// Make sure we have a room
const roomUpsertResult = Rooms.upsert({
_id: rid,
}, {
$set: {
usernames: [me.username, to.username],
},
$setOnInsert: {
t: 'd',
msgs: 0,
ts: now,
usersCount: 2,
},
});

const myNotificationPref = getDefaultSubscriptionPref(me);

// Make user I have a subcription to this room
const upsertSubscription = {
$set: {
ls: now,
open: true,
},
$setOnInsert: {
fname: to.name,
name: to.username,
t: 'd',
alert: false,
unread: 0,
userMentions: 0,
groupMentions: 0,
customFields: me.customFields,
u: {
_id: me._id,
username: me.username,
},
ts: now,
...myNotificationPref,
},
};

if (to.active === false) {
upsertSubscription.$set.archived = true;
}

Subscriptions.upsert({
rid,
$and: [{ 'u._id': me._id }], // work around to solve problems with upsert and dot
}, upsertSubscription);

const toNotificationPref = getDefaultSubscriptionPref(to);

Subscriptions.upsert({
rid,
$and: [{ 'u._id': to._id }], // work around to solve problems with upsert and dot
}, {
$setOnInsert: {
fname: me.name,
name: me.username,
t: 'd',
open: false,
alert: false,
unread: 0,
userMentions: 0,
groupMentions: 0,
customFields: to.customFields,
u: {
_id: to._id,
username: to.username,
},
ts: now,
...toNotificationPref,
},
});

// If the room is new, run a callback
if (roomUpsertResult.insertedId) {
const insertedRoom = Rooms.findOneById(rid);

callbacks.run('afterCreateDirectRoom', insertedRoom, { from: me, to });
}
const { _id: rid } = createRoom('d', undefined, undefined, [me, to]);

return {
rid,
Expand Down

0 comments on commit 12fe0c3

Please sign in to comment.