Fix read-only shared folders with password change

pull/1/head
yflory 5 years ago
parent 0583ed3c8b
commit f9723a6183

@ -6,6 +6,7 @@ define([
'/common/common-messaging.js',
'/common/common-constants.js',
'/common/common-feedback.js',
'/common/userObject.js',
'/common/outer/local-store.js',
'/common/outer/worker-channel.js',
'/common/outer/login-block.js',
@ -13,7 +14,7 @@ define([
'/customize/application_config.js',
'/bower_components/nthen/index.js',
], function (Config, Messages, Util, Hash,
Messaging, Constants, Feedback, LocalStore, Channel, Block,
Messaging, Constants, Feedback, UserObject, LocalStore, Channel, Block,
AppConfig, Nthen) {
/* This file exposes functionality which is specific to Cryptpad, but not to
@ -158,7 +159,7 @@ define([
});
};
common.addSharedFolder = function (teamId, secret, cb) {
var href = secret.keys && secret.keys.editKeyStr ? '/drive/#' + Hash.getEditHashFromKeys(secret) : undefined;
var href = (secret.keys && secret.keys.editKeyStr) ? '/drive/#' + Hash.getEditHashFromKeys(secret) : undefined;
postMessage("ADD_SHARED_FOLDER", {
teamId: teamId,
path: ['root'],
@ -878,6 +879,8 @@ define([
initialState: isSharedFolder ? '{}' : undefined
};
var cryptgetVal;
Nthen(function (waitFor) {
if (parsed.hashData && parsed.hashData.password) {
common.getPadAttribute('password', waitFor(function (err, password) {
@ -946,13 +949,22 @@ define([
waitFor.abort();
return void cb({ error: err });
}
Crypt.put(newHash, val, waitFor(function (err) {
if (err) {
waitFor.abort();
return void cb({ error: err });
}
}), optsPut);
cryptgetVal = val;
if (isSharedFolder) {
var parsed = JSON.parse(val || '{}');
var oldKey = parsed.version === 2 && oldSecret.keys.secondaryKey;
var newKey = newSecret.keys.secondaryKey;
UserObject.reencrypt(oldKey, newKey, parsed);
cryptgetVal = JSON.stringify(parsed);
}
}), optsGet);
}).nThen(function (waitFor) {
Crypt.put(newHash, cryptgetVal, waitFor(function (err) {
if (err) {
waitFor.abort();
return void cb({ error: err });
}
}), optsPut);
}).nThen(function (waitFor) {
if (isSharedFolder) {
postMessage("UPDATE_SHARED_FOLDER_PASSWORD", {
@ -1514,7 +1526,6 @@ define([
noWorker = localStorage.CryptPad_noWorkers === '1';
console.error('WebWorker/SharedWorker state forced to ' + !noWorker);
}
noWorker = true;
Nthen(function (waitFor2) {
if (Worker) {
var w = waitFor2();

@ -116,6 +116,7 @@ define([
sf.teams.push({
cb: cb,
store: store,
secondaryKey: secondaryKey,
id: id
});
if (handler) { handler(id, sf.rt); }
@ -126,16 +127,17 @@ define([
teams: [{
cb: cb,
store: store,
secondaryKey: secondaryKey,
id: id
}],
readOnly: Boolean(secondaryKey)
readOnly: !Boolean(secondaryKey)
};
var owners = data.owners;
var listmapConfig = {
data: {},
channel: secret.channel,
readOnly: Boolean(secondaryKey),
readOnly: !Boolean(secondaryKey),
crypto: Crypto.createEncryptor(secret.keys),
userName: 'sharedFolder',
logLevel: 1,
@ -158,7 +160,7 @@ define([
}
sf.teams.forEach(function (obj) {
var leave = function () { SF.leave(secret.channel, teamId); };
var uo = obj.store.manager.addProxy(obj.id, rt, leave, secondaryKey);
var uo = obj.store.manager.addProxy(obj.id, rt, leave, obj.secondaryKey);
SF.checkMigration(secondaryKey, rt.proxy, uo, function () {
obj.cb(sf.rt, info.metadata);
});
@ -171,10 +173,8 @@ define([
if (info.error === "EDELETED" ) {
try {
// Deprecate the shared folder from each team
// XXX We can't deprecate a read-only proxy: the read-only seed will change...
// We can only remove it
// We can only hide it
sf.teams.forEach(function (obj) {
console.log(obj.store.id, obj.store, obj.id);
obj.store.manager.deprecateProxy(obj.id, secret.channel);
});
} catch (e) {}
@ -187,6 +187,7 @@ define([
});
};
SF.upgrade = function (channel, secret) {
var sf = allSharedFolders[channel];
if (!sf || !sf.readOnly) { return; }
@ -235,17 +236,21 @@ define([
}
var nt = nThen;
sf.teams.forEach(function (obj) {
// XXX if we're a viewer in this team, we can't update the keys
nt = nt(function (waitFor) {
var s = obj.store;
var sfId = obj.id;
// We can't update the password of a shared folder in a read-only team
if (s.manager.user.userObject.readOnly) {
// Just deprecate the folder so that inner can stop displaying a folder no longer available
if (s.manager.folders[sfId]) {
s.manager.folders[sfId].proxy = { deprecated: true };
}
return;
}
var shared = Util.find(s.proxy, ['drive', UserObject.SHARED_FOLDERS]) || {};
if (!sfId || !shared[sfId]) { return; }
var sf = JSON.parse(JSON.stringify(shared[sfId]));
sf.password = password;
sf.channel = secret.channel;
sf.href = '/drive/#'+Hash.getEditHashFromKeys(secret); // XXX encrypt
sf.roHref = '/drive/#'+Hash.getViewHashFromKeys(secret);
SF.load({
network: network,
store: s,
@ -256,7 +261,9 @@ define([
s.rpc.pin([secret.channel], waitFor());
}).nThen;
});
nt(cb);
nt(function () {
cb();
});
};
/* loadSharedFolders

@ -71,19 +71,21 @@ define([
cb(null, clone(data[attr]));
};
exp.pushData = function (data, cb) {
exp.pushData = function (_data, cb) {
if (typeof cb !== "function") { cb = function () {}; }
if (readOnly) { return void cb('EFORBIDDEN'); }
var id = Util.createRandomInteger();
var data = clone(_data);
// If we were given an edit link, encrypt its value if needed
if (data.href) { data.href = exp.cryptor.encrypt(data.href); }
files[FILES_DATA][id] = data;
cb(null, id);
};
exp.pushSharedFolder = function (data, cb) {
exp.pushSharedFolder = function (_data, cb) {
if (typeof cb !== "function") { cb = function () {}; }
if (readOnly) { return void cb('EFORBIDDEN'); }
var data = clone(_data);
// Check if we already have this shared folder in our drive
var exists;
@ -476,6 +478,9 @@ define([
files.migrateRo = 1;
var next = function () {
var copy = JSON.parse(JSON.stringify(files));
exp.reencrypt(null, config.editKey, copy);
// XXX test migration again
/*
Object.keys(copy[FILES_DATA]).forEach(function (id) {
var data = copy[FILES_DATA][id] || {};
// If this pad has a visible href, encrypt it
@ -490,7 +495,7 @@ define([
if (data.href && data.roHref && !data.fileType && data.href.indexOf('#') !== -1) {
data.href = exp.cryptor.encrypt(data.href);
}
});
});*/
copy.version = 2;
delete copy.migrateRo;

@ -52,6 +52,13 @@ define([
// Password may have changed
var deprecateProxy = function (Env, id, channel) {
if (Env.user.userObject.readOnly) {
// In a read-only team, we can't deprecate a shared folder
if (Env.folders[id]) {
Env.folders[id].proxy = { deprecated: true };
}
return void Env.Store.refreshDriveUI();
}
Env.unpinPads([channel], function () {});
Env.user.userObject.deprecateSharedFolder(id);
if (Env.Store && Env.Store.refreshDriveUI) {
@ -554,7 +561,8 @@ define([
var secret = Hash.getSecrets(parsed.type, parsed.hash, newPassword);
data.password = newPassword;
data.channel = secret.channel;
data.href = '/drive/#'+Hash.getEditHashFromKeys(secret); // XXX encrypt
var _href = '/drive/#'+Hash.getEditHashFromKeys(secret);
data.href = Env.user.userObject.cryptor.encrypt(_href);
data.roHref = '/drive/#'+Hash.getViewHashFromKeys(secret);
_addSharedFolder(Env, {
path: ['root'],

@ -15,6 +15,8 @@ define([
var TEMPLATE = module.TEMPLATE = "template";
var SHARED_FOLDERS = module.SHARED_FOLDERS = "sharedFolders";
var SHARED_FOLDERS_TEMP = module.SHARED_FOLDERS_TEMP = "sharedFoldersTemp"; // Maybe deleted or new password
var FILES_DATA = module.FILES_DATA = Constants.storageKey;
var OLD_FILES_DATA = module.OLD_FILES_DATA = Constants.oldStorageKey;
// Create untitled documents when no name is given
var getLocaleDate = function () {
@ -66,6 +68,37 @@ define([
return pad.roHref;
};
module.reencrypt = function (oldKey, newKey, obj) {
obj = obj || {};
var oldCryptor = createCryptor(oldKey);
var newCryptor = createCryptor(newKey);
Object.keys(obj[FILES_DATA]).forEach(function (id) {
var data = obj[FILES_DATA][id] || {};
// If this pad has a visible href, encrypt it
// "&& data.roHref" is here to make sure this is not a "file"
if (data.href && data.roHref && !data.fileType) {
var _href = oldCryptor.decrypt(data.href);
data.href = newCryptor.encrypt(_href);
}
});
Object.keys(obj[SHARED_FOLDERS] || {}).forEach(function (id) {
var data = obj[SHARED_FOLDERS][id] || {};
// If this folder has a visible href, encrypt it
if (data.href) {
var _href = oldCryptor.decrypt(data.href);
data.href = newCryptor.encrypt(_href);
}
});
Object.keys(obj[SHARED_FOLDERS_TEMP] || {}).forEach(function (id) {
var data = obj[SHARED_FOLDERS_TEMP][id] || {};
// If this folder has a visible href, encrypt it
if (data.href) {
var _href = oldCryptor.decrypt(data.href);
data.href = newCryptor.encrypt(_href);
}
});
};
module.init = function (files, config) {
var exp = {};
@ -74,18 +107,19 @@ define([
exp.setReadOnly = function (state, key) {
config.editKey = key;
createCryptor(key);
exp.readOnly = state;
if (exp._setReadOnly) {
// Change outer
exp._setReadOnly(state);
}
};
exp.readOnly = config.readOnly;
exp.reencrypt = module.reencrypt;
exp.getDefaultName = module.getDefaultName;
var sframeChan = config.sframeChan;
var FILES_DATA = module.FILES_DATA = exp.FILES_DATA = Constants.storageKey;
var OLD_FILES_DATA = module.OLD_FILES_DATA = exp.OLD_FILES_DATA = Constants.oldStorageKey;
var NEW_FOLDER_NAME = Messages.fm_newFolder || 'New folder';
var NEW_FILE_NAME = Messages.fm_newFile || 'New file';
@ -95,6 +129,8 @@ define([
exp.TEMPLATE = TEMPLATE;
exp.SHARED_FOLDERS = SHARED_FOLDERS;
exp.SHARED_FOLDERS_TEMP = SHARED_FOLDERS_TEMP;
exp.FILES_DATA = FILES_DATA;
exp.OLD_FILES_DATA = OLD_FILES_DATA;
var sharedFolder = exp.sharedFolder = config.sharedFolder;
exp.id = config.id;

Loading…
Cancel
Save