Create default groups when creating new database

Increase and randomize default key transformation number
Better cleanup when loading database fails

git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@196 b624d157-de02-0410-bad0-e51aec6abb33
master
sniperbeamer 17 years ago
parent 1905150642
commit 7c34d2010a
  1. 51
      src/Kdb3Database.cpp
  2. 6
      src/forms/EditEntryDlg.ui
  3. 22
      src/lib/GroupView.cpp
  4. 1
      src/lib/GroupView.h
  5. 2
      src/mainwindow.cpp

@ -414,6 +414,12 @@ void Kdb3Database::restoreGroupTreeState(){
} }
} }
#define LOAD_RETURN_CLEANUP \
delete File; \
File = NULL; \
delete[] buffer; \
return false;
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;
@ -422,12 +428,12 @@ quint8 FinalRandomSeed[16];
quint8 ContentsHash[32]; quint8 ContentsHash[32];
quint8 EncryptionIV[16]; quint8 EncryptionIV[16];
File=new QFile(filename); File = new QFile(filename);
if(!File->open(QIODevice::ReadWrite)){ if(!File->open(QIODevice::ReadWrite)){
if(!File->open(QIODevice::ReadOnly)){ if(!File->open(QIODevice::ReadOnly)){
error=tr("Could not open file."); error=tr("Could not open file.");
delete File; delete File;
File=NULL; File = NULL;
return false; return false;
} }
} }
@ -437,7 +443,7 @@ File->read(buffer,total_size);
if(total_size < DB_HEADER_SIZE){ if(total_size < DB_HEADER_SIZE){
error=tr("Unexpected file size (DB_TOTAL_SIZE < DB_HEADER_SIZE)"); error=tr("Unexpected file size (DB_TOTAL_SIZE < DB_HEADER_SIZE)");
return false; LOAD_RETURN_CLEANUP
} }
memcpyFromLEnd32(&Signature1,buffer); memcpyFromLEnd32(&Signature1,buffer);
@ -454,12 +460,12 @@ memcpyFromLEnd32(&KeyTransfRounds,buffer+120);
if((Signature1!=PWM_DBSIG_1) || (Signature2!=PWM_DBSIG_2)){ if((Signature1!=PWM_DBSIG_1) || (Signature2!=PWM_DBSIG_2)){
error=tr("Wrong Signature"); error=tr("Wrong Signature");
return false; LOAD_RETURN_CLEANUP
} }
if((Version & 0xFFFFFF00) != (PWM_DBVER_DW & 0xFFFFFF00)){ if((Version & 0xFFFFFF00) != (PWM_DBVER_DW & 0xFFFFFF00)){
error=tr("Unsupported File Version."); error=tr("Unsupported File Version.");
return false; LOAD_RETURN_CLEANUP
} }
if (Flags & PWM_FLAG_RIJNDAEL) if (Flags & PWM_FLAG_RIJNDAEL)
@ -468,7 +474,7 @@ else if (Flags & PWM_FLAG_TWOFISH)
Algorithm = Twofish_Cipher; Algorithm = Twofish_Cipher;
else{ else{
error=tr("Unknown Encryption Algorithm."); error=tr("Unknown Encryption Algorithm.");
return false; LOAD_RETURN_CLEANUP
} }
@ -490,20 +496,22 @@ if(Algorithm == Rijndael_Cipher){
else if(Algorithm == Twofish_Cipher){ else if(Algorithm == Twofish_Cipher){
CTwofish twofish; CTwofish twofish;
if (twofish.init(FinalKey, 32, EncryptionIV) != true) if (twofish.init(FinalKey, 32, EncryptionIV) != true)
return false; LOAD_RETURN_CLEANUP
crypto_size = (unsigned long)twofish.padDecrypt((quint8 *)buffer + DB_HEADER_SIZE, crypto_size = (unsigned long)twofish.padDecrypt((quint8 *)buffer + DB_HEADER_SIZE,
total_size - DB_HEADER_SIZE, (quint8 *)buffer + DB_HEADER_SIZE); total_size - DB_HEADER_SIZE, (quint8 *)buffer + DB_HEADER_SIZE);
} }
if ((crypto_size > 2147483446) || (!crypto_size && NumGroups)){ if ((crypto_size > 2147483446) || (!crypto_size && NumGroups)){
error=tr("Decryption failed.\nThe key is wrong or the file is damaged."); error=tr("Decryption failed.\nThe key is wrong or the file is damaged.");
return false; LOAD_RETURN_CLEANUP
} }
SHA256::hashBuffer(buffer+DB_HEADER_SIZE,FinalKey,crypto_size); SHA256::hashBuffer(buffer+DB_HEADER_SIZE,FinalKey,crypto_size);
if(memcmp(ContentsHash, FinalKey, 32) != 0){ if(memcmp(ContentsHash, FinalKey, 32) != 0){
delete buffer;
if(PotentialEncodingIssue){ if(PotentialEncodingIssue){
delete[] buffer;
delete File;
File = NULL;
// KeePassX used Latin-1 encoding for passwords until version 0.3.1 // KeePassX used Latin-1 encoding for passwords until version 0.3.1
// 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
@ -515,7 +523,7 @@ if(memcmp(ContentsHash, FinalKey, 32) != 0){
} }
error=tr("Hash test failed.\nThe key is wrong or the file is damaged."); error=tr("Hash test failed.\nThe key is wrong or the file is damaged.");
KeyError=true; KeyError=true;
return false; LOAD_RETURN_CLEANUP
} }
unsigned long pos = DB_HEADER_SIZE; unsigned long pos = DB_HEADER_SIZE;
@ -537,14 +545,14 @@ for(unsigned long CurGroup = 0; CurGroup < NumGroups; )
pField += 2; pos += 2; pField += 2; pos += 2;
if (pos >= total_size){ if (pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [G1]"); error=tr("Unexpected error: Offset is out of range.").append(" [G1]");
return false; LOAD_RETURN_CLEANUP
} }
memcpyFromLEnd32(&FieldSize, pField); memcpyFromLEnd32(&FieldSize, pField);
pField += 4; pos += 4; pField += 4; pos += 4;
if (pos >= (total_size + FieldSize)){ if (pos >= (total_size + FieldSize)){
error=tr("Unexpected error: Offset is out of range.").append(" [G2]"); error=tr("Unexpected error: Offset is out of range.").append(" [G2]");
return false; LOAD_RETURN_CLEANUP
} }
bRet = readGroupField(&group,Levels, FieldType, FieldSize, (quint8 *)pField); bRet = readGroupField(&group,Levels, FieldType, FieldSize, (quint8 *)pField);
@ -556,7 +564,7 @@ for(unsigned long CurGroup = 0; CurGroup < NumGroups; )
pos += FieldSize; pos += FieldSize;
if (pos >= total_size){ if (pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [G1]"); error=tr("Unexpected error: Offset is out of range.").append(" [G1]");
return false; LOAD_RETURN_CLEANUP
} }
} }
@ -570,14 +578,14 @@ for (unsigned long CurEntry = 0; CurEntry < NumEntries;)
pField += 2; pos += 2; pField += 2; pos += 2;
if(pos >= total_size){ if(pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [E1]"); error=tr("Unexpected error: Offset is out of range.").append(" [E1]");
return false; LOAD_RETURN_CLEANUP
} }
memcpyFromLEnd32(&FieldSize, pField); memcpyFromLEnd32(&FieldSize, pField);
pField += 4; pos += 4; pField += 4; pos += 4;
if (pos >= (total_size + FieldSize)){ if (pos >= (total_size + FieldSize)){
error=tr("Unexpected error: Offset is out of range.").append(" [E2]"); error=tr("Unexpected error: Offset is out of range.").append(" [E2]");
return false; LOAD_RETURN_CLEANUP
} }
bRet = readEntryField(&entry,FieldType,FieldSize,(quint8*)pField); bRet = readEntryField(&entry,FieldType,FieldSize,(quint8*)pField);
@ -593,13 +601,13 @@ for (unsigned long CurEntry = 0; CurEntry < NumEntries;)
pos += FieldSize; pos += FieldSize;
if (pos >= total_size){ if (pos >= total_size){
error=tr("Unexpected error: Offset is out of range.").append(" [E3]"); error=tr("Unexpected error: Offset is out of range.").append(" [E3]");
return false; LOAD_RETURN_CLEANUP
} }
} }
if(!createGroupTree(Levels)){ if(!createGroupTree(Levels)){
error=tr("Invalid group tree."); error=tr("Invalid group tree.");
return false; LOAD_RETURN_CLEANUP
} }
delete [] buffer; delete [] buffer;
@ -1258,7 +1266,8 @@ bool Kdb3Database::save(){
if(twofish.init(FinalKey, 32, EncryptionIV) == false){ if(twofish.init(FinalKey, 32, EncryptionIV) == false){
UNEXP_ERROR UNEXP_ERROR
delete [] buffer; delete [] buffer;
return false;} return false;
}
EncryptedPartSize = (unsigned long)twofish.padEncrypt((quint8*)buffer+DB_HEADER_SIZE, EncryptedPartSize = (unsigned long)twofish.padEncrypt((quint8*)buffer+DB_HEADER_SIZE,
pos - DB_HEADER_SIZE,(quint8*)buffer+DB_HEADER_SIZE); pos - DB_HEADER_SIZE,(quint8*)buffer+DB_HEADER_SIZE);
} }
@ -1523,6 +1532,8 @@ void Kdb3Database::serializeEntries(QList<StdEntry>& EntryList,char* buffer,unsi
} }
bool Kdb3Database::close(){ bool Kdb3Database::close(){
if (File!=NULL)
delete File;
return true; return true;
} }
@ -1532,7 +1543,9 @@ void Kdb3Database::create(){
RootGroup.Parent=NULL; RootGroup.Parent=NULL;
RootGroup.Handle=NULL; RootGroup.Handle=NULL;
Algorithm=Rijndael_Cipher; Algorithm=Rijndael_Cipher;
KeyTransfRounds=6000; quint8 ran;
randomize(&ran,1);
KeyTransfRounds=10000 + 3*ran;
KeyError=false; KeyError=false;
} }

@ -484,14 +484,12 @@
</widget> </widget>
<layoutdefault spacing="6" margin="11" /> <layoutdefault spacing="6" margin="11" />
<tabstops> <tabstops>
<tabstop>Combo_Group</tabstop>
<tabstop>Button_Icons</tabstop>
<tabstop>Edit_Title</tabstop> <tabstop>Edit_Title</tabstop>
<tabstop>Edit_UserName</tabstop> <tabstop>Edit_UserName</tabstop>
<tabstop>Edit_URL</tabstop> <tabstop>Edit_URL</tabstop>
<tabstop>Edit_Password</tabstop> <tabstop>Edit_Password</tabstop>
<tabstop>ButtonEchoMode</tabstop>
<tabstop>Edit_Password_w</tabstop> <tabstop>Edit_Password_w</tabstop>
<tabstop>ButtonEchoMode</tabstop>
<tabstop>ButtonGenPw</tabstop> <tabstop>ButtonGenPw</tabstop>
<tabstop>Edit_Comment</tabstop> <tabstop>Edit_Comment</tabstop>
<tabstop>DateTime_Expire</tabstop> <tabstop>DateTime_Expire</tabstop>
@ -501,6 +499,8 @@
<tabstop>ButtonOpenAttachment</tabstop> <tabstop>ButtonOpenAttachment</tabstop>
<tabstop>ButtonSaveAttachment</tabstop> <tabstop>ButtonSaveAttachment</tabstop>
<tabstop>ButtonDeleteAttachment</tabstop> <tabstop>ButtonDeleteAttachment</tabstop>
<tabstop>Combo_Group</tabstop>
<tabstop>Button_Icons</tabstop>
<tabstop>buttonBox</tabstop> <tabstop>buttonBox</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>

@ -127,6 +127,28 @@ void KeepassGroupView::OnNewGroup(){
emit fileModified(); emit fileModified();
} }
void KeepassGroupView::createGroup(const QString& title, quint32 image){
CGroup NewGroup;
NewGroup.Title = title;
NewGroup.Image = image;
IGroupHandle* group;
if(topLevelItemCount()){
if(topLevelItem(topLevelItemCount()-1)==SearchResultItem)
Items.append(new GroupViewItem(this,topLevelItem(topLevelItemCount()-2)));
else
Items.append(new GroupViewItem(this,topLevelItem(topLevelItemCount()-1)));
}
else
Items.append(new GroupViewItem(this));
group = db->addGroup(&NewGroup,NULL);
Items.back()->GroupHandle = group;
Items.back()->setText(0, group->title());
Items.back()->setIcon(0, db->icon(group->image()));
}
void KeepassGroupView::OnEditGroup(){ void KeepassGroupView::OnEditGroup(){
GroupViewItem* item=(GroupViewItem*)currentItem(); GroupViewItem* item=(GroupViewItem*)currentItem();
CEditGroupDialog dlg(db,item->GroupHandle,parentWidget(),true); CEditGroupDialog dlg(db,item->GroupHandle,parentWidget(),true);

@ -36,6 +36,7 @@ class KeepassGroupView:public QTreeWidget{
void createItems(); void createItems();
void showSearchResults(); void showSearchResults();
void setCurrentGroup(IGroupHandle* group); void setCurrentGroup(IGroupHandle* group);
void createGroup(const QString& title, quint32 image);
private: private:
virtual void dragEnterEvent(QDragEnterEvent* event); virtual void dragEnterEvent(QDragEnterEvent* event);

@ -519,6 +519,8 @@ void KeepassMainWindow::OnFileNewKdb(){
setupDatabaseConnections(db); setupDatabaseConnections(db);
setStateGroupSelected(NONE); setStateGroupSelected(NONE);
setStateEntrySelected(NONE); setStateEntrySelected(NONE);
GroupView->createGroup("Internet", 1);
GroupView->createGroup("eMail", 19);
} }
else{ else{
delete db_new; delete db_new;