Cache and protect MasterKey - speeds up saving a lot
Added option to save database after every change Improved license information git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@226 b624d157-de02-0410-bad0-e51aec6abb33
This commit is contained in:
parent
5fe4a5d2c3
commit
598d204716
44
COPYING
44
COPYING
|
@ -1,11 +1,5 @@
|
||||||
Copyright (C) 2005-2007 Tarek Saidi <tarek.saidi@arcor.de>
|
Copyright (C) 2005-2007 Tarek Saidi <tarek.saidi@arcor.de>
|
||||||
Copyright (C) 2003-2007 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2007-2008 Felix Geyer
|
||||||
Copyright (C) 2001 Niels Müler
|
|
||||||
Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc.
|
|
||||||
Copyright (C) 2003, 2004 Michael Buesch <mbuesch@freenet.de>
|
|
||||||
Copyright (c) 2003 Dr Brian Gladman, Worcester, UK
|
|
||||||
Copyright (C) 2001-2003 Christophe Devine
|
|
||||||
Copyright (C) 1992-2007 Trolltech ASA
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -16,6 +10,42 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
text of the GNU General Public License below for more details.
|
text of the GNU General Public License below for more details.
|
||||||
|
|
||||||
|
|
||||||
|
Other licenses:
|
||||||
|
|
||||||
|
apg/*:
|
||||||
|
Copyright (c) 1999, 2000, 2001, 2002, 2003 Adel I. Mirzazhanov
|
||||||
|
3-clause BSD license
|
||||||
|
|
||||||
|
crypto/aes*:
|
||||||
|
Copyright (c) 1998-2008, Brian Gladman, Worcester
|
||||||
|
3-clause BSD license
|
||||||
|
|
||||||
|
crypto/arcfour*:
|
||||||
|
Copyright (C) 2003-2008 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
GPLv2 or later
|
||||||
|
|
||||||
|
crypto/blowfish*:
|
||||||
|
Copyright (C) 1998, 2001, 2002 Free Software Foundation, Inc.
|
||||||
|
Copyright (C) 2003 by Michael Buesch
|
||||||
|
Copyright (C) 2007 by Tarek Saidi <tarek.saidi@arcor.de>
|
||||||
|
GPLv2
|
||||||
|
|
||||||
|
crypto/sha256*:
|
||||||
|
Copyright (C) 2001-2003 by Christophe Devine
|
||||||
|
Copyright (C) 2005-2006 by Tarek Saidi
|
||||||
|
GPLv2
|
||||||
|
|
||||||
|
crypto/two*:
|
||||||
|
Copyright (C) 2005-2007 Tarek Saidi <tarek.saidi@arcor.de>
|
||||||
|
Copyright (c) 2003,2004 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
GPLv2
|
||||||
|
|
||||||
|
crypto/yarrow*:
|
||||||
|
Copyright (C) 2007 Tarek Saidi <tarek.saidi@arcor.de>
|
||||||
|
Copyright (C) 2001 Niels Müler
|
||||||
|
GPLv2
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
|
|
@ -239,6 +239,7 @@ public:
|
||||||
|
|
||||||
virtual bool setKey(const QString& password,const QString& keyfile)=0;
|
virtual bool setKey(const QString& password,const QString& keyfile)=0;
|
||||||
virtual bool isKeyError()=0;
|
virtual bool isKeyError()=0;
|
||||||
|
virtual void generateMasterKey()=0;
|
||||||
|
|
||||||
//! Loads a database.
|
//! Loads a database.
|
||||||
/*! It is not allowed to call this function if a database is already loaded.
|
/*! It is not allowed to call this function if a database is already loaded.
|
||||||
|
|
|
@ -40,6 +40,9 @@ bool StdEntryLessThan(const Kdb3Database::StdEntry& This,const Kdb3Database::Std
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Kdb3Database::Kdb3Database() : RawMasterKey(32), RawMasterKey_Latin1(32), MasterKey(32){
|
||||||
|
}
|
||||||
|
|
||||||
QString Kdb3Database::getError(){
|
QString Kdb3Database::getError(){
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -477,7 +480,6 @@ void Kdb3Database::restoreGroupTreeState(){
|
||||||
bool Kdb3Database::load(QString filename){
|
bool Kdb3Database::load(QString filename){
|
||||||
unsigned long total_size,crypto_size;
|
unsigned long total_size,crypto_size;
|
||||||
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
|
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
|
||||||
quint8 TransfRandomSeed[32];
|
|
||||||
quint8 FinalRandomSeed[16];
|
quint8 FinalRandomSeed[16];
|
||||||
quint8 ContentsHash[32];
|
quint8 ContentsHash[32];
|
||||||
quint8 EncryptionIV[16];
|
quint8 EncryptionIV[16];
|
||||||
|
@ -531,16 +533,20 @@ else{
|
||||||
LOAD_RETURN_CLEANUP
|
LOAD_RETURN_CLEANUP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RawMasterKey.unlock();
|
||||||
KeyTransform::transform(RawMasterKey,MasterKey,TransfRandomSeed,KeyTransfRounds);
|
MasterKey.unlock();
|
||||||
|
KeyTransform::transform(*RawMasterKey,*MasterKey,TransfRandomSeed,KeyTransfRounds);
|
||||||
|
|
||||||
quint8 FinalKey[32];
|
quint8 FinalKey[32];
|
||||||
|
|
||||||
SHA256 sha;
|
SHA256 sha;
|
||||||
sha.update(FinalRandomSeed,16);
|
sha.update(FinalRandomSeed,16);
|
||||||
sha.update(MasterKey,32);
|
sha.update(*MasterKey,32);
|
||||||
sha.finish(FinalKey);
|
sha.finish(FinalKey);
|
||||||
|
|
||||||
|
RawMasterKey.lock();
|
||||||
|
MasterKey.lock();
|
||||||
|
|
||||||
if(Algorithm == Rijndael_Cipher){
|
if(Algorithm == Rijndael_Cipher){
|
||||||
AESdecrypt aes;
|
AESdecrypt aes;
|
||||||
aes.key256(FinalKey);
|
aes.key256(FinalKey);
|
||||||
|
@ -572,7 +578,8 @@ if(memcmp(ContentsHash, FinalKey, 32) != 0){
|
||||||
// but KeePass/Win32 uses Windows Codepage 1252.
|
// but KeePass/Win32 uses Windows Codepage 1252.
|
||||||
// Too stay compatible with databases created with KeePassX <= 0.3.1
|
// Too stay compatible with databases created with KeePassX <= 0.3.1
|
||||||
// the loading function gives both encodings a try.
|
// the loading function gives both encodings a try.
|
||||||
memcpy(RawMasterKey,RawMasterKey_Latin1,32);
|
|
||||||
|
RawMasterKey.copyData(RawMasterKey_Latin1);
|
||||||
PotentialEncodingIssue=false;
|
PotentialEncodingIssue=false;
|
||||||
qDebug("Decryption failed. Retrying with Latin-1.");
|
qDebug("Decryption failed. Retrying with Latin-1.");
|
||||||
return load(filename); // second try
|
return load(filename); // second try
|
||||||
|
@ -829,7 +836,9 @@ bool Kdb3Database::setPasswordKey(const QString& Password){
|
||||||
assert(Password.size());
|
assert(Password.size());
|
||||||
QTextCodec* codec=QTextCodec::codecForName("Windows-1252");
|
QTextCodec* codec=QTextCodec::codecForName("Windows-1252");
|
||||||
QByteArray Password_CP1252 = codec->fromUnicode(Password);
|
QByteArray Password_CP1252 = codec->fromUnicode(Password);
|
||||||
SHA256::hashBuffer(Password_CP1252.data(),RawMasterKey,Password_CP1252.size());
|
RawMasterKey.unlock();
|
||||||
|
SHA256::hashBuffer(Password_CP1252.data(),*RawMasterKey,Password_CP1252.size());
|
||||||
|
RawMasterKey.lock();
|
||||||
QByteArray Password_Latin1 = Password.toLatin1();
|
QByteArray Password_Latin1 = Password.toLatin1();
|
||||||
if(Password_Latin1 != Password_CP1252){
|
if(Password_Latin1 != Password_CP1252){
|
||||||
// KeePassX used Latin-1 encoding for passwords until version 0.3.1
|
// KeePassX used Latin-1 encoding for passwords until version 0.3.1
|
||||||
|
@ -837,7 +846,9 @@ bool Kdb3Database::setPasswordKey(const QString& Password){
|
||||||
// Too stay compatible with databases created with KeePassX <= 0.3.1
|
// Too stay compatible with databases created with KeePassX <= 0.3.1
|
||||||
// the loading function gives both encodings a try.
|
// the loading function gives both encodings a try.
|
||||||
PotentialEncodingIssue = true;
|
PotentialEncodingIssue = true;
|
||||||
SHA256::hashBuffer(Password_Latin1.data(),RawMasterKey_Latin1,Password_Latin1.size());
|
RawMasterKey_Latin1.unlock();
|
||||||
|
SHA256::hashBuffer(Password_Latin1.data(),*RawMasterKey_Latin1,Password_Latin1.size());
|
||||||
|
RawMasterKey_Latin1.lock();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If the password does not contain problematic characters we don't need
|
// If the password does not contain problematic characters we don't need
|
||||||
|
@ -858,22 +869,28 @@ bool Kdb3Database::setFileKey(const QString& filename){
|
||||||
error=tr("Key file is empty.");
|
error=tr("Key file is empty.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
RawMasterKey.unlock();
|
||||||
if(FileSize == 32){
|
if(FileSize == 32){
|
||||||
if(file.read((char*)RawMasterKey,32) != 32){
|
if(file.read((char*)(*RawMasterKey),32) != 32){
|
||||||
error=decodeFileError(file.error());
|
error=decodeFileError(file.error());
|
||||||
|
RawMasterKey.lock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
RawMasterKey.lock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(FileSize == 64){
|
if(FileSize == 64){
|
||||||
char hex[64];
|
char hex[64];
|
||||||
if(file.read(hex,64) != 64){
|
if(file.read(hex,64) != 64){
|
||||||
error=decodeFileError(file.error());
|
error=decodeFileError(file.error());
|
||||||
|
RawMasterKey.lock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (convHexToBinaryKey(hex,(char*)RawMasterKey))
|
if (convHexToBinaryKey(hex,(char*)(*RawMasterKey))){
|
||||||
|
RawMasterKey.lock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
SHA256 sha;
|
SHA256 sha;
|
||||||
unsigned char* buffer = new unsigned char[2048];
|
unsigned char* buffer = new unsigned char[2048];
|
||||||
while(1)
|
while(1)
|
||||||
|
@ -883,22 +900,25 @@ bool Kdb3Database::setFileKey(const QString& filename){
|
||||||
sha.update(buffer,read);
|
sha.update(buffer,read);
|
||||||
if(read != 2048) break;
|
if(read != 2048) break;
|
||||||
}
|
}
|
||||||
sha.finish(RawMasterKey);
|
sha.finish(*RawMasterKey);
|
||||||
|
RawMasterKey.lock();
|
||||||
delete [] buffer;
|
delete [] buffer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Kdb3Database::setCompositeKey(const QString& Password,const QString& filename){
|
bool Kdb3Database::setCompositeKey(const QString& Password,const QString& filename){
|
||||||
unsigned char PasswordKey[32];
|
|
||||||
unsigned char FileKey[32];
|
|
||||||
if(!setFileKey(filename))return false;
|
|
||||||
memcpy(FileKey,RawMasterKey,32);
|
|
||||||
setPasswordKey(Password);
|
|
||||||
memcpy(PasswordKey,RawMasterKey,32);
|
|
||||||
SHA256 sha;
|
SHA256 sha;
|
||||||
sha.update(PasswordKey,32);
|
|
||||||
sha.update(FileKey,32);
|
if(!setFileKey(filename))return false;
|
||||||
sha.finish(RawMasterKey);
|
RawMasterKey.unlock();
|
||||||
|
sha.update(*RawMasterKey,32);
|
||||||
|
RawMasterKey.lock();
|
||||||
|
|
||||||
|
setPasswordKey(Password);
|
||||||
|
RawMasterKey.unlock();
|
||||||
|
sha.update(*RawMasterKey,32);
|
||||||
|
sha.finish(*RawMasterKey);
|
||||||
|
RawMasterKey.lock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,7 +1207,6 @@ bool Kdb3Database::save(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
quint32 NumGroups,NumEntries,Signature1,Signature2,Flags,Version;
|
quint32 NumGroups,NumEntries,Signature1,Signature2,Flags,Version;
|
||||||
quint8 TransfRandomSeed[32];
|
|
||||||
quint8 FinalRandomSeed[16];
|
quint8 FinalRandomSeed[16];
|
||||||
quint8 ContentsHash[32];
|
quint8 ContentsHash[32];
|
||||||
quint8 EncryptionIV[16];
|
quint8 EncryptionIV[16];
|
||||||
|
@ -1260,7 +1279,6 @@ bool Kdb3Database::save(){
|
||||||
qSort(saveEntries.begin(),saveEntries.end(),StdEntryLessThan);
|
qSort(saveEntries.begin(),saveEntries.end(),StdEntryLessThan);
|
||||||
|
|
||||||
randomize(FinalRandomSeed,16);
|
randomize(FinalRandomSeed,16);
|
||||||
randomize(TransfRandomSeed,32);
|
|
||||||
randomize(EncryptionIV,16);
|
randomize(EncryptionIV,16);
|
||||||
|
|
||||||
unsigned int pos=DB_HEADER_SIZE; // Skip the header, it will be written later
|
unsigned int pos=DB_HEADER_SIZE; // Skip the header, it will be written later
|
||||||
|
@ -1281,12 +1299,13 @@ bool Kdb3Database::save(){
|
||||||
memcpy(buffer+56,ContentsHash,32);
|
memcpy(buffer+56,ContentsHash,32);
|
||||||
memcpy(buffer+88,TransfRandomSeed,32);
|
memcpy(buffer+88,TransfRandomSeed,32);
|
||||||
memcpyToLEnd32(buffer+120,&KeyTransfRounds);
|
memcpyToLEnd32(buffer+120,&KeyTransfRounds);
|
||||||
KeyTransform::transform(RawMasterKey,MasterKey,TransfRandomSeed,KeyTransfRounds);
|
|
||||||
quint8 FinalKey[32];
|
quint8 FinalKey[32];
|
||||||
|
|
||||||
SHA256 sha;
|
SHA256 sha;
|
||||||
sha.update(FinalRandomSeed,16);
|
sha.update(FinalRandomSeed,16);
|
||||||
sha.update(MasterKey,32);
|
MasterKey.unlock();
|
||||||
|
sha.update(*MasterKey,32);
|
||||||
|
MasterKey.lock();
|
||||||
sha.finish(FinalKey);
|
sha.finish(FinalKey);
|
||||||
|
|
||||||
unsigned long EncryptedPartSize;
|
unsigned long EncryptedPartSize;
|
||||||
|
@ -1805,6 +1824,15 @@ QList<IEntryHandle*> Kdb3Database::trashEntries(){
|
||||||
return handles;
|
return handles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Kdb3Database::generateMasterKey(){
|
||||||
|
randomize(TransfRandomSeed,32);
|
||||||
|
RawMasterKey.unlock();
|
||||||
|
MasterKey.unlock();
|
||||||
|
KeyTransform::transform(*RawMasterKey,*MasterKey,TransfRandomSeed,KeyTransfRounds);
|
||||||
|
RawMasterKey.lock();
|
||||||
|
MasterKey.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyTransform::transform(quint8* src, quint8* dst, quint8* KeySeed, int rounds){
|
void KeyTransform::transform(quint8* src, quint8* dst, quint8* KeySeed, int rounds){
|
||||||
KeyTransform* ktLeft = new KeyTransform(&src[0], &dst[0], KeySeed, rounds);
|
KeyTransform* ktLeft = new KeyTransform(&src[0], &dst[0], KeySeed, rounds);
|
||||||
|
|
|
@ -137,6 +137,7 @@ public:
|
||||||
QStringList GroupPath;
|
QStringList GroupPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Kdb3Database();
|
||||||
virtual ~Kdb3Database(){};
|
virtual ~Kdb3Database(){};
|
||||||
virtual bool load(QString identifier);
|
virtual bool load(QString identifier);
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
@ -188,6 +189,7 @@ public:
|
||||||
virtual IGroupHandle* addGroup(const CGroup* Group,IGroupHandle* Parent);
|
virtual IGroupHandle* addGroup(const CGroup* Group,IGroupHandle* Parent);
|
||||||
virtual bool isParent(IGroupHandle* parent, IGroupHandle* child);
|
virtual bool isParent(IGroupHandle* parent, IGroupHandle* child);
|
||||||
|
|
||||||
|
virtual void generateMasterKey();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -241,9 +243,10 @@ private:
|
||||||
QMap<quint32,bool> TreeStateMetaStream;
|
QMap<quint32,bool> TreeStateMetaStream;
|
||||||
unsigned int KeyTransfRounds;
|
unsigned int KeyTransfRounds;
|
||||||
CryptAlgorithm Algorithm;
|
CryptAlgorithm Algorithm;
|
||||||
quint8 RawMasterKey[32];
|
SecData RawMasterKey;
|
||||||
quint8 RawMasterKey_Latin1[32];
|
SecData RawMasterKey_Latin1;
|
||||||
quint8 MasterKey[32];
|
SecData MasterKey;
|
||||||
|
quint8 TransfRandomSeed[32];
|
||||||
bool hasV4IconMetaStream;
|
bool hasV4IconMetaStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ public:
|
||||||
QString mountDir(){return settings.value("Options/MountDir",DEFAULT_MOUNT_DIR).toString();}
|
QString mountDir(){return settings.value("Options/MountDir",DEFAULT_MOUNT_DIR).toString();}
|
||||||
bool openLastFile(){return settings.value("Options/OpenLastFile",true).toBool();}
|
bool openLastFile(){return settings.value("Options/OpenLastFile",true).toBool();}
|
||||||
bool autoSave(){return settings.value("Options/AutoSave",false).toBool();}
|
bool autoSave(){return settings.value("Options/AutoSave",false).toBool();}
|
||||||
|
bool autoSaveChange(){return settings.value("Options/AutoSaveChange",false).toBool();}
|
||||||
int pwGenCategory(){return settings.value("Options/PwGenCategory",0).toInt();}
|
int pwGenCategory(){return settings.value("Options/PwGenCategory",0).toInt();}
|
||||||
QString pwGenCharList(){return settings.value("Options/PwGenCharList").toString();}
|
QString pwGenCharList(){return settings.value("Options/PwGenCharList").toString();}
|
||||||
int pwGenLength(){return settings.value("Options/PwGenLength",25).toInt();}
|
int pwGenLength(){return settings.value("Options/PwGenLength",25).toInt();}
|
||||||
|
@ -132,6 +133,7 @@ public:
|
||||||
void setMountDir(const QString& value){settings.setValue("Options/MountDir",value);}
|
void setMountDir(const QString& value){settings.setValue("Options/MountDir",value);}
|
||||||
void setOpenLastFile(bool value){settings.setValue("Options/OpenLastFile",value);}
|
void setOpenLastFile(bool value){settings.setValue("Options/OpenLastFile",value);}
|
||||||
void setAutoSave(bool value){settings.setValue("Options/AutoSave",value);}
|
void setAutoSave(bool value){settings.setValue("Options/AutoSave",value);}
|
||||||
|
void setAutoSaveChange(bool value){settings.setValue("Options/AutoSaveChange",value);}
|
||||||
void setPwGenCategory(int value){settings.setValue("Options/PwGenCategory",value);}
|
void setPwGenCategory(int value){settings.setValue("Options/PwGenCategory",value);}
|
||||||
void setPwGenCharList(const QString& value){settings.setValue("Options/PwGenCharList",value);}
|
void setPwGenCharList(const QString& value){settings.setValue("Options/PwGenCharList",value);}
|
||||||
void setPwGenLength(int value){settings.setValue("Options/PwGenLength",value);}
|
void setPwGenLength(int value){settings.setValue("Options/PwGenLength",value);}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2001-2003 by Christophe Devine *
|
||||||
* Copyright (C) 2005-2006 by Tarek Saidi *
|
* Copyright (C) 2005-2006 by Tarek Saidi *
|
||||||
* based on the FIPS-180-2 compliant SHA-256 implementation of *
|
|
||||||
* Christophe Devine. *
|
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
* Copyright (C) 2001-2003 by Christophe Devine *
|
||||||
* Copyright (C) 2005-2006 by Tarek Saidi *
|
* Copyright (C) 2005-2006 by Tarek Saidi *
|
||||||
* based on the FIPS-180-2 compliant SHA-256 implementation of *
|
|
||||||
* Christophe Devine. *
|
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
|
|
@ -51,6 +51,8 @@ CSettingsDlg::CSettingsDlg(QWidget* parent):QDialog(parent,Qt::Dialog)
|
||||||
|
|
||||||
connect(Button_CustomizeEntryDetails,SIGNAL(clicked()),this,SLOT(OnCustomizeEntryDetails()));
|
connect(Button_CustomizeEntryDetails,SIGNAL(clicked()),this,SLOT(OnCustomizeEntryDetails()));
|
||||||
connect(CheckBox_InactivityLock, SIGNAL(toggled(bool)), SLOT(OnInactivityLockChange(bool)));
|
connect(CheckBox_InactivityLock, SIGNAL(toggled(bool)), SLOT(OnInactivityLockChange(bool)));
|
||||||
|
connect(CheckBox_AutoSave, SIGNAL(toggled(bool)), SLOT(OnAutoSaveToggle(bool)));
|
||||||
|
connect(CheckBox_AutoSaveChange, SIGNAL(toggled(bool)), SLOT(OnAutoSaveChangeToggle(bool)));
|
||||||
|
|
||||||
#if !defined(AUTOTYPE)
|
#if !defined(AUTOTYPE)
|
||||||
Box_AutoType->setVisible(false);
|
Box_AutoType->setVisible(false);
|
||||||
|
@ -76,6 +78,7 @@ CSettingsDlg::CSettingsDlg(QWidget* parent):QDialog(parent,Qt::Dialog)
|
||||||
CheckBox_StartLocked->setChecked(config->startLocked());
|
CheckBox_StartLocked->setChecked(config->startLocked());
|
||||||
checkBox_SaveFileDlgHistory->setChecked(config->saveFileDlgHistory());
|
checkBox_SaveFileDlgHistory->setChecked(config->saveFileDlgHistory());
|
||||||
CheckBox_AutoSave->setChecked(config->autoSave());
|
CheckBox_AutoSave->setChecked(config->autoSave());
|
||||||
|
CheckBox_AutoSaveChange->setChecked(config->autoSaveChange());
|
||||||
checkBox_AskBeforeDelete->setChecked(config->askBeforeDelete());
|
checkBox_AskBeforeDelete->setChecked(config->askBeforeDelete());
|
||||||
|
|
||||||
switch(config->groupTreeState()){
|
switch(config->groupTreeState()){
|
||||||
|
@ -211,6 +214,7 @@ void CSettingsDlg::apply(){
|
||||||
config->setOpenLastFile(CheckBox_OpenLast->isChecked());
|
config->setOpenLastFile(CheckBox_OpenLast->isChecked());
|
||||||
config->setRememberLastKey(CheckBox_RememberLastKey->isChecked());
|
config->setRememberLastKey(CheckBox_RememberLastKey->isChecked());
|
||||||
config->setAutoSave(CheckBox_AutoSave->isChecked());
|
config->setAutoSave(CheckBox_AutoSave->isChecked());
|
||||||
|
config->setAutoSaveChange(CheckBox_AutoSaveChange->isChecked());
|
||||||
config->setAskBeforeDelete(checkBox_AskBeforeDelete->isChecked());
|
config->setAskBeforeDelete(checkBox_AskBeforeDelete->isChecked());
|
||||||
|
|
||||||
//Appearence
|
//Appearence
|
||||||
|
@ -330,6 +334,14 @@ void CSettingsDlg::OnInactivityLockChange(bool checked){
|
||||||
SpinBox_InacitivtyTime->setEnabled(checked);
|
SpinBox_InacitivtyTime->setEnabled(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSettingsDlg::OnAutoSaveToggle(bool checked){
|
||||||
|
CheckBox_AutoSaveChange->setEnabled(!checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSettingsDlg::OnAutoSaveChangeToggle(bool checked){
|
||||||
|
CheckBox_AutoSave->setEnabled(!checked);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef GLOBAL_AUTOTYPE
|
#ifdef GLOBAL_AUTOTYPE
|
||||||
void CSettingsDlg::resetGlobalShortcut(){
|
void CSettingsDlg::resetGlobalShortcut(){
|
||||||
AutoType::unregisterGlobalShortcut();
|
AutoType::unregisterGlobalShortcut();
|
||||||
|
|
|
@ -45,6 +45,8 @@ class CSettingsDlg : public QDialog, private Ui_SettingsDialog
|
||||||
void OnBrowserCmdBrowse();
|
void OnBrowserCmdBrowse();
|
||||||
void OnCustomizeEntryDetails();
|
void OnCustomizeEntryDetails();
|
||||||
void OnInactivityLockChange(bool checked);
|
void OnInactivityLockChange(bool checked);
|
||||||
|
void OnAutoSaveToggle(bool checked);
|
||||||
|
void OnAutoSaveChangeToggle(bool checked);
|
||||||
|
|
||||||
#ifdef GLOBAL_AUTOTYPE
|
#ifdef GLOBAL_AUTOTYPE
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>606</width>
|
<width>606</width>
|
||||||
<height>475</height>
|
<height>479</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle" >
|
<property name="windowTitle" >
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>584</width>
|
<width>584</width>
|
||||||
<height>341</height>
|
<height>345</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="whatsThis" >
|
<property name="whatsThis" >
|
||||||
|
@ -290,6 +290,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="CheckBox_AutoSaveChange" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Automatically save database after every change</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkBox_AskBeforeDelete" >
|
<widget class="QCheckBox" name="checkBox_AskBeforeDelete" >
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
|
@ -318,7 +325,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>584</width>
|
<width>584</width>
|
||||||
<height>341</height>
|
<height>345</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
|
@ -678,7 +685,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>584</width>
|
<width>584</width>
|
||||||
<height>341</height>
|
<height>345</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
|
@ -840,7 +847,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>584</width>
|
<width>584</width>
|
||||||
<height>341</height>
|
<height>345</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
|
@ -885,7 +892,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>584</width>
|
<width>584</width>
|
||||||
<height>341</height>
|
<height>345</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
|
@ -1005,7 +1012,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>584</width>
|
<width>584</width>
|
||||||
<height>341</height>
|
<height>345</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
|
|
|
@ -105,8 +105,8 @@ bool Import_PwManager::importDatabase(QWidget* GuiParent, IDatabase* db){
|
||||||
|
|
||||||
if(!parseXmlContent((char*)xml)){
|
if(!parseXmlContent((char*)xml)){
|
||||||
delete [] xml;
|
delete [] xml;
|
||||||
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Invalid XML data (see stdout for details).")); return false;}
|
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Invalid XML data (see stdout for details).")); return false;
|
||||||
database->setKey(password,QString());
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,3 +98,46 @@ void SecString::generateSessionKey(){
|
||||||
randomize(sessionkey, 32);
|
randomize(sessionkey, 32);
|
||||||
RC4.setKey(sessionkey, 32);
|
RC4.setKey(sessionkey, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SecData::SecData(int len) : locked(true){
|
||||||
|
length = len;
|
||||||
|
data = new quint8[len];
|
||||||
|
}
|
||||||
|
|
||||||
|
SecData::~SecData(){
|
||||||
|
if (!locked){
|
||||||
|
for (int i=0; i<length; i++)
|
||||||
|
data[i] = 0;
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecData::lock(){
|
||||||
|
Q_ASSERT(!locked);
|
||||||
|
SecString::RC4.encrypt(data, data, length);
|
||||||
|
locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecData::unlock(){
|
||||||
|
Q_ASSERT(locked);
|
||||||
|
SecString::RC4.decrypt(data, data, length);
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecData::copyData(quint8* src){
|
||||||
|
unlock();
|
||||||
|
memcpy(data, src, length);
|
||||||
|
lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SecData::copyData(SecData& secData){
|
||||||
|
secData.unlock();
|
||||||
|
copyData(*secData);
|
||||||
|
secData.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8* SecData::operator*(){
|
||||||
|
Q_ASSERT(!locked);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
|
@ -22,11 +22,16 @@
|
||||||
|
|
||||||
#include "crypto/arcfour.h"
|
#include "crypto/arcfour.h"
|
||||||
|
|
||||||
|
class SecData;
|
||||||
|
|
||||||
//! QString based class with in-memory encryption of its content.
|
//! QString based class with in-memory encryption of its content.
|
||||||
/*!
|
/*!
|
||||||
This class can hold a QString object in an encrypted buffer. To get access to the string it is neccassary to unlock the SecString object.
|
This class can hold a QString object in an encrypted buffer. To get access to the string it is neccassary to unlock the SecString object.
|
||||||
*/
|
*/
|
||||||
class SecString{
|
class SecString{
|
||||||
|
|
||||||
|
friend class SecData;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SecString();
|
SecString();
|
||||||
~SecString();
|
~SecString();
|
||||||
|
@ -56,5 +61,21 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SecData{
|
||||||
|
public:
|
||||||
|
SecData(int len);
|
||||||
|
~SecData();
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
void copyData(quint8* src);
|
||||||
|
void copyData(SecData& secData);
|
||||||
|
quint8* operator*();
|
||||||
|
|
||||||
|
private:
|
||||||
|
quint8* data;
|
||||||
|
int length;
|
||||||
|
bool locked;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -224,3 +224,13 @@ bool lockPage(void* addr, int len){
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool unlockPage(void* addr, int len){
|
||||||
|
#if defined(Q_WS_X11) || defined(Q_WS_MAC)
|
||||||
|
return (munlock(addr, len)==0);
|
||||||
|
#elif defined(Q_WS_WIN)
|
||||||
|
return VirtualUnlock(addr, len);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -34,5 +34,6 @@ QString makePathRelative(const QString& Abs,const QString& Cur);
|
||||||
QString getImageFile(const QString& name);
|
QString getImageFile(const QString& name);
|
||||||
bool createKeyFile(const QString& filename,QString* err, int length=32, bool Hex=true);
|
bool createKeyFile(const QString& filename,QString* err, int length=32, bool Hex=true);
|
||||||
bool lockPage(void* addr, int len);
|
bool lockPage(void* addr, int len);
|
||||||
|
bool unlockPage(void* addr, int len);
|
||||||
|
|
||||||
#endif //TOOLS_H
|
#endif //TOOLS_H
|
||||||
|
|
|
@ -488,12 +488,12 @@ bool KeepassMainWindow::closeDatabase(bool lock){
|
||||||
Q_ASSERT(FileOpen);
|
Q_ASSERT(FileOpen);
|
||||||
Q_ASSERT(db!=NULL);
|
Q_ASSERT(db!=NULL);
|
||||||
if(ModFlag){
|
if(ModFlag){
|
||||||
if(config->autoSave()){
|
if(config->autoSave() && db->file()){
|
||||||
if(!OnFileSave()) return false;
|
if(!OnFileSave()) return false;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
QMessageBox::StandardButton r=QMessageBox::question(this,tr("Save modified file?"),
|
QMessageBox::StandardButton r=QMessageBox::question(this,tr("Save modified file?"),
|
||||||
tr("The current file was modified. Do you want\nto save the changes?"),
|
tr("The current file was modified.\nDo you want to save the changes?"),
|
||||||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
|
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
|
||||||
if(r==QMessageBox::Cancel) return false; //Cancel
|
if(r==QMessageBox::Cancel) return false; //Cancel
|
||||||
if(r==QMessageBox::Yes){ //Yes (Save file)
|
if(r==QMessageBox::Yes){ //Yes (Save file)
|
||||||
|
@ -538,6 +538,7 @@ void KeepassMainWindow::OnFileNewKdb(){
|
||||||
resetLock();
|
resetLock();
|
||||||
db=db_new;
|
db=db_new;
|
||||||
db->setKey(dlg.password(),dlg.keyFile());
|
db->setKey(dlg.password(),dlg.keyFile());
|
||||||
|
db->generateMasterKey();
|
||||||
setWindowTitle(QString("[%1][*] - KeePassX").arg(tr("new")));
|
setWindowTitle(QString("[%1][*] - KeePassX").arg(tr("new")));
|
||||||
GroupView->db=db;
|
GroupView->db=db;
|
||||||
EntryView->db=db;
|
EntryView->db=db;
|
||||||
|
@ -545,7 +546,6 @@ void KeepassMainWindow::OnFileNewKdb(){
|
||||||
EntryView->showGroup(NULL);
|
EntryView->showGroup(NULL);
|
||||||
setStateFileOpen(true);
|
setStateFileOpen(true);
|
||||||
setStateFileModified(true);
|
setStateFileModified(true);
|
||||||
FileOpen=true;
|
|
||||||
setupDatabaseConnections(db);
|
setupDatabaseConnections(db);
|
||||||
setStateGroupSelected(NONE);
|
setStateGroupSelected(NONE);
|
||||||
setStateEntrySelected(NONE);
|
setStateEntrySelected(NONE);
|
||||||
|
@ -592,6 +592,7 @@ void KeepassMainWindow::setStateFileOpen(bool IsOpen){
|
||||||
FileCloseAction->setEnabled(IsOpen||IsLocked);
|
FileCloseAction->setEnabled(IsOpen||IsLocked);
|
||||||
FileSettingsAction->setEnabled(IsOpen);
|
FileSettingsAction->setEnabled(IsOpen);
|
||||||
FileChangeKeyAction->setEnabled(IsOpen);
|
FileChangeKeyAction->setEnabled(IsOpen);
|
||||||
|
menuExport->setEnabled(IsOpen);
|
||||||
EditSearchAction->setEnabled(IsOpen);
|
EditSearchAction->setEnabled(IsOpen);
|
||||||
GroupView->setEnabled(IsOpen);
|
GroupView->setEnabled(IsOpen);
|
||||||
EntryView->setEnabled(IsOpen);
|
EntryView->setEnabled(IsOpen);
|
||||||
|
@ -627,10 +628,11 @@ void KeepassMainWindow::setStateFileOpen(bool IsOpen){
|
||||||
|
|
||||||
|
|
||||||
void KeepassMainWindow::setStateFileModified(bool mod){
|
void KeepassMainWindow::setStateFileModified(bool mod){
|
||||||
if(!FileOpen){
|
if (config->autoSaveChange() && mod && db->file()){
|
||||||
FileSaveAction->setIcon(getIcon("filesave"));
|
OnFileSave();
|
||||||
return;
|
mod = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModFlag=mod;
|
ModFlag=mod;
|
||||||
if(mod)
|
if(mod)
|
||||||
FileSaveAction->setIcon(getIcon("filesave"));
|
FileSaveAction->setIcon(getIcon("filesave"));
|
||||||
|
@ -884,7 +886,10 @@ bool KeepassMainWindow::OnFileSaveAs(){
|
||||||
|
|
||||||
void KeepassMainWindow::OnFileSettings(){
|
void KeepassMainWindow::OnFileSettings(){
|
||||||
CDbSettingsDlg dlg(this,db);
|
CDbSettingsDlg dlg(this,db);
|
||||||
if(dlg.exec()) setStateFileModified(true);
|
if(dlg.exec()){
|
||||||
|
db->generateMasterKey();
|
||||||
|
setStateFileModified(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeepassMainWindow::OnFileChangeKey(){
|
void KeepassMainWindow::OnFileChangeKey(){
|
||||||
|
@ -892,8 +897,9 @@ void KeepassMainWindow::OnFileChangeKey(){
|
||||||
QString filename = file ? file->fileName() : QString();
|
QString filename = file ? file->fileName() : QString();
|
||||||
PasswordDialog dlg(this,PasswordDialog::Mode_Change,PasswordDialog::Flag_None,filename);
|
PasswordDialog dlg(this,PasswordDialog::Mode_Change,PasswordDialog::Flag_None,filename);
|
||||||
if(dlg.exec()==PasswordDialog::Exit_Ok){
|
if(dlg.exec()==PasswordDialog::Exit_Ok){
|
||||||
setStateFileModified(true);
|
|
||||||
db->setKey(dlg.password(),dlg.keyFile());
|
db->setKey(dlg.password(),dlg.keyFile());
|
||||||
|
db->generateMasterKey();
|
||||||
|
setStateFileModified(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -920,6 +926,7 @@ void KeepassMainWindow::OnImport(QAction* action){
|
||||||
}
|
}
|
||||||
db=tmpdb;
|
db=tmpdb;
|
||||||
db->setKey(dlg.password(),dlg.keyFile());
|
db->setKey(dlg.password(),dlg.keyFile());
|
||||||
|
db->generateMasterKey();
|
||||||
GroupView->db=db;
|
GroupView->db=db;
|
||||||
EntryView->db=db;
|
EntryView->db=db;
|
||||||
setupDatabaseConnections(db);
|
setupDatabaseConnections(db);
|
||||||
|
@ -989,7 +996,7 @@ void KeepassMainWindow::OnUsernPasswVisibilityChanged(bool value){
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeepassMainWindow::OnFileModified(){
|
void KeepassMainWindow::OnFileModified(){
|
||||||
setStateFileModified(true);
|
setStateFileModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
||||||
|
@ -1017,7 +1024,8 @@ void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
||||||
if(!closeDatabase()){
|
if(!closeDatabase()){
|
||||||
ShutingDown=false;
|
ShutingDown=false;
|
||||||
e->ignore();
|
e->ignore();
|
||||||
return;}
|
return;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue