Restructured locations of source.
This commit is contained in:
parent
78a4c6d730
commit
7c4e8e95e8
151 changed files with 1 additions and 0 deletions
|
|
@ -1,100 +0,0 @@
|
|||
#include "BackupFormatModel.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
class BackupFormatItem {
|
||||
public:
|
||||
const QString shortFlag;
|
||||
const QString longFlag;
|
||||
const QString description;
|
||||
|
||||
BackupFormatItem(QString s, QString l, QString d)
|
||||
: shortFlag(std::move(s))
|
||||
, longFlag(std::move(l))
|
||||
, description(std::move(d))
|
||||
{}
|
||||
};
|
||||
|
||||
using t_BackupFormatItemVector = std::vector<BackupFormatItem>;
|
||||
|
||||
|
||||
t_BackupFormatItemVector g_BackupFormats = {
|
||||
BackupFormatItem{ "p", "plain", "Output a plaintext SQL script, restore with psql" },
|
||||
BackupFormatItem{ "c", "custom", "Postgresql's own format most flexible and compressed, restore with pg_restore" },
|
||||
BackupFormatItem{ "d", "directory", "Generates a directory with a file for each table or blob" },
|
||||
BackupFormatItem{ "t", "tar", "Similar to directory if untarred it results in a valid directory backup" }
|
||||
};
|
||||
|
||||
} // end of unnamed namespace
|
||||
|
||||
|
||||
|
||||
BackupFormatModel::BackupFormatModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
//QVariant BackupFormatModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
//{
|
||||
// QVariant result;
|
||||
|
||||
// if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
|
||||
// switch (section) {
|
||||
// case Column::Short:
|
||||
// result = tr("Short");
|
||||
// break;
|
||||
// case Column::Long:
|
||||
// result = tr("Long");
|
||||
// break;
|
||||
// case Column::Description:
|
||||
// result = tr("Description");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// return result;
|
||||
//}
|
||||
|
||||
|
||||
int BackupFormatModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
int size = g_BackupFormats.size();
|
||||
return size;
|
||||
}
|
||||
|
||||
int BackupFormatModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return 3;
|
||||
|
||||
}
|
||||
|
||||
QVariant BackupFormatModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QVariant result;
|
||||
if (index.isValid()) {
|
||||
const int row = index.row();
|
||||
const int col = index.column();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
const auto &item = g_BackupFormats.at(row);
|
||||
switch (col) {
|
||||
case ColumnShort:
|
||||
result = item.shortFlag;
|
||||
break;
|
||||
case ColumnLong:
|
||||
result = item.longFlag;
|
||||
break;
|
||||
case ColumnDescription:
|
||||
result = item.description;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (role == Qt::ToolTipRole) {
|
||||
const auto &item = g_BackupFormats.at(row);
|
||||
result = item.description;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef BACKUPFORMATMODEL_H
|
||||
#define BACKUPFORMATMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
class BackupFormatModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Column { ColumnShort=1, ColumnLong=0, ColumnDescription=2 };
|
||||
|
||||
explicit BackupFormatModel(QObject *parent);
|
||||
|
||||
// Header:
|
||||
// QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // BACKUPFORMATMODEL_H
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
#include "CsvWriter.h"
|
||||
|
||||
CsvWriter::CsvWriter()
|
||||
{}
|
||||
|
||||
CsvWriter::CsvWriter(QTextStream *output)
|
||||
: m_output(output)
|
||||
{}
|
||||
|
||||
void CsvWriter::setDestination(QTextStream *output)
|
||||
{
|
||||
m_output = output;
|
||||
m_column = 0;
|
||||
}
|
||||
|
||||
void CsvWriter::setSeperator(QChar ch)
|
||||
{
|
||||
m_seperator = ch;
|
||||
}
|
||||
|
||||
void CsvWriter::setQuote(QChar ch)
|
||||
{
|
||||
m_quote = ch;
|
||||
}
|
||||
|
||||
void CsvWriter::writeField(QString field)
|
||||
{
|
||||
QTextStream &out = *m_output;
|
||||
if (m_column > 0) {
|
||||
out << m_seperator;
|
||||
}
|
||||
// if field contains any of seperator, quote or newline then it needs to be quoted
|
||||
// when quoted quotes need to be doubled to escape them
|
||||
bool needs_quotes = false;
|
||||
for (auto ch : field) {
|
||||
if (ch == '\n' || ch == m_seperator || ch == m_quote) {
|
||||
needs_quotes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_quotes) {
|
||||
out << m_quote;
|
||||
for (auto ch : field) {
|
||||
if (ch == m_quote)
|
||||
out << m_quote;
|
||||
out << ch;
|
||||
}
|
||||
out << m_quote;
|
||||
}
|
||||
else {
|
||||
out << field;
|
||||
}
|
||||
++m_column;
|
||||
}
|
||||
|
||||
|
||||
void CsvWriter::nextRow()
|
||||
{
|
||||
QTextStream &out = *m_output;
|
||||
out << '\n';
|
||||
m_column = 0;
|
||||
}
|
||||
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef CSVWRITER_H
|
||||
#define CSVWRITER_H
|
||||
|
||||
#include <ostream>
|
||||
#include <QTextStream>
|
||||
|
||||
class CsvWriter {
|
||||
public:
|
||||
CsvWriter();
|
||||
explicit CsvWriter(QTextStream *output);
|
||||
void setDestination(QTextStream *output);
|
||||
void setSeperator(QChar ch);
|
||||
void setQuote(QChar ch);
|
||||
void writeField(QString field);
|
||||
void nextRow();
|
||||
private:
|
||||
QChar m_seperator = ',';
|
||||
QChar m_quote = '"';
|
||||
QTextStream *m_output = nullptr;
|
||||
int m_column = 0;
|
||||
};
|
||||
|
||||
#endif // CSVWRITER_H
|
||||
271
core/Expected.h
271
core/Expected.h
|
|
@ -1,271 +0,0 @@
|
|||
#ifndef EXPECTED_H
|
||||
#define EXPECTED_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
|
||||
template <typename T>
|
||||
class Expected {
|
||||
union {
|
||||
T m_value;
|
||||
std::exception_ptr m_error;
|
||||
};
|
||||
bool m_valid;
|
||||
Expected() {} // internal use
|
||||
|
||||
public:
|
||||
|
||||
Expected(const T& rhs)
|
||||
: m_value(rhs), m_valid(true)
|
||||
{}
|
||||
|
||||
Expected(T&& rhs)
|
||||
: m_value(std::move(rhs))
|
||||
, m_valid(true)
|
||||
{}
|
||||
|
||||
|
||||
Expected(const Expected& rhs)
|
||||
: m_valid(rhs.valid)
|
||||
{
|
||||
if (m_valid) {
|
||||
new (&m_value) T(rhs.m_value);
|
||||
}
|
||||
else {
|
||||
new (&m_error) std::exception_ptr(rhs.m_error);
|
||||
}
|
||||
}
|
||||
|
||||
Expected(Expected &&rhs)
|
||||
: m_valid(rhs.m_valid)
|
||||
{
|
||||
if (m_valid) {
|
||||
new (&m_value) T(std::move(rhs.m_value));
|
||||
}
|
||||
else {
|
||||
new (&m_error) std::exception_ptr(std::move(rhs.m_error));
|
||||
}
|
||||
}
|
||||
|
||||
~Expected()
|
||||
{
|
||||
if (m_valid) {
|
||||
m_value.~T();
|
||||
}
|
||||
else {
|
||||
using std::exception_ptr;
|
||||
m_error.~exception_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
// void swap(Expected& rhs)
|
||||
// {
|
||||
// if (m_valid) {
|
||||
// if (rhs.m_valid) {
|
||||
// using std::swap;
|
||||
// swap(m_value, rhs.m_value);
|
||||
// }
|
||||
// else {
|
||||
// auto t = std::move(rhs.m_error);
|
||||
// new(&rhs.m_value) T(std::move(m_value));
|
||||
// new(&m_error) std::exception_ptr(t);
|
||||
// std::swap(m_valid, rhs.m_valid);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (rhs.m_valid) {
|
||||
// rhs.swap(*this);
|
||||
// }
|
||||
// else {
|
||||
// using std::swap;
|
||||
// swap(m_error, rhs.m_error);
|
||||
// std::swap(m_valid, rhs.m_valid);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
template <class E>
|
||||
static Expected<T> fromException(const E& exception)
|
||||
{
|
||||
if (typeid(exception) != typeid(E)) {
|
||||
throw std::invalid_argument("slicing detected");
|
||||
}
|
||||
return fromException(std::make_exception_ptr(exception));
|
||||
}
|
||||
|
||||
static Expected<T> fromException(std::exception_ptr p)
|
||||
{
|
||||
Expected<T> result;
|
||||
result.m_valid = false;
|
||||
new (&result.m_error) std::exception_ptr(std::move(p));
|
||||
return result;
|
||||
}
|
||||
|
||||
static Expected<T> fromException()
|
||||
{
|
||||
return fromException(std::current_exception());
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
T& get()
|
||||
{
|
||||
if (!m_valid) {
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
return m_value;
|
||||
}
|
||||
|
||||
const T& get() const
|
||||
{
|
||||
if (!m_valid) {
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
return m_value;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
bool hasException() const
|
||||
{
|
||||
try {
|
||||
if (!m_valid) {
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
}
|
||||
catch (const E& ) {
|
||||
return true;
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class F>
|
||||
static Expected fromCode(F fun)
|
||||
{
|
||||
try {
|
||||
return Expected(fun());
|
||||
}
|
||||
catch (...) {
|
||||
return fromException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
class Expected<void> {
|
||||
std::exception_ptr m_error;
|
||||
bool m_valid;
|
||||
|
||||
public:
|
||||
|
||||
Expected<void>()
|
||||
: m_valid(true)
|
||||
{}
|
||||
|
||||
|
||||
Expected(const Expected& rhs)
|
||||
: m_error(rhs.m_error)
|
||||
, m_valid(rhs.m_valid)
|
||||
{}
|
||||
|
||||
Expected(Expected<void> &&rhs)
|
||||
: m_error(std::move(rhs.m_error))
|
||||
, m_valid(rhs.m_valid)
|
||||
{}
|
||||
|
||||
~Expected()
|
||||
{}
|
||||
|
||||
// void swap(Expected& rhs)
|
||||
// {
|
||||
// if (m_valid) {
|
||||
// if (!rhs.m_valid) {
|
||||
// m_error = rhs.m_error;
|
||||
// std::swap(m_valid, rhs.m_valid);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (rhs.m_valid) {
|
||||
// rhs.swap(*this);
|
||||
// }
|
||||
// else {
|
||||
// using std::swap;
|
||||
// swap(m_error, rhs.m_error);
|
||||
// std::swap(m_valid, rhs.m_valid);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
template <class E>
|
||||
static Expected<void> fromException(const E& exception)
|
||||
{
|
||||
if (typeid(exception) != typeid(E)) {
|
||||
throw std::invalid_argument("slicing detected");
|
||||
}
|
||||
return fromException(std::make_exception_ptr(exception));
|
||||
}
|
||||
|
||||
static Expected<void> fromException(std::exception_ptr p)
|
||||
{
|
||||
Expected<void> result;
|
||||
result.m_valid = false;
|
||||
result.m_error = std::exception_ptr(std::move(p));
|
||||
return result;
|
||||
}
|
||||
|
||||
static Expected<void> fromException()
|
||||
{
|
||||
return fromException(std::current_exception());
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
void get() const
|
||||
{
|
||||
if (!m_valid) {
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class E>
|
||||
bool hasException() const
|
||||
{
|
||||
try {
|
||||
if (!m_valid) {
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
}
|
||||
catch (const E& ) {
|
||||
return true;
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class F>
|
||||
static Expected fromCode(F fun)
|
||||
{
|
||||
try {
|
||||
fun();
|
||||
return Expected<void>();
|
||||
}
|
||||
catch (...) {
|
||||
return fromException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // EXPECTED_H
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
#include "PasswordManager.h"
|
||||
|
||||
#include <botan/filters.h>
|
||||
#include <botan/pipe.h>
|
||||
#include <botan/sha2_64.h>
|
||||
#include <botan/hash.h>
|
||||
#include <botan/hmac.h>
|
||||
#include <botan/pbkdf2.h>
|
||||
#include <botan/rng.h>
|
||||
#include <botan/base64.h>
|
||||
#include <botan/loadstor.h>
|
||||
#include <botan/mem_ops.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
||||
using namespace Botan;
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
First 24 bits of SHA-256("Botan Cryptobox"), followed by 8 0 bits
|
||||
for later use as flags, etc if needed
|
||||
*/
|
||||
const uint8_t c_PasswordVersionCode = 0x10;
|
||||
|
||||
const size_t c_VersionCodeLen = 1;
|
||||
|
||||
const size_t CIPHER_KEY_LEN = 32;
|
||||
const size_t CIPHER_IV_LEN = 16;
|
||||
const size_t MAC_KEY_LEN = 32;
|
||||
const size_t MAC_OUTPUT_LEN = 20;
|
||||
const size_t PBKDF_SALT_LEN = 10;
|
||||
const size_t PBKDF_ITERATIONS = 8 * 1024;
|
||||
|
||||
const size_t PBKDF_OUTPUT_LEN = CIPHER_KEY_LEN + CIPHER_IV_LEN + MAC_KEY_LEN;
|
||||
|
||||
const char * const c_Cipher = "Serpent/CTR-BE";
|
||||
|
||||
const char * const c_IniGroupSecurity = "Security";
|
||||
|
||||
|
||||
|
||||
StrengthenedKey generateKey(const std::string &passphrase, const uint8_t *salt, int saltlength)
|
||||
{
|
||||
PKCS5_PBKDF2 pbkdf(new HMAC(new SHA_512));
|
||||
OctetString master_key = pbkdf.derive_key(
|
||||
PBKDF_OUTPUT_LEN,
|
||||
passphrase,
|
||||
salt, saltlength,
|
||||
PBKDF_ITERATIONS);
|
||||
|
||||
const uint8_t* mk = master_key.begin();
|
||||
|
||||
return StrengthenedKey(
|
||||
SymmetricKey(mk, CIPHER_KEY_LEN),
|
||||
SymmetricKey(mk + CIPHER_KEY_LEN, MAC_KEY_LEN),
|
||||
InitializationVector(mk + CIPHER_KEY_LEN + MAC_KEY_LEN, CIPHER_IV_LEN));
|
||||
}
|
||||
|
||||
// secure_vector<uint8_t> pbkdf_salt(PBKDF_SALT_LEN);
|
||||
// rng.randomize( pbkdf_salt.data(), pbkdf_salt.size());
|
||||
// StrengthenedKey strengthened_key = generateKey(passphrase, pbkdf_salt.data(), pbkdf_salt.size());
|
||||
|
||||
|
||||
std::string encrypt(const std::string &input,
|
||||
const StrengthenedKey &strengthened_key)
|
||||
{
|
||||
|
||||
Pipe pipe(get_cipher(c_Cipher, strengthened_key.cipher_key,
|
||||
strengthened_key.iv, ENCRYPTION),
|
||||
new Fork(
|
||||
nullptr,
|
||||
new MAC_Filter(new HMAC(new SHA_512),
|
||||
strengthened_key.mac_key, MAC_OUTPUT_LEN)));
|
||||
|
||||
pipe.process_msg((const uint8_t*)input.data(), input.length());
|
||||
|
||||
/*
|
||||
Output format is:
|
||||
mac (20 bytes)
|
||||
ciphertext
|
||||
*/
|
||||
const size_t ciphertext_len = pipe.remaining(0);
|
||||
std::vector<uint8_t> out_buf(MAC_OUTPUT_LEN + ciphertext_len);
|
||||
|
||||
BOTAN_ASSERT_EQUAL(
|
||||
pipe.read(&out_buf[0], MAC_OUTPUT_LEN, 1),
|
||||
MAC_OUTPUT_LEN, "MAC output");
|
||||
BOTAN_ASSERT_EQUAL(
|
||||
pipe.read(&out_buf[MAC_OUTPUT_LEN], ciphertext_len, 0),
|
||||
ciphertext_len, "Ciphertext size");
|
||||
|
||||
return base64_encode(out_buf.data(), out_buf.size());
|
||||
}
|
||||
|
||||
std::string decrypt(const std::string &input, const StrengthenedKey &strengthened_key)
|
||||
{
|
||||
secure_vector<uint8_t> ciphertext = base64_decode(input);
|
||||
|
||||
if(ciphertext.size() < (MAC_OUTPUT_LEN)) {
|
||||
throw Decoding_Error("Invalid encrypted password input");
|
||||
}
|
||||
|
||||
Pipe pipe(new Fork(
|
||||
get_cipher(c_Cipher, strengthened_key.cipher_key, strengthened_key.iv, DECRYPTION),
|
||||
new MAC_Filter(new HMAC(new SHA_512), strengthened_key.mac_key, MAC_OUTPUT_LEN)
|
||||
));
|
||||
|
||||
const size_t ciphertext_offset = MAC_OUTPUT_LEN;
|
||||
pipe.process_msg(&ciphertext[ciphertext_offset], ciphertext.size() - ciphertext_offset);
|
||||
|
||||
uint8_t computed_mac[MAC_OUTPUT_LEN];
|
||||
BOTAN_ASSERT_EQUAL(MAC_OUTPUT_LEN, pipe.read(computed_mac, MAC_OUTPUT_LEN, 1), "MAC size");
|
||||
|
||||
if(!same_mem(computed_mac, &ciphertext[0], MAC_OUTPUT_LEN)) {
|
||||
throw Decoding_Error("Encrypted password integrity failure");
|
||||
}
|
||||
|
||||
return pipe.read_all_as_string(0);
|
||||
}
|
||||
|
||||
struct constants {
|
||||
const int pbkdf_salt_len;
|
||||
};
|
||||
|
||||
constants v1_consts = {
|
||||
10
|
||||
};
|
||||
|
||||
} // end of unnamed namespace
|
||||
|
||||
/*
|
||||
* File layout:
|
||||
*
|
||||
* Header
|
||||
* version
|
||||
* key_salt
|
||||
* hash_salt
|
||||
* master_hash
|
||||
*
|
||||
*
|
||||
* Passwords
|
||||
* key = pw
|
||||
*/
|
||||
|
||||
|
||||
|
||||
PasswordManager::PasswordManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Expected<bool> PasswordManager::unlock(const std::string &master_password)
|
||||
{
|
||||
try {
|
||||
bool result = false;
|
||||
if (m_masterHash.length() == 0 && master_password.empty()) {
|
||||
result = true;
|
||||
} else {
|
||||
StrengthenedKey key = generateKey(master_password, m_keySalt.begin(), m_keySalt.length());
|
||||
OctetString hash = hashStrengthenedKey(key, m_hashSalt);
|
||||
|
||||
BOOST_ASSERT_MSG(hash.length() == m_masterHash.length(), "Both hashes should have the same length! Versioning error?");
|
||||
|
||||
if (same_mem(m_masterHash.begin(), hash.begin(), hash.length())) {
|
||||
result = true;
|
||||
m_masterKey = key;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (...) {
|
||||
return Expected<bool>::fromException();
|
||||
}
|
||||
}
|
||||
|
||||
Expected<bool> PasswordManager::changeMasterPassword(const std::string &old_master_password,
|
||||
const std::string &new_master_password)
|
||||
{
|
||||
try {
|
||||
bool result = false;
|
||||
if (m_masterHash.length() == 0 && old_master_password.empty()) {
|
||||
// Nothing set yet so we initialize for first use
|
||||
m_keySalt = OctetString(m_rng, v1_consts.pbkdf_salt_len);
|
||||
m_masterKey = generateKey(new_master_password, m_keySalt.begin(), m_keySalt.length());
|
||||
|
||||
m_hashSalt = OctetString(m_rng, v1_consts.pbkdf_salt_len);
|
||||
m_masterHash = hashStrengthenedKey(m_masterKey, m_hashSalt);
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
} catch (...) {
|
||||
return Expected<bool>::fromException();
|
||||
}
|
||||
}
|
||||
|
||||
void PasswordManager::lock()
|
||||
{
|
||||
m_masterKey = StrengthenedKey();
|
||||
}
|
||||
|
||||
bool PasswordManager::locked() const
|
||||
{
|
||||
return m_masterKey.cipher_key.size() == 0;
|
||||
}
|
||||
|
||||
Expected<void> PasswordManager::savePassword(const std::string &key, const std::string &password)
|
||||
{
|
||||
if (locked()) {
|
||||
return Expected<void>::fromException(std::logic_error("Need to unlock the password manager first"));
|
||||
}
|
||||
std::string epw = encrypt(password, m_masterKey);
|
||||
m_store.emplace(key, epw);
|
||||
|
||||
return Expected<void>();
|
||||
}
|
||||
|
||||
Expected<bool> PasswordManager::getPassword(const std::string &key, std::string &out)
|
||||
{
|
||||
if (locked()) {
|
||||
return Expected<bool>::fromException(std::logic_error("Need to unlock the password manager first"));
|
||||
}
|
||||
auto fi = m_store.find(key);
|
||||
|
||||
bool result = false;
|
||||
if (fi != m_store.end()) {
|
||||
out = decrypt(fi->second, m_masterKey);
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Botan::OctetString PasswordManager::hashStrengthenedKey(const StrengthenedKey &key, const OctetString &salt)
|
||||
{
|
||||
std::unique_ptr<Botan::HashFunction> hash3(Botan::HashFunction::create("SHA-3"));
|
||||
BOOST_ASSERT_MSG(hash3 != nullptr, "SHA-3 algorithm not available");
|
||||
hash3->update(salt.begin(), salt.length());
|
||||
hash3->update(key.cipher_key.begin(), key.cipher_key.length());
|
||||
hash3->update(key.mac_key.begin(), key.mac_key.length());
|
||||
hash3->update(key.iv.begin(), key.iv.length());
|
||||
return hash3->final();
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
#ifndef PASSWORDMANAGER_H
|
||||
#define PASSWORDMANAGER_H
|
||||
|
||||
#include "Expected.h"
|
||||
#include <string>
|
||||
|
||||
#include <botan/botan.h>
|
||||
#include <botan/symkey.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
struct StrengthenedKey {
|
||||
Botan::SymmetricKey cipher_key;
|
||||
Botan::SymmetricKey mac_key;
|
||||
Botan::InitializationVector iv;
|
||||
|
||||
StrengthenedKey() {}
|
||||
StrengthenedKey(const Botan::SymmetricKey &ck, const Botan::SymmetricKey &mk,
|
||||
const Botan::InitializationVector &i)
|
||||
: cipher_key(ck)
|
||||
, mac_key(mk)
|
||||
, iv(i)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
class PasswordManager {
|
||||
public:
|
||||
|
||||
// static PasswordManager create(const std::string &file_name);
|
||||
|
||||
PasswordManager();
|
||||
/** Unlocks the passwords of the connections.
|
||||
*
|
||||
* \return Normally it return a bool specifying if the password was accepted.
|
||||
* on rare occasions it could return an error.
|
||||
*/
|
||||
Expected<bool> unlock(const std::string &master_password);
|
||||
|
||||
Expected<bool> changeMasterPassword(const std::string &master_password,
|
||||
const std::string &new_master_password);
|
||||
|
||||
/** Forget master password
|
||||
*/
|
||||
void lock();
|
||||
bool locked() const;
|
||||
|
||||
Expected<void> savePassword(const std::string &key, const std::string &password);
|
||||
Expected<bool> getPassword(const std::string &key, std::string &out);
|
||||
|
||||
private:
|
||||
Botan::AutoSeeded_RNG m_rng;
|
||||
Botan::OctetString m_keySalt; // salt for generating crypto key
|
||||
StrengthenedKey m_masterKey; // crypto key
|
||||
Botan::OctetString m_hashSalt; // salt of the hash of the passphrase
|
||||
Botan::OctetString m_masterHash; // hash for checking the passphrase
|
||||
|
||||
using t_KeyPasswords = std::map<std::string, std::string>;
|
||||
|
||||
t_KeyPasswords m_store;
|
||||
|
||||
static Botan::OctetString hashStrengthenedKey(const StrengthenedKey &key, const Botan::OctetString &salt);
|
||||
};
|
||||
|
||||
|
||||
#endif // PASSWORDMANAGER_H
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
#ifndef SCOPEGUARD_H
|
||||
#define SCOPEGUARD_H
|
||||
|
||||
/** \brief Template class for executing code at scope exit.
|
||||
*
|
||||
* By default the object will be an active mode and execute the function
|
||||
* passed to the constructor when the object is destructed. You can however
|
||||
* cancel this action by calling dismiss().
|
||||
*
|
||||
* There is a clever macro that allows you to write something like
|
||||
* SCOPE_EXIT { foo(); };
|
||||
*/
|
||||
template<class Fun>
|
||||
class ScopeGuard {
|
||||
Fun f_;
|
||||
bool active_;
|
||||
public:
|
||||
ScopeGuard(Fun f)
|
||||
: f_(std::move(f))
|
||||
, active_(true) {
|
||||
}
|
||||
|
||||
~ScopeGuard() { if(active_) f_(); }
|
||||
|
||||
void dismiss() { active_=false; }
|
||||
|
||||
ScopeGuard() = delete;
|
||||
ScopeGuard(const ScopeGuard&) = delete;
|
||||
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
||||
ScopeGuard(ScopeGuard&& rhs)
|
||||
: f_(std::move(rhs.f_))
|
||||
, active_(rhs.active_)
|
||||
{
|
||||
rhs.dismiss();
|
||||
}
|
||||
};
|
||||
|
||||
template<class Fun>
|
||||
ScopeGuard<Fun> scopeGuard(Fun f)
|
||||
{
|
||||
return ScopeGuard<Fun>(std::move(f));
|
||||
}
|
||||
|
||||
namespace ScopeGuard_detail {
|
||||
|
||||
enum class ScopeGuardOnExit {};
|
||||
|
||||
template<typename Fun>
|
||||
ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun&& fn) {
|
||||
return ScopeGuard<Fun>(std::forward<Fun>(fn));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define CONCATENATE_IMPL(s1, s2) s1##s2
|
||||
#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
|
||||
#ifdef __COUNTER__
|
||||
#define ANONYMOUS_VARIABLE(str) \
|
||||
CONCATENATE(str,__COUNTER__)
|
||||
#else
|
||||
#define ANONYMOUS_VARIABLE(str) \
|
||||
CONCATENATE(str,__LINE__)
|
||||
#endif
|
||||
|
||||
#define SCOPE_EXIT \
|
||||
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) \
|
||||
= ::ScopeGuard_detail::ScopeGuardOnExit() + [&]()
|
||||
|
||||
#endif // SCOPEGUARD_H
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
#include "SqlLexer.h"
|
||||
|
||||
SqlLexer::SqlLexer(const QString &block, LexerState currentstate)
|
||||
: m_block(block)
|
||||
, m_state(currentstate)
|
||||
{}
|
||||
|
||||
QChar SqlLexer::nextChar()
|
||||
{
|
||||
QChar result = QChar::Null;
|
||||
if (m_pos < m_block.size()) {
|
||||
result = m_block.at(m_pos++);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QChar SqlLexer::peekChar()
|
||||
{
|
||||
QChar result = QChar::Null;
|
||||
if (m_pos < m_block.size()) {
|
||||
result = m_block.at(m_pos);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NextBasicToken
|
||||
* @param in
|
||||
* @param ofs
|
||||
* @param start
|
||||
* @param length
|
||||
* @return false when input seems invalid, it will return what it did recognize but something wasn't right, parser should try to recover
|
||||
*/
|
||||
bool SqlLexer::nextBasicToken(int &startpos, int &length, BasicTokenType &tokentype, QString &out)
|
||||
{
|
||||
// Basically chops based on white space
|
||||
// it does also recognize comments and quoted strings/identifiers
|
||||
while (true) {
|
||||
startpos = m_pos;
|
||||
QChar c = nextChar();
|
||||
// if (LexerState::Null == m_state) {
|
||||
if (c.isSpace()) {
|
||||
// Just skip whitespace
|
||||
}
|
||||
else if (c == '-' && peekChar() == '-') { // two dashes, start of comment
|
||||
// Loop till end of line or end of block
|
||||
c = nextChar();
|
||||
for (;;) {
|
||||
c = peekChar();
|
||||
if (c != QChar::Null && c != '\n')
|
||||
nextChar();
|
||||
else
|
||||
break;
|
||||
}
|
||||
length = m_pos - startpos;
|
||||
tokentype = BasicTokenType::Comment;
|
||||
return true;
|
||||
}
|
||||
else if (c == '\'') {
|
||||
// Single quoted string so it's an SQL text literal
|
||||
while (true) {
|
||||
c = peekChar();
|
||||
if (c == QChar::Null || c == '\n') {
|
||||
// unexpected end, pretend nothings wrong
|
||||
length = m_pos - startpos;
|
||||
tokentype = BasicTokenType::QuotedString;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
nextChar();
|
||||
if (c == '\'') {
|
||||
// maybe end of string literal
|
||||
if (peekChar() == '\'') {
|
||||
// Nope, just double quote to escape quote
|
||||
nextChar(); // eat it
|
||||
}
|
||||
else {
|
||||
length = m_pos - startpos;
|
||||
tokentype = BasicTokenType::QuotedString;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (c == '"') {
|
||||
// Double quoted identifier
|
||||
while (true) {
|
||||
c = peekChar();
|
||||
if (c == QChar::Null || c == '\n') {
|
||||
// unexpected end, pretend nothings wrong
|
||||
length = m_pos - startpos;
|
||||
tokentype = BasicTokenType::QuotedIdentifier;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
nextChar();
|
||||
if (c == '"') {
|
||||
// maybe end of string literal
|
||||
if (peekChar() == '"') {
|
||||
// Nope, just double quote to escape quote
|
||||
nextChar(); // eat it
|
||||
}
|
||||
else {
|
||||
length = m_pos - startpos;
|
||||
tokentype = BasicTokenType::QuotedIdentifier;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// else if (c == '/' && peekChar() == '*') {
|
||||
// nextChar();
|
||||
// m_state = LexerState::InBlockComment;
|
||||
// }
|
||||
else if (c == QChar::Null) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// Undetermined symbol
|
||||
for (;;) {
|
||||
c = peekChar();
|
||||
if (c.isLetterOrNumber() || c == '_')
|
||||
nextChar();
|
||||
else
|
||||
break;
|
||||
}
|
||||
length = m_pos - startpos;
|
||||
tokentype = BasicTokenType::Symbol;
|
||||
QStringRef sr(&m_block, startpos, length);
|
||||
out = sr.toString();
|
||||
return true;
|
||||
}
|
||||
// }
|
||||
// else if (LexerState::InBlockComment == m_state) {
|
||||
// if (c == QChar::Null) {
|
||||
// // eof current buffer, we need to return state so
|
||||
// if (m_pos == startpos) {
|
||||
// break;
|
||||
// }
|
||||
// else {
|
||||
// length = m_pos - startpos;
|
||||
// tokentype = BasicTokenType::OpenBlockComment;
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// else if (c == '*') {
|
||||
// nextChar();
|
||||
// if (peekChar() == '/') {
|
||||
// nextChar();
|
||||
// length = m_pos - startpos;
|
||||
// tokentype = BasicTokenType::BlockComment;
|
||||
// m_state = LexerState::Null;
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#ifndef SQLLEXER_H
|
||||
#define SQLLEXER_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
enum class BasicTokenType {
|
||||
None,
|
||||
End, // End of input
|
||||
Symbol, // can be many things, keyword, object name, operator, ..
|
||||
Comment,
|
||||
BlockComment,
|
||||
OpenBlockComment, // Busy with a block comment end not detected before end of current input
|
||||
QuotedString,
|
||||
DollarQuotedString,
|
||||
QuotedIdentifier
|
||||
};
|
||||
|
||||
enum class LexerState {
|
||||
Null,
|
||||
InDollarQuotedString,
|
||||
InBlockComment
|
||||
};
|
||||
|
||||
|
||||
class SqlLexer {
|
||||
public:
|
||||
SqlLexer(const QString &block, LexerState currentstate);
|
||||
QChar nextChar();
|
||||
QChar peekChar();
|
||||
/**
|
||||
* @brief NextBasicToken
|
||||
* @param in
|
||||
* @param ofs
|
||||
* @param start
|
||||
* @param length
|
||||
* @return false when input seems invalid, it will return what it did recognize but something wasn't right, parser should try to recover
|
||||
*/
|
||||
bool nextBasicToken(int &startpos, int &length, BasicTokenType &tokentype, QString &out);
|
||||
|
||||
LexerState currentState() const { return m_state; }
|
||||
private:
|
||||
QString m_block;
|
||||
int m_pos = 0;
|
||||
LexerState m_state;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // SQLLEXER_H
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
void assertion_failed(char const * expr, char const * function, char const * file, long line)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Assertion failure int " << function << " " << file << ":" << line;
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
|
||||
void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "Assertion failure int " << function << " " << file << ":" << line << "\n"<< msg;
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue