mirror of https://github.com/qTox/qTox.git
Browse Source
Conflicts: src/autoupdate.cpp src/core.cpp src/core.h src/misc/settings.cpp src/widget/widget.cpppull/985/head
26 changed files with 1065 additions and 734 deletions
@ -0,0 +1,327 @@ |
|||||||
|
/*
|
||||||
|
Copyright (C) 2014 by Project Tox <https://tox.im>
|
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||||
|
|
||||||
|
This program is libre software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||||
|
|
||||||
|
See the COPYING file for more details. |
||||||
|
*/ |
||||||
|
|
||||||
|
/* This file is part of the Core class, but was separated for my sanity */ |
||||||
|
/* The load function delegates to loadEncrypted here, and the save function */ |
||||||
|
/* was permanently moved here to handle encryption */ |
||||||
|
|
||||||
|
#include "core.h" |
||||||
|
#include "src/widget/widget.h" |
||||||
|
#include <tox/tox.h> |
||||||
|
#include <tox/toxencryptsave.h> |
||||||
|
#include "src/misc/settings.h" |
||||||
|
#include "misc/cstring.h" |
||||||
|
#include "historykeeper.h" |
||||||
|
#include <QApplication> |
||||||
|
|
||||||
|
#include <QDebug> |
||||||
|
#include <QSaveFile> |
||||||
|
#include <QFile> |
||||||
|
#include <QThread> |
||||||
|
|
||||||
|
void Core::setPassword(QString& password, PasswordType passtype, uint8_t* salt) |
||||||
|
{ |
||||||
|
clearPassword(passtype); |
||||||
|
if (password.isEmpty()) |
||||||
|
return; |
||||||
|
|
||||||
|
pwsaltedkeys[passtype] = new uint8_t[tox_pass_key_length()]; |
||||||
|
|
||||||
|
CString str(password); |
||||||
|
if (salt) |
||||||
|
tox_derive_key_with_salt(str.data(), str.size(), salt, pwsaltedkeys[passtype]); |
||||||
|
else |
||||||
|
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkeys[passtype]); |
||||||
|
|
||||||
|
password.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
#include <algorithm> |
||||||
|
void Core::useOtherPassword(PasswordType type) |
||||||
|
{ |
||||||
|
clearPassword(type); |
||||||
|
pwsaltedkeys[type] = new uint8_t[tox_pass_key_length()]; |
||||||
|
|
||||||
|
PasswordType other = (type == ptMain) ? ptHistory : ptMain; |
||||||
|
|
||||||
|
std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+tox_pass_key_length(), pwsaltedkeys[type]); |
||||||
|
} |
||||||
|
|
||||||
|
void Core::clearPassword(PasswordType passtype) |
||||||
|
{ |
||||||
|
delete[] pwsaltedkeys[passtype]; |
||||||
|
pwsaltedkeys[passtype] = nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
// part of a hack, see core.h
|
||||||
|
void Core::saveCurrentInformation() |
||||||
|
{ |
||||||
|
if (pwsaltedkeys[ptMain]) |
||||||
|
{ |
||||||
|
backupkeys[ptMain] = new uint8_t[tox_pass_key_length()]; |
||||||
|
std::copy(pwsaltedkeys[ptMain], pwsaltedkeys[ptMain]+tox_pass_key_length(), backupkeys[ptMain]); |
||||||
|
} |
||||||
|
if (pwsaltedkeys[ptHistory]) |
||||||
|
{ |
||||||
|
backupkeys[ptHistory] = new uint8_t[tox_pass_key_length()]; |
||||||
|
std::copy(pwsaltedkeys[ptHistory], pwsaltedkeys[ptHistory]+tox_pass_key_length(), backupkeys[ptHistory]); |
||||||
|
} |
||||||
|
backupProfile = new QString(Settings::getInstance().getCurrentProfile()); |
||||||
|
} |
||||||
|
|
||||||
|
QString Core::loadOldInformation() |
||||||
|
{ |
||||||
|
QString out; |
||||||
|
if (backupProfile) |
||||||
|
{ |
||||||
|
out = *backupProfile; |
||||||
|
delete backupProfile; |
||||||
|
backupProfile = nullptr; |
||||||
|
} |
||||||
|
backupProfile = nullptr; |
||||||
|
clearPassword(ptMain); |
||||||
|
clearPassword(ptHistory); |
||||||
|
// we can just copy the pointer, as long as we null out backupkeys
|
||||||
|
// (if backupkeys was null anyways, then this is a null-op)
|
||||||
|
pwsaltedkeys[ptMain] = backupkeys[ptMain]; |
||||||
|
pwsaltedkeys[ptHistory] = backupkeys[ptHistory]; |
||||||
|
backupkeys[ptMain] = nullptr; |
||||||
|
backupkeys[ptHistory] = nullptr; |
||||||
|
return out; |
||||||
|
} |
||||||
|
|
||||||
|
QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype) |
||||||
|
{ |
||||||
|
if (!pwsaltedkeys[passtype]) |
||||||
|
return QByteArray(); |
||||||
|
uint8_t encrypted[data.size() + tox_pass_encryption_extra_length()]; |
||||||
|
if (tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkeys[passtype], encrypted) == -1) |
||||||
|
{ |
||||||
|
qWarning() << "Core::encryptData: encryption failed"; |
||||||
|
return QByteArray(); |
||||||
|
} |
||||||
|
return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + tox_pass_encryption_extra_length()); |
||||||
|
} |
||||||
|
|
||||||
|
QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype) |
||||||
|
{ |
||||||
|
if (!pwsaltedkeys[passtype]) |
||||||
|
return QByteArray(); |
||||||
|
int sz = data.size() - tox_pass_encryption_extra_length(); |
||||||
|
uint8_t decrypted[sz]; |
||||||
|
int decr_size = tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkeys[passtype], decrypted); |
||||||
|
if (decr_size != sz) |
||||||
|
{ |
||||||
|
qWarning() << "Core::decryptData: decryption failed"; |
||||||
|
return QByteArray(); |
||||||
|
} |
||||||
|
return QByteArray(reinterpret_cast<char*>(decrypted), sz); |
||||||
|
} |
||||||
|
|
||||||
|
bool Core::isPasswordSet(PasswordType passtype) |
||||||
|
{ |
||||||
|
if (pwsaltedkeys[passtype]) |
||||||
|
return true; |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
QByteArray Core::getSaltFromFile(QString filename) |
||||||
|
{ |
||||||
|
QFile file(filename); |
||||||
|
if (!file.open(QIODevice::ReadOnly)) |
||||||
|
{ |
||||||
|
qWarning() << "Core: file" << filename << "doesn't exist"; |
||||||
|
return QByteArray(); |
||||||
|
} |
||||||
|
QByteArray data = file.read(tox_pass_encryption_extra_length()); |
||||||
|
file.close(); |
||||||
|
|
||||||
|
uint8_t *salt = new uint8_t[tox_pass_salt_length()]; |
||||||
|
int err = tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt); |
||||||
|
if (err) |
||||||
|
{ |
||||||
|
qWarning() << "Core: can't get salt from" << filename << "header"; |
||||||
|
return QByteArray(); |
||||||
|
} |
||||||
|
|
||||||
|
QByteArray res = QByteArray::fromRawData(reinterpret_cast<const char*>(salt), tox_pass_salt_length()); |
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
bool Core::loadEncryptedSave(QByteArray& data) |
||||||
|
{ |
||||||
|
if (!Settings::getInstance().getEncryptTox()) |
||||||
|
Widget::getInstance()->showWarningMsgBox(tr("Encryption error"), tr("The .tox file is encrypted, but encryption was not checked, continuing regardless.")); |
||||||
|
|
||||||
|
int error = -1; |
||||||
|
QString a(tr("Please enter the password for the %1 profile.", "used in load() when no pw is already set").arg(Settings::getInstance().getCurrentProfile())); |
||||||
|
QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()")); |
||||||
|
QString dialogtxt; |
||||||
|
|
||||||
|
if (pwsaltedkeys[ptMain]) // password set, try it
|
||||||
|
{ |
||||||
|
error = tox_encrypted_key_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size(), pwsaltedkeys[ptMain]); |
||||||
|
if (!error) |
||||||
|
{ |
||||||
|
Settings::getInstance().setEncryptTox(true); |
||||||
|
return true; |
||||||
|
} |
||||||
|
dialogtxt = tr("The stored profile password failed. Please try another:", "used only when pw set before load() doesn't work"); |
||||||
|
} |
||||||
|
else |
||||||
|
dialogtxt = a; |
||||||
|
|
||||||
|
uint8_t salt[tox_pass_salt_length()]; |
||||||
|
tox_get_salt(reinterpret_cast<uint8_t *>(data.data()), salt); |
||||||
|
|
||||||
|
do |
||||||
|
{ |
||||||
|
QString pw = Widget::getInstance()->passwordDialog(tr("Change profile"), dialogtxt); |
||||||
|
|
||||||
|
if (pw.isEmpty()) |
||||||
|
{ |
||||||
|
clearPassword(ptMain); |
||||||
|
return false; |
||||||
|
} |
||||||
|
else |
||||||
|
setPassword(pw, ptMain, salt); |
||||||
|
|
||||||
|
error = tox_encrypted_key_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size(), pwsaltedkeys[ptMain]); |
||||||
|
dialogtxt = a + "\n" + b; |
||||||
|
} while (error != 0); |
||||||
|
|
||||||
|
Settings::getInstance().setEncryptTox(true); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
void Core::checkEncryptedHistory() |
||||||
|
{ |
||||||
|
QString path = HistoryKeeper::getHistoryPath(); |
||||||
|
bool exists = QFile::exists(path); |
||||||
|
|
||||||
|
QByteArray salt = getSaltFromFile(path); |
||||||
|
if (exists && salt.size() == 0) |
||||||
|
{ // maybe we should handle this better
|
||||||
|
Widget::getInstance()->showWarningMsgBox(tr("Encrypted History"), tr("No encrypted history file found, or it was corrupted.\nHistory will be disabled!")); |
||||||
|
Settings::getInstance().setEncryptLogs(false); |
||||||
|
Settings::getInstance().setEnableLogging(false); |
||||||
|
HistoryKeeper::resetInstance(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
QString a(tr("Please enter the password for the chat logs for the %1 profile.", "used in load() when no hist pw set").arg(Settings::getInstance().getCurrentProfile())); |
||||||
|
QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()")); |
||||||
|
QString dialogtxt; |
||||||
|
|
||||||
|
if (pwsaltedkeys[ptHistory]) |
||||||
|
{ |
||||||
|
if (!exists || HistoryKeeper::checkPassword()) |
||||||
|
return; |
||||||
|
dialogtxt = tr("The stored chat log password failed. Please try another:", "used only when pw set before load() doesn't work"); |
||||||
|
} |
||||||
|
else |
||||||
|
dialogtxt = a; |
||||||
|
|
||||||
|
if (pwsaltedkeys[ptMain]) |
||||||
|
{ |
||||||
|
useOtherPassword(ptHistory); |
||||||
|
if (!exists || HistoryKeeper::checkPassword()) |
||||||
|
{ |
||||||
|
qDebug() << "Core: using main password for history"; |
||||||
|
return; |
||||||
|
} |
||||||
|
clearPassword(ptHistory); |
||||||
|
} |
||||||
|
|
||||||
|
bool error = true; |
||||||
|
do |
||||||
|
{ |
||||||
|
QString pw = Widget::getInstance()->passwordDialog(tr("Disable history"), dialogtxt); |
||||||
|
|
||||||
|
if (pw.isEmpty()) |
||||||
|
{ |
||||||
|
clearPassword(ptHistory); |
||||||
|
Settings::getInstance().setEncryptLogs(false); |
||||||
|
Settings::getInstance().setEnableLogging(false); |
||||||
|
HistoryKeeper::resetInstance(); |
||||||
|
return; |
||||||
|
} |
||||||
|
else |
||||||
|
setPassword(pw, ptHistory, reinterpret_cast<uint8_t*>(salt.data())); |
||||||
|
|
||||||
|
error = exists && !HistoryKeeper::checkPassword(); |
||||||
|
dialogtxt = a + "\n" + b; |
||||||
|
} while (error); |
||||||
|
} |
||||||
|
|
||||||
|
void Core::saveConfiguration(const QString& path) |
||||||
|
{ |
||||||
|
if (QThread::currentThread() != coreThread) |
||||||
|
return (void) QMetaObject::invokeMethod(this, "saveConfiguration", Q_ARG(const QString&, path)); |
||||||
|
|
||||||
|
if (!isReady()) |
||||||
|
{ |
||||||
|
qWarning() << "Core::saveConfiguration: Tox not started, aborting!"; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
QSaveFile configurationFile(path); |
||||||
|
if (!configurationFile.open(QIODevice::WriteOnly)) { |
||||||
|
qCritical() << "File " << path << " cannot be opened"; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
qDebug() << "Core: writing tox_save to " << path; |
||||||
|
|
||||||
|
uint32_t fileSize; bool encrypt = Settings::getInstance().getEncryptTox(); |
||||||
|
if (encrypt) |
||||||
|
fileSize = tox_encrypted_size(tox); |
||||||
|
else |
||||||
|
fileSize = tox_size(tox); |
||||||
|
|
||||||
|
if (fileSize > 0 && fileSize <= INT32_MAX) { |
||||||
|
uint8_t *data = new uint8_t[fileSize]; |
||||||
|
|
||||||
|
if (encrypt) |
||||||
|
{ |
||||||
|
if (!pwsaltedkeys[ptMain]) |
||||||
|
{ |
||||||
|
// probably zero chance event
|
||||||
|
Widget::getInstance()->showWarningMsgBox(tr("NO Password"), tr("Encryption is enabled, but there is no password! Encryption will be disabled.")); |
||||||
|
Settings::getInstance().setEncryptTox(false); |
||||||
|
tox_save(tox, data); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
int ret = tox_encrypted_key_save(tox, data, pwsaltedkeys[ptMain]); |
||||||
|
if (ret == -1) |
||||||
|
{ |
||||||
|
qCritical() << "Core::saveConfiguration: encryption of save file failed!!!"; |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
tox_save(tox, data); |
||||||
|
|
||||||
|
configurationFile.write(reinterpret_cast<char *>(data), fileSize); |
||||||
|
configurationFile.commit(); |
||||||
|
delete[] data; |
||||||
|
} |
||||||
|
|
||||||
|
Settings::getInstance().save(); |
||||||
|
} |
@ -1,38 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
||||||
|
|
||||||
This program is libre software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||||
|
|
||||||
See the COPYING file for more details. |
|
||||||
*/ |
|
||||||
|
|
||||||
#include "inputpassworddialog.h" |
|
||||||
#include "ui_inputpassworddialog.h" |
|
||||||
|
|
||||||
InputPasswordDialog::InputPasswordDialog(QString title, QWidget *parent) : |
|
||||||
QDialog(parent), |
|
||||||
ui(new Ui::InputPasswordDialog) |
|
||||||
{ |
|
||||||
ui->setupUi(this); |
|
||||||
|
|
||||||
if (title != QString()) |
|
||||||
setWindowTitle(title); |
|
||||||
} |
|
||||||
|
|
||||||
InputPasswordDialog::~InputPasswordDialog() |
|
||||||
{ |
|
||||||
delete ui; |
|
||||||
} |
|
||||||
|
|
||||||
QString InputPasswordDialog::getPassword() |
|
||||||
{ |
|
||||||
return ui->passwordLineEdit->text(); |
|
||||||
} |
|
@ -1,40 +0,0 @@ |
|||||||
/*
|
|
||||||
Copyright (C) 2014 by Project Tox <https://tox.im>
|
|
||||||
|
|
||||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
|
||||||
|
|
||||||
This program is libre software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||||
|
|
||||||
See the COPYING file for more details. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef INPUTPASSWORDDIALOG_H |
|
||||||
#define INPUTPASSWORDDIALOG_H |
|
||||||
|
|
||||||
#include <QDialog> |
|
||||||
|
|
||||||
namespace Ui { |
|
||||||
class InputPasswordDialog; |
|
||||||
} |
|
||||||
|
|
||||||
class InputPasswordDialog : public QDialog |
|
||||||
{ |
|
||||||
Q_OBJECT |
|
||||||
|
|
||||||
public: |
|
||||||
explicit InputPasswordDialog(QString title = QString(), QWidget *parent = 0); |
|
||||||
~InputPasswordDialog(); |
|
||||||
|
|
||||||
QString getPassword(); |
|
||||||
|
|
||||||
private: |
|
||||||
Ui::InputPasswordDialog *ui; |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // INPUTPASSWORDDIALOG_H
|
|
@ -1,97 +0,0 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
|
||||||
<ui version="4.0"> |
|
||||||
<class>InputPasswordDialog</class> |
|
||||||
<widget class="QDialog" name="InputPasswordDialog"> |
|
||||||
<property name="geometry"> |
|
||||||
<rect> |
|
||||||
<x>0</x> |
|
||||||
<y>0</y> |
|
||||||
<width>400</width> |
|
||||||
<height>123</height> |
|
||||||
</rect> |
|
||||||
</property> |
|
||||||
<property name="windowTitle"> |
|
||||||
<string>Password Dialog</string> |
|
||||||
</property> |
|
||||||
<property name="modal"> |
|
||||||
<bool>true</bool> |
|
||||||
</property> |
|
||||||
<layout class="QVBoxLayout" name="verticalLayout"> |
|
||||||
<item> |
|
||||||
<widget class="QLabel" name="label"> |
|
||||||
<property name="text"> |
|
||||||
<string>Input password:</string> |
|
||||||
</property> |
|
||||||
</widget> |
|
||||||
</item> |
|
||||||
<item> |
|
||||||
<widget class="QLineEdit" name="passwordLineEdit"> |
|
||||||
<property name="cursor"> |
|
||||||
<cursorShape>IBeamCursor</cursorShape> |
|
||||||
</property> |
|
||||||
<property name="echoMode"> |
|
||||||
<enum>QLineEdit::Password</enum> |
|
||||||
</property> |
|
||||||
</widget> |
|
||||||
</item> |
|
||||||
<item> |
|
||||||
<spacer name="verticalSpacer"> |
|
||||||
<property name="orientation"> |
|
||||||
<enum>Qt::Vertical</enum> |
|
||||||
</property> |
|
||||||
<property name="sizeHint" stdset="0"> |
|
||||||
<size> |
|
||||||
<width>20</width> |
|
||||||
<height>40</height> |
|
||||||
</size> |
|
||||||
</property> |
|
||||||
</spacer> |
|
||||||
</item> |
|
||||||
<item> |
|
||||||
<widget class="QDialogButtonBox" name="buttonBox"> |
|
||||||
<property name="orientation"> |
|
||||||
<enum>Qt::Horizontal</enum> |
|
||||||
</property> |
|
||||||
<property name="standardButtons"> |
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> |
|
||||||
</property> |
|
||||||
</widget> |
|
||||||
</item> |
|
||||||
</layout> |
|
||||||
</widget> |
|
||||||
<resources/> |
|
||||||
<connections> |
|
||||||
<connection> |
|
||||||
<sender>buttonBox</sender> |
|
||||||
<signal>accepted()</signal> |
|
||||||
<receiver>InputPasswordDialog</receiver> |
|
||||||
<slot>accept()</slot> |
|
||||||
<hints> |
|
||||||
<hint type="sourcelabel"> |
|
||||||
<x>248</x> |
|
||||||
<y>254</y> |
|
||||||
</hint> |
|
||||||
<hint type="destinationlabel"> |
|
||||||
<x>157</x> |
|
||||||
<y>274</y> |
|
||||||
</hint> |
|
||||||
</hints> |
|
||||||
</connection> |
|
||||||
<connection> |
|
||||||
<sender>buttonBox</sender> |
|
||||||
<signal>rejected()</signal> |
|
||||||
<receiver>InputPasswordDialog</receiver> |
|
||||||
<slot>reject()</slot> |
|
||||||
<hints> |
|
||||||
<hint type="sourcelabel"> |
|
||||||
<x>316</x> |
|
||||||
<y>260</y> |
|
||||||
</hint> |
|
||||||
<hint type="destinationlabel"> |
|
||||||
<x>286</x> |
|
||||||
<y>274</y> |
|
||||||
</hint> |
|
||||||
</hints> |
|
||||||
</connection> |
|
||||||
</connections> |
|
||||||
</ui> |
|
Loading…
Reference in new issue