Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove table for e2e and add an e2eMangledName column #169

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 17 additions & 86 deletions src/common/syncjournaldb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Q_LOGGING_CATEGORY(lcDb, "nextcloud.sync.database", QtInfoMsg)

#define GET_FILE_RECORD_QUERY \
"SELECT path, inode, modtime, type, md5, fileid, remotePerm, filesize," \
" ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum" \
" ignoredChildrenRemote, contentchecksumtype.name || ':' || contentChecksum, e2eMangledName " \
" FROM metadata" \
" LEFT JOIN checksumtype as contentchecksumtype ON metadata.contentChecksumTypeId == contentchecksumtype.id"

Expand All @@ -55,6 +55,7 @@ static void fillFileRecordFromGetQuery(SyncJournalFileRecord &rec, SqlQuery &que
rec._fileSize = query.int64Value(7);
rec._serverHasIgnoredFiles = (query.intValue(8) > 0);
rec._checksumHeader = query.baValue(9);
rec._e2eMangledName = query.baValue(10);
}

static QString defaultJournalMode(const QString &dbPath)
Expand Down Expand Up @@ -468,17 +469,6 @@ bool SyncJournalDb::checkConnect()
return sqlFail("Create table version", createQuery);
}

/* maps the end to end filename in the server/metadata to the actuall filename in disk
*/
createQuery.prepare("CREATE TABLE IF NOT EXISTS e2efilemap("
"mangledname TEXT UNIQUE,"
"name TEXT UNIQUE"
")");

if (!createQuery.exec()) {
return sqlFail("Create table e2efilemap", createQuery);
}

bool forceRemoteDiscovery = false;

SqlQuery versionQuery("SELECT major, minor, patch FROM version;", _db);
Expand Down Expand Up @@ -595,8 +585,8 @@ bool SyncJournalDb::checkConnect()

_setFileRecordQuery.reset(new SqlQuery(_db));
if (_setFileRecordQuery->prepare("INSERT OR REPLACE INTO metadata "
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, contentChecksum, contentChecksumTypeId) "
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16);")) {
"(phash, pathlen, path, inode, uid, gid, mode, modtime, type, md5, fileid, remotePerm, filesize, ignoredChildrenRemote, contentChecksum, contentChecksumTypeId, e2eMangledName) "
"VALUES (?1 , ?2, ?3 , ?4 , ?5 , ?6 , ?7, ?8 , ?9 , ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17);")) {
return sqlFail("prepare _setFileRecordQuery", *_setFileRecordQuery);
}

Expand Down Expand Up @@ -716,16 +706,6 @@ bool SyncJournalDb::checkConnect()
return sqlFail("prepare _setDataFingerprintQuery2", *_setDataFingerprintQuery2);
}

_getE2eFileMangledName.reset(new SqlQuery(_db));
if (_getE2eFileMangledName->prepare("SELECT mangledname FROM e2efilemap WHERE name =?1;")) {
return sqlFail("prepare _getE2eFileMangledName", *_getE2eFileMangledName);
}

_setE2eFileRelationQuery.reset(new SqlQuery(_db));
if (_setE2eFileRelationQuery->prepare("INSERT INTO e2efilemap (mangledname, name) VALUES (?1, ?2);")) {
return sqlFail("prepare _setE2eFileRelationQuery", *_setE2eFileRelationQuery);
}

_getConflictRecordQuery.reset(new SqlQuery(_db));
if (_getConflictRecordQuery->prepare("SELECT baseFileId, baseModtime, baseEtag FROM conflicts WHERE path=?1;")) {
return sqlFail("prepare _getConflictRecordQuery", *_getConflictRecordQuery);
Expand Down Expand Up @@ -791,8 +771,6 @@ void SyncJournalDb::close()
_getDataFingerprintQuery.reset(0);
_setDataFingerprintQuery1.reset(0);
_setDataFingerprintQuery2.reset(0);
_setE2eFileRelationQuery.reset(0);
_getE2eFileMangledName.reset(0);
_getConflictRecordQuery.reset(0);
_setConflictRecordQuery.reset(0);
_deleteConflictRecordQuery.reset(0);
Expand All @@ -814,7 +792,7 @@ bool SyncJournalDb::updateDatabaseStructure()

bool SyncJournalDb::updateMetadataTableStructure()
{
QStringList columns = tableColumns("metadata");
const QStringList columns = tableColumns("metadata");
bool re = true;

// check if the file_id column is there and create it if not
Expand Down Expand Up @@ -905,6 +883,16 @@ bool SyncJournalDb::updateMetadataTableStructure()
commitInternal("update database structure: add contentChecksumTypeId col");
}

if (!columns.contains(QLatin1String("e2eMangledName"))) {
SqlQuery query(_db);
query.prepare("ALTER TABLE metadata ADD COLUMN e2eMangledName TEXT;");
if (!query.exec()) {
sqlFail("updateMetadataTableStructure: add e2eMangledName column", query);
re = false;
}
commitInternal("update database structure: add e2eMangledName col");
}

if (!tableColumns("uploadinfo").contains("contentChecksum")) {
SqlQuery query(_db);
query.prepare("ALTER TABLE uploadinfo ADD COLUMN contentChecksum TEXT;");
Expand Down Expand Up @@ -1063,6 +1051,7 @@ bool SyncJournalDb::setFileRecord(const SyncJournalFileRecord &_record)
_setFileRecordQuery->bindValue(14, record._serverHasIgnoredFiles ? 1 : 0);
_setFileRecordQuery->bindValue(15, checksum);
_setFileRecordQuery->bindValue(16, contentChecksumTypeId);
_setFileRecordQuery->bindValue(17, record._e2eMangledName);

if (!_setFileRecordQuery->exec()) {
return false;
Expand Down Expand Up @@ -1382,6 +1371,7 @@ bool SyncJournalDb::setFileRecordMetadata(const SyncJournalFileRecord &record)
existing._remotePerm = record._remotePerm;
existing._fileSize = record._fileSize;
existing._serverHasIgnoredFiles = record._serverHasIgnoredFiles;
existing._e2eMangledName = record._e2eMangledName;
return setFileRecord(existing);
}

Expand Down Expand Up @@ -1463,65 +1453,6 @@ void SyncJournalDb::setDownloadInfo(const QString &file, const SyncJournalDb::Do
}
}

QString SyncJournalDb::getE2eMangledName(const QString& originalName)
{
QMutexLocker locker(&_mutex);
qCDebug(lcDb) << "######### Trying to find database entry for name " << originalName << ". #######";

if (! checkConnect()) {
qCDebug(lcDb) << "######### Connection to the database is wrong. #######";
return QString{};
}

if (originalName.isEmpty()) {
qCDebug(lcDb) << "######### Original Name is Empty. #######";
return QString{};
}

_getE2eFileMangledName->reset_and_clear_bindings();
_getE2eFileMangledName->bindValue(1, originalName);
if (!_getE2eFileMangledName->exec()) {
qCDebug(lcDb) << "######### Error Executing query. #######";
return QString{};
}

if (!_getE2eFileMangledName->next()) {
qCDebug(lcDb) << "######### Query returned empty. #######";
return QString{};
}

const QString ret = _getE2eFileMangledName->stringValue(0);

qCDebug(lcDb) << "The return of the mangled name is" << ret;
return ret;
}

bool SyncJournalDb::setE2eRelation(const QString& mangledName, const QString& originalName)
{
Q_ASSERT(!mangledName.isEmpty());
Q_ASSERT(!originalName.isEmpty());

if (! checkConnect()) {
qCDebug(lcDb) << "######### Connection to the database is wrong. #######";
return false;
}

if (mangledName.isEmpty()) {
qCDebug(lcDb) << "Cant create e2e relation on the database, mangled name is empty.";
return false;
}

if (originalName.isEmpty()) {
qCDebug(lcDb) << "Cant create e2e relation on the database, original name is empty.";
return false;
}

_setE2eFileRelationQuery->reset_and_clear_bindings();
_setE2eFileRelationQuery->bindValue(1, mangledName);
_setE2eFileRelationQuery->bindValue(2, originalName);
return _setE2eFileRelationQuery->exec();
}

QVector<SyncJournalDb::DownloadInfo> SyncJournalDb::getAndDeleteStaleDownloadInfos(const QSet<QString> &keep)
{
QVector<SyncJournalDb::DownloadInfo> empty_result;
Expand Down
7 changes: 0 additions & 7 deletions src/common/syncjournaldb.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,6 @@ class OCSYNC_EXPORT SyncJournalDb : public QObject
void avoidRenamesOnNextSync(const QByteArray &path);
void setPollInfo(const PollInfo &);

bool setE2eRelation(const QString& mangledName, const QString& originalName);
QString getE2eMangledName(const QString& originalName);

QVector<PollInfo> getPollInfos();

enum SelectiveSyncListType {
Expand Down Expand Up @@ -290,10 +287,6 @@ class OCSYNC_EXPORT SyncJournalDb : public QObject
QScopedPointer<SqlQuery> _setConflictRecordQuery;
QScopedPointer<SqlQuery> _deleteConflictRecordQuery;

// End to End Encryption Related Queries/
QScopedPointer<SqlQuery> _setE2eFileRelationQuery;
QScopedPointer<SqlQuery> _getE2eFileMangledName;

/* This is the list of paths we called avoidReadFromDbOnNextSync on.
* It means that they should not be written to the DB in any case since doing
* that would write the etag and would void the purpose of avoidReadFromDbOnNextSync
Expand Down
1 change: 1 addition & 0 deletions src/common/syncjournalfilerecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class OCSYNC_EXPORT SyncJournalFileRecord
RemotePermissions _remotePerm;
bool _serverHasIgnoredFiles;
QByteArray _checksumHeader;
QByteArray _e2eMangledName;
};

bool OCSYNC_EXPORT
Expand Down
1 change: 1 addition & 0 deletions src/csync/csync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,5 +409,6 @@ std::unique_ptr<csync_file_stat_t> csync_file_stat_s::fromSyncJournalFileRecord(
st->size = rec._fileSize;
st->has_ignored_files = rec._serverHasIgnoredFiles;
st->checksumHeader = rec._checksumHeader;
st->e2eMangledName = rec._e2eMangledName;
return st;
}
1 change: 1 addition & 0 deletions src/csync/csync.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ struct OCSYNC_EXPORT csync_file_stat_s {
// In the remote tree, this will have the server checksum, if available.
// In both cases, the format is "SHA1:baff".
QByteArray checksumHeader;
QByteArray e2eMangledName;

CSYNC_STATUS error_status;

Expand Down
20 changes: 13 additions & 7 deletions src/csync/csync_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
return -1;
}

/*
* When file is encrypted it's phash (path hash) will not match the local file phash,
* we could match the e2eMangledName but that might be slow wihout index, and it's
* not UNIQUE at the moment.
*/

if(base.isValid()) { /* there is an entry in the database */
/* we have an update! */
qCInfo(lcUpdate, "Database entry found, compare: %" PRId64 " <-> %" PRId64
Expand Down Expand Up @@ -354,14 +360,14 @@ static int _csync_detect_update(CSYNC *ctx, std::unique_ptr<csync_file_stat_t> f
/* A remote rename can also mean Encryption Mangled Name.
* if we find one of those in the database, we ignore it.
*/
qCDebug(lcUpdate) << "Tryig to get the mangled name!";
QString remoteEncryptedName = ctx->statedb->getE2eMangledName(base._path);
if (remoteEncryptedName.isEmpty()) {
qCDebug(lcUpdate, "remote rename detected based on fileid %s --> %s", base._path.constData(), fs->path.constData());
fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
} else {
qCDebug(lcUpdate) << "Should *not* rename the file.";
if (!base._e2eMangledName.isEmpty()) {
qCWarning(lcUpdate, "Encrypted file can not rename");
done = true;
return;
}

qCDebug(lcUpdate, "remote rename detected based on fileid %s --> %s", qPrintable(base._path), qPrintable(fs->path.constData()));
fs->instruction = CSYNC_INSTRUCTION_EVAL_RENAME;
done = true;
};

Expand Down
6 changes: 4 additions & 2 deletions src/libsync/propagatedownload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -934,9 +934,11 @@ void PropagateDownloadFile::updateMetadata(bool isConflict)
done(SyncFileItem::FatalError, tr("Error writing metadata to the database"));
return;
}
propagator()->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo());

if (_isEncrypted) {
propagator()->_journal->setE2eRelation(_item->_encryptedFileName, _item->_file);
propagator()->_journal->setDownloadInfo(_item->_file, SyncJournalDb::DownloadInfo());
} else {
propagator()->_journal->setDownloadInfo(_item->_encryptedFileName, SyncJournalDb::DownloadInfo());
}

propagator()->_journal->commit("download file start2");
Expand Down
6 changes: 3 additions & 3 deletions src/libsync/propagatedownloadencrypted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,11 @@ bool PropagateDownloadEncrypted::decryptFile(QFile& tmpFile)

//TODO: This seems what's breaking the logic.
// Let's fool the rest of the logic into thinking this is the right name of the DAV file
_item->_isEndToEndEncrypted = true;
_item->_encryptedFileName = _item->_file;
_item->_file = _item->_file.section(QLatin1Char('/'), 0, -2)
+ QLatin1Char('/') + _encryptedInfo.originalFilename;
+ QLatin1Char('/') + _encryptedInfo.originalFilename;

_item->_isEndToEndEncrypted = true;
_item->_encryptedFileName = _encryptedInfo.encryptedFilename;

return true;
}
Expand Down
11 changes: 9 additions & 2 deletions src/libsync/propagateremotedelete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,17 @@ void PropagateRemoteDelete::start()
if (propagator()->_abortRequested.fetchAndAddRelaxed(0))
return;

qCDebug(lcPropagateRemoteDelete) << _item->_file;

QString remoteFile = _item->_file;
if (!_item->_encryptedFileName.isEmpty()) {
remoteFile = _item->_encryptedFileName;
// TODO update the JSON metadata
}

qCDebug(lcPropagateRemoteDelete) << "local" << _item->_file << "remote" << remoteFile;

_job = new DeleteJob(propagator()->account(),
propagator()->_remoteFolder + _item->_file,
propagator()->_remoteFolder + remoteFile,
this);
connect(_job.data(), &DeleteJob::finishedSignal, this, &PropagateRemoteDelete::slotDeleteJobFinished);
propagator()->_activeJobList.append(this);
Expand Down
8 changes: 0 additions & 8 deletions src/libsync/propagateupload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,14 +681,6 @@ void PropagateUploadFileCommon::finalize()
return;
}

if (_uploadingEncrypted) {
if (!propagator()->_journal->setE2eRelation(_item->_encryptedFileName, _item->_file)) {
qDebug() << "Error saving the encryption relation of the file.";
} else {
qDebug() << "Sabed the encryption relation of the file successfully";
}
}

// Remove from the progress database:
propagator()->_journal->setUploadInfo(_item->_file, SyncJournalDb::UploadInfo());
propagator()->_journal->commit("upload file start");
Expand Down
4 changes: 3 additions & 1 deletion src/libsync/propagateuploadencrypted.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ void PropagateUploadEncrypted::slotFolderEncriptedMetadataReceived(const QJsonDo
encryptedFile.initializationVector = EncryptionHelper::generateRandom(16);

// New encrypted file so set it all up!

if (encryptedFile.encryptedFilename.isEmpty()) {
encryptedFile.encryptedFilename = EncryptionHelper::generateRandomFilename();
encryptedFile.fileVersion = 1;
Expand All @@ -141,7 +142,8 @@ void PropagateUploadEncrypted::slotFolderEncriptedMetadataReceived(const QJsonDo
}

_item->_isEndToEndEncrypted = true;
_item->_encryptedFileName = encryptedFile.encryptedFilename;
_item->_encryptedFileName = _item->_file.section(QLatin1Char('/'), 0, -2)
+ QLatin1Char('/') + encryptedFile.encryptedFilename;

qCDebug(lcPropagateUploadEncrypted) << "Creating the encrypted file.";

Expand Down
4 changes: 3 additions & 1 deletion src/libsync/syncfileitem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SyncJournalFileRecord SyncFileItem::toSyncJournalFileRecordWithInode(const QStri
rec._remotePerm = _remotePerm;
rec._serverHasIgnoredFiles = _serverHasIgnoredFiles;
rec._checksumHeader = _checksumHeader;
rec._e2eMangledName = _encryptedFileName.toUtf8();

// Go through csync vio just to get the inode.
csync_file_stat_t fs;
Expand All @@ -55,7 +56,7 @@ SyncJournalFileRecord SyncFileItem::toSyncJournalFileRecordWithInode(const QStri
SyncFileItemPtr SyncFileItem::fromSyncJournalFileRecord(const SyncJournalFileRecord &rec)
{
SyncFileItemPtr item(new SyncFileItem);
item->_file = rec._path;
item->_file = QString::fromUtf8(rec._path);
item->_inode = rec._inode;
item->_modtime = rec._modtime;
item->_type = rec._type;
Expand All @@ -65,6 +66,7 @@ SyncFileItemPtr SyncFileItem::fromSyncJournalFileRecord(const SyncJournalFileRec
item->_remotePerm = rec._remotePerm;
item->_serverHasIgnoredFiles = rec._serverHasIgnoredFiles;
item->_checksumHeader = rec._checksumHeader;
item->_encryptedFileName = QString::fromUtf8(rec._e2eMangledName);
return item;
}

Expand Down