Commit 7c895730 authored by Karel Slaný's avatar Karel Slaný

Using shared class PinSettings.

parent 9a213117
......@@ -94,6 +94,7 @@ SOURCES += \
src/datovka_shared/io/sqlite/db.cpp \
src/datovka_shared/io/sqlite/db_single.cpp \
src/datovka_shared/io/sqlite/table.cpp \
src/datovka_shared/settings/pin.cpp \
src/datovka_shared/worker/pool.cpp \
src/dialogues/dialogues.cpp \
src/dialogues/qml_dialogue_helper.cpp \
......@@ -156,6 +157,7 @@ HEADERS += \
src/datovka_shared/io/sqlite/db.h \
src/datovka_shared/io/sqlite/db_single.h \
src/datovka_shared/io/sqlite/table.h \
src/datovka_shared/settings/pin.h \
src/datovka_shared/worker/pool.h \
src/dialogues/dialogues.h \
src/dialogues/qml_dialogue_helper.h \
......
/*
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include "src/datovka_shared/crypto/crypto_pin.h"
#include "src/datovka_shared/crypto/crypto_wrapped.h"
#include "src/datovka_shared/settings/pin.h"
#include "src/log/log.h"
#define SETTINGS_SECURITY_GROUP "security"
//#define SETTINGS_PIN_VAL "pin_val" // Don't store readable PIN value into settings.
#define SETTINGS_PIN_ALG "pin_alg"
#define SETTINGS_PIN_SALT "pin_salt"
#define SETTINGS_PIN_CODE "pin_code"
PinSettings::PinSettings(void)
: _pinVal(),
pinAlg(),
pinSalt(),
pinCode()
{
}
void PinSettings::loadFromSettings(const QSettings &settings)
{
//_pinVal = QString::fromUtf8(QByteArray::fromBase64(
// settings.value(SETTINGS_SECURITY_GROUP "/" SETTINGS_PIN_VAL,
// QString()).toString().toUtf8()));
pinAlg = settings.value(SETTINGS_SECURITY_GROUP "/" SETTINGS_PIN_ALG,
QString()).toString();
pinSalt = QByteArray::fromBase64(settings.value(
SETTINGS_SECURITY_GROUP "/" SETTINGS_PIN_SALT,
QString()).toString().toUtf8());
pinCode = QByteArray::fromBase64(settings.value(
SETTINGS_SECURITY_GROUP "/" SETTINGS_PIN_CODE,
QString()).toString().toUtf8());
}
void PinSettings::saveToSettings(QSettings &settings) const
{
settings.beginGroup(SETTINGS_SECURITY_GROUP);
if (!_pinVal.isEmpty()) {
//settings.setValue(SETTINGS_PIN_VAL,
// QString::fromUtf8(_pinVal.toUtf8().toBase64()));
Q_ASSERT(!pinAlg.isEmpty());
settings.setValue(SETTINGS_PIN_ALG, pinAlg);
Q_ASSERT(!pinSalt.isEmpty());
settings.setValue(SETTINGS_PIN_SALT,
QString::fromUtf8(pinSalt.toBase64()));
Q_ASSERT(!pinCode.isEmpty());
settings.setValue(SETTINGS_PIN_CODE,
QString::fromUtf8(pinCode.toBase64()));
}
settings.endGroup();
}
bool PinSettings::pinConfigured(void) const
{
return !pinAlg.isEmpty() && !pinSalt.isEmpty() && !pinCode.isEmpty();
}
void PinSettings::updatePinSettings(PinSettings &sett, const QString &pinValue)
{
QByteArray pinSalt;
QByteArray pinCode;
if (!pinValue.isEmpty()) {
/* Generate random salt. */
pinSalt = randomSalt(pbkdf2_sha256.out_len);
pinCode = computePinCode(pinValue, pbkdf2_sha256.name, pinSalt,
pbkdf2_sha256.out_len);
}
if (!pinCode.isEmpty()) {
sett._pinVal = pinValue;
sett.pinAlg = pbkdf2_sha256.name;
sett.pinSalt = pinSalt;
sett.pinCode = pinCode;
} else {
sett._pinVal.clear();
sett.pinAlg.clear();
sett.pinSalt.clear();
sett.pinCode.clear();
}
}
bool PinSettings::verifyPin(PinSettings &sett, const QString &pinValue)
{
if (sett.pinAlg.isEmpty() || sett.pinSalt.isEmpty() ||
sett.pinCode.isEmpty()) {
logErrorNL("%s",
"PIN algorithm, PIN salt or encoded PIN are missing.");
return false;
}
bool verResult = sett.pinCode == computePinCode(pinValue,
sett.pinAlg, sett.pinSalt, pbkdf2_sha256.out_len);
if (verResult) {
/* Remember entered correct PIN. */
sett._pinVal = pinValue;
logDebugLv0NL("%s", "Remembering entered PIN value.");
}
return verResult;
}
/*
* Copyright (C) 2014-2017 CZ.NIC
*
* This program is free 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#pragma once
#include <QByteArray>
#include <QSettings>
#include <QString>
/*!
* @brief Encapsulates code needed for storing PIN code.
*/
class PinSettings {
public:
/*!
* @brief Constructor.
*/
PinSettings(void);
/*!
* @brief Load data from supplied settings.
*
* @param[in] settings Settings structure.
*/
void loadFromSettings(const QSettings &settings);
/*!
* @brief Store data to settings structure.
*
* @param[out] settings Settings structure.
*/
void saveToSettings(QSettings &settings) const;
/*!
* @brief Check whether PIN value is configured.
*
* @return True if algorithm, salt and encoded PIN are set.
*/
bool pinConfigured(void) const;
/*!
* @brief Update PIN settings.
*
* @param[in,out] sett Settings to be modified.
* @param[in] pinValue New PIN value.
*/
static
void updatePinSettings(PinSettings &sett, const QString &pinValue);
/*!
* @brief Verifies the PIN.
*
* @note PIN value is stored within setting structure if ented PIN is
* valid.
*
* @param[in,out] sett PIN settings to be verified.
* @param[in] pinValue PIN to be verified.
* @return True if PIN value was successfully verified.
*/
static
bool verifyPin(PinSettings &sett, const QString &pinValue);
QString _pinVal; /*! PIN value is not read from the configuration file, nor it is stored to the configuration file. */
QString pinAlg; /*!< PIN algorithm identifier. */
QByteArray pinSalt; /*!< Salt value used to generate PIN hash. */
QByteArray pinCode; /*!< Hashed PIN code. */
};
......@@ -470,8 +470,7 @@ int main(int argc, char *argv[])
* Store the configuration only when PIN has been recovered or is not
* used.
*/
if (!globSet._pinVal.isEmpty() ||
globSet.pinAlg.isEmpty() || globSet.pinSalt.isEmpty() || globSet.pinCode.isEmpty()) {
if (!globSet._pinVal.isEmpty() || !globSet.pinConfigured()) {
/*
* The PIN was set/recovered or
* incomplete data to check/recover the PIN were supplied.
......
......@@ -27,21 +27,53 @@
#include <QStandardPaths>
#include "src/io/filesystem.h"
#include "src/log/log.h"
#include "src/settings.h"
/* Name of Datovka configuration file */
#define SETTINGS_FILE_NAME "datovka.conf"
/* Supported languages. Default is system */
#define LANGUAGE_SYSTEM "system"
#define LANGUAGE_CS "cs"
#define LANGUAGE_EN "en"
/* Default value which define how long will have
* attachment files stored in local database (in days)*/
#define DEFAULT_MSG_LIFETIME 90
#define DEFAULT_FILE_LIFETIME 10
#define DEFAULT_ZFO_LIMIT_MB 200
#define DEFAULT_PIN_INACT_TIMEOUT 0
#define DEFAULT_FONT_SIZE 16
/* Names of setting items in GLOBALS group in the datovka.conf file */
#define SETTINGS_GLOBAL_GROUP "GLOBALS"
#define SETTINGS_ONLY_NEW_MSGS "only_new_msgs"
#define SETTINGS_COMPLETE_MSG "complete_msgs"
#define SETTINGS_MSG_LIFETIME_IN_DAYS "msg_lifetime"
#define SETTINGS_FILE_LIFETIME_IN_DAYS "file_lifetime"
#define SETTINGS_ZFO_LIMIT_MB "zfo_db_max_size"
#define SETTINGS_PIN_INACT_TIMEOUT_IN_SECS "pin_inact_timeout"
#define SETTINGS_LAST_UPDATE "last_update"
#define SETTINGS_LANGUAGE "language"
#define SETTINGS_FONTSIZE "font_size"
#define SETTINGS_DBS_LOCATION "dbs_location"
/*
* These names are kept for backward compatibility purposes. They were formerly
* in GLOBALS, now they are in separate group.
*/
#define SETTINGS_PIN_ALG "pin_alg"
#define SETTINGS_PIN_SALT "pin_salt"
#define SETTINGS_PIN_CODE "pin_code"
Settings globSet;
Settings::Settings(void)
: language(LANGUAGE_SYSTEM),
: PinSettings(),
language(LANGUAGE_SYSTEM),
fontSize(DEFAULT_FONT_SIZE),
downloadOnlyNewMsgs(true),
downloadCompleteMsgs(false),
msgLifeTimeInDays(DEFAULT_MSG_LIFETIME),
fileLifeTimeInDays(DEFAULT_FILE_LIFETIME),
_pinVal(),
pinAlg(),
pinSalt(),
pinCode(),
pinInactTimeoutInSecs(DEFAULT_PIN_INACT_TIMEOUT),
dbsLocation(),
zfoDbSizeMBs(DEFAULT_ZFO_LIMIT_MB),
......@@ -63,17 +95,21 @@ void Settings::saveToSettings(QSettings &settings) const
settings.setValue(SETTINGS_ZFO_LIMIT_MB, zfoDbSizeMBs);
if (!_pinVal.isEmpty()) {
Q_ASSERT(!pinAlg.isEmpty());
settings.setValue(SETTINGS_PIN_ALG, pinAlg);
Q_ASSERT(!pinSalt.isEmpty());
settings.setValue(SETTINGS_PIN_SALT,
QString::fromUtf8(pinSalt.toBase64()));
Q_ASSERT(!pinCode.isEmpty());
settings.setValue(SETTINGS_PIN_CODE,
QString::fromUtf8(pinCode.toBase64()));
{
/*
* Code in this block needs to be kept for a while
* (until the end of 2018?) because of keeping
* backward compatibility.
*/
Q_ASSERT(!pinAlg.isEmpty());
settings.setValue(SETTINGS_PIN_ALG, pinAlg);
Q_ASSERT(!pinSalt.isEmpty());
settings.setValue(SETTINGS_PIN_SALT,
QString::fromUtf8(pinSalt.toBase64()));
Q_ASSERT(!pinCode.isEmpty());
settings.setValue(SETTINGS_PIN_CODE,
QString::fromUtf8(pinCode.toBase64()));
}
if (pinInactTimeoutInSecs > 0) {
/* Only when some value is used. */
......@@ -89,6 +125,11 @@ void Settings::saveToSettings(QSettings &settings) const
}
settings.endGroup();
/*
* The PIN settings are newly kept in a separate group.
*/
PinSettings::saveToSettings(settings);
}
void Settings::loadFromSettings(const QSettings &settings)
......@@ -113,16 +154,32 @@ void Settings::loadFromSettings(const QSettings &settings)
SETTINGS_GLOBAL_GROUP "/" SETTINGS_ZFO_LIMIT_MB,
DEFAULT_ZFO_LIMIT_MB).toInt();
pinAlg = settings.value(SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_ALG,
QString()).toString();
pinSalt = QByteArray::fromBase64(settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_SALT,
QString()).toString().toUtf8());
pinCode = QByteArray::fromBase64(settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_CODE,
QString()).toString().toUtf8());
/*
* The PIN settings are newly kept in a separate group.
*/
PinSettings::loadFromSettings(settings);
/* Clear read PIN settings in not entire data present. */
if (!PinSettings::pinConfigured()) {
PinSettings::updatePinSettings(*this, QString());
logWarningNL("Trying to read PIn settings from '%s' group.",
SETTINGS_GLOBAL_GROUP);
/*
* First, the PIN settings were stored in 'GLOBALS' group.
* Therefore we need to keep this code functional at least for
* a while (until the end of 2018?).
*/
pinAlg = settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_ALG,
QString()).toString();
pinSalt = QByteArray::fromBase64(settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_SALT,
QString()).toString().toUtf8());
pinCode = QByteArray::fromBase64(settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_CODE,
QString()).toString().toUtf8());
}
pinInactTimeoutInSecs = settings.value(
SETTINGS_GLOBAL_GROUP "/" SETTINGS_PIN_INACT_TIMEOUT_IN_SECS,
......
......@@ -27,40 +27,13 @@
#include <QSettings>
#include <QString>
/* Name of Datovka configuration file */
#define SETTINGS_FILE_NAME "datovka.conf"
/* Supported languages. Default is system */
#define LANGUAGE_SYSTEM "system"
#define LANGUAGE_CS "cs"
#define LANGUAGE_EN "en"
/* Default value which define how long will have
* attachment files stored in local database (in days)*/
#define DEFAULT_MSG_LIFETIME 90
#define DEFAULT_FILE_LIFETIME 10
#define DEFAULT_ZFO_LIMIT_MB 200
#define DEFAULT_PIN_INACT_TIMEOUT 0
#define DEFAULT_FONT_SIZE 16
/* Names of setting items in GLOBALS group in the datovka.conf file */
#define SETTINGS_GLOBAL_GROUP "GLOBALS"
#define SETTINGS_ONLY_NEW_MSGS "only_new_msgs"
#define SETTINGS_COMPLETE_MSG "complete_msgs"
#define SETTINGS_MSG_LIFETIME_IN_DAYS "msg_lifetime"
#define SETTINGS_FILE_LIFETIME_IN_DAYS "file_lifetime"
#define SETTINGS_ZFO_LIMIT_MB "zfo_db_max_size"
#define SETTINGS_PIN_ALG "pin_alg"
#define SETTINGS_PIN_SALT "pin_salt"
#define SETTINGS_PIN_CODE "pin_code"
#define SETTINGS_PIN_INACT_TIMEOUT_IN_SECS "pin_inact_timeout"
#define SETTINGS_LAST_UPDATE "last_update"
#define SETTINGS_LANGUAGE "language"
#define SETTINGS_FONTSIZE "font_size"
#define SETTINGS_DBS_LOCATION "dbs_location"
#include "src/datovka_shared/settings/pin.h"
/*
* This class hold and manage global settings data of Datovka.
* Class is initialized as global instance here.
*/
class Settings {
class Settings : public PinSettings {
public:
/*!
......@@ -123,10 +96,6 @@ public:
bool downloadCompleteMsgs; /*!< Download complete messages. */
int msgLifeTimeInDays; /*!< Message life time in days. */
int fileLifeTimeInDays; /*!< File life time in days. */
QString _pinVal; /*! PIN value is not read from the configuration file, nor it is stored to the configuration file. */
QString pinAlg; /*!< PIN algorithm identifier. */
QByteArray pinSalt; /*!< Salt value used to generate PIN hash. */
QByteArray pinCode; /*!< Hashed PIN code. */
int pinInactTimeoutInSecs; /*!< Inactivity locking interval. */
QString dbsLocation; /*!< Path to databses location. */
int zfoDbSizeMBs; /*!< Zfo database max size in MB. */
......
......@@ -133,46 +133,17 @@ QString GlobalSettingsQmlWrapper::pinValue(void) const
void GlobalSettingsQmlWrapper::updatePinSettings(const QString &pinValue)
{
QByteArray pinSalt;
QByteArray pinCode;
if (!pinValue.isEmpty()) {
/* Generate random salt. */
pinSalt = randomSalt(pbkdf2_sha256.out_len);
pinCode = computePinCode(pinValue, pbkdf2_sha256.name, pinSalt,
pbkdf2_sha256.out_len);
}
if (!pinCode.isEmpty()) {
globSet._pinVal = pinValue;
globSet.pinAlg = pbkdf2_sha256.name;
globSet.pinSalt = pinSalt;
globSet.pinCode = pinCode;
} else {
globSet._pinVal.clear();
globSet.pinAlg.clear();
globSet.pinSalt.clear();
globSet.pinCode.clear();
}
PinSettings::updatePinSettings(globSet, pinValue);
}
void GlobalSettingsQmlWrapper::verifyPin(const QString &pinValue)
{
if (globSet.pinAlg.isEmpty() || globSet.pinSalt.isEmpty() ||
globSet.pinCode.isEmpty()) {
qCritical("%s",
"PIN algorithm, PIN salt or encoded PIN are missing.");
if (!globSet.pinConfigured()) {
return;
}
bool verResult = globSet.pinCode == computePinCode(pinValue,
globSet.pinAlg, globSet.pinSalt, pbkdf2_sha256.out_len);
bool verResult = PinSettings::verifyPin(globSet, pinValue);
if (verResult) {
/* Remember entered correct PIN. */
globSet._pinVal = pinValue;
qDebug("%s", "Remembering entered PIN value.");
/* Decrypt all keys in account model. */
AccountListModel::decryptAllPwds(globSet._pinVal);
}
......@@ -180,8 +151,9 @@ void GlobalSettingsQmlWrapper::verifyPin(const QString &pinValue)
emit sendPinReply(verResult);
if (verResult && !globSet.lastUpdateStr().isEmpty()) {
emit statusBarTextChanged(tr("Last synchronisation: %1")
.arg(globSet.lastUpdateStr()), false);
emit statusBarTextChanged(
tr("Last synchronisation: %1").arg(globSet.lastUpdateStr()),
false);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment