keepassxc

Форк
0
/
TestKdbx3.cpp 
256 строк · 9.2 Кб
1
/*
2
 *  Copyright (C) 2018 KeePassXC Team <team@keepassxc.org>
3
 *
4
 *  This program is free software: you can redistribute it and/or modify
5
 *  it under the terms of the GNU General Public License as published by
6
 *  the Free Software Foundation, either version 2 or (at your option)
7
 *  version 3 of the License.
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17

18
#include "TestKdbx3.h"
19

20
#include "config-keepassx-tests.h"
21
#include "core/Metadata.h"
22
#include "format/KdbxXmlReader.h"
23
#include "format/KdbxXmlWriter.h"
24
#include "format/KeePass2.h"
25
#include "format/KeePass2Reader.h"
26
#include "format/KeePass2Writer.h"
27
#include "keys/PasswordKey.h"
28
#include <QTest>
29

30
QTEST_GUILESS_MAIN(TestKdbx3)
31

32
void TestKdbx3::initTestCaseImpl()
33
{
34
    m_xmlDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3)));
35
    m_kdbxSourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3)));
36
}
37

38
QSharedPointer<Database> TestKdbx3::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
39
{
40
    KdbxXmlReader reader(KeePass2::FILE_VERSION_3_1);
41
    reader.setStrictMode(strictMode);
42
    auto db = reader.readDatabase(path);
43
    hasError = reader.hasError();
44
    errorString = reader.errorString();
45
    return db;
46
}
47

48
QSharedPointer<Database> TestKdbx3::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString)
49
{
50
    KdbxXmlReader reader(KeePass2::FILE_VERSION_3_1);
51
    reader.setStrictMode(strictMode);
52
    auto db = reader.readDatabase(buf);
53
    hasError = reader.hasError();
54
    errorString = reader.errorString();
55
    return db;
56
}
57

58
void TestKdbx3::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString)
59
{
60
    KdbxXmlWriter writer(KeePass2::FILE_VERSION_3_1);
61
    writer.writeDatabase(buf, db);
62
    hasError = writer.hasError();
63
    errorString = writer.errorString();
64
}
65

66
void TestKdbx3::readKdbx(QIODevice* device,
67
                         QSharedPointer<const CompositeKey> key,
68
                         QSharedPointer<Database> db,
69
                         bool& hasError,
70
                         QString& errorString)
71
{
72
    KeePass2Reader reader;
73
    reader.readDatabase(device, key, db.data());
74
    hasError = reader.hasError();
75
    if (hasError) {
76
        errorString = reader.errorString();
77
    }
78
    QCOMPARE(reader.version(), KeePass2::FILE_VERSION_3_1);
79
}
80

81
void TestKdbx3::writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString)
82
{
83
    KeePass2Writer writer;
84
    hasError = writer.writeDatabase(device, db);
85
    hasError = writer.hasError();
86
    if (hasError) {
87
        errorString = writer.errorString();
88
    }
89
    QCOMPARE(writer.version(), KeePass2::FILE_VERSION_3_1);
90
}
91

92
void TestKdbx3::testFormat300()
93
{
94
    QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format300.kdbx");
95
    auto key = QSharedPointer<CompositeKey>::create();
96
    key->addKey(QSharedPointer<PasswordKey>::create("a"));
97
    KeePass2Reader reader;
98
    auto db = QSharedPointer<Database>::create();
99
    QVERIFY(reader.readDatabase(filename, key, db.data()));
100
    QCOMPARE(reader.version(), KeePass2::FILE_VERSION_3);
101
    QVERIFY(db.data());
102
    QVERIFY(!reader.hasError());
103

104
    QCOMPARE(db->rootGroup()->name(), QString("Format300"));
105
    QCOMPARE(db->metadata()->name(), QString("Test Database Format 0x00030000"));
106
}
107

108
void TestKdbx3::testNonAscii()
109
{
110
    QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/NonAscii.kdbx");
111
    auto key = QSharedPointer<CompositeKey>::create();
112
    key->addKey(QSharedPointer<PasswordKey>::create(QString::fromUtf8("\xce\x94\xc3\xb6\xd8\xb6")));
113
    KeePass2Reader reader;
114
    auto db = QSharedPointer<Database>::create();
115
    QVERIFY(db->open(filename, key, nullptr));
116
    QVERIFY(db.data());
117
    QVERIFY(!reader.hasError());
118
    QCOMPARE(db->metadata()->name(), QString("NonAsciiTest"));
119
    QCOMPARE(db->compressionAlgorithm(), Database::CompressionNone);
120
}
121

122
void TestKdbx3::testCompressed()
123
{
124
    QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Compressed.kdbx");
125
    auto key = QSharedPointer<CompositeKey>::create();
126
    key->addKey(QSharedPointer<PasswordKey>::create(""));
127
    KeePass2Reader reader;
128
    auto db = QSharedPointer<Database>::create();
129
    QVERIFY(db->open(filename, key, nullptr));
130
    QVERIFY(db.data());
131
    QVERIFY(!reader.hasError());
132
    QCOMPARE(db->metadata()->name(), QString("Compressed"));
133
    QCOMPARE(db->compressionAlgorithm(), Database::CompressionGZip);
134
}
135

136
void TestKdbx3::testProtectedStrings()
137
{
138
    QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/ProtectedStrings.kdbx");
139
    auto key = QSharedPointer<CompositeKey>::create();
140
    key->addKey(QSharedPointer<PasswordKey>::create("masterpw"));
141
    KeePass2Reader reader;
142
    auto db = QSharedPointer<Database>::create();
143
    QVERIFY(db->open(filename, key, nullptr));
144
    QVERIFY(db.data());
145
    QVERIFY(!reader.hasError());
146
    QCOMPARE(db->metadata()->name(), QString("Protected Strings Test"));
147

148
    Entry* entry = db->rootGroup()->entries().at(0);
149

150
    QCOMPARE(entry->title(), QString("Sample Entry"));
151
    QCOMPARE(entry->username(), QString("Protected User Name"));
152
    QCOMPARE(entry->password(), QString("ProtectedPassword"));
153
    QCOMPARE(entry->attributes()->value("TestProtected"), QString("ABC"));
154
    QCOMPARE(entry->attributes()->value("TestUnprotected"), QString("DEF"));
155

156
    QVERIFY(db->metadata()->protectPassword());
157
    QVERIFY(entry->attributes()->isProtected("TestProtected"));
158
    QVERIFY(!entry->attributes()->isProtected("TestUnprotected"));
159
}
160

161
void TestKdbx3::testBrokenHeaderHash()
162
{
163
    // The protected stream key has been modified in the header.
164
    // Make sure the database won't open.
165

166
    QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/BrokenHeaderHash.kdbx");
167
    auto key = QSharedPointer<CompositeKey>::create();
168
    key->addKey(QSharedPointer<PasswordKey>::create(""));
169
    auto db = QSharedPointer<Database>::create();
170
    QVERIFY(!db->open(filename, key, nullptr));
171
}
172

173
void TestKdbx3::testAttachmentIndexStability()
174
{
175
    QScopedPointer<Database> db(new Database());
176
    db->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3)));
177
    auto compositeKey = QSharedPointer<CompositeKey>::create();
178
    db->setKey(compositeKey);
179
    QVERIFY(!db->uuid().isNull());
180

181
    auto root = db->rootGroup();
182

183
    auto group1 = new Group();
184
    group1->setUuid(QUuid::createUuid());
185
    QVERIFY(!group1->uuid().isNull());
186
    group1->setParent(root);
187

188
    auto attachment1 = QByteArray("qwerty");
189
    auto attachment2 = QByteArray("asdf");
190
    auto attachment3 = QByteArray("zxcv");
191

192
    auto entry1 = new Entry();
193
    entry1->setUuid(QUuid::createUuid());
194
    QVERIFY(!entry1->uuid().isNull());
195
    auto uuid1 = entry1->uuid();
196
    entry1->attachments()->set("a", attachment1);
197
    QCOMPARE(entry1->attachments()->keys().size(), 1);
198
    QCOMPARE(entry1->attachments()->values().size(), 1);
199
    entry1->setGroup(root);
200

201
    auto entry2 = new Entry();
202
    entry2->setUuid(QUuid::createUuid());
203
    QVERIFY(!entry2->uuid().isNull());
204
    auto uuid2 = entry2->uuid();
205
    entry2->attachments()->set("a", attachment1);
206
    entry2->attachments()->set("b", attachment2);
207
    QCOMPARE(entry2->attachments()->keys().size(), 2);
208
    QCOMPARE(entry2->attachments()->values().size(), 2);
209
    entry2->setGroup(group1);
210

211
    auto entry3 = new Entry();
212
    entry3->setUuid(QUuid::createUuid());
213
    QVERIFY(!entry3->uuid().isNull());
214
    auto uuid3 = entry3->uuid();
215
    entry3->attachments()->set("a", attachment1);
216
    entry3->attachments()->set("b", attachment2);
217
    entry3->attachments()->set("x", attachment3);
218
    entry3->attachments()->set("y", attachment3);
219
    QCOMPARE(entry3->attachments()->keys().size(), 4);
220
    QCOMPARE(entry3->attachments()->values().size(), 3);
221
    entry3->setGroup(group1);
222

223
    QBuffer buffer;
224
    buffer.open(QBuffer::ReadWrite);
225
    KeePass2Writer writer;
226
    QVERIFY(writer.writeDatabase(&buffer, db.data()));
227
    QCOMPARE(writer.version(), KeePass2::FILE_VERSION_3_1);
228

229
    buffer.seek(0);
230
    KeePass2Reader reader;
231

232
    // Re-read database and check that all attachments are still correctly assigned
233
    auto db2 = QSharedPointer<Database>::create();
234
    reader.readDatabase(&buffer, QSharedPointer<CompositeKey>::create(), db2.data());
235
    QVERIFY(!reader.hasError());
236
    QVERIFY(!db->uuid().isNull());
237

238
    auto a1 = db2->rootGroup()->findEntryByUuid(uuid1)->attachments();
239
    QCOMPARE(a1->keys().size(), 1);
240
    QCOMPARE(a1->values().size(), 1);
241
    QCOMPARE(a1->value("a"), attachment1);
242

243
    auto a2 = db2->rootGroup()->findEntryByUuid(uuid2)->attachments();
244
    QCOMPARE(a2->keys().size(), 2);
245
    QCOMPARE(a2->values().size(), 2);
246
    QCOMPARE(a2->value("a"), attachment1);
247
    QCOMPARE(a2->value("b"), attachment2);
248

249
    auto a3 = db2->rootGroup()->findEntryByUuid(uuid3)->attachments();
250
    QCOMPARE(a3->keys().size(), 4);
251
    QCOMPARE(a3->values().size(), 3);
252
    QCOMPARE(a3->value("a"), attachment1);
253
    QCOMPARE(a3->value("b"), attachment2);
254
    QCOMPARE(a3->value("x"), attachment3);
255
    QCOMPARE(a3->value("y"), attachment3);
256
}
257

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.