mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-27 00:09:53 -05:00
Merge branch 'develop' into feature/yubikey
This commit is contained in:
commit
e17576a6f7
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
## Your Environment
|
## Your Environment
|
||||||
<!--- Include relevant details about the environment you experienced the bug in -->
|
<!--- Include relevant details about the environment you experienced the bug in -->
|
||||||
* KeePassXR version/commit used:
|
* KeePassXC version/commit used: (can be found under Help -> About)
|
||||||
* Qt version (e.g. Qt 5.3):
|
* Qt version (e.g. Qt 5.3):
|
||||||
* Compiler (e.g. Clang++3.6.0):
|
* Compiler (e.g. Clang++3.6.0):
|
||||||
* Operating System and version:
|
* Operating System and version:
|
||||||
|
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
32
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,4 +1,4 @@
|
|||||||
<!--- Provide a general summary of your changes in the Title above -->
|
<!--- Provide a general summary of your changes in the title above -->
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
<!--- Describe your changes in detail -->
|
<!--- Describe your changes in detail -->
|
||||||
@ -15,21 +15,19 @@
|
|||||||
## Screenshots (if appropriate):
|
## Screenshots (if appropriate):
|
||||||
|
|
||||||
## Types of changes
|
## Types of changes
|
||||||
<!--- What types of changes does your code introduce? If it apply to your pull request, -->
|
<!--- What types of changes does your code introduce? -->
|
||||||
<!--- replace all the `:negative_squared_cross_mark:` with `:white_check_mark:` -->
|
<!--- Please remove all lines which don't apply. -->
|
||||||
<!--- Everybody loves emoji -->
|
- ✅ Bug fix (non-breaking change which fixes an issue)
|
||||||
- :negative_squared_cross_mark: Bug fix (non-breaking change which fixes an issue)
|
- ✅ New feature (non-breaking change which adds functionality)
|
||||||
- :negative_squared_cross_mark: New feature (non-breaking change which adds functionality)
|
- ✅ Breaking change (fix or feature that would cause existing functionality to change)
|
||||||
- :negative_squared_cross_mark: Breaking change (fix or feature that would cause existing functionality to change)
|
|
||||||
|
|
||||||
## Checklist:
|
## Checklist:
|
||||||
<!--- Go over all the following points, if it apply to your pull request, -->
|
<!--- Please go over all the following points. -->
|
||||||
<!--- replace all the `:negative_squared_cross_mark:` with `:white_check_mark:`. -->
|
<!--- Again, remove any lines which don't apply. -->
|
||||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
<!--- Pull Requests that don't fulfill all [REQUIRED] requisites are likely -->
|
||||||
<!--- Pull Requests that fail the [REQUIRED] field will likely be sent back for corrections or rejected -->
|
<!--- to be sent back to you for correction or will be rejected. -->
|
||||||
- :negative_squared_cross_mark: I have read the **CONTRIBUTING** document. [REQUIRED]
|
- ✅ I have read the **CONTRIBUTING** document. **[REQUIRED]**
|
||||||
- :negative_squared_cross_mark: My code follows the code style of this project. [REQUIRED]
|
- ✅ My code follows the code style of this project. **[REQUIRED]**
|
||||||
- :negative_squared_cross_mark: All new and existing tests passed. [REQUIRED]
|
- ✅ All new and existing tests passed. **[REQUIRED]**
|
||||||
- :negative_squared_cross_mark: My change requires a change to the documentation.
|
- ✅ My change requires a change to the documentation and I have updated it accordingly.
|
||||||
- :negative_squared_cross_mark: I have updated the documentation accordingly.
|
- ✅ I have added tests to cover my changes.
|
||||||
- :negative_squared_cross_mark: I have added tests to cover my changes.
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
|
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
|
||||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo Debug Debugfull Profile MinSizeRel."
|
"Choose the type of build, options are: None Debug Release RelWithDebInfo Debug DebugFull Profile MinSizeRel."
|
||||||
FORCE)
|
FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ int AutoTypePlatformTest::platformEventFilter(void* event)
|
|||||||
|
|
||||||
AutoTypeExecutor* AutoTypePlatformTest::createExecutor()
|
AutoTypeExecutor* AutoTypePlatformTest::createExecutor()
|
||||||
{
|
{
|
||||||
return new AutoTypeExecturorTest(this);
|
return new AutoTypeExecutorTest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypePlatformTest::setActiveWindowTitle(const QString& title)
|
void AutoTypePlatformTest::setActiveWindowTitle(const QString& title)
|
||||||
@ -127,17 +127,17 @@ bool AutoTypePlatformTest::raiseOwnWindow()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
AutoTypeExecturorTest::AutoTypeExecturorTest(AutoTypePlatformTest* platform)
|
AutoTypeExecutorTest::AutoTypeExecutorTest(AutoTypePlatformTest* platform)
|
||||||
: m_platform(platform)
|
: m_platform(platform)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypeExecturorTest::execChar(AutoTypeChar* action)
|
void AutoTypeExecutorTest::execChar(AutoTypeChar* action)
|
||||||
{
|
{
|
||||||
m_platform->addActionChar(action);
|
m_platform->addActionChar(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypeExecturorTest::execKey(AutoTypeKey* action)
|
void AutoTypeExecutorTest::execKey(AutoTypeKey* action)
|
||||||
{
|
{
|
||||||
m_platform->addActionKey(action);
|
m_platform->addActionKey(action);
|
||||||
}
|
}
|
||||||
|
@ -69,10 +69,10 @@ private:
|
|||||||
QString m_actionChars;
|
QString m_actionChars;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoTypeExecturorTest : public AutoTypeExecutor
|
class AutoTypeExecutorTest : public AutoTypeExecutor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AutoTypeExecturorTest(AutoTypePlatformTest* platform);
|
explicit AutoTypeExecutorTest(AutoTypePlatformTest* platform);
|
||||||
|
|
||||||
void execChar(AutoTypeChar* action) override;
|
void execChar(AutoTypeChar* action) override;
|
||||||
void execKey(AutoTypeKey* action) override;
|
void execKey(AutoTypeKey* action) override;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
bool AutoTypePlatformX11::m_catchXErrors = false;
|
bool AutoTypePlatformX11::m_catchXErrors = false;
|
||||||
bool AutoTypePlatformX11::m_xErrorOccured = false;
|
bool AutoTypePlatformX11::m_xErrorOccurred = false;
|
||||||
int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = nullptr;
|
int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = nullptr;
|
||||||
|
|
||||||
AutoTypePlatformX11::AutoTypePlatformX11()
|
AutoTypePlatformX11::AutoTypePlatformX11()
|
||||||
@ -153,7 +153,7 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi
|
|||||||
GrabModeAsync, GrabModeAsync);
|
GrabModeAsync, GrabModeAsync);
|
||||||
stopCatchXErrors();
|
stopCatchXErrors();
|
||||||
|
|
||||||
if (!m_xErrorOccured) {
|
if (!m_xErrorOccurred) {
|
||||||
m_currentGlobalKey = key;
|
m_currentGlobalKey = key;
|
||||||
m_currentGlobalModifiers = modifiers;
|
m_currentGlobalModifiers = modifiers;
|
||||||
m_currentGlobalKeycode = keycode;
|
m_currentGlobalKeycode = keycode;
|
||||||
@ -247,7 +247,7 @@ int AutoTypePlatformX11::platformEventFilter(void* event)
|
|||||||
|
|
||||||
AutoTypeExecutor* AutoTypePlatformX11::createExecutor()
|
AutoTypeExecutor* AutoTypePlatformX11::createExecutor()
|
||||||
{
|
{
|
||||||
return new AutoTypeExecturorX11(this);
|
return new AutoTypeExecutorX11(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
|
QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
|
||||||
@ -556,7 +556,7 @@ void AutoTypePlatformX11::startCatchXErrors()
|
|||||||
Q_ASSERT(!m_catchXErrors);
|
Q_ASSERT(!m_catchXErrors);
|
||||||
|
|
||||||
m_catchXErrors = true;
|
m_catchXErrors = true;
|
||||||
m_xErrorOccured = false;
|
m_xErrorOccurred = false;
|
||||||
m_oldXErrorHandler = XSetErrorHandler(x11ErrorHandler);
|
m_oldXErrorHandler = XSetErrorHandler(x11ErrorHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,7 +575,7 @@ int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
|
|||||||
Q_UNUSED(error)
|
Q_UNUSED(error)
|
||||||
|
|
||||||
if (m_catchXErrors) {
|
if (m_catchXErrors) {
|
||||||
m_xErrorOccured = true;
|
m_xErrorOccurred = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -823,17 +823,17 @@ int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AutoTypeExecturorX11::AutoTypeExecturorX11(AutoTypePlatformX11* platform)
|
AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform)
|
||||||
: m_platform(platform)
|
: m_platform(platform)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypeExecturorX11::execChar(AutoTypeChar* action)
|
void AutoTypeExecutorX11::execChar(AutoTypeChar* action)
|
||||||
{
|
{
|
||||||
m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character));
|
m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypeExecturorX11::execKey(AutoTypeKey* action)
|
void AutoTypeExecutorX11::execKey(AutoTypeKey* action)
|
||||||
{
|
{
|
||||||
m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key));
|
m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key));
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ private:
|
|||||||
uint m_currentGlobalNativeModifiers;
|
uint m_currentGlobalNativeModifiers;
|
||||||
int m_modifierMask;
|
int m_modifierMask;
|
||||||
static bool m_catchXErrors;
|
static bool m_catchXErrors;
|
||||||
static bool m_xErrorOccured;
|
static bool m_xErrorOccurred;
|
||||||
static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
|
static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
|
||||||
|
|
||||||
static const int m_unicodeToKeysymLen;
|
static const int m_unicodeToKeysymLen;
|
||||||
@ -119,10 +119,10 @@ private:
|
|||||||
bool m_loaded;
|
bool m_loaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoTypeExecturorX11 : public AutoTypeExecutor
|
class AutoTypeExecutorX11 : public AutoTypeExecutor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AutoTypeExecturorX11(AutoTypePlatformX11* platform);
|
explicit AutoTypeExecutorX11(AutoTypePlatformX11* platform);
|
||||||
|
|
||||||
void execChar(AutoTypeChar* action) override;
|
void execChar(AutoTypeChar* action) override;
|
||||||
void execKey(AutoTypeKey* action) override;
|
void execKey(AutoTypeKey* action) override;
|
||||||
|
@ -449,7 +449,7 @@ void Entry::truncateHistory()
|
|||||||
int histMaxSize = db->metadata()->historyMaxSize();
|
int histMaxSize = db->metadata()->historyMaxSize();
|
||||||
if (histMaxSize > -1) {
|
if (histMaxSize > -1) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
QSet<QByteArray> foundAttachements = attachments()->values().toSet();
|
QSet<QByteArray> foundAttachments = attachments()->values().toSet();
|
||||||
|
|
||||||
QMutableListIterator<Entry*> i(m_history);
|
QMutableListIterator<Entry*> i(m_history);
|
||||||
i.toBack();
|
i.toBack();
|
||||||
@ -460,11 +460,11 @@ void Entry::truncateHistory()
|
|||||||
if (size <= histMaxSize) {
|
if (size <= histMaxSize) {
|
||||||
size += historyItem->attributes()->attributesSize();
|
size += historyItem->attributes()->attributesSize();
|
||||||
|
|
||||||
const QSet<QByteArray> newAttachments = historyItem->attachments()->values().toSet() - foundAttachements;
|
const QSet<QByteArray> newAttachments = historyItem->attachments()->values().toSet() - foundAttachments;
|
||||||
for (const QByteArray& attachment : newAttachments) {
|
for (const QByteArray& attachment : newAttachments) {
|
||||||
size += attachment.size();
|
size += attachment.size();
|
||||||
}
|
}
|
||||||
foundAttachements += newAttachments;
|
foundAttachments += newAttachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > histMaxSize) {
|
if (size > histMaxSize) {
|
||||||
|
@ -36,7 +36,7 @@ QObject* SignalMultiplexer::currentObject() const
|
|||||||
|
|
||||||
void SignalMultiplexer::setCurrentObject(QObject* object)
|
void SignalMultiplexer::setCurrentObject(QObject* object)
|
||||||
{
|
{
|
||||||
// remove all Connections from the list whoes senders/receivers have been deleted
|
// remove all Connections from the list whose senders/receivers have been deleted
|
||||||
QMutableListIterator<Connection> i = m_connections;
|
QMutableListIterator<Connection> i = m_connections;
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
const Connection& con = i.next();
|
const Connection& con = i.next();
|
||||||
|
@ -153,14 +153,14 @@ bool Crypto::testAes256Cbc()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymmetricCipher aes256Descrypt(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
|
SymmetricCipher aes256Decrypt(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt);
|
||||||
if (!aes256Descrypt.init(key, iv)) {
|
if (!aes256Decrypt.init(key, iv)) {
|
||||||
raiseError(aes256Descrypt.errorString());
|
raiseError(aes256Decrypt.errorString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QByteArray decryptedText = aes256Descrypt.process(cipherText, &ok);
|
QByteArray decryptedText = aes256Decrypt.process(cipherText, &ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
raiseError(aes256Descrypt.errorString());
|
raiseError(aes256Decrypt.errorString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (decryptedText != plainText) {
|
if (decryptedText != plainText) {
|
||||||
@ -196,14 +196,14 @@ bool Crypto::testAes256Ecb()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymmetricCipher aes256Descrypt(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Decrypt);
|
SymmetricCipher aes256Decrypt(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Decrypt);
|
||||||
if (!aes256Descrypt.init(key, iv)) {
|
if (!aes256Decrypt.init(key, iv)) {
|
||||||
raiseError(aes256Descrypt.errorString());
|
raiseError(aes256Decrypt.errorString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QByteArray decryptedText = aes256Descrypt.process(cipherText, &ok);
|
QByteArray decryptedText = aes256Decrypt.process(cipherText, &ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
raiseError(aes256Descrypt.errorString());
|
raiseError(aes256Decrypt.errorString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (decryptedText != plainText) {
|
if (decryptedText != plainText) {
|
||||||
|
@ -301,7 +301,7 @@ bool KeePass2Reader::readHeaderField()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case KeePass2::TransformRounds:
|
case KeePass2::TransformRounds:
|
||||||
setTansformRounds(fieldData);
|
setTransformRounds(fieldData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KeePass2::EncryptionIV:
|
case KeePass2::EncryptionIV:
|
||||||
@ -382,7 +382,7 @@ void KeePass2Reader::setTransformSeed(const QByteArray& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeePass2Reader::setTansformRounds(const QByteArray& data)
|
void KeePass2Reader::setTransformRounds(const QByteArray& data)
|
||||||
{
|
{
|
||||||
if (data.size() != 8) {
|
if (data.size() != 8) {
|
||||||
raiseError("Invalid transform rounds size");
|
raiseError("Invalid transform rounds size");
|
||||||
|
@ -48,7 +48,7 @@ private:
|
|||||||
void setCompressionFlags(const QByteArray& data);
|
void setCompressionFlags(const QByteArray& data);
|
||||||
void setMasterSeed(const QByteArray& data);
|
void setMasterSeed(const QByteArray& data);
|
||||||
void setTransformSeed(const QByteArray& data);
|
void setTransformSeed(const QByteArray& data);
|
||||||
void setTansformRounds(const QByteArray& data);
|
void setTransformRounds(const QByteArray& data);
|
||||||
void setEncryptionIV(const QByteArray& data);
|
void setEncryptionIV(const QByteArray& data);
|
||||||
void setProtectedStreamKey(const QByteArray& data);
|
void setProtectedStreamKey(const QByteArray& data);
|
||||||
void setStreamStartBytes(const QByteArray& data);
|
void setStreamStartBytes(const QByteArray& data);
|
||||||
|
@ -178,7 +178,7 @@ bool KeePass2XmlReader::parseKeePassFile()
|
|||||||
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "KeePassFile");
|
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "KeePassFile");
|
||||||
|
|
||||||
bool rootElementFound = false;
|
bool rootElementFound = false;
|
||||||
bool rootParsedSuccesfully = false;
|
bool rootParsedSuccessfully = false;
|
||||||
|
|
||||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||||
if (m_xml.name() == "Meta") {
|
if (m_xml.name() == "Meta") {
|
||||||
@ -186,11 +186,11 @@ bool KeePass2XmlReader::parseKeePassFile()
|
|||||||
}
|
}
|
||||||
else if (m_xml.name() == "Root") {
|
else if (m_xml.name() == "Root") {
|
||||||
if (rootElementFound) {
|
if (rootElementFound) {
|
||||||
rootParsedSuccesfully = false;
|
rootParsedSuccessfully = false;
|
||||||
raiseError("Multiple root elements");
|
raiseError("Multiple root elements");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rootParsedSuccesfully = parseRoot();
|
rootParsedSuccessfully = parseRoot();
|
||||||
rootElementFound = true;
|
rootElementFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ bool KeePass2XmlReader::parseKeePassFile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootParsedSuccesfully;
|
return rootParsedSuccessfully;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeePass2XmlReader::parseMeta()
|
void KeePass2XmlReader::parseMeta()
|
||||||
@ -458,12 +458,12 @@ bool KeePass2XmlReader::parseRoot()
|
|||||||
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Root");
|
Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Root");
|
||||||
|
|
||||||
bool groupElementFound = false;
|
bool groupElementFound = false;
|
||||||
bool groupParsedSuccesfully = false;
|
bool groupParsedSuccessfully = false;
|
||||||
|
|
||||||
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
while (!m_xml.error() && m_xml.readNextStartElement()) {
|
||||||
if (m_xml.name() == "Group") {
|
if (m_xml.name() == "Group") {
|
||||||
if (groupElementFound) {
|
if (groupElementFound) {
|
||||||
groupParsedSuccesfully = false;
|
groupParsedSuccessfully = false;
|
||||||
raiseError("Multiple group elements");
|
raiseError("Multiple group elements");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -473,7 +473,7 @@ bool KeePass2XmlReader::parseRoot()
|
|||||||
Group* oldRoot = m_db->rootGroup();
|
Group* oldRoot = m_db->rootGroup();
|
||||||
m_db->setRootGroup(rootGroup);
|
m_db->setRootGroup(rootGroup);
|
||||||
delete oldRoot;
|
delete oldRoot;
|
||||||
groupParsedSuccesfully = true;
|
groupParsedSuccessfully = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
groupElementFound = true;
|
groupElementFound = true;
|
||||||
@ -486,7 +486,7 @@ bool KeePass2XmlReader::parseRoot()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return groupParsedSuccesfully;
|
return groupParsedSuccessfully;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group* KeePass2XmlReader::parseGroup()
|
Group* KeePass2XmlReader::parseGroup()
|
||||||
|
@ -566,9 +566,9 @@ QString KeePass2XmlWriter::stripInvalidXml10Chars(QString str)
|
|||||||
// keep valid surrogate pair
|
// keep valid surrogate pair
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control chracters
|
else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters
|
||||||
|| (uc >= 0x7F && uc <= 0x84) // control chracters, valid but discouraged by XML
|
|| (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML
|
||||||
|| (uc >= 0x86 && uc <= 0x9F) // control chracters, valid but discouraged by XML
|
|| (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML
|
||||||
|| (uc > 0xFFFD) // noncharacter
|
|| (uc > 0xFFFD) // noncharacter
|
||||||
|| ch.isLowSurrogate() // single low surrogate
|
|| ch.isLowSurrogate() // single low surrogate
|
||||||
|| ch.isHighSurrogate()) // single high surrogate
|
|| ch.isHighSurrogate()) // single high surrogate
|
||||||
|
@ -333,8 +333,8 @@ void DatabaseWidget::deleteEntries()
|
|||||||
selectedEntries.append(m_entryView->entryFromIndex(index));
|
selectedEntries.append(m_entryView->entryFromIndex(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inRecylceBin = Tools::hasChild(m_db->metadata()->recycleBin(), selectedEntries.first());
|
bool inRecycleBin = Tools::hasChild(m_db->metadata()->recycleBin(), selectedEntries.first());
|
||||||
if (inRecylceBin || !m_db->metadata()->recycleBinEnabled()) {
|
if (inRecycleBin || !m_db->metadata()->recycleBinEnabled()) {
|
||||||
QMessageBox::StandardButton result;
|
QMessageBox::StandardButton result;
|
||||||
|
|
||||||
if (selected.size() == 1) {
|
if (selected.size() == 1) {
|
||||||
@ -525,10 +525,10 @@ void DatabaseWidget::deleteGroup()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inRecylceBin = Tools::hasChild(m_db->metadata()->recycleBin(), currentGroup);
|
bool inRecycleBin = Tools::hasChild(m_db->metadata()->recycleBin(), currentGroup);
|
||||||
bool isRecycleBin = (currentGroup == m_db->metadata()->recycleBin());
|
bool isRecycleBin = (currentGroup == m_db->metadata()->recycleBin());
|
||||||
bool isRecycleBinSubgroup = Tools::hasChild(currentGroup, m_db->metadata()->recycleBin());
|
bool isRecycleBinSubgroup = Tools::hasChild(currentGroup, m_db->metadata()->recycleBin());
|
||||||
if (inRecylceBin || isRecycleBin || isRecycleBinSubgroup || !m_db->metadata()->recycleBinEnabled()) {
|
if (inRecycleBin || isRecycleBin || isRecycleBinSubgroup || !m_db->metadata()->recycleBinEnabled()) {
|
||||||
QMessageBox::StandardButton result = MessageBox::question(
|
QMessageBox::StandardButton result = MessageBox::question(
|
||||||
this, tr("Delete group?"),
|
this, tr("Delete group?"),
|
||||||
tr("Do you really want to delete the group \"%1\" for good?")
|
tr("Do you really want to delete the group \"%1\" for good?")
|
||||||
@ -1033,13 +1033,13 @@ void DatabaseWidget::reloadDatabaseFile()
|
|||||||
else {
|
else {
|
||||||
MessageBox::critical(this, tr("Autoreload Failed"),
|
MessageBox::critical(this, tr("Autoreload Failed"),
|
||||||
tr("Could not parse or unlock the new database file while attempting"
|
tr("Could not parse or unlock the new database file while attempting"
|
||||||
"to autoreload this database."));
|
" to autoreload this database."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MessageBox::critical(this, tr("Autoreload Failed"),
|
MessageBox::critical(this, tr("Autoreload Failed"),
|
||||||
tr("Could not open the new database file while attempting to autoreload"
|
tr("Could not open the new database file while attempting to autoreload"
|
||||||
"this database."));
|
" this database."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewatch the database file
|
// Rewatch the database file
|
||||||
|
@ -90,7 +90,7 @@ void EditEntryWidget::setupMain()
|
|||||||
|
|
||||||
m_mainUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
|
m_mainUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show"));
|
||||||
connect(m_mainUi->togglePasswordButton, SIGNAL(toggled(bool)), m_mainUi->passwordEdit, SLOT(setShowPassword(bool)));
|
connect(m_mainUi->togglePasswordButton, SIGNAL(toggled(bool)), m_mainUi->passwordEdit, SLOT(setShowPassword(bool)));
|
||||||
connect(m_mainUi->tooglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
|
connect(m_mainUi->togglePasswordGeneratorButton, SIGNAL(toggled(bool)), SLOT(togglePasswordGeneratorButton(bool)));
|
||||||
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
|
connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool)));
|
||||||
m_mainUi->passwordRepeatEdit->enableVerifyMode(m_mainUi->passwordEdit);
|
m_mainUi->passwordRepeatEdit->enableVerifyMode(m_mainUi->passwordEdit);
|
||||||
connect(m_mainUi->passwordGenerator, SIGNAL(appliedPassword(QString)), SLOT(setGeneratedPassword(QString)));
|
connect(m_mainUi->passwordGenerator, SIGNAL(appliedPassword(QString)), SLOT(setGeneratedPassword(QString)));
|
||||||
@ -299,8 +299,8 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore)
|
|||||||
m_mainUi->expireCheck->setEnabled(!m_history);
|
m_mainUi->expireCheck->setEnabled(!m_history);
|
||||||
m_mainUi->expireDatePicker->setReadOnly(m_history);
|
m_mainUi->expireDatePicker->setReadOnly(m_history);
|
||||||
m_mainUi->notesEdit->setReadOnly(m_history);
|
m_mainUi->notesEdit->setReadOnly(m_history);
|
||||||
m_mainUi->tooglePasswordGeneratorButton->setChecked(false);
|
m_mainUi->togglePasswordGeneratorButton->setChecked(false);
|
||||||
m_mainUi->tooglePasswordGeneratorButton->setDisabled(m_history);
|
m_mainUi->togglePasswordGeneratorButton->setDisabled(m_history);
|
||||||
m_mainUi->passwordGenerator->reset();
|
m_mainUi->passwordGenerator->reset();
|
||||||
m_advancedUi->addAttachmentButton->setEnabled(!m_history);
|
m_advancedUi->addAttachmentButton->setEnabled(!m_history);
|
||||||
updateAttachmentButtonsEnabled(m_advancedUi->attachmentsView->currentIndex());
|
updateAttachmentButtonsEnabled(m_advancedUi->attachmentsView->currentIndex());
|
||||||
@ -529,7 +529,7 @@ void EditEntryWidget::setGeneratedPassword(const QString& password)
|
|||||||
m_mainUi->passwordEdit->setText(password);
|
m_mainUi->passwordEdit->setText(password);
|
||||||
m_mainUi->passwordRepeatEdit->setText(password);
|
m_mainUi->passwordRepeatEdit->setText(password);
|
||||||
|
|
||||||
m_mainUi->tooglePasswordGeneratorButton->setChecked(false);
|
m_mainUi->togglePasswordGeneratorButton->setChecked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditEntryWidget::insertAttribute()
|
void EditEntryWidget::insertAttribute()
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="tooglePasswordGeneratorButton">
|
<widget class="QToolButton" name="togglePasswordGeneratorButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Generate</string>
|
<string>Generate</string>
|
||||||
</property>
|
</property>
|
||||||
@ -166,7 +166,7 @@
|
|||||||
<tabstop>passwordEdit</tabstop>
|
<tabstop>passwordEdit</tabstop>
|
||||||
<tabstop>passwordRepeatEdit</tabstop>
|
<tabstop>passwordRepeatEdit</tabstop>
|
||||||
<tabstop>togglePasswordButton</tabstop>
|
<tabstop>togglePasswordButton</tabstop>
|
||||||
<tabstop>tooglePasswordGeneratorButton</tabstop>
|
<tabstop>togglePasswordGeneratorButton</tabstop>
|
||||||
<tabstop>urlEdit</tabstop>
|
<tabstop>urlEdit</tabstop>
|
||||||
<tabstop>expireCheck</tabstop>
|
<tabstop>expireCheck</tabstop>
|
||||||
<tabstop>expireDatePicker</tabstop>
|
<tabstop>expireDatePicker</tabstop>
|
||||||
|
@ -19,12 +19,15 @@
|
|||||||
#include "CompositeKey_p.h"
|
#include "CompositeKey_p.h"
|
||||||
#include "ChallengeResponseKey.h"
|
#include "ChallengeResponseKey.h"
|
||||||
|
|
||||||
#include <QtConcurrent>
|
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QtConcurrent>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
#include "crypto/CryptoHash.h"
|
#include "crypto/CryptoHash.h"
|
||||||
#include "crypto/SymmetricCipher.h"
|
#include "crypto/SymmetricCipher.h"
|
||||||
|
#include "keys/FileKey.h"
|
||||||
|
#include "keys/PasswordKey.h"
|
||||||
|
|
||||||
CompositeKey::CompositeKey()
|
CompositeKey::CompositeKey()
|
||||||
{
|
{
|
||||||
@ -77,6 +80,29 @@ CompositeKey& CompositeKey::operator=(const CompositeKey& key)
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a key from a line of input.
|
||||||
|
* If the line references a valid file
|
||||||
|
* path, the key is loaded from file.
|
||||||
|
*/
|
||||||
|
CompositeKey CompositeKey::readFromLine(QString line)
|
||||||
|
{
|
||||||
|
|
||||||
|
CompositeKey key;
|
||||||
|
if (QFile::exists(line)) {
|
||||||
|
FileKey fileKey;
|
||||||
|
fileKey.load(line);
|
||||||
|
key.addKey(fileKey);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PasswordKey password;
|
||||||
|
password.setPassword(line);
|
||||||
|
key.addKey(password);
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray CompositeKey::rawKey() const
|
QByteArray CompositeKey::rawKey() const
|
||||||
{
|
{
|
||||||
CryptoHash cryptoHash(CryptoHash::Sha256);
|
CryptoHash cryptoHash(CryptoHash::Sha256);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#define KEEPASSX_COMPOSITEKEY_H
|
#define KEEPASSX_COMPOSITEKEY_H
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "keys/Key.h"
|
#include "keys/Key.h"
|
||||||
#include "keys/ChallengeResponseKey.h"
|
#include "keys/ChallengeResponseKey.h"
|
||||||
@ -43,6 +44,7 @@ public:
|
|||||||
void addChallengeResponseKey(const ChallengeResponseKey& key);
|
void addChallengeResponseKey(const ChallengeResponseKey& key);
|
||||||
|
|
||||||
static int transformKeyBenchmark(int msec);
|
static int transformKeyBenchmark(int msec);
|
||||||
|
static CompositeKey readFromLine(QString line);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QByteArray transformKeyRaw(const QByteArray& key, const QByteArray& seed,
|
static QByteArray transformKeyRaw(const QByteArray& key, const QByteArray& seed,
|
||||||
|
@ -190,18 +190,18 @@ bool FileKey::loadXml(QIODevice* device)
|
|||||||
|
|
||||||
bool FileKey::loadXmlMeta(QXmlStreamReader& xmlReader)
|
bool FileKey::loadXmlMeta(QXmlStreamReader& xmlReader)
|
||||||
{
|
{
|
||||||
bool corectVersion = false;
|
bool correctVersion = false;
|
||||||
|
|
||||||
while (!xmlReader.error() && xmlReader.readNextStartElement()) {
|
while (!xmlReader.error() && xmlReader.readNextStartElement()) {
|
||||||
if (xmlReader.name() == "Version") {
|
if (xmlReader.name() == "Version") {
|
||||||
// TODO: error message about incompatible key file version
|
// TODO: error message about incompatible key file version
|
||||||
if (xmlReader.readElementText() == "1.00") {
|
if (xmlReader.readElementText() == "1.00") {
|
||||||
corectVersion = true;
|
correctVersion = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return corectVersion;
|
return correctVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray FileKey::loadXmlKey(QXmlStreamReader& xmlReader)
|
QByteArray FileKey::loadXmlKey(QXmlStreamReader& xmlReader)
|
||||||
|
@ -135,7 +135,7 @@ void QtIOCompressorPrivate::flushZlib(int flushMode)
|
|||||||
if (!writeBytes(buffer, outputSize))
|
if (!writeBytes(buffer, outputSize))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the mode is Z_FNISH we must loop until we get Z_STREAM_END,
|
// If the mode is Z_FINISH we must loop until we get Z_STREAM_END,
|
||||||
// else we loop as long as zlib is able to fill the output buffer.
|
// else we loop as long as zlib is able to fill the output buffer.
|
||||||
} while ((flushMode == Z_FINISH && status != Z_STREAM_END) || (flushMode != Z_FINISH && zlibStream.avail_out == 0));
|
} while ((flushMode == Z_FINISH && status != Z_STREAM_END) || (flushMode != Z_FINISH && zlibStream.avail_out == 0));
|
||||||
|
|
||||||
@ -522,11 +522,11 @@ qint64 QtIOCompressor::readData(char *data, qint64 maxSize)
|
|||||||
// Read data if if the input buffer is empty. There could be data in the buffer
|
// Read data if if the input buffer is empty. There could be data in the buffer
|
||||||
// from a previous readData call.
|
// from a previous readData call.
|
||||||
if (d->zlibStream.avail_in == 0) {
|
if (d->zlibStream.avail_in == 0) {
|
||||||
qint64 bytesAvalible = d->device->read(reinterpret_cast<char *>(d->buffer), d->bufferSize);
|
qint64 bytesAvailable = d->device->read(reinterpret_cast<char *>(d->buffer), d->bufferSize);
|
||||||
d->zlibStream.next_in = d->buffer;
|
d->zlibStream.next_in = d->buffer;
|
||||||
d->zlibStream.avail_in = bytesAvalible;
|
d->zlibStream.avail_in = bytesAvailable;
|
||||||
|
|
||||||
if (bytesAvalible == -1) {
|
if (bytesAvailable == -1) {
|
||||||
d->state = QtIOCompressorPrivate::Error;
|
d->state = QtIOCompressorPrivate::Error;
|
||||||
setErrorString(QT_TRANSLATE_NOOP("QtIOCompressor", "Error reading data from underlying device: ") + d->device->errorString());
|
setErrorString(QT_TRANSLATE_NOOP("QtIOCompressor", "Error reading data from underlying device: ") + d->device->errorString());
|
||||||
return -1;
|
return -1;
|
||||||
@ -534,9 +534,9 @@ qint64 QtIOCompressor::readData(char *data, qint64 maxSize)
|
|||||||
|
|
||||||
if (d->state != QtIOCompressorPrivate::InStream) {
|
if (d->state != QtIOCompressorPrivate::InStream) {
|
||||||
// If we are not in a stream and get 0 bytes, we are probably trying to read from an empty device.
|
// If we are not in a stream and get 0 bytes, we are probably trying to read from an empty device.
|
||||||
if(bytesAvalible == 0)
|
if(bytesAvailable == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (bytesAvalible > 0)
|
else if (bytesAvailable > 0)
|
||||||
d->state = QtIOCompressorPrivate::InStream;
|
d->state = QtIOCompressorPrivate::InStream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**********************************************************************************
|
/**********************************************************************************
|
||||||
* C implementation of the zxcvbn password strength estimation method.
|
* C implementation of the zxcvbn password strength estimation method.
|
||||||
* Copyright (c) 2015, Tony Evans
|
* Copyright (c) 2015, Tony Evans
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -228,12 +228,13 @@ static void AddMatchRepeats(ZxcMatch_t **Result, ZxcMatch_t *Match, const uint8_
|
|||||||
|
|
||||||
while(MaxLen >= (Len * RepeatCount))
|
while(MaxLen >= (Len * RepeatCount))
|
||||||
{
|
{
|
||||||
if (strncmp((const char *)Passwd, (const char *)Rpt, Len) == 0)
|
if (strncmp(reinterpret_cast<const char *>(Passwd),
|
||||||
|
reinterpret_cast<const char *>(Rpt), Len) == 0)
|
||||||
{
|
{
|
||||||
/* Found a repeat */
|
/* Found a repeat */
|
||||||
ZxcMatch_t *p = AllocMatch();
|
ZxcMatch_t *p = AllocMatch();
|
||||||
p->Entrpy = Match->Entrpy + log(RepeatCount);
|
p->Entrpy = Match->Entrpy + log(RepeatCount);
|
||||||
p->Type = (ZxcTypeMatch_t)(Match->Type + MULTIPLE_MATCH);
|
p->Type = static_cast<ZxcTypeMatch_t>(Match->Type + MULTIPLE_MATCH);
|
||||||
p->Length = Len * RepeatCount;
|
p->Length = Len * RepeatCount;
|
||||||
p->Begin = Match->Begin;
|
p->Begin = Match->Begin;
|
||||||
AddResult(Result, p, MaxLen);
|
AddResult(Result, p, MaxLen);
|
||||||
@ -617,7 +618,7 @@ static void DictionaryEntropy(ZxcMatch_t *m, DictMatchInfo_t *Extra, const uint8
|
|||||||
e += d;
|
e += d;
|
||||||
}
|
}
|
||||||
/* Add entropy due to word's rank */
|
/* Add entropy due to word's rank */
|
||||||
e += log((double)Extra->Rank);
|
e += log(static_cast<double>(Extra->Rank));
|
||||||
m->Entrpy = e;
|
m->Entrpy = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,7 +795,7 @@ static void UserMatch(ZxcMatch_t **Result, const char *Words[], const uint8_t *P
|
|||||||
int Caps = 0;
|
int Caps = 0;
|
||||||
int Lowers = 0;
|
int Lowers = 0;
|
||||||
int Leets = 0;
|
int Leets = 0;
|
||||||
const uint8_t *Wrd = (const uint8_t *)(Words[Rank]);
|
const uint8_t *Wrd = reinterpret_cast<const uint8_t *>(Words[Rank]);
|
||||||
const uint8_t *Pwd = Passwd;
|
const uint8_t *Pwd = Passwd;
|
||||||
memset(Extra.Leeted, 0, sizeof Extra.Leeted);
|
memset(Extra.Leeted, 0, sizeof Extra.Leeted);
|
||||||
memset(Extra.UnLeet, 0, sizeof Extra.UnLeet);
|
memset(Extra.UnLeet, 0, sizeof Extra.UnLeet);
|
||||||
@ -1169,7 +1170,7 @@ static void SpatialMatch(ZxcMatch_t **Result, const uint8_t *Passwd, int Start,
|
|||||||
int i, j, s;
|
int i, j, s;
|
||||||
double Degree, Entropy;
|
double Degree, Entropy;
|
||||||
ZxcMatch_t *p;
|
ZxcMatch_t *p;
|
||||||
Degree = (k->NumNear-1) - (double)k->NumBlank / (double)k->NumKeys;
|
Degree = (k->NumNear-1) - static_cast<double>(k->NumBlank) / static_cast<double>(k->NumKeys);
|
||||||
s = k->NumKeys;
|
s = k->NumKeys;
|
||||||
if (k->Shifts)
|
if (k->Shifts)
|
||||||
s *= 2;
|
s *= 2;
|
||||||
@ -1405,13 +1406,13 @@ static void RepeatMatch(ZxcMatch_t **Result, const uint8_t *Passwd, int Start, i
|
|||||||
int RepeatCount = 2;
|
int RepeatCount = 2;
|
||||||
while(MaxLen >= (Len * RepeatCount))
|
while(MaxLen >= (Len * RepeatCount))
|
||||||
{
|
{
|
||||||
if (strncmp((const char *)Passwd, (const char *)Rpt, Len) == 0)
|
if (strncmp(reinterpret_cast<const char *>(Passwd), reinterpret_cast<const char *>(Rpt), Len) == 0)
|
||||||
{
|
{
|
||||||
/* Found a repeat */
|
/* Found a repeat */
|
||||||
int c = Cardinality(Passwd, Len);
|
int c = Cardinality(Passwd, Len);
|
||||||
ZxcMatch_t *p = AllocMatch();
|
ZxcMatch_t *p = AllocMatch();
|
||||||
p->Entrpy = log((double)c) * Len + log(RepeatCount);
|
p->Entrpy = log(static_cast<double>(c)) * Len + log(RepeatCount);
|
||||||
p->Type = (ZxcTypeMatch_t)(BRUTE_MATCH + MULTIPLE_MATCH);
|
p->Type = static_cast<ZxcTypeMatch_t>(BRUTE_MATCH + MULTIPLE_MATCH);
|
||||||
p->Length = Len * RepeatCount;
|
p->Length = Len * RepeatCount;
|
||||||
p->Begin = Start;
|
p->Begin = Start;
|
||||||
AddResult(Result, p, MaxLen);
|
AddResult(Result, p, MaxLen);
|
||||||
@ -1527,7 +1528,7 @@ static void SequenceMatch(ZxcMatch_t **Result, const uint8_t *Passwd, int Start,
|
|||||||
p->Type = SEQUENCE_MATCH;
|
p->Type = SEQUENCE_MATCH;
|
||||||
p->Begin = Start;
|
p->Begin = Start;
|
||||||
p->Length = i;
|
p->Length = i;
|
||||||
p->Entrpy = e + log((double)i);
|
p->Entrpy = e + log(static_cast<double>(i));
|
||||||
AddMatchRepeats(Result, p, Pwd, MaxLen);
|
AddMatchRepeats(Result, p, Pwd, MaxLen);
|
||||||
AddResult(Result, p, MaxLen);
|
AddResult(Result, p, MaxLen);
|
||||||
}
|
}
|
||||||
@ -1578,13 +1579,13 @@ double ZxcvbnMatch(const char *Pwd, const char *UserDict[], ZxcMatch_t **Info)
|
|||||||
Node_t *Np;
|
Node_t *Np;
|
||||||
double e;
|
double e;
|
||||||
int Len = strlen(Pwd);
|
int Len = strlen(Pwd);
|
||||||
const uint8_t *Passwd = (const uint8_t *)Pwd;
|
const uint8_t *Passwd = reinterpret_cast<const uint8_t *>(Pwd);
|
||||||
uint8_t *RevPwd;
|
uint8_t *RevPwd;
|
||||||
/* Create the paths */
|
/* Create the paths */
|
||||||
Node_t *Nodes = MallocFn(Node_t, Len+1);
|
Node_t *Nodes = MallocFn(Node_t, Len+1);
|
||||||
memset(Nodes, 0, (Len+1) * sizeof *Nodes);
|
memset(Nodes, 0, (Len+1) * sizeof *Nodes);
|
||||||
i = Cardinality(Passwd, Len);
|
i = Cardinality(Passwd, Len);
|
||||||
e = log((double)i);
|
e = log(static_cast<double>(i));
|
||||||
|
|
||||||
/* Do matching for all parts of the password */
|
/* Do matching for all parts of the password */
|
||||||
for(i = 0; i < Len; ++i)
|
for(i = 0; i < Len; ++i)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#ifndef ZXCVBN_H_F98183CE2A01_INCLUDED
|
#ifndef ZXCVBN_H_F98183CE2A01_INCLUDED
|
||||||
#define ZXCVBN_H_F98183CE2A01_INCLUDED
|
#define ZXCVBN_H_F98183CE2A01_INCLUDED
|
||||||
/**********************************************************************************
|
/**********************************************************************************
|
||||||
* C implementation of the zxcvbn password strength estimation method.
|
* C implementation of the zxcvbn password strength estimation method.
|
||||||
|
@ -236,15 +236,15 @@ void TestEntryModel::testAutoTypeAssociationsModel()
|
|||||||
|
|
||||||
QCOMPARE(model->rowCount(), 0);
|
QCOMPARE(model->rowCount(), 0);
|
||||||
|
|
||||||
AutoTypeAssociations* assocications = new AutoTypeAssociations(this);
|
AutoTypeAssociations* associations = new AutoTypeAssociations(this);
|
||||||
model->setAutoTypeAssociations(assocications);
|
model->setAutoTypeAssociations(associations);
|
||||||
|
|
||||||
QCOMPARE(model->rowCount(), 0);
|
QCOMPARE(model->rowCount(), 0);
|
||||||
|
|
||||||
AutoTypeAssociations::Association assoc;
|
AutoTypeAssociations::Association assoc;
|
||||||
assoc.window = "1";
|
assoc.window = "1";
|
||||||
assoc.sequence = "2";
|
assoc.sequence = "2";
|
||||||
assocications->add(assoc);
|
associations->add(assoc);
|
||||||
|
|
||||||
QCOMPARE(model->rowCount(), 1);
|
QCOMPARE(model->rowCount(), 1);
|
||||||
QCOMPARE(model->data(model->index(0, 0)).toString(), QString("1"));
|
QCOMPARE(model->data(model->index(0, 0)).toString(), QString("1"));
|
||||||
@ -252,17 +252,17 @@ void TestEntryModel::testAutoTypeAssociationsModel()
|
|||||||
|
|
||||||
assoc.window = "3";
|
assoc.window = "3";
|
||||||
assoc.sequence = "4";
|
assoc.sequence = "4";
|
||||||
assocications->update(0, assoc);
|
associations->update(0, assoc);
|
||||||
QCOMPARE(model->data(model->index(0, 0)).toString(), QString("3"));
|
QCOMPARE(model->data(model->index(0, 0)).toString(), QString("3"));
|
||||||
QCOMPARE(model->data(model->index(0, 1)).toString(), QString("4"));
|
QCOMPARE(model->data(model->index(0, 1)).toString(), QString("4"));
|
||||||
|
|
||||||
assocications->add(assoc);
|
associations->add(assoc);
|
||||||
assocications->remove(0);
|
associations->remove(0);
|
||||||
QCOMPARE(model->rowCount(), 1);
|
QCOMPARE(model->rowCount(), 1);
|
||||||
|
|
||||||
delete modelTest;
|
delete modelTest;
|
||||||
delete model;
|
delete model;
|
||||||
delete assocications;
|
delete associations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEntryModel::testProxyModel()
|
void TestEntryModel::testProxyModel()
|
||||||
|
@ -83,6 +83,22 @@ void TestKeys::testComposite()
|
|||||||
delete compositeKey4;
|
delete compositeKey4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestKeys::testCompositeKeyReadFromLine()
|
||||||
|
{
|
||||||
|
|
||||||
|
QString keyFilename = QString("%1/FileKeyXml.key").arg(QString(KEEPASSX_TEST_DATA_DIR));
|
||||||
|
|
||||||
|
CompositeKey compositeFileKey = CompositeKey::readFromLine(keyFilename);
|
||||||
|
FileKey fileKey;
|
||||||
|
fileKey.load(keyFilename);
|
||||||
|
QCOMPARE(compositeFileKey.rawKey().size(), fileKey.rawKey().size());
|
||||||
|
|
||||||
|
CompositeKey compositePasswordKey = CompositeKey::readFromLine(QString("password"));
|
||||||
|
PasswordKey passwordKey(QString("password"));
|
||||||
|
QCOMPARE(compositePasswordKey.rawKey().size(), passwordKey.rawKey().size());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void TestKeys::testFileKey()
|
void TestKeys::testFileKey()
|
||||||
{
|
{
|
||||||
QFETCH(QString, type);
|
QFETCH(QString, type);
|
||||||
|
@ -27,6 +27,7 @@ class TestKeys : public QObject
|
|||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
void testComposite();
|
void testComposite();
|
||||||
|
void testCompositeKeyReadFromLine();
|
||||||
void testFileKey();
|
void testFileKey();
|
||||||
void testFileKey_data();
|
void testFileKey_data();
|
||||||
void testCreateFileKey();
|
void testCreateFileKey();
|
||||||
|
@ -328,7 +328,7 @@ void TestGui::testEntryEntropy()
|
|||||||
QTest::keyClicks(titleEdit, "test");
|
QTest::keyClicks(titleEdit, "test");
|
||||||
|
|
||||||
// Open the password generator
|
// Open the password generator
|
||||||
QToolButton* generatorButton = editEntryWidget->findChild<QToolButton*>("tooglePasswordGeneratorButton");
|
QToolButton* generatorButton = editEntryWidget->findChild<QToolButton*>("togglePasswordGeneratorButton");
|
||||||
QTest::mouseClick(generatorButton, Qt::LeftButton);
|
QTest::mouseClick(generatorButton, Qt::LeftButton);
|
||||||
|
|
||||||
// Type in some password
|
// Type in some password
|
||||||
|
@ -18,10 +18,14 @@ include_directories(../src)
|
|||||||
add_executable(kdbx-extract kdbx-extract.cpp)
|
add_executable(kdbx-extract kdbx-extract.cpp)
|
||||||
target_link_libraries(kdbx-extract
|
target_link_libraries(kdbx-extract
|
||||||
keepassx_core
|
keepassx_core
|
||||||
${MHD_LIBRARIES}
|
|
||||||
Qt5::Core
|
Qt5::Core
|
||||||
Qt5::Concurrent
|
${GCRYPT_LIBRARIES}
|
||||||
Qt5::Widgets
|
${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
|
add_executable(kdbx-merge kdbx-merge.cpp)
|
||||||
|
target_link_libraries(kdbx-merge
|
||||||
|
keepassx_core
|
||||||
|
Qt5::Core
|
||||||
${GCRYPT_LIBRARIES}
|
${GCRYPT_LIBRARIES}
|
||||||
${ZLIB_LIBRARIES})
|
${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <QCommandLineParser>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
@ -33,8 +34,16 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
QCoreApplication app(argc, argv);
|
QCoreApplication app(argc, argv);
|
||||||
|
|
||||||
if (app.arguments().size() != 3) {
|
QCommandLineParser parser;
|
||||||
qCritical("Usage: kdbx-extract <password/key file> <kdbx file>");
|
parser.setApplicationDescription(QCoreApplication::translate("main",
|
||||||
|
"Extract and print a KeePassXC database file."));
|
||||||
|
parser.addPositionalArgument("database", QCoreApplication::translate("main", "path of the database to extract."));
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
|
const QStringList args = parser.positionalArguments();
|
||||||
|
if (args.size() != 1) {
|
||||||
|
parser.showHelp();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,25 +51,18 @@ int main(int argc, char **argv)
|
|||||||
qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString()));
|
qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositeKey key;
|
static QTextStream inputTextStream(stdin, QIODevice::ReadOnly);
|
||||||
if (QFile::exists(app.arguments().at(1))) {
|
QString line = inputTextStream.readLine();
|
||||||
FileKey fileKey;
|
CompositeKey key = CompositeKey::readFromLine(line);
|
||||||
fileKey.load(app.arguments().at(1));
|
|
||||||
key.addKey(fileKey);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PasswordKey password;
|
|
||||||
password.setPassword(app.arguments().at(1));
|
|
||||||
key.addKey(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile dbFile(app.arguments().at(2));
|
QString databaseFilename = args.at(0);
|
||||||
|
QFile dbFile(databaseFilename);
|
||||||
if (!dbFile.exists()) {
|
if (!dbFile.exists()) {
|
||||||
qCritical("File does not exist.");
|
qCritical("File %s does not exist.", qPrintable(databaseFilename));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!dbFile.open(QIODevice::ReadOnly)) {
|
if (!dbFile.open(QIODevice::ReadOnly)) {
|
||||||
qCritical("Unable to open file.");
|
qCritical("Unable to open file %s.", qPrintable(databaseFilename));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
138
utils/kdbx-merge.cpp
Normal file
138
utils/kdbx-merge.cpp
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
|
||||||
|
*
|
||||||
|
* 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 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QSaveFile>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
#include "core/Database.h"
|
||||||
|
#include "crypto/Crypto.h"
|
||||||
|
#include "format/KeePass2Reader.h"
|
||||||
|
#include "format/KeePass2Writer.h"
|
||||||
|
#include "keys/CompositeKey.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription(QCoreApplication::translate("main", "Merge 2 KeePassXC database files."));
|
||||||
|
parser.addPositionalArgument("database1", QCoreApplication::translate("main", "path of the database to merge into."));
|
||||||
|
parser.addPositionalArgument("database2", QCoreApplication::translate("main", "path of the database to merge from."));
|
||||||
|
|
||||||
|
QCommandLineOption samePasswordOption(QStringList() << "s" << "same-password",
|
||||||
|
QCoreApplication::translate("main", "use the same password for both database files."));
|
||||||
|
|
||||||
|
parser.addHelpOption();
|
||||||
|
parser.addOption(samePasswordOption);
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
|
const QStringList args = parser.positionalArguments();
|
||||||
|
if (args.size() != 2) {
|
||||||
|
parser.showHelp();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Crypto::init()) {
|
||||||
|
qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static QTextStream inputTextStream(stdin, QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
QString line1 = inputTextStream.readLine();
|
||||||
|
CompositeKey key1 = CompositeKey::readFromLine(line1);
|
||||||
|
|
||||||
|
CompositeKey key2;
|
||||||
|
if (parser.isSet("same-password")) {
|
||||||
|
key2 = *key1.clone();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
QString line2 = inputTextStream.readLine();
|
||||||
|
key2 = CompositeKey::readFromLine(line2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString databaseFilename1 = args.at(0);
|
||||||
|
QFile dbFile1(databaseFilename1);
|
||||||
|
if (!dbFile1.exists()) {
|
||||||
|
qCritical("File %s does not exist.", qPrintable(databaseFilename1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!dbFile1.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical("Unable to open file %s.", qPrintable(databaseFilename1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeePass2Reader reader1;
|
||||||
|
Database* db1 = reader1.readDatabase(&dbFile1, key1);
|
||||||
|
|
||||||
|
if (reader1.hasError()) {
|
||||||
|
qCritical("Error while parsing the database:\n%s\n", qPrintable(reader1.errorString()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString databaseFilename2 = args.at(1);
|
||||||
|
QFile dbFile2(databaseFilename2);
|
||||||
|
if (!dbFile2.exists()) {
|
||||||
|
qCritical("File %s does not exist.", qPrintable(databaseFilename2));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!dbFile2.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical("Unable to open file %s.", qPrintable(databaseFilename2));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeePass2Reader reader2;
|
||||||
|
Database* db2 = reader2.readDatabase(&dbFile2, key2);
|
||||||
|
|
||||||
|
if (reader2.hasError()) {
|
||||||
|
qCritical("Error while parsing the database:\n%s\n", qPrintable(reader2.errorString()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
db1->merge(db2);
|
||||||
|
|
||||||
|
QSaveFile saveFile(databaseFilename1);
|
||||||
|
if (!saveFile.open(QIODevice::WriteOnly)) {
|
||||||
|
qCritical("Unable to open file %s for writing.", qPrintable(databaseFilename1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeePass2Writer writer;
|
||||||
|
writer.writeDatabase(&saveFile, db1);
|
||||||
|
|
||||||
|
if (writer.hasError()) {
|
||||||
|
qCritical("Error while updating the database:\n%s\n", qPrintable(writer.errorString()));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!saveFile.commit()) {
|
||||||
|
qCritical("Error while updating the database:\n%s\n", qPrintable(writer.errorString()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug("Successfully merged the database files.\n");
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user