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) 2003-2007 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
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
|
||||
Copyright (C) 2007-2008 Felix Geyer
|
||||
|
||||
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
|
||||
|
@ -16,6 +10,42 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
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
|
||||
|
|
|
@ -239,6 +239,7 @@ public:
|
|||
|
||||
virtual bool setKey(const QString& password,const QString& keyfile)=0;
|
||||
virtual bool isKeyError()=0;
|
||||
virtual void generateMasterKey()=0;
|
||||
|
||||
//! Loads a database.
|
||||
/*! 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(){
|
||||
return error;
|
||||
}
|
||||
|
@ -477,7 +480,6 @@ void Kdb3Database::restoreGroupTreeState(){
|
|||
bool Kdb3Database::load(QString filename){
|
||||
unsigned long total_size,crypto_size;
|
||||
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
|
||||
quint8 TransfRandomSeed[32];
|
||||
quint8 FinalRandomSeed[16];
|
||||
quint8 ContentsHash[32];
|
||||
quint8 EncryptionIV[16];
|
||||
|
@ -531,16 +533,20 @@ else{
|
|||
LOAD_RETURN_CLEANUP
|
||||
}
|
||||
|
||||
|
||||
KeyTransform::transform(RawMasterKey,MasterKey,TransfRandomSeed,KeyTransfRounds);
|
||||
RawMasterKey.unlock();
|
||||
MasterKey.unlock();
|
||||
KeyTransform::transform(*RawMasterKey,*MasterKey,TransfRandomSeed,KeyTransfRounds);
|
||||
|
||||
quint8 FinalKey[32];
|
||||
|
||||
SHA256 sha;
|
||||
sha.update(FinalRandomSeed,16);
|
||||
sha.update(MasterKey,32);
|
||||
sha.update(*MasterKey,32);
|
||||
sha.finish(FinalKey);
|
||||
|
||||
RawMasterKey.lock();
|
||||
MasterKey.lock();
|
||||
|
||||
if(Algorithm == Rijndael_Cipher){
|
||||
AESdecrypt aes;
|
||||
aes.key256(FinalKey);
|
||||
|
@ -572,7 +578,8 @@ if(memcmp(ContentsHash, FinalKey, 32) != 0){
|
|||
// but KeePass/Win32 uses Windows Codepage 1252.
|
||||
// Too stay compatible with databases created with KeePassX <= 0.3.1
|
||||
// the loading function gives both encodings a try.
|
||||
memcpy(RawMasterKey,RawMasterKey_Latin1,32);
|
||||
|
||||
RawMasterKey.copyData(RawMasterKey_Latin1);
|
||||
PotentialEncodingIssue=false;
|
||||
qDebug("Decryption failed. Retrying with Latin-1.");
|
||||
return load(filename); // second try
|
||||
|
@ -829,7 +836,9 @@ bool Kdb3Database::setPasswordKey(const QString& Password){
|
|||
assert(Password.size());
|
||||
QTextCodec* codec=QTextCodec::codecForName("Windows-1252");
|
||||
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();
|
||||
if(Password_Latin1 != Password_CP1252){
|
||||
// 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
|
||||
// the loading function gives both encodings a try.
|
||||
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 {
|
||||
// If the password does not contain problematic characters we don't need
|
||||
|
@ -858,21 +869,27 @@ bool Kdb3Database::setFileKey(const QString& filename){
|
|||
error=tr("Key file is empty.");
|
||||
return false;
|
||||
}
|
||||
RawMasterKey.unlock();
|
||||
if(FileSize == 32){
|
||||
if(file.read((char*)RawMasterKey,32) != 32){
|
||||
if(file.read((char*)(*RawMasterKey),32) != 32){
|
||||
error=decodeFileError(file.error());
|
||||
RawMasterKey.lock();
|
||||
return false;
|
||||
}
|
||||
RawMasterKey.lock();
|
||||
return true;
|
||||
}
|
||||
if(FileSize == 64){
|
||||
char hex[64];
|
||||
if(file.read(hex,64) != 64){
|
||||
error=decodeFileError(file.error());
|
||||
RawMasterKey.lock();
|
||||
return false;
|
||||
}
|
||||
if (convHexToBinaryKey(hex,(char*)RawMasterKey))
|
||||
if (convHexToBinaryKey(hex,(char*)(*RawMasterKey))){
|
||||
RawMasterKey.lock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
SHA256 sha;
|
||||
unsigned char* buffer = new unsigned char[2048];
|
||||
|
@ -883,22 +900,25 @@ bool Kdb3Database::setFileKey(const QString& filename){
|
|||
sha.update(buffer,read);
|
||||
if(read != 2048) break;
|
||||
}
|
||||
sha.finish(RawMasterKey);
|
||||
sha.finish(*RawMasterKey);
|
||||
RawMasterKey.lock();
|
||||
delete [] buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
sha.update(PasswordKey,32);
|
||||
sha.update(FileKey,32);
|
||||
sha.finish(RawMasterKey);
|
||||
|
||||
if(!setFileKey(filename))return false;
|
||||
RawMasterKey.unlock();
|
||||
sha.update(*RawMasterKey,32);
|
||||
RawMasterKey.lock();
|
||||
|
||||
setPasswordKey(Password);
|
||||
RawMasterKey.unlock();
|
||||
sha.update(*RawMasterKey,32);
|
||||
sha.finish(*RawMasterKey);
|
||||
RawMasterKey.lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1187,7 +1207,6 @@ bool Kdb3Database::save(){
|
|||
return false;
|
||||
}
|
||||
quint32 NumGroups,NumEntries,Signature1,Signature2,Flags,Version;
|
||||
quint8 TransfRandomSeed[32];
|
||||
quint8 FinalRandomSeed[16];
|
||||
quint8 ContentsHash[32];
|
||||
quint8 EncryptionIV[16];
|
||||
|
@ -1260,7 +1279,6 @@ bool Kdb3Database::save(){
|
|||
qSort(saveEntries.begin(),saveEntries.end(),StdEntryLessThan);
|
||||
|
||||
randomize(FinalRandomSeed,16);
|
||||
randomize(TransfRandomSeed,32);
|
||||
randomize(EncryptionIV,16);
|
||||
|
||||
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+88,TransfRandomSeed,32);
|
||||
memcpyToLEnd32(buffer+120,&KeyTransfRounds);
|
||||
KeyTransform::transform(RawMasterKey,MasterKey,TransfRandomSeed,KeyTransfRounds);
|
||||
quint8 FinalKey[32];
|
||||
|
||||
SHA256 sha;
|
||||
sha.update(FinalRandomSeed,16);
|
||||
sha.update(MasterKey,32);
|
||||
MasterKey.unlock();
|
||||
sha.update(*MasterKey,32);
|
||||
MasterKey.lock();
|
||||
sha.finish(FinalKey);
|
||||
|
||||
unsigned long EncryptedPartSize;
|
||||
|
@ -1805,6 +1824,15 @@ QList<IEntryHandle*> Kdb3Database::trashEntries(){
|
|||
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){
|
||||
KeyTransform* ktLeft = new KeyTransform(&src[0], &dst[0], KeySeed, rounds);
|
||||
|
|
|
@ -137,6 +137,7 @@ public:
|
|||
QStringList GroupPath;
|
||||
};
|
||||
|
||||
Kdb3Database();
|
||||
virtual ~Kdb3Database(){};
|
||||
virtual bool load(QString identifier);
|
||||
virtual bool save();
|
||||
|
@ -187,7 +188,8 @@ public:
|
|||
virtual void moveGroup(IGroupHandle* Group,IGroupHandle* NewParent,int Position);
|
||||
virtual IGroupHandle* addGroup(const CGroup* Group,IGroupHandle* Parent);
|
||||
virtual bool isParent(IGroupHandle* parent, IGroupHandle* child);
|
||||
|
||||
|
||||
virtual void generateMasterKey();
|
||||
|
||||
|
||||
|
||||
|
@ -241,9 +243,10 @@ private:
|
|||
QMap<quint32,bool> TreeStateMetaStream;
|
||||
unsigned int KeyTransfRounds;
|
||||
CryptAlgorithm Algorithm;
|
||||
quint8 RawMasterKey[32];
|
||||
quint8 RawMasterKey_Latin1[32];
|
||||
quint8 MasterKey[32];
|
||||
SecData RawMasterKey;
|
||||
SecData RawMasterKey_Latin1;
|
||||
SecData MasterKey;
|
||||
quint8 TransfRandomSeed[32];
|
||||
bool hasV4IconMetaStream;
|
||||
};
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ public:
|
|||
QString mountDir(){return settings.value("Options/MountDir",DEFAULT_MOUNT_DIR).toString();}
|
||||
bool openLastFile(){return settings.value("Options/OpenLastFile",true).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();}
|
||||
QString pwGenCharList(){return settings.value("Options/PwGenCharList").toString();}
|
||||
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 setOpenLastFile(bool value){settings.setValue("Options/OpenLastFile",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 setPwGenCharList(const QString& value){settings.setValue("Options/PwGenCharList",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 *
|
||||
* 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 *
|
||||
* 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 *
|
||||
* 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 *
|
||||
* 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(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)
|
||||
Box_AutoType->setVisible(false);
|
||||
|
@ -76,6 +78,7 @@ CSettingsDlg::CSettingsDlg(QWidget* parent):QDialog(parent,Qt::Dialog)
|
|||
CheckBox_StartLocked->setChecked(config->startLocked());
|
||||
checkBox_SaveFileDlgHistory->setChecked(config->saveFileDlgHistory());
|
||||
CheckBox_AutoSave->setChecked(config->autoSave());
|
||||
CheckBox_AutoSaveChange->setChecked(config->autoSaveChange());
|
||||
checkBox_AskBeforeDelete->setChecked(config->askBeforeDelete());
|
||||
|
||||
switch(config->groupTreeState()){
|
||||
|
@ -211,6 +214,7 @@ void CSettingsDlg::apply(){
|
|||
config->setOpenLastFile(CheckBox_OpenLast->isChecked());
|
||||
config->setRememberLastKey(CheckBox_RememberLastKey->isChecked());
|
||||
config->setAutoSave(CheckBox_AutoSave->isChecked());
|
||||
config->setAutoSaveChange(CheckBox_AutoSaveChange->isChecked());
|
||||
config->setAskBeforeDelete(checkBox_AskBeforeDelete->isChecked());
|
||||
|
||||
//Appearence
|
||||
|
@ -330,6 +334,14 @@ void CSettingsDlg::OnInactivityLockChange(bool 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
|
||||
void CSettingsDlg::resetGlobalShortcut(){
|
||||
AutoType::unregisterGlobalShortcut();
|
||||
|
|
|
@ -45,6 +45,8 @@ class CSettingsDlg : public QDialog, private Ui_SettingsDialog
|
|||
void OnBrowserCmdBrowse();
|
||||
void OnCustomizeEntryDetails();
|
||||
void OnInactivityLockChange(bool checked);
|
||||
void OnAutoSaveToggle(bool checked);
|
||||
void OnAutoSaveChangeToggle(bool checked);
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
private slots:
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>606</width>
|
||||
<height>475</height>
|
||||
<height>479</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
|
@ -52,7 +52,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>341</height>
|
||||
<height>345</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="whatsThis" >
|
||||
|
@ -290,6 +290,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="CheckBox_AutoSaveChange" >
|
||||
<property name="text" >
|
||||
<string>Automatically save database after every change</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_AskBeforeDelete" >
|
||||
<property name="text" >
|
||||
|
@ -318,7 +325,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>341</height>
|
||||
<height>345</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="title" >
|
||||
|
@ -678,7 +685,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>341</height>
|
||||
<height>345</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="title" >
|
||||
|
@ -840,7 +847,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>341</height>
|
||||
<height>345</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="title" >
|
||||
|
@ -885,7 +892,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>341</height>
|
||||
<height>345</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="title" >
|
||||
|
@ -1005,7 +1012,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>584</width>
|
||||
<height>341</height>
|
||||
<height>345</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="title" >
|
||||
|
|
|
@ -105,8 +105,8 @@ bool Import_PwManager::importDatabase(QWidget* GuiParent, IDatabase* db){
|
|||
|
||||
if(!parseXmlContent((char*)xml)){
|
||||
delete [] xml;
|
||||
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Invalid XML data (see stdout for details).")); return false;}
|
||||
database->setKey(password,QString());
|
||||
QMessageBox::critical(GuiParent,tr("Import Failed"),tr("Invalid XML data (see stdout for details).")); return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,3 +98,46 @@ void SecString::generateSessionKey(){
|
|||
randomize(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"
|
||||
|
||||
class SecData;
|
||||
|
||||
//! 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.
|
||||
*/
|
||||
class SecString{
|
||||
|
||||
friend class SecData;
|
||||
|
||||
public:
|
||||
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
|
||||
|
|
|
@ -224,3 +224,13 @@ bool lockPage(void* addr, int len){
|
|||
return false;
|
||||
#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);
|
||||
bool createKeyFile(const QString& filename,QString* err, int length=32, bool Hex=true);
|
||||
bool lockPage(void* addr, int len);
|
||||
bool unlockPage(void* addr, int len);
|
||||
|
||||
#endif //TOOLS_H
|
||||
|
|
|
@ -488,12 +488,12 @@ bool KeepassMainWindow::closeDatabase(bool lock){
|
|||
Q_ASSERT(FileOpen);
|
||||
Q_ASSERT(db!=NULL);
|
||||
if(ModFlag){
|
||||
if(config->autoSave()){
|
||||
if(config->autoSave() && db->file()){
|
||||
if(!OnFileSave()) return false;
|
||||
}
|
||||
else{
|
||||
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);
|
||||
if(r==QMessageBox::Cancel) return false; //Cancel
|
||||
if(r==QMessageBox::Yes){ //Yes (Save file)
|
||||
|
@ -536,8 +536,9 @@ void KeepassMainWindow::OnFileNewKdb(){
|
|||
if(!closeDatabase())return;
|
||||
if (IsLocked)
|
||||
resetLock();
|
||||
db=db_new;
|
||||
db->setKey(dlg.password(),dlg.keyFile());
|
||||
db=db_new;
|
||||
db->setKey(dlg.password(),dlg.keyFile());
|
||||
db->generateMasterKey();
|
||||
setWindowTitle(QString("[%1][*] - KeePassX").arg(tr("new")));
|
||||
GroupView->db=db;
|
||||
EntryView->db=db;
|
||||
|
@ -545,7 +546,6 @@ void KeepassMainWindow::OnFileNewKdb(){
|
|||
EntryView->showGroup(NULL);
|
||||
setStateFileOpen(true);
|
||||
setStateFileModified(true);
|
||||
FileOpen=true;
|
||||
setupDatabaseConnections(db);
|
||||
setStateGroupSelected(NONE);
|
||||
setStateEntrySelected(NONE);
|
||||
|
@ -592,6 +592,7 @@ void KeepassMainWindow::setStateFileOpen(bool IsOpen){
|
|||
FileCloseAction->setEnabled(IsOpen||IsLocked);
|
||||
FileSettingsAction->setEnabled(IsOpen);
|
||||
FileChangeKeyAction->setEnabled(IsOpen);
|
||||
menuExport->setEnabled(IsOpen);
|
||||
EditSearchAction->setEnabled(IsOpen);
|
||||
GroupView->setEnabled(IsOpen);
|
||||
EntryView->setEnabled(IsOpen);
|
||||
|
@ -627,10 +628,11 @@ void KeepassMainWindow::setStateFileOpen(bool IsOpen){
|
|||
|
||||
|
||||
void KeepassMainWindow::setStateFileModified(bool mod){
|
||||
if(!FileOpen){
|
||||
FileSaveAction->setIcon(getIcon("filesave"));
|
||||
return;
|
||||
if (config->autoSaveChange() && mod && db->file()){
|
||||
OnFileSave();
|
||||
mod = false;
|
||||
}
|
||||
|
||||
ModFlag=mod;
|
||||
if(mod)
|
||||
FileSaveAction->setIcon(getIcon("filesave"));
|
||||
|
@ -884,7 +886,10 @@ bool KeepassMainWindow::OnFileSaveAs(){
|
|||
|
||||
void KeepassMainWindow::OnFileSettings(){
|
||||
CDbSettingsDlg dlg(this,db);
|
||||
if(dlg.exec()) setStateFileModified(true);
|
||||
if(dlg.exec()){
|
||||
db->generateMasterKey();
|
||||
setStateFileModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassMainWindow::OnFileChangeKey(){
|
||||
|
@ -892,8 +897,9 @@ void KeepassMainWindow::OnFileChangeKey(){
|
|||
QString filename = file ? file->fileName() : QString();
|
||||
PasswordDialog dlg(this,PasswordDialog::Mode_Change,PasswordDialog::Flag_None,filename);
|
||||
if(dlg.exec()==PasswordDialog::Exit_Ok){
|
||||
setStateFileModified(true);
|
||||
db->setKey(dlg.password(),dlg.keyFile());
|
||||
db->generateMasterKey();
|
||||
setStateFileModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -920,6 +926,7 @@ void KeepassMainWindow::OnImport(QAction* action){
|
|||
}
|
||||
db=tmpdb;
|
||||
db->setKey(dlg.password(),dlg.keyFile());
|
||||
db->generateMasterKey();
|
||||
GroupView->db=db;
|
||||
EntryView->db=db;
|
||||
setupDatabaseConnections(db);
|
||||
|
@ -989,7 +996,7 @@ void KeepassMainWindow::OnUsernPasswVisibilityChanged(bool value){
|
|||
}
|
||||
|
||||
void KeepassMainWindow::OnFileModified(){
|
||||
setStateFileModified(true);
|
||||
setStateFileModified(true);
|
||||
}
|
||||
|
||||
void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
||||
|
@ -1017,7 +1024,8 @@ void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
|||
if(!closeDatabase()){
|
||||
ShutingDown=false;
|
||||
e->ignore();
|
||||
return;}
|
||||
return;
|
||||
}
|
||||
else
|
||||
e->accept();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue