summaryrefslogtreecommitdiffabout
authorulf69 <ulf69>2004-11-07 02:10:50 (UTC)
committer ulf69 <ulf69>2004-11-07 02:10:50 (UTC)
commit31c3fc0e0673b9403fb4ef4a9836305d1d49ff83 (patch) (unidiff)
treef5a44f4402294d6fd61e204489cdd776acb804aa
parent2b6072e39edbc8c9ab36e1e835b252a799db97a1 (diff)
downloadkdepimpi-31c3fc0e0673b9403fb4ef4a9836305d1d49ff83.zip
kdepimpi-31c3fc0e0673b9403fb4ef4a9836305d1d49ff83.tar.gz
kdepimpi-31c3fc0e0673b9403fb4ef4a9836305d1d49ff83.tar.bz2
Fixed nasty PwM/Pi file reading bug, when
the used hash algo of file is different then the global hash algo. CVS ----------------------------------------------------------------------
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/libgcryptif.cpp25
-rw-r--r--pwmanager/pwmanager/libgcryptif.h12
-rw-r--r--pwmanager/pwmanager/pwmdoc.cpp20
-rw-r--r--pwmanager/pwmanager/pwmdoc.h8
4 files changed, 46 insertions, 19 deletions
diff --git a/pwmanager/pwmanager/libgcryptif.cpp b/pwmanager/pwmanager/libgcryptif.cpp
index ff94bf6..15f6cef 100644
--- a/pwmanager/pwmanager/libgcryptif.cpp
+++ b/pwmanager/pwmanager/libgcryptif.cpp
@@ -1,454 +1,463 @@
1/*************************************************************************** 1/***************************************************************************
2 * * 2 * *
3 * copyright (C) 2004 by Michael Buesch * 3 * copyright (C) 2004 by Michael Buesch *
4 * email: mbuesch@freenet.de * 4 * email: mbuesch@freenet.de *
5 * * 5 * *
6 * hashPassphrase() is derived from GnuPG and is * 6 * hashPassphrase() is derived from GnuPG and is *
7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 * 7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 *
8 * Free Software Foundation, Inc. * 8 * Free Software Foundation, Inc. *
9 * * 9 * *
10 * This program is free software; you can redistribute it and/or modify * 10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License version 2 * 11 * it under the terms of the GNU General Public License version 2 *
12 * as published by the Free Software Foundation. * 12 * as published by the Free Software Foundation. *
13 * * 13 * *
14 ***************************************************************************/ 14 ***************************************************************************/
15 15
16/*************************************************************************** 16/***************************************************************************
17 * copyright (C) 2004 by Ulf Schenk 17 * copyright (C) 2004 by Ulf Schenk
18 * This file is originaly based on version 1.1 of pwmanager 18 * This file is originaly based on version 1.1 of pwmanager
19 * and was modified to run on embedded devices that run microkde 19 * and was modified to run on embedded devices that run microkde
20 * 20 *
21 * $Id$ 21 * $Id$
22 **************************************************************************/ 22 **************************************************************************/
23 23
24#include "libgcryptif.h" 24#include "libgcryptif.h"
25 25
26#ifdef CONFIG_PWMANAGER_GCRY 26#ifdef CONFIG_PWMANAGER_GCRY
27 27
28#include "pwmdoc.h" 28#include "pwmdoc.h"
29#include "randomizer.h" 29#include "randomizer.h"
30 30
31#include <gcrypt.h> 31#include <gcrypt.h>
32 32
33#ifdef PWM_EMBEDDED 33#ifdef PWM_EMBEDDED
34#include <pwmprefs.h> 34#include <pwmprefs.h>
35#endif 35#endif
36 36
37 37
38PwMerror LibGCryptIf::encrypt(unsigned char **outBuf, 38PwMerror LibGCryptIf::encrypt(unsigned char **outBuf,
39 size_t *outBufLen, 39 size_t *outBufLen,
40 unsigned char *inBuf, 40 unsigned char *inBuf,
41 size_t inBufLen, 41 size_t inBufLen,
42 const unsigned char *key, 42 const unsigned char *key,
43 size_t keylen, 43 size_t keylen,
44 char _algo) 44 char _algo,
45 char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
46 )
45{ 47{
46 PwMerror ret = e_success; 48 PwMerror ret = e_success;
47 gcry_error_t err; 49 gcry_error_t err;
48 gcry_cipher_hd_t handle; 50 gcry_cipher_hd_t handle;
49 size_t blklen; 51 size_t blklen;
50 size_t unpaddedLen = inBufLen; 52 size_t unpaddedLen = inBufLen;
51 size_t cipherKeylen; 53 size_t cipherKeylen;
52 unsigned char *hashedKey; 54 unsigned char *hashedKey;
53 unsigned char salt[STRING2KEY_SALTLEN]; 55 unsigned char salt[STRING2KEY_SALTLEN];
54 int algo = mapCipherId(_algo); 56 int algo = mapCipherId(_algo);
55 57
56 if (!inBufLen || !keylen) 58 if (!inBufLen || !keylen)
57 return e_invalidArg; 59 return e_invalidArg;
58 60
59 // test if algo is ready for encryption 61 // test if algo is ready for encryption
60 err = gcry_cipher_algo_info(algo, 62 err = gcry_cipher_algo_info(algo,
61 GCRYCTL_TEST_ALGO, 63 GCRYCTL_TEST_ALGO,
62 0, 0); 64 0, 0);
63 if (err != GPG_ERR_NO_ERROR) { 65 if (err != GPG_ERR_NO_ERROR) {
64 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_TEST_ALGO failed: ") 66 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_TEST_ALGO failed: ")
65 + gcry_strerror(err)); 67 + gcry_strerror(err));
66 ret = e_cryptNotImpl; 68 ret = e_cryptNotImpl;
67 goto out; 69 goto out;
68 } 70 }
69 // get the algo block length 71 // get the algo block length
70 err = gcry_cipher_algo_info(algo, 72 err = gcry_cipher_algo_info(algo,
71 GCRYCTL_GET_BLKLEN, 73 GCRYCTL_GET_BLKLEN,
72 0, 74 0,
73 &blklen); 75 &blklen);
74 if (err != GPG_ERR_NO_ERROR) { 76 if (err != GPG_ERR_NO_ERROR) {
75 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_BLKLEN failed: ") 77 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_BLKLEN failed: ")
76 + gcry_strerror(err)); 78 + gcry_strerror(err));
77 ret = e_cryptNotImpl; 79 ret = e_cryptNotImpl;
78 goto out; 80 goto out;
79 } 81 }
80 /* double check if we have enough space. 82 /* double check if we have enough space.
81 * We have only 1024 extra bytes for padding and salt. 83 * We have only 1024 extra bytes for padding and salt.
82 */ 84 */
83 BUG_ON(blklen > 1024 - STRING2KEY_SALTLEN); 85 BUG_ON(blklen > 1024 - STRING2KEY_SALTLEN);
84 // get the algo key length 86 // get the algo key length
85 err = gcry_cipher_algo_info(algo, 87 err = gcry_cipher_algo_info(algo,
86 GCRYCTL_GET_KEYLEN, 88 GCRYCTL_GET_KEYLEN,
87 0, 89 0,
88 &cipherKeylen); 90 &cipherKeylen);
89 if (err != GPG_ERR_NO_ERROR) { 91 if (err != GPG_ERR_NO_ERROR) {
90 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_KEYLEN failed: ") 92 printDebug(string("LibGCryptIf::doEncrypt(): GCRYCTL_GET_KEYLEN failed: ")
91 + gcry_strerror(err)); 93 + gcry_strerror(err));
92 ret = e_cryptNotImpl; 94 ret = e_cryptNotImpl;
93 goto out; 95 goto out;
94 } 96 }
95 // now open the algo and get a handle 97 // now open the algo and get a handle
96 err = gcry_cipher_open(&handle, 98 err = gcry_cipher_open(&handle,
97 algo, 99 algo,
98 GCRY_CIPHER_MODE_CBC, 100 GCRY_CIPHER_MODE_CBC,
99 0); 101 0);
100 if (err != GPG_ERR_NO_ERROR) { 102 if (err != GPG_ERR_NO_ERROR) {
101 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_open() failed: ") 103 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_open() failed: ")
102 + gcry_strerror(err)); 104 + gcry_strerror(err));
103 ret = e_cryptNotImpl; 105 ret = e_cryptNotImpl;
104 goto out; 106 goto out;
105 } 107 }
106 // hash the "key" to a fixed size hash matching "cipherKeylen" 108 // hash the "key" to a fixed size hash matching "cipherKeylen"
107 hashedKey = new unsigned char[cipherKeylen]; 109 hashedKey = new unsigned char[cipherKeylen];
108 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, true); 110 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, true, _hashalgo);
109 // so now set the hashed key 111 // so now set the hashed key
110 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen); 112 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
111 if (err != GPG_ERR_NO_ERROR) { 113 if (err != GPG_ERR_NO_ERROR) {
112 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_setkey() failed: ") 114 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_setkey() failed: ")
113 + gcry_strerror(err)); 115 + gcry_strerror(err));
114 ret = e_cryptNotImpl; 116 ret = e_cryptNotImpl;
115 delete [] hashedKey; 117 delete [] hashedKey;
116 goto out_close; 118 goto out_close;
117 } 119 }
118 delete [] hashedKey; 120 delete [] hashedKey;
119 /* allocate a buffer for the encrypted data. 121 /* allocate a buffer for the encrypted data.
120 * The size of the buffer is the inBuf length, but blklen 122 * The size of the buffer is the inBuf length, but blklen
121 * aligned and plus the length of the salt, that is appended. 123 * aligned and plus the length of the salt, that is appended.
122 */ 124 */
123 *outBufLen = getBufLen(unpaddedLen, blklen) + STRING2KEY_SALTLEN; 125 *outBufLen = getBufLen(unpaddedLen, blklen) + STRING2KEY_SALTLEN;
124 *outBuf = new unsigned char[*outBufLen]; 126 *outBuf = new unsigned char[*outBufLen];
125 padData(inBuf, unpaddedLen, blklen); 127 padData(inBuf, unpaddedLen, blklen);
126 // encrypt the padded data 128 // encrypt the padded data
127 err = gcry_cipher_encrypt(handle, 129 err = gcry_cipher_encrypt(handle,
128 *outBuf, 130 *outBuf,
129 *outBufLen - STRING2KEY_SALTLEN, 131 *outBufLen - STRING2KEY_SALTLEN,
130 inBuf, 132 inBuf,
131 *outBufLen - STRING2KEY_SALTLEN); 133 *outBufLen - STRING2KEY_SALTLEN);
132 if (err != GPG_ERR_NO_ERROR) { 134 if (err != GPG_ERR_NO_ERROR) {
133 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ") 135 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
134 + gcry_strerror(err)); 136 + gcry_strerror(err));
135 ret = e_cryptNotImpl; 137 ret = e_cryptNotImpl;
136 goto out_delete; 138 goto out_delete;
137 } 139 }
138 // append the salt to the encrypted data 140 // append the salt to the encrypted data
139 memcpy(*outBuf + *outBufLen - STRING2KEY_SALTLEN, salt, STRING2KEY_SALTLEN); 141 memcpy(*outBuf + *outBufLen - STRING2KEY_SALTLEN, salt, STRING2KEY_SALTLEN);
140 goto out_close; 142 goto out_close;
141out_delete: 143out_delete:
142 delete [] *outBuf; 144 delete [] *outBuf;
143out_close: 145out_close:
144 gcry_cipher_close(handle); 146 gcry_cipher_close(handle);
145out: 147out:
146 return ret; 148 return ret;
147} 149}
148 150
149PwMerror LibGCryptIf::decrypt(unsigned char **outBuf, 151PwMerror LibGCryptIf::decrypt(unsigned char **outBuf,
150 size_t *outBufLen, 152 size_t *outBufLen,
151 const unsigned char *inBuf, 153 const unsigned char *inBuf,
152 size_t inBufLen, 154 size_t inBufLen,
153 const unsigned char *key, 155 const unsigned char *key,
154 size_t keylen, 156 size_t keylen,
155 char _algo) 157 char _algo,
158 char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
159)
156{ 160{
157 PwMerror ret = e_success; 161 PwMerror ret = e_success;
158 gcry_error_t err; 162 gcry_error_t err;
159 gcry_cipher_hd_t handle; 163 gcry_cipher_hd_t handle;
160 size_t cipherKeylen; 164 size_t cipherKeylen;
161 unsigned char *hashedKey; 165 unsigned char *hashedKey;
162 unsigned char salt[STRING2KEY_SALTLEN]; 166 unsigned char salt[STRING2KEY_SALTLEN];
163 int algo = mapCipherId(_algo); 167 int algo = mapCipherId(_algo);
164 168
165 if (!inBufLen || !keylen) 169 if (!inBufLen || !keylen)
166 return e_invalidArg; 170 return e_invalidArg;
167 171
168 // test if algo is ready for encryption 172 // test if algo is ready for encryption
169 err = gcry_cipher_algo_info(algo, 173 err = gcry_cipher_algo_info(algo,
170 GCRYCTL_TEST_ALGO, 174 GCRYCTL_TEST_ALGO,
171 0, 0); 175 0, 0);
172 if (err != GPG_ERR_NO_ERROR) { 176 if (err != GPG_ERR_NO_ERROR) {
173 printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_TEST_ALGO failed: ") 177 printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_TEST_ALGO failed: ")
174 + gcry_strerror(err)); 178 + gcry_strerror(err));
175 ret = e_cryptNotImpl; 179 ret = e_cryptNotImpl;
176 goto out; 180 goto out;
177 } 181 }
178 // get algo key length 182 // get algo key length
179 err = gcry_cipher_algo_info(algo, 183 err = gcry_cipher_algo_info(algo,
180 GCRYCTL_GET_KEYLEN, 184 GCRYCTL_GET_KEYLEN,
181 0, 185 0,
182 &cipherKeylen); 186 &cipherKeylen);
183 if (err != GPG_ERR_NO_ERROR) { 187 if (err != GPG_ERR_NO_ERROR) {
184 printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_GET_KEYLEN failed: ") 188 printDebug(string("LibGCryptIf::doDecrypt(): GCRYCTL_GET_KEYLEN failed: ")
185 + gcry_strerror(err)); 189 + gcry_strerror(err));
186 ret = e_cryptNotImpl; 190 ret = e_cryptNotImpl;
187 goto out; 191 goto out;
188 } 192 }
189 // extract the salt of the encrypted data buffer 193 // extract the salt of the encrypted data buffer
190 memcpy(salt, inBuf + inBufLen - STRING2KEY_SALTLEN, STRING2KEY_SALTLEN); 194 memcpy(salt, inBuf + inBufLen - STRING2KEY_SALTLEN, STRING2KEY_SALTLEN);
191 // open the algo and get a handle 195 // open the algo and get a handle
192 err = gcry_cipher_open(&handle, 196 err = gcry_cipher_open(&handle,
193 algo, 197 algo,
194 GCRY_CIPHER_MODE_CBC, 198 GCRY_CIPHER_MODE_CBC,
195 0); 199 0);
196 if (err != GPG_ERR_NO_ERROR) { 200 if (err != GPG_ERR_NO_ERROR) {
197 printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_open() failed: ") 201 printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_open() failed: ")
198 + gcry_strerror(err)); 202 + gcry_strerror(err));
199 ret = e_cryptNotImpl; 203 ret = e_cryptNotImpl;
200 goto out; 204 goto out;
201 } 205 }
202 // hash the "key" to a fixed size hash matching "cipherKeylen" 206 // hash the "key" to a fixed size hash matching "cipherKeylen"
203 hashedKey = new unsigned char[cipherKeylen]; 207 hashedKey = new unsigned char[cipherKeylen];
204 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, false); 208 hashPassphrase(key, keylen, salt, hashedKey, cipherKeylen, false, _hashalgo);
205 // so now set the hashed key 209 // so now set the hashed key
206 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen); 210 err = gcry_cipher_setkey(handle, hashedKey, cipherKeylen);
207 if (err != GPG_ERR_NO_ERROR) { 211 if (err != GPG_ERR_NO_ERROR) {
208 printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_setkey() failed: ") 212 printDebug(string("LibGCryptIf::doDecrypt(): gcry_cipher_setkey() failed: ")
209 + gcry_strerror(err)); 213 + gcry_strerror(err));
210 ret = e_cryptNotImpl; 214 ret = e_cryptNotImpl;
211 delete [] hashedKey; 215 delete [] hashedKey;
212 goto out_close; 216 goto out_close;
213 } 217 }
214 delete [] hashedKey; 218 delete [] hashedKey;
215 *outBufLen = inBufLen - STRING2KEY_SALTLEN; 219 *outBufLen = inBufLen - STRING2KEY_SALTLEN;
216 *outBuf = new unsigned char[*outBufLen]; 220 *outBuf = new unsigned char[*outBufLen];
217 // decrypt the data 221 // decrypt the data
218 err = gcry_cipher_decrypt(handle, 222 err = gcry_cipher_decrypt(handle,
219 *outBuf, 223 *outBuf,
220 *outBufLen, 224 *outBufLen,
221 inBuf, 225 inBuf,
222 *outBufLen); 226 *outBufLen);
223 if (err != GPG_ERR_NO_ERROR) { 227 if (err != GPG_ERR_NO_ERROR) {
224 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ") 228 printDebug(string("LibGCryptIf::doEncrypt(): gcry_cipher_encrypt() failed: ")
225 + gcry_strerror(err)); 229 + gcry_strerror(err));
226 ret = e_cryptNotImpl; 230 ret = e_cryptNotImpl;
227 goto out_delete; 231 goto out_delete;
228 } 232 }
229 // remove all random padding 233 // remove all random padding
230 unpadData(*outBuf, outBufLen); 234 unpadData(*outBuf, outBufLen);
231 goto out_close; 235 goto out_close;
232out_delete: 236out_delete:
233 delete [] *outBuf; 237 delete [] *outBuf;
234out_close: 238out_close:
235 gcry_cipher_close(handle); 239 gcry_cipher_close(handle);
236out: 240out:
237 return ret; 241 return ret;
238} 242}
239 243
240PwMerror LibGCryptIf::hash(unsigned char **outBuf, 244PwMerror LibGCryptIf::hash(unsigned char **outBuf,
241 size_t *outBufLen, 245 size_t *outBufLen,
242 const unsigned char *inBuf, 246 const unsigned char *inBuf,
243 size_t inBufLen, 247 size_t inBufLen,
244 char _algo) 248 char _algo)
245{ 249{
246 PwMerror ret = e_success; 250 PwMerror ret = e_success;
247 unsigned int hashLen; 251 unsigned int hashLen;
248 int algo = mapHashId(_algo); 252 int algo = mapHashId(_algo);
249 253
250 hashLen = gcry_md_get_algo_dlen(algo); 254 hashLen = gcry_md_get_algo_dlen(algo);
251 *outBufLen = hashLen; 255 *outBufLen = hashLen;
252 *outBuf = new unsigned char[*outBufLen]; 256 *outBuf = new unsigned char[*outBufLen];
253 gcry_md_hash_buffer(algo, 257 gcry_md_hash_buffer(algo,
254 *outBuf, 258 *outBuf,
255 inBuf, 259 inBuf,
256 inBufLen); 260 inBufLen);
257 return ret; 261 return ret;
258} 262}
259 263
260unsigned int LibGCryptIf::hashLength(char _algo) 264unsigned int LibGCryptIf::hashLength(char _algo)
261{ 265{
262 unsigned int ret; 266 unsigned int ret;
263 int algo = mapHashId(_algo); 267 int algo = mapHashId(_algo);
264 ret = gcry_md_get_algo_dlen(algo); 268 ret = gcry_md_get_algo_dlen(algo);
265 return ret; 269 return ret;
266} 270}
267 271
268int LibGCryptIf::mapCipherId(char algo) 272int LibGCryptIf::mapCipherId(char algo)
269{ 273{
270 switch (algo) { 274 switch (algo) {
271 case PWM_CRYPT_AES128: 275 case PWM_CRYPT_AES128:
272 return GCRY_CIPHER_AES; 276 return GCRY_CIPHER_AES;
273 case PWM_CRYPT_AES192: 277 case PWM_CRYPT_AES192:
274 return GCRY_CIPHER_AES192; 278 return GCRY_CIPHER_AES192;
275 case PWM_CRYPT_AES256: 279 case PWM_CRYPT_AES256:
276 return GCRY_CIPHER_AES256; 280 return GCRY_CIPHER_AES256;
277 case PWM_CRYPT_3DES: 281 case PWM_CRYPT_3DES:
278 return GCRY_CIPHER_3DES; 282 return GCRY_CIPHER_3DES;
279 case PWM_CRYPT_TWOFISH: 283 case PWM_CRYPT_TWOFISH:
280 return GCRY_CIPHER_TWOFISH; 284 return GCRY_CIPHER_TWOFISH;
281 case PWM_CRYPT_TWOFISH128: 285 case PWM_CRYPT_TWOFISH128:
282 return GCRY_CIPHER_TWOFISH128; 286 return GCRY_CIPHER_TWOFISH128;
283 default: 287 default:
284 BUG(); 288 BUG();
285 } 289 }
286 return GCRY_CIPHER_NONE; 290 return GCRY_CIPHER_NONE;
287} 291}
288 292
289int LibGCryptIf::mapHashId(char algo) 293int LibGCryptIf::mapHashId(char algo)
290{ 294{
291 switch (algo) { 295 switch (algo) {
292 case PWM_HASH_SHA1: 296 case PWM_HASH_SHA1:
293 return GCRY_MD_SHA1; 297 return GCRY_MD_SHA1;
294 case PWM_HASH_SHA256: 298 case PWM_HASH_SHA256:
295 return GCRY_MD_SHA256; 299 return GCRY_MD_SHA256;
296 case PWM_HASH_SHA384: 300 case PWM_HASH_SHA384:
297 return GCRY_MD_SHA384; 301 return GCRY_MD_SHA384;
298 case PWM_HASH_SHA512: 302 case PWM_HASH_SHA512:
299 return GCRY_MD_SHA512; 303 return GCRY_MD_SHA512;
300 case PWM_HASH_MD5: 304 case PWM_HASH_MD5:
301 return GCRY_MD_MD5; 305 return GCRY_MD_MD5;
302 case PWM_HASH_RMD160: 306 case PWM_HASH_RMD160:
303 return GCRY_MD_RMD160; 307 return GCRY_MD_RMD160;
304 case PWM_HASH_TIGER: 308 case PWM_HASH_TIGER:
305 return GCRY_MD_TIGER; 309 return GCRY_MD_TIGER;
306 default: 310 default:
307 BUG(); 311 BUG();
308 } 312 }
309 return GCRY_MD_NONE; 313 return GCRY_MD_NONE;
310} 314}
311 315
312bool LibGCryptIf::hashPassphrase(const unsigned char *pw, 316bool LibGCryptIf::hashPassphrase(const unsigned char *pw,
313 size_t pwlen, 317 size_t pwlen,
314 unsigned char *salt, 318 unsigned char *salt,
315 unsigned char *key, 319 unsigned char *key,
316 size_t keylen, 320 size_t keylen,
317 bool create) 321 bool create,
322 char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
323)
318{ 324{
319 DEK dek; 325 DEK dek;
320 STRING2KEY s2k; 326 STRING2KEY s2k;
321 bool ret; 327 bool ret;
322 328
323 dek.keylen = keylen; 329 dek.keylen = keylen;
324 s2k.mode = 1; 330 s2k.mode = 1;
325 s2k.hash_algo = mapHashId(conf()->confGlobHashAlgo()); 331 //US bug: do not use the global hash algo here. Use the passed ago instead. The hashalgo stored in the file can
332 // be different from the one in the configuration.
333 s2k.hash_algo = mapHashId(_hashalgo //conf()->confGlobHashAlgo()
334 );
326 s2k.count = 0; 335 s2k.count = 0;
327 if (!create) 336 if (!create)
328 memcpy(s2k.salt, salt, STRING2KEY_SALTLEN); 337 memcpy(s2k.salt, salt, STRING2KEY_SALTLEN);
329 ret = doHashPassphrase(&dek, 338 ret = doHashPassphrase(&dek,
330 pw, 339 pw,
331 pwlen, 340 pwlen,
332 &s2k, 341 &s2k,
333 create); 342 create);
334 if (!ret) 343 if (!ret)
335 goto out; 344 goto out;
336 memcpy(key, dek.key, dek.keylen); 345 memcpy(key, dek.key, dek.keylen);
337 if (create) 346 if (create)
338 memcpy(salt, s2k.salt, STRING2KEY_SALTLEN); 347 memcpy(salt, s2k.salt, STRING2KEY_SALTLEN);
339out: 348out:
340 return ret; 349 return ret;
341} 350}
342 351
343 352
344bool LibGCryptIf::doHashPassphrase(DEK *dek, 353bool LibGCryptIf::doHashPassphrase(DEK *dek,
345 const unsigned char *pw, 354 const unsigned char *pw,
346 size_t pwlen, 355 size_t pwlen,
347 STRING2KEY *s2k, 356 STRING2KEY *s2k,
348 bool create) 357 bool create)
349{ 358{
350 // This function is derived from GnuPG-1.2.5-rc2 359 // This function is derived from GnuPG-1.2.5-rc2
351 gcry_md_hd_t md; 360 gcry_md_hd_t md;
352 gcry_error_t err; 361 gcry_error_t err;
353 bool ret = true; 362 bool ret = true;
354 size_t pass, i; 363 size_t pass, i;
355 size_t used = 0; 364 size_t used = 0;
356 365
357 PWM_ASSERT(s2k->hash_algo); 366 PWM_ASSERT(s2k->hash_algo);
358 BUG_ON(!(dek->keylen > 0 && dek->keylen <= array_size(dek->key))); 367 BUG_ON(!(dek->keylen > 0 && dek->keylen <= array_size(dek->key)));
359 368
360 err = gcry_md_open(&md, s2k->hash_algo, 0); 369 err = gcry_md_open(&md, s2k->hash_algo, 0);
361 if (err != GPG_ERR_NO_ERROR) { 370 if (err != GPG_ERR_NO_ERROR) {
362 ret = false; 371 ret = false;
363 goto out; 372 goto out;
364 } 373 }
365 for (pass = 0; used < dek->keylen; pass++) { 374 for (pass = 0; used < dek->keylen; pass++) {
366 if (pass) { 375 if (pass) {
367 gcry_md_reset(md); 376 gcry_md_reset(md);
368 for (i = 0; i < pass; i++) // preset the hash context 377 for (i = 0; i < pass; i++) // preset the hash context
369 gcry_md_putc(md, 0); 378 gcry_md_putc(md, 0);
370 } 379 }
371 if (s2k->mode == 1 || s2k->mode == 3) { 380 if (s2k->mode == 1 || s2k->mode == 3) {
372 size_t len2 = pwlen + 8; 381 size_t len2 = pwlen + 8;
373 size_t count = len2; 382 size_t count = len2;
374 383
375 if (create && !pass) { 384 if (create && !pass) {
376 Randomizer *rnd = Randomizer::obj(); 385 Randomizer *rnd = Randomizer::obj();
377 const unsigned int salt_len = 8; 386 const unsigned int salt_len = 8;
378 string rndBuf(rnd->genRndBuf(salt_len)); 387 string rndBuf(rnd->genRndBuf(salt_len));
379 memcpy(s2k->salt, rndBuf.c_str(), salt_len); 388 memcpy(s2k->salt, rndBuf.c_str(), salt_len);
380 if (s2k->mode == 3) 389 if (s2k->mode == 3)
381 s2k->count = 96; // 65536 iterations 390 s2k->count = 96; // 65536 iterations
382 } 391 }
383 if (s2k->mode == 3) { 392 if (s2k->mode == 3) {
384 count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6); 393 count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
385 if (count < len2) 394 if (count < len2)
386 count = len2; 395 count = len2;
387 } 396 }
388 // a little bit complicated because we need a ulong for count 397 // a little bit complicated because we need a ulong for count
389 while (count > len2) { // maybe iterated+salted 398 while (count > len2) { // maybe iterated+salted
390 gcry_md_write(md, s2k->salt, 8); 399 gcry_md_write(md, s2k->salt, 8);
391 gcry_md_write(md, pw, pwlen); 400 gcry_md_write(md, pw, pwlen);
392 count -= len2; 401 count -= len2;
393 } 402 }
394 if (count < 8) { 403 if (count < 8) {
395 gcry_md_write(md, s2k->salt, count); 404 gcry_md_write(md, s2k->salt, count);
396 } else { 405 } else {
397 gcry_md_write(md, s2k->salt, 8); 406 gcry_md_write(md, s2k->salt, 8);
398 count -= 8; 407 count -= 8;
399 gcry_md_write(md, pw, count); 408 gcry_md_write(md, pw, count);
400 } 409 }
401 } else 410 } else
402 gcry_md_write(md, pw, pwlen); 411 gcry_md_write(md, pw, pwlen);
403 gcry_md_final(md); 412 gcry_md_final(md);
404 i = gcry_md_get_algo_dlen(s2k->hash_algo); 413 i = gcry_md_get_algo_dlen(s2k->hash_algo);
405 if (i > dek->keylen - used) 414 if (i > dek->keylen - used)
406 i = dek->keylen - used; 415 i = dek->keylen - used;
407 memcpy(dek->key+used, gcry_md_read(md, s2k->hash_algo), i); 416 memcpy(dek->key+used, gcry_md_read(md, s2k->hash_algo), i);
408 used += i; 417 used += i;
409 } 418 }
410 gcry_md_close(md); 419 gcry_md_close(md);
411out: 420out:
412 return ret; 421 return ret;
413} 422}
414 423
415void LibGCryptIf::padData(unsigned char *buf, 424void LibGCryptIf::padData(unsigned char *buf,
416 size_t bufLen, 425 size_t bufLen,
417 size_t boundary) 426 size_t boundary)
418{ 427{
419 size_t numPadBytes = boundary - ((bufLen + 1) % boundary); 428 size_t numPadBytes = boundary - ((bufLen + 1) % boundary);
420 buf[bufLen] = static_cast<char>(0x01); 429 buf[bufLen] = static_cast<char>(0x01);
421 size_t i = 0; 430 size_t i = 0;
422 Randomizer *rnd = Randomizer::obj(); 431 Randomizer *rnd = Randomizer::obj();
423 char c; 432 char c;
424 unsigned char *b; 433 unsigned char *b;
425 while (i < numPadBytes) { 434 while (i < numPadBytes) {
426 c = rnd->genRndChar(); 435 c = rnd->genRndChar();
427 if (c == static_cast<char>(0x01)) 436 if (c == static_cast<char>(0x01))
428 continue; 437 continue;
429 b = buf + bufLen + 1 + i; 438 b = buf + bufLen + 1 + i;
430 *b = c; 439 *b = c;
431 ++i; 440 ++i;
432 } 441 }
433} 442}
434 443
435void LibGCryptIf::unpadData(const unsigned char *buf, 444void LibGCryptIf::unpadData(const unsigned char *buf,
436 size_t *bufLen) 445 size_t *bufLen)
437{ 446{
438 size_t pos; 447 size_t pos;
439 BUG_ON(*bufLen % 8); 448 BUG_ON(*bufLen % 8);
440 pos = *bufLen - 1; 449 pos = *bufLen - 1;
441 while (buf[pos] != static_cast<char>(0x01)) { 450 while (buf[pos] != static_cast<char>(0x01)) {
442 qDebug("pos %d %d %d", pos, buf[pos], static_cast<char>(0x01) ); 451 //qDebug("pos %d %d %d", pos, buf[pos], static_cast<char>(0x01) );
443 BUG_ON(!pos); 452 BUG_ON(!pos);
444 //LR BUG we should terminte the loop if p == 0 453 //LR BUG we should terminte the loop if p == 0
445 if ( pos == 0 ) 454 if ( pos == 0 )
446 break; 455 break;
447 --pos; 456 --pos;
448 } 457 }
449 *bufLen = pos; 458 *bufLen = pos;
450 qDebug("ente "); 459 //qDebug("ente ");
451} 460}
452 461
453#endif // CONFIG_PWMANAGER_GCRY 462#endif // CONFIG_PWMANAGER_GCRY
454 463
diff --git a/pwmanager/pwmanager/libgcryptif.h b/pwmanager/pwmanager/libgcryptif.h
index 1a7b658..9a987a2 100644
--- a/pwmanager/pwmanager/libgcryptif.h
+++ b/pwmanager/pwmanager/libgcryptif.h
@@ -1,171 +1,177 @@
1/*************************************************************************** 1/***************************************************************************
2 * * 2 * *
3 * copyright (C) 2004 by Michael Buesch * 3 * copyright (C) 2004 by Michael Buesch *
4 * email: mbuesch@freenet.de * 4 * email: mbuesch@freenet.de *
5 * * 5 * *
6 * hashPassphrase() is derived from GnuPG and is * 6 * hashPassphrase() is derived from GnuPG and is *
7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 * 7 * Copyright (C) 1998, 1999, 2000, 2001, 2003 *
8 * Free Software Foundation, Inc. * 8 * Free Software Foundation, Inc. *
9 * * 9 * *
10 * This program is free software; you can redistribute it and/or modify * 10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License version 2 * 11 * it under the terms of the GNU General Public License version 2 *
12 * as published by the Free Software Foundation. * 12 * as published by the Free Software Foundation. *
13 * * 13 * *
14 ***************************************************************************/ 14 ***************************************************************************/
15 15
16/*************************************************************************** 16/***************************************************************************
17 * copyright (C) 2004 by Ulf Schenk 17 * copyright (C) 2004 by Ulf Schenk
18 * This file is originaly based on version 1.1 of pwmanager 18 * This file is originaly based on version 1.1 of pwmanager
19 * and was modified to run on embedded devices that run microkde 19 * and was modified to run on embedded devices that run microkde
20 * 20 *
21 * $Id$ 21 * $Id$
22 **************************************************************************/ 22 **************************************************************************/
23 23
24#ifndef __LIBGCRYPTIF_H 24#ifndef __LIBGCRYPTIF_H
25#define __LIBGCRYPTIF_H 25#define __LIBGCRYPTIF_H
26 26
27#include "pwmexception.h" 27#include "pwmexception.h"
28 28
29//#undef CONFIG_PWMANAGER_GCRY // for debugging only. 29//#undef CONFIG_PWMANAGER_GCRY // for debugging only.
30#ifdef CONFIG_PWMANAGER_GCRY 30#ifdef CONFIG_PWMANAGER_GCRY
31 31
32#include <stddef.h> 32#include <stddef.h>
33#include <sys/types.h> 33#include <sys/types.h>
34#ifndef _WIN32_ 34#ifndef _WIN32_
35#include <stdint.h> 35#include <stdint.h>
36#else 36#else
37#define uint8_t Q_UINT8 37#define uint8_t Q_UINT8
38#define byte Q_UINT8 38#define byte Q_UINT8
39#define uint32_t Q_UINT32 39#define uint32_t Q_UINT32
40#endif 40#endif
41 #define STRING2KEY_SALTLEN8 41 #define STRING2KEY_SALTLEN8
42 42
43/** interface class for the libgcrypt cipher and hash algorithms 43/** interface class for the libgcrypt cipher and hash algorithms
44 * NOTE: Always allocate 1024 extra bytes for the inBuf (for padding) 44 * NOTE: Always allocate 1024 extra bytes for the inBuf (for padding)
45 */ 45 */
46class LibGCryptIf 46class LibGCryptIf
47{ 47{
48protected: 48protected:
49 struct STRING2KEY 49 struct STRING2KEY
50 { 50 {
51 int mode; 51 int mode;
52 int hash_algo; 52 int hash_algo;
53 uint8_t salt[STRING2KEY_SALTLEN]; 53 uint8_t salt[STRING2KEY_SALTLEN];
54 uint32_t count; 54 uint32_t count;
55 }; 55 };
56 struct DEK 56 struct DEK
57 { 57 {
58 size_t keylen; 58 size_t keylen;
59 uint8_t key[32]; // this is the largest used keylen (256 bit) 59 uint8_t key[32]; // this is the largest used keylen (256 bit)
60 }; 60 };
61 61
62public: 62public:
63 LibGCryptIf() { } 63 LibGCryptIf() { }
64 /** is libgcrypt available? */ 64 /** is libgcrypt available? */
65 static bool available() 65 static bool available()
66 { return true; } 66 { return true; }
67 /** encrypt data. _algo is the PWM_CRYPT_* ID 67 /** encrypt data. _algo is the PWM_CRYPT_* ID
68 * of the algorithm. 68 * of the algorithm.
69 */ 69 */
70 PwMerror encrypt(unsigned char **outBuf, 70 PwMerror encrypt(unsigned char **outBuf,
71 size_t *outBufLen, 71 size_t *outBufLen,
72 unsigned char *inBuf, 72 unsigned char *inBuf,
73 size_t inBufLen, 73 size_t inBufLen,
74 const unsigned char *key, 74 const unsigned char *key,
75 size_t keylen, 75 size_t keylen,
76 char _algo); 76 char _algo,
77 char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
78);
77 /** decrypt data. _algo is the PWM_CRYPT_* ID 79 /** decrypt data. _algo is the PWM_CRYPT_* ID
78 * of the algorithm. 80 * of the algorithm.
79 */ 81 */
80 PwMerror decrypt(unsigned char **outBuf, 82 PwMerror decrypt(unsigned char **outBuf,
81 size_t *outBufLen, 83 size_t *outBufLen,
82 const unsigned char *inBuf, 84 const unsigned char *inBuf,
83 size_t inBufLen, 85 size_t inBufLen,
84 const unsigned char *key, 86 const unsigned char *key,
85 size_t keylen, 87 size_t keylen,
86 char _algo); 88 char _algo,
89 char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
90);
87 /** hash data. _algo is the PWM_HASH_* ID of the hash */ 91 /** hash data. _algo is the PWM_HASH_* ID of the hash */
88 PwMerror hash(unsigned char **outBuf, 92 PwMerror hash(unsigned char **outBuf,
89 size_t *outBufLen, 93 size_t *outBufLen,
90 const unsigned char *inBuf, 94 const unsigned char *inBuf,
91 size_t inBufLen, 95 size_t inBufLen,
92 char _algo); 96 char _algo);
93 /** returns the length of the hash. _algo is the PWM_HASH_* 97 /** returns the length of the hash. _algo is the PWM_HASH_*
94 * id of the hash. returns 0 on error. 98 * id of the hash. returns 0 on error.
95 */ 99 */
96 unsigned int hashLength(char _algo); 100 unsigned int hashLength(char _algo);
97 101
98protected: 102protected:
99 /** returns the total buffer length */ 103 /** returns the total buffer length */
100 size_t getBufLen(size_t inBufLen, size_t boundary) 104 size_t getBufLen(size_t inBufLen, size_t boundary)
101 { 105 {
102 return ((boundary - (inBufLen % boundary)) + inBufLen); 106 return ((boundary - (inBufLen % boundary)) + inBufLen);
103 } 107 }
104 /** pad the data up to the given boundary. 108 /** pad the data up to the given boundary.
105 * "buf" has to be big enough! 109 * "buf" has to be big enough!
106 */ 110 */
107 void padData(unsigned char *buf, 111 void padData(unsigned char *buf,
108 size_t bufLen, 112 size_t bufLen,
109 size_t boundary); 113 size_t boundary);
110 /** unpad the data */ 114 /** unpad the data */
111 void unpadData(const unsigned char *buf, 115 void unpadData(const unsigned char *buf,
112 size_t *bufLen); 116 size_t *bufLen);
113 /** maps the PWM_CRYPT_* ID of an algorithm 117 /** maps the PWM_CRYPT_* ID of an algorithm
114 * to the libgcrypt GCRY_CIPHER_* ID 118 * to the libgcrypt GCRY_CIPHER_* ID
115 */ 119 */
116 int mapCipherId(char algo); 120 int mapCipherId(char algo);
117 /** maps the PWM_HASH_* ID of an algorithm 121 /** maps the PWM_HASH_* ID of an algorithm
118 * to the libgcrypt GCRY_MD_* ID 122 * to the libgcrypt GCRY_MD_* ID
119 */ 123 */
120 int mapHashId(char algo); 124 int mapHashId(char algo);
121 /** hash a passphrase to a cipher key */ 125 /** hash a passphrase to a cipher key */
122 bool hashPassphrase(const unsigned char *pw, 126 bool hashPassphrase(const unsigned char *pw,
123 size_t pwlen, 127 size_t pwlen,
124 unsigned char *salt, 128 unsigned char *salt,
125 unsigned char *key, 129 unsigned char *key,
126 size_t keylen, 130 size_t keylen,
127 bool create); 131 bool create,
132 char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
133);
128 /** hash a passphrase to a cipher key */ 134 /** hash a passphrase to a cipher key */
129 bool doHashPassphrase(DEK *dek, 135 bool doHashPassphrase(DEK *dek,
130 const unsigned char *pw, 136 const unsigned char *pw,
131 size_t pwlen, 137 size_t pwlen,
132 STRING2KEY *s2k, 138 STRING2KEY *s2k,
133 bool create); 139 bool create);
134}; 140};
135 141
136 142
137#else // CONFIG_PWMANAGER_GCRY 143#else // CONFIG_PWMANAGER_GCRY
138/** libgcrypt is not installed. This is a NOP wrapper. */ 144/** libgcrypt is not installed. This is a NOP wrapper. */
139class LibGCryptIf 145class LibGCryptIf
140{ 146{
141public: 147public:
142 LibGCryptIf() { } 148 LibGCryptIf() { }
143 static bool available() 149 static bool available()
144 { return false; } 150 { return false; }
145 PwMerror encrypt(unsigned char **, 151 PwMerror encrypt(unsigned char **,
146 size_t *, 152 size_t *,
147 unsigned char *, 153 unsigned char *,
148 size_t, 154 size_t,
149 const unsigned char *, 155 const unsigned char *,
150 size_t, 156 size_t,
151 char) 157 char)
152 { return e_cryptNotImpl; } 158 { return e_cryptNotImpl; }
153 PwMerror decrypt(unsigned char **, 159 PwMerror decrypt(unsigned char **,
154 size_t *, 160 size_t *,
155 const unsigned char *, 161 const unsigned char *,
156 size_t, 162 size_t,
157 const unsigned char *, 163 const unsigned char *,
158 size_t, 164 size_t,
159 char) 165 char)
160 { return e_cryptNotImpl; } 166 { return e_cryptNotImpl; }
161 PwMerror hash(unsigned char **, 167 PwMerror hash(unsigned char **,
162 size_t *, 168 size_t *,
163 const unsigned char *, 169 const unsigned char *,
164 size_t, 170 size_t,
165 char) 171 char)
166 { return e_hashNotImpl; } 172 { return e_hashNotImpl; }
167 unsigned int hashLength(char) 173 unsigned int hashLength(char)
168 { return 0; } 174 { return 0; }
169}; 175};
170#endif // CONFIG_PWMANAGER_GCRY 176#endif // CONFIG_PWMANAGER_GCRY
171#endif // __LIBGCRYPTIF_H 177#endif // __LIBGCRYPTIF_H
diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp
index 17cb74a..a740d6d 100644
--- a/pwmanager/pwmanager/pwmdoc.cpp
+++ b/pwmanager/pwmanager/pwmdoc.cpp
@@ -234,633 +234,633 @@ void DocTimer::putLock(TimerIDs timer)
234 break; 234 break;
235 case id_metaCheckTimer: 235 case id_metaCheckTimer:
236 if (metaCheckLock) 236 if (metaCheckLock)
237 --metaCheckLock; 237 --metaCheckLock;
238 break; 238 break;
239 } 239 }
240} 240}
241 241
242void DocTimer::mpwTimeout() 242void DocTimer::mpwTimeout()
243{ 243{
244 if (mpwLock) { 244 if (mpwLock) {
245 mpwTimer->start(1000, true); 245 mpwTimer->start(1000, true);
246 return; 246 return;
247 } 247 }
248 doc->unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); 248 doc->unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW);
249} 249}
250 250
251void DocTimer::autoLockTimeout() 251void DocTimer::autoLockTimeout()
252{ 252{
253 if (autoLockLock) { 253 if (autoLockLock) {
254 autoLockTimer->start(1000, true); 254 autoLockTimer->start(1000, true);
255 return; 255 return;
256 } 256 }
257 if (conf()->confGlobAutoDeepLock() && 257 if (conf()->confGlobAutoDeepLock() &&
258 doc->filename != QString::null && 258 doc->filename != QString::null &&
259 doc->filename != "") { 259 doc->filename != "") {
260 doc->deepLock(true); 260 doc->deepLock(true);
261 } else { 261 } else {
262 doc->lockAll(true); 262 doc->lockAll(true);
263 } 263 }
264} 264}
265 265
266void DocTimer::metaCheckTimeout() 266void DocTimer::metaCheckTimeout()
267{ 267{
268 if (metaCheckLock) { 268 if (metaCheckLock) {
269 // check again in one second. 269 // check again in one second.
270 metaCheckTimer->start(1000, true); 270 metaCheckTimer->start(1000, true);
271 return; 271 return;
272 } 272 }
273 if (doc->isDeepLocked()) { 273 if (doc->isDeepLocked()) {
274 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); 274 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
275 return; 275 return;
276 } 276 }
277 if (doc->isDocEmpty()) { 277 if (doc->isDocEmpty()) {
278 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); 278 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
279 return; 279 return;
280 } 280 }
281#ifdef CONFIG_KWALLETIF 281#ifdef CONFIG_KWALLETIF
282 KWalletEmu *kwlEmu = doc->init->kwalletEmu(); 282 KWalletEmu *kwlEmu = doc->init->kwalletEmu();
283 if (kwlEmu) 283 if (kwlEmu)
284 kwlEmu->suspendDocSignals(); 284 kwlEmu->suspendDocSignals();
285#endif // CONFIG_KWALLETIF 285#endif // CONFIG_KWALLETIF
286 /* We simply trigger all views to update their 286 /* We simply trigger all views to update their
287 * displayed values. This way they have a chance 287 * displayed values. This way they have a chance
288 * to get notified when some meta changes over time. 288 * to get notified when some meta changes over time.
289 * (for example an entry expired). 289 * (for example an entry expired).
290 * The _view_ is responsive for not updating its 290 * The _view_ is responsive for not updating its
291 * contents if nothing really changed! 291 * contents if nothing really changed!
292 */ 292 */
293 emit doc->dataChanged(doc); 293 emit doc->dataChanged(doc);
294#ifdef CONFIG_KWALLETIF 294#ifdef CONFIG_KWALLETIF
295 if (kwlEmu) 295 if (kwlEmu)
296 kwlEmu->resumeDocSignals(); 296 kwlEmu->resumeDocSignals();
297#endif // CONFIG_KWALLETIF 297#endif // CONFIG_KWALLETIF
298 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); 298 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
299} 299}
300 300
301 301
302 302
303PwMDocList PwMDoc::openDocList; 303PwMDocList PwMDoc::openDocList;
304unsigned int PwMDocList::unnamedDocCnt = 1; 304unsigned int PwMDocList::unnamedDocCnt = 1;
305 305
306PwMDoc::PwMDoc(QObject *parent, const char *name) 306PwMDoc::PwMDoc(QObject *parent, const char *name)
307 : PwMDocUi(parent, name) 307 : PwMDocUi(parent, name)
308 , dataChangedLock (0) 308 , dataChangedLock (0)
309{ 309{
310 deleted = false; 310 deleted = false;
311 unnamedNum = 0; 311 unnamedNum = 0;
312 getOpenDocList()->add(this, getTitle().latin1()); 312 getOpenDocList()->add(this, getTitle().latin1());
313 curDocStat = 0; 313 curDocStat = 0;
314 setMaxNumEntries(); 314 setMaxNumEntries();
315 _timer = new DocTimer(this); 315 _timer = new DocTimer(this);
316 timer()->start(DocTimer::id_mpwTimer); 316 timer()->start(DocTimer::id_mpwTimer);
317 timer()->start(DocTimer::id_autoLockTimer); 317 timer()->start(DocTimer::id_autoLockTimer);
318 timer()->start(DocTimer::id_metaCheckTimer); 318 timer()->start(DocTimer::id_metaCheckTimer);
319 addCategory(DEFAULT_CATEGORY, 0, false); 319 addCategory(DEFAULT_CATEGORY, 0, false);
320 listView = 0; 320 listView = 0;
321 emit docCreated(this); 321 emit docCreated(this);
322} 322}
323 323
324PwMDoc::~PwMDoc() 324PwMDoc::~PwMDoc()
325{ 325{
326 emit docClosed(this); 326 emit docClosed(this);
327 getOpenDocList()->del(this); 327 getOpenDocList()->del(this);
328 delete _timer; 328 delete _timer;
329} 329}
330 330
331PwMerror PwMDoc::saveDoc(char compress, const QString *file) 331PwMerror PwMDoc::saveDoc(char compress, const QString *file)
332{ 332{
333 PwMerror ret, e; 333 PwMerror ret, e;
334 string serialized; 334 string serialized;
335 QFile f; 335 QFile f;
336 QString tmpFileMoved(QString::null); 336 QString tmpFileMoved(QString::null);
337 bool wasDeepLocked; 337 bool wasDeepLocked;
338 QString savedFilename(filename); 338 QString savedFilename(filename);
339 339
340 if (!file) { 340 if (!file) {
341 if (filename == "") 341 if (filename == "")
342 return e_filename; 342 return e_filename;
343 if (isDeepLocked()) { 343 if (isDeepLocked()) {
344 /* We don't need to save any data. 344 /* We don't need to save any data.
345 * It's already all on disk, because 345 * It's already all on disk, because
346 * we are deeplocked. 346 * we are deeplocked.
347 */ 347 */
348 unsetDocStatFlag(DOC_STAT_DISK_DIRTY); 348 unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
349 ret = e_success; 349 ret = e_success;
350 return ret; 350 return ret;
351 } 351 }
352 } else { 352 } else {
353 if (*file == "" && filename == "") 353 if (*file == "" && filename == "")
354 return e_filename; 354 return e_filename;
355 if (*file != "") 355 if (*file != "")
356 filename = *file; 356 filename = *file;
357 } 357 }
358 358
359 wasDeepLocked = isDeepLocked(); 359 wasDeepLocked = isDeepLocked();
360 if (wasDeepLocked) { 360 if (wasDeepLocked) {
361 /* We are deeplocked. That means all data is already 361 /* We are deeplocked. That means all data is already
362 * on disk. BUT we need to do saving procedure, 362 * on disk. BUT we need to do saving procedure,
363 * because *file != savedFilename. 363 * because *file != savedFilename.
364 * Additionally we need to tempoarly restore 364 * Additionally we need to tempoarly restore
365 * the old "filename", because deepLock() references it. 365 * the old "filename", because deepLock() references it.
366 */ 366 */
367 QString newFilename(filename); 367 QString newFilename(filename);
368 filename = savedFilename; 368 filename = savedFilename;
369 getDataChangedLock(); 369 getDataChangedLock();
370 e = deepLock(false); 370 e = deepLock(false);
371 putDataChangedLock(); 371 putDataChangedLock();
372 filename = newFilename; 372 filename = newFilename;
373 switch (e) { 373 switch (e) {
374 case e_success: 374 case e_success:
375 break; 375 break;
376 case e_wrongPw: 376 case e_wrongPw:
377 case e_noPw: 377 case e_noPw:
378 emitDataChanged(this); 378 emitDataChanged(this);
379 return e; 379 return e;
380 default: 380 default:
381 emitDataChanged(this); 381 emitDataChanged(this);
382 return e_openFile; 382 return e_openFile;
383 } 383 }
384 } 384 }
385 385
386 if (!isPwAvailable()) { 386 if (!isPwAvailable()) {
387 /* password is not available. This means, the 387 /* password is not available. This means, the
388 * document wasn't saved, yet. 388 * document wasn't saved, yet.
389 */ 389 */
390 bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD); 390 bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD);
391 QString pw(requestNewMpw(&useChipcard)); 391 QString pw(requestNewMpw(&useChipcard));
392 if (pw != "") { 392 if (pw != "") {
393 currentPw = pw; 393 currentPw = pw;
394 } else { 394 } else {
395 return e_noPw; 395 return e_noPw;
396 } 396 }
397 if (useChipcard) { 397 if (useChipcard) {
398 setDocStatFlag(DOC_STAT_USE_CHIPCARD); 398 setDocStatFlag(DOC_STAT_USE_CHIPCARD);
399 } else { 399 } else {
400 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); 400 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
401 } 401 }
402 } 402 }
403 403
404 int _cryptAlgo = conf()->confGlobCryptAlgo(); 404 int _cryptAlgo = conf()->confGlobCryptAlgo();
405 int _hashAlgo = conf()->confGlobHashAlgo(); 405 int _hashAlgo = conf()->confGlobHashAlgo();
406 406
407 // sanity check for the selected algorithms 407 // sanity check for the selected algorithms
408 if (_cryptAlgo < PWM_CRYPT_BLOWFISH || 408 if (_cryptAlgo < PWM_CRYPT_BLOWFISH ||
409 _cryptAlgo > PWM_CRYPT_TWOFISH128) { 409 _cryptAlgo > PWM_CRYPT_TWOFISH128) {
410 printWarn("Invalid Crypto-Algorithm selected! " 410 printWarn("Invalid Crypto-Algorithm selected! "
411 "Config-file seems to be corrupt. " 411 "Config-file seems to be corrupt. "
412 "Falling back to Blowfish."); 412 "Falling back to Blowfish.");
413 _cryptAlgo = PWM_CRYPT_BLOWFISH; 413 _cryptAlgo = PWM_CRYPT_BLOWFISH;
414 } 414 }
415 if (_hashAlgo < PWM_HASH_SHA1 || 415 if (_hashAlgo < PWM_HASH_SHA1 ||
416 _hashAlgo > PWM_HASH_TIGER) { 416 _hashAlgo > PWM_HASH_TIGER) {
417 printWarn("Invalid Hash-Algorithm selected! " 417 printWarn("Invalid Hash-Algorithm selected! "
418 "Config-file seems to be corrupt. " 418 "Config-file seems to be corrupt. "
419 "Falling back to SHA1."); 419 "Falling back to SHA1.");
420 _hashAlgo = PWM_HASH_SHA1; 420 _hashAlgo = PWM_HASH_SHA1;
421 } 421 }
422 char cryptAlgo = static_cast<char>(_cryptAlgo); 422 char cryptAlgo = static_cast<char>(_cryptAlgo);
423 char hashAlgo = static_cast<char>(_hashAlgo); 423 char hashAlgo = static_cast<char>(_hashAlgo);
424 424
425 if (conf()->confGlobMakeFileBackup()) { 425 if (conf()->confGlobMakeFileBackup()) {
426 if (!backupFile(filename)) 426 if (!backupFile(filename))
427 return e_fileBackup; 427 return e_fileBackup;
428 } 428 }
429 if (QFile::exists(filename)) { 429 if (QFile::exists(filename)) {
430 /* Move the existing file to some tmp file. 430 /* Move the existing file to some tmp file.
431 * When saving file succeeds, delete tmp file. Otherwise 431 * When saving file succeeds, delete tmp file. Otherwise
432 * move tmp file back. See below. 432 * move tmp file back. See below.
433 */ 433 */
434 Randomizer *rnd = Randomizer::obj(); 434 Randomizer *rnd = Randomizer::obj();
435 char rnd_buf[5]; 435 char rnd_buf[5];
436 sprintf(rnd_buf, "%X%X%X%X", rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF, 436 sprintf(rnd_buf, "%X%X%X%X", rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF,
437 rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF); 437 rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF);
438 tmpFileMoved = filename + "." + rnd_buf + ".mv"; 438 tmpFileMoved = filename + "." + rnd_buf + ".mv";
439 if (!copyFile(filename, tmpFileMoved)) 439 if (!copyFile(filename, tmpFileMoved))
440 return e_openFile; 440 return e_openFile;
441 if (!QFile::remove(filename)) { 441 if (!QFile::remove(filename)) {
442 printWarn(string("removing orig file ") 442 printWarn(string("removing orig file ")
443 + filename.latin1() 443 + filename.latin1()
444 + " failed!"); 444 + " failed!");
445 } 445 }
446 } 446 }
447 f.setName(filename); 447 f.setName(filename);
448 if (!f.open(IO_ReadWrite)) { 448 if (!f.open(IO_ReadWrite)) {
449 ret = e_openFile; 449 ret = e_openFile;
450 goto out_moveback; 450 goto out_moveback;
451 } 451 }
452 e = writeFileHeader(hashAlgo, hashAlgo, 452 e = writeFileHeader(hashAlgo, hashAlgo,
453 cryptAlgo, compress, 453 cryptAlgo, compress,
454 &currentPw, &f); 454 &currentPw, &f);
455 if (e == e_hashNotImpl) { 455 if (e == e_hashNotImpl) {
456 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed: e_hashNotImpl"); 456 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed: e_hashNotImpl");
457 f.close(); 457 f.close();
458 ret = e_hashNotImpl; 458 ret = e_hashNotImpl;
459 goto out_moveback; 459 goto out_moveback;
460 } else if (e != e_success) { 460 } else if (e != e_success) {
461 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed"); 461 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed");
462 f.close(); 462 f.close();
463 ret = e_writeHeader; 463 ret = e_writeHeader;
464 goto out_moveback; 464 goto out_moveback;
465 } 465 }
466 if (!serializeDta(&serialized)) { 466 if (!serializeDta(&serialized)) {
467 printDebug("PwMDoc::saveDoc(): serializeDta() failed"); 467 printDebug("PwMDoc::saveDoc(): serializeDta() failed");
468 f.close(); 468 f.close();
469 ret = e_serializeDta; 469 ret = e_serializeDta;
470 goto out_moveback; 470 goto out_moveback;
471 } 471 }
472 e = writeDataHash(hashAlgo, &serialized, &f); 472 e = writeDataHash(hashAlgo, &serialized, &f);
473 if (e == e_hashNotImpl) { 473 if (e == e_hashNotImpl) {
474 printDebug("PwMDoc::saveDoc(): writeDataHash() failed: e_hashNotImpl"); 474 printDebug("PwMDoc::saveDoc(): writeDataHash() failed: e_hashNotImpl");
475 f.close(); 475 f.close();
476 ret = e_hashNotImpl; 476 ret = e_hashNotImpl;
477 goto out_moveback; 477 goto out_moveback;
478 } else if (e != e_success) { 478 } else if (e != e_success) {
479 printDebug("PwMDoc::saveDoc(): writeDataHash() failed"); 479 printDebug("PwMDoc::saveDoc(): writeDataHash() failed");
480 f.close(); 480 f.close();
481 ret = e_writeHeader; 481 ret = e_writeHeader;
482 goto out_moveback; 482 goto out_moveback;
483 } 483 }
484 if (!compressDta(&serialized, compress)) { 484 if (!compressDta(&serialized, compress)) {
485 printDebug("PwMDoc::saveDoc(): compressDta() failed"); 485 printDebug("PwMDoc::saveDoc(): compressDta() failed");
486 f.close(); 486 f.close();
487 ret = e_enc; 487 ret = e_enc;
488 goto out_moveback; 488 goto out_moveback;
489 } 489 }
490 e = encrypt(&serialized, &currentPw, &f, cryptAlgo); 490 e = encrypt(&serialized, &currentPw, &f, cryptAlgo, hashAlgo);
491 if (e == e_weakPw) { 491 if (e == e_weakPw) {
492 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_weakPw"); 492 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_weakPw");
493 f.close(); 493 f.close();
494 ret = e_weakPw; 494 ret = e_weakPw;
495 goto out_moveback; 495 goto out_moveback;
496 } else if (e == e_cryptNotImpl) { 496 } else if (e == e_cryptNotImpl) {
497 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl"); 497 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl");
498 f.close(); 498 f.close();
499 ret = e_cryptNotImpl; 499 ret = e_cryptNotImpl;
500 goto out_moveback; 500 goto out_moveback;
501 } else if (e != e_success) { 501 } else if (e != e_success) {
502 printDebug("PwMDoc::saveDoc(): encrypt() failed"); 502 printDebug("PwMDoc::saveDoc(): encrypt() failed");
503 f.close(); 503 f.close();
504 ret = e_enc; 504 ret = e_enc;
505 goto out_moveback; 505 goto out_moveback;
506 } 506 }
507 unsetDocStatFlag(DOC_STAT_DISK_DIRTY); 507 unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
508 f.close(); 508 f.close();
509#ifndef _WIN32_ 509#ifndef _WIN32_
510 if (chmod(filename.latin1(), 510 if (chmod(filename.latin1(),
511 conf()->confGlobFilePermissions())) { 511 conf()->confGlobFilePermissions())) {
512 printWarn(string("chmod failed: ") + strerror(errno)); 512 printWarn(string("chmod failed: ") + strerror(errno));
513 } 513 }
514#endif 514#endif
515 openDocList.edit(this, getTitle().latin1()); 515 openDocList.edit(this, getTitle().latin1());
516 if (wasDeepLocked) { 516 if (wasDeepLocked) {
517 /* Do _not_ save the data with the deepLock() 517 /* Do _not_ save the data with the deepLock()
518 * call, because this will recurse 518 * call, because this will recurse
519 * into saveDoc() 519 * into saveDoc()
520 */ 520 */
521 deepLock(true, false); 521 deepLock(true, false);
522 /* We don't check return value here, because 522 /* We don't check return value here, because
523 * it won't fail. See NOTE in deepLock() 523 * it won't fail. See NOTE in deepLock()
524 */ 524 */
525 } 525 }
526 if (tmpFileMoved != QString::null) { 526 if (tmpFileMoved != QString::null) {
527 // now remove the moved file. 527 // now remove the moved file.
528 if (!QFile::remove(tmpFileMoved)) { 528 if (!QFile::remove(tmpFileMoved)) {
529 printWarn(string("removing file ") 529 printWarn(string("removing file ")
530 + tmpFileMoved.latin1() 530 + tmpFileMoved.latin1()
531 + " failed!"); 531 + " failed!");
532 } 532 }
533 } 533 }
534 ret = e_success; 534 ret = e_success;
535 printDebug(string("writing file { name: ") 535 printDebug(string("writing file { name: ")
536 + filename.latin1() + " compress: " 536 + filename.latin1() + " compress: "
537 + tostr(static_cast<int>(compress)) + " cryptAlgo: " 537 + tostr(static_cast<int>(compress)) + " cryptAlgo: "
538 + tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: " 538 + tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: "
539 + tostr(static_cast<int>(hashAlgo)) 539 + tostr(static_cast<int>(hashAlgo))
540 + " }"); 540 + " }");
541 goto out; 541 goto out;
542out_moveback: 542out_moveback:
543 if (tmpFileMoved != QString::null) { 543 if (tmpFileMoved != QString::null) {
544 if (copyFile(tmpFileMoved, filename)) { 544 if (copyFile(tmpFileMoved, filename)) {
545 if (!QFile::remove(tmpFileMoved)) { 545 if (!QFile::remove(tmpFileMoved)) {
546 printWarn(string("removing tmp file ") 546 printWarn(string("removing tmp file ")
547 + filename.latin1() 547 + filename.latin1()
548 + " failed!"); 548 + " failed!");
549 } 549 }
550 } else { 550 } else {
551 printWarn(string("couldn't copy file ") 551 printWarn(string("couldn't copy file ")
552 + tmpFileMoved.latin1() 552 + tmpFileMoved.latin1()
553 + " back to " 553 + " back to "
554 + filename.latin1()); 554 + filename.latin1());
555 } 555 }
556 } 556 }
557out: 557out:
558 return ret; 558 return ret;
559} 559}
560 560
561PwMerror PwMDoc::openDoc(const QString *file, int openLocked) 561PwMerror PwMDoc::openDoc(const QString *file, int openLocked)
562{ 562{
563 PWM_ASSERT(file); 563 PWM_ASSERT(file);
564 PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2); 564 PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2);
565 string decrypted, dataHash; 565 string decrypted, dataHash;
566 PwMerror ret; 566 PwMerror ret;
567 char cryptAlgo, dataHashType, compress; 567 char cryptAlgo, dataHashType, compress;
568 unsigned int headerLen; 568 unsigned int headerLen;
569 569
570 if (*file == "") 570 if (*file == "")
571 return e_readFile; 571 return e_readFile;
572 filename = *file; 572 filename = *file;
573 /* check if this file is already open. 573 /* check if this file is already open.
574 * This does not catch symlinks! 574 * This does not catch symlinks!
575 */ 575 */
576 if (!isDeepLocked()) { 576 if (!isDeepLocked()) {
577 if (getOpenDocList()->find(filename.latin1())) 577 if (getOpenDocList()->find(filename.latin1()))
578 return e_alreadyOpen; 578 return e_alreadyOpen;
579 } 579 }
580 QFile f(filename); 580 QFile f(filename);
581 581
582 if (openLocked == 2) { 582 if (openLocked == 2) {
583 // open deep-locked 583 // open deep-locked
584 if (!QFile::exists(filename)) 584 if (!QFile::exists(filename))
585 return e_openFile; 585 return e_openFile;
586 if (deepLock(true, false) != e_success) 586 if (deepLock(true, false) != e_success)
587 return e_openFile; 587 return e_openFile;
588 goto out_success; 588 goto out_success;
589 } 589 }
590 590
591 if (!f.open(IO_ReadOnly)) 591 if (!f.open(IO_ReadOnly))
592 return e_openFile; 592 return e_openFile;
593 593
594 ret = checkHeader(&cryptAlgo, &currentPw, &compress, &headerLen, 594 ret = checkHeader(&cryptAlgo, &currentPw, &compress, &headerLen,
595 &dataHashType, &dataHash, &f); 595 &dataHashType, &dataHash, &f);
596 if (ret != e_success) { 596 if (ret != e_success) {
597 printDebug("PwMDoc::openDoc(): checkHeader() failed"); 597 printDebug("PwMDoc::openDoc(): checkHeader() failed");
598 f.close(); 598 f.close();
599 if (ret == e_wrongPw) { 599 if (ret == e_wrongPw) {
600 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 600 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
601 return ret; 601 return ret;
602 } else if (ret == e_noPw || 602 } else if (ret == e_noPw ||
603 ret == e_fileVer || 603 ret == e_fileVer ||
604 ret == e_fileFormat || 604 ret == e_fileFormat ||
605 ret == e_hashNotImpl) { 605 ret == e_hashNotImpl) {
606 return ret; 606 return ret;
607 } else 607 } else
608 return e_readFile; 608 return e_readFile;
609 } 609 }
610 ret = decrypt(&decrypted, headerLen, &currentPw, cryptAlgo, &f); 610 ret = decrypt(&decrypted, headerLen, &currentPw, cryptAlgo, dataHashType, &f);
611 if (ret == e_cryptNotImpl) { 611 if (ret == e_cryptNotImpl) {
612 printDebug("PwMDoc::openDoc(): decrypt() failed: e_cryptNotImpl"); 612 printDebug("PwMDoc::openDoc(): decrypt() failed: e_cryptNotImpl");
613 f.close(); 613 f.close();
614 return e_cryptNotImpl; 614 return e_cryptNotImpl;
615 } else if (ret != e_success) { 615 } else if (ret != e_success) {
616 printDebug("PwMDoc::openDoc(): decrypt() failed"); 616 printDebug("PwMDoc::openDoc(): decrypt() failed");
617 f.close(); 617 f.close();
618 return e_readFile; 618 return e_readFile;
619 } 619 }
620 if (!decompressDta(&decrypted, compress)) { 620 if (!decompressDta(&decrypted, compress)) {
621 printDebug("PwMDoc::openDoc(): decompressDta() failed"); 621 printDebug("PwMDoc::openDoc(): decompressDta() failed");
622 f.close(); 622 f.close();
623 return e_fileCorrupt; 623 return e_fileCorrupt;
624 } 624 }
625 ret = checkDataHash(dataHashType, &dataHash, &decrypted); 625 ret = checkDataHash(dataHashType, &dataHash, &decrypted);
626 if (ret == e_hashNotImpl) { 626 if (ret == e_hashNotImpl) {
627 printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl"); 627 printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl");
628 f.close(); 628 f.close();
629 return e_hashNotImpl; 629 return e_hashNotImpl;
630 } else if (ret != e_success) { 630 } else if (ret != e_success) {
631 printDebug("PwMDoc::openDoc(): checkDataHash() failed"); 631 printDebug("PwMDoc::openDoc(): checkDataHash() failed");
632 f.close(); 632 f.close();
633 return e_fileCorrupt; 633 return e_fileCorrupt;
634 } 634 }
635 if (!deSerializeDta(&decrypted, openLocked == 1)) { 635 if (!deSerializeDta(&decrypted, openLocked == 1)) {
636 printDebug("PwMDoc::openDoc(): deSerializeDta() failed"); 636 printDebug("PwMDoc::openDoc(): deSerializeDta() failed");
637 f.close(); 637 f.close();
638 return e_readFile; 638 return e_readFile;
639 } 639 }
640 f.close(); 640 f.close();
641 timer()->start(DocTimer::id_mpwTimer); 641 timer()->start(DocTimer::id_mpwTimer);
642 timer()->start(DocTimer::id_autoLockTimer); 642 timer()->start(DocTimer::id_autoLockTimer);
643out_success: 643out_success:
644 openDocList.edit(this, getTitle().latin1()); 644 openDocList.edit(this, getTitle().latin1());
645 emit docOpened(this); 645 emit docOpened(this);
646 return e_success; 646 return e_success;
647} 647}
648 648
649PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress, 649PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress,
650 QString *pw, QFile *f) 650 QString *pw, QFile *f)
651{ 651{
652 PWM_ASSERT(pw); 652 PWM_ASSERT(pw);
653 PWM_ASSERT(f); 653 PWM_ASSERT(f);
654 //US ENH: or maybe a bug: checking here for listView does not make sense because we do not check anywhere else 654 //US ENH: or maybe a bug: checking here for listView does not make sense because we do not check anywhere else
655 //Wenn I sync, I open a doc without a view => listView is 0 => Assertion 655 //Wenn I sync, I open a doc without a view => listView is 0 => Assertion
656 //USPWM_ASSERT(listView); 656 //USPWM_ASSERT(listView);
657 if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) != 657 if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) !=
658 static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) { 658 static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) {
659 return e_writeFile; 659 return e_writeFile;
660 } 660 }
661 if (f->putch(PWM_FILE_VER) == -1 || 661 if (f->putch(PWM_FILE_VER) == -1 ||
662 f->putch(keyHash) == -1 || 662 f->putch(keyHash) == -1 ||
663 f->putch(dataHash) == -1 || 663 f->putch(dataHash) == -1 ||
664 f->putch(crypt) == -1 || 664 f->putch(crypt) == -1 ||
665 f->putch(compress) == -1 || 665 f->putch(compress) == -1 ||
666 f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ? 666 f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ?
667 (static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) { 667 (static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) {
668 return e_writeFile; 668 return e_writeFile;
669 } 669 }
670 670
671 // write bytes of NUL-data. These bytes are reserved for future-use. 671 // write bytes of NUL-data. These bytes are reserved for future-use.
672 const int bufSize = 64; 672 const int bufSize = 64;
673 char tmp_buf[bufSize]; 673 char tmp_buf[bufSize];
674 memset(tmp_buf, 0x00, bufSize); 674 memset(tmp_buf, 0x00, bufSize);
675 if (f->writeBlock(tmp_buf, bufSize) != bufSize) 675 if (f->writeBlock(tmp_buf, bufSize) != bufSize)
676 return e_writeFile; 676 return e_writeFile;
677 677
678 switch (keyHash) { 678 switch (keyHash) {
679 case PWM_HASH_SHA1: { 679 case PWM_HASH_SHA1: {
680 const int hashlen = SHA1_HASH_LEN_BYTE; 680 const int hashlen = SHA1_HASH_LEN_BYTE;
681 Sha1 hash; 681 Sha1 hash;
682 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length()); 682 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length());
683 string ret = hash.sha1_read(); 683 string ret = hash.sha1_read();
684 if (f->writeBlock(ret.c_str(), hashlen) != hashlen) 684 if (f->writeBlock(ret.c_str(), hashlen) != hashlen)
685 return e_writeFile; 685 return e_writeFile;
686 break; 686 break;
687 } 687 }
688 case PWM_HASH_SHA256: 688 case PWM_HASH_SHA256:
689 /*... fall through */ 689 /*... fall through */
690 case PWM_HASH_SHA384: 690 case PWM_HASH_SHA384:
691 case PWM_HASH_SHA512: 691 case PWM_HASH_SHA512:
692 case PWM_HASH_MD5: 692 case PWM_HASH_MD5:
693 case PWM_HASH_RMD160: 693 case PWM_HASH_RMD160:
694 case PWM_HASH_TIGER: 694 case PWM_HASH_TIGER:
695 { 695 {
696 if (!LibGCryptIf::available()) 696 if (!LibGCryptIf::available())
697 return e_hashNotImpl; 697 return e_hashNotImpl;
698 LibGCryptIf gc; 698 LibGCryptIf gc;
699 PwMerror err; 699 PwMerror err;
700 unsigned char *buf; 700 unsigned char *buf;
701 size_t hashLen; 701 size_t hashLen;
702 err = gc.hash(&buf, 702 err = gc.hash(&buf,
703 &hashLen, 703 &hashLen,
704 reinterpret_cast<const unsigned char *>(pw->latin1()), 704 reinterpret_cast<const unsigned char *>(pw->latin1()),
705 pw->length(), 705 pw->length(),
706 keyHash); 706 keyHash);
707 if (err != e_success) 707 if (err != e_success)
708 return e_hashNotImpl; 708 return e_hashNotImpl;
709 if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen) 709 if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen)
710 != static_cast<Q_LONG>(hashLen)) { 710 != static_cast<Q_LONG>(hashLen)) {
711 delete [] buf; 711 delete [] buf;
712 return e_hashNotImpl; 712 return e_hashNotImpl;
713 } 713 }
714 delete [] buf; 714 delete [] buf;
715 break; 715 break;
716 } 716 }
717 default: { 717 default: {
718 return e_hashNotImpl; 718 return e_hashNotImpl;
719 } } 719 } }
720 return e_success; 720 return e_success;
721} 721}
722 722
723PwMerror PwMDoc::checkHeader(char *cryptAlgo, QString *pw, char *compress, 723PwMerror PwMDoc::checkHeader(char *cryptAlgo, QString *pw, char *compress,
724 unsigned int *headerLength, char *dataHashType, 724 unsigned int *headerLength, char *dataHashType,
725 string *dataHash, QFile *f) 725 string *dataHash, QFile *f)
726{ 726{
727 PWM_ASSERT(cryptAlgo); 727 PWM_ASSERT(cryptAlgo);
728 PWM_ASSERT(pw); 728 PWM_ASSERT(pw);
729 PWM_ASSERT(headerLength); 729 PWM_ASSERT(headerLength);
730 PWM_ASSERT(dataHashType); 730 PWM_ASSERT(dataHashType);
731 PWM_ASSERT(dataHash); 731 PWM_ASSERT(dataHash);
732 PWM_ASSERT(f); 732 PWM_ASSERT(f);
733 int tmpRet; 733 int tmpRet;
734 // check "magic" header 734 // check "magic" header
735 const char magicHdr[] = FILE_ID_HEADER; 735 const char magicHdr[] = FILE_ID_HEADER;
736 const int hdrLen = array_size(magicHdr) - 1; 736 const int hdrLen = array_size(magicHdr) - 1;
737 char tmp[hdrLen]; 737 char tmp[hdrLen];
738 if (f->readBlock(tmp, hdrLen) != hdrLen) 738 if (f->readBlock(tmp, hdrLen) != hdrLen)
739 return e_readFile; 739 return e_readFile;
740 if (memcmp(tmp, magicHdr, hdrLen) != 0) 740 if (memcmp(tmp, magicHdr, hdrLen) != 0)
741 return e_fileFormat; 741 return e_fileFormat;
742 // read and check file ver 742 // read and check file ver
743 int fileV = f->getch(); 743 int fileV = f->getch();
744 if (fileV == -1) 744 if (fileV == -1)
745 return e_fileFormat; 745 return e_fileFormat;
746 if (fileV != PWM_FILE_VER) 746 if (fileV != PWM_FILE_VER)
747 return e_fileVer; 747 return e_fileVer;
748 // read hash hash type 748 // read hash hash type
749 int keyHash = f->getch(); 749 int keyHash = f->getch();
750 if (keyHash == -1) 750 if (keyHash == -1)
751 return e_fileFormat; 751 return e_fileFormat;
752 // read data hash type 752 // read data hash type
753 tmpRet = f->getch(); 753 tmpRet = f->getch();
754 if (tmpRet == -1) 754 if (tmpRet == -1)
755 return e_fileFormat; 755 return e_fileFormat;
756 *dataHashType = tmpRet; 756 *dataHashType = tmpRet;
757 // read crypt algo 757 // read crypt algo
758 tmpRet = f->getch(); 758 tmpRet = f->getch();
759 if (tmpRet == -1) 759 if (tmpRet == -1)
760 return e_fileFormat; 760 return e_fileFormat;
761 *cryptAlgo = tmpRet; 761 *cryptAlgo = tmpRet;
762 // get compression-algo 762 // get compression-algo
763 tmpRet = f->getch(); 763 tmpRet = f->getch();
764 if (tmpRet == -1) 764 if (tmpRet == -1)
765 return e_fileFormat; 765 return e_fileFormat;
766 *compress = tmpRet; 766 *compress = tmpRet;
767 // get the MPW-flag 767 // get the MPW-flag
768 int mpw_flag = f->getch(); 768 int mpw_flag = f->getch();
769 if (mpw_flag == -1) 769 if (mpw_flag == -1)
770 return e_fileFormat; 770 return e_fileFormat;
771 if (mpw_flag == 0x01) 771 if (mpw_flag == 0x01)
772 setDocStatFlag(DOC_STAT_USE_CHIPCARD); 772 setDocStatFlag(DOC_STAT_USE_CHIPCARD);
773 else 773 else
774 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); 774 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
775 // skip the "RESERVED"-bytes 775 // skip the "RESERVED"-bytes
776 if (!(f->at(f->at() + 64))) 776 if (!(f->at(f->at() + 64)))
777 return e_fileFormat; 777 return e_fileFormat;
778 778
779 *pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 779 *pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
780 if (*pw == "") { 780 if (*pw == "") {
781 /* the user didn't give a master-password 781 /* the user didn't give a master-password
782 * or didn't insert a chipcard 782 * or didn't insert a chipcard
783 */ 783 */
784 return e_noPw; 784 return e_noPw;
785 } 785 }
786 // verify key-hash 786 // verify key-hash
787 switch (keyHash) { 787 switch (keyHash) {
788 case PWM_HASH_SHA1: { 788 case PWM_HASH_SHA1: {
789 // read hash from header 789 // read hash from header
790 const int hashLen = SHA1_HASH_LEN_BYTE; 790 const int hashLen = SHA1_HASH_LEN_BYTE;
791 string readHash; 791 string readHash;
792 int i; 792 int i;
793 for (i = 0; i < hashLen; ++i) 793 for (i = 0; i < hashLen; ++i)
794 readHash.push_back(f->getch()); 794 readHash.push_back(f->getch());
795 Sha1 hash; 795 Sha1 hash;
796 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length()); 796 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length());
797 string ret = hash.sha1_read(); 797 string ret = hash.sha1_read();
798 if (ret != readHash) 798 if (ret != readHash)
799 return e_wrongPw;// hash doesn't match (wrong key) 799 return e_wrongPw;// hash doesn't match (wrong key)
800 break; 800 break;
801 } 801 }
802 case PWM_HASH_SHA256: 802 case PWM_HASH_SHA256:
803 /*... fall through */ 803 /*... fall through */
804 case PWM_HASH_SHA384: 804 case PWM_HASH_SHA384:
805 case PWM_HASH_SHA512: 805 case PWM_HASH_SHA512:
806 case PWM_HASH_MD5: 806 case PWM_HASH_MD5:
807 case PWM_HASH_RMD160: 807 case PWM_HASH_RMD160:
808 case PWM_HASH_TIGER: { 808 case PWM_HASH_TIGER: {
809 if (!LibGCryptIf::available()) 809 if (!LibGCryptIf::available())
810 return e_hashNotImpl; 810 return e_hashNotImpl;
811 LibGCryptIf gc; 811 LibGCryptIf gc;
812 PwMerror err; 812 PwMerror err;
813 unsigned char *buf; 813 unsigned char *buf;
814 size_t hashLen; 814 size_t hashLen;
815 err = gc.hash(&buf, 815 err = gc.hash(&buf,
816 &hashLen, 816 &hashLen,
817 reinterpret_cast<const unsigned char *>(pw->latin1()), 817 reinterpret_cast<const unsigned char *>(pw->latin1()),
818 pw->length(), 818 pw->length(),
819 keyHash); 819 keyHash);
820 if (err != e_success) 820 if (err != e_success)
821 return e_hashNotImpl; 821 return e_hashNotImpl;
822 string calcHash(reinterpret_cast<const char *>(buf), 822 string calcHash(reinterpret_cast<const char *>(buf),
823 static_cast<string::size_type>(hashLen)); 823 static_cast<string::size_type>(hashLen));
824 delete [] buf; 824 delete [] buf;
825 // read hash from header 825 // read hash from header
826 string readHash; 826 string readHash;
827 size_t i; 827 size_t i;
828 for (i = 0; i < hashLen; ++i) 828 for (i = 0; i < hashLen; ++i)
829 readHash.push_back(f->getch()); 829 readHash.push_back(f->getch());
830 if (calcHash != readHash) 830 if (calcHash != readHash)
831 return e_wrongPw;// hash doesn't match (wrong key) 831 return e_wrongPw;// hash doesn't match (wrong key)
832 break; 832 break;
833 } 833 }
834 default: { 834 default: {
835 return e_hashNotImpl; 835 return e_hashNotImpl;
836 } } 836 } }
837 // read the data-hash from the file 837 // read the data-hash from the file
838 unsigned int hashLen, i; 838 unsigned int hashLen, i;
839 switch (*dataHashType) { 839 switch (*dataHashType) {
840 case PWM_HASH_SHA1: 840 case PWM_HASH_SHA1:
841 hashLen = SHA1_HASH_LEN_BYTE; 841 hashLen = SHA1_HASH_LEN_BYTE;
842 break; 842 break;
843 case PWM_HASH_SHA256: 843 case PWM_HASH_SHA256:
844 /*... fall through */ 844 /*... fall through */
845 case PWM_HASH_SHA384: 845 case PWM_HASH_SHA384:
846 case PWM_HASH_SHA512: 846 case PWM_HASH_SHA512:
847 case PWM_HASH_MD5: 847 case PWM_HASH_MD5:
848 case PWM_HASH_RMD160: 848 case PWM_HASH_RMD160:
849 case PWM_HASH_TIGER: { 849 case PWM_HASH_TIGER: {
850 if (!LibGCryptIf::available()) 850 if (!LibGCryptIf::available())
851 return e_hashNotImpl; 851 return e_hashNotImpl;
852 LibGCryptIf gc; 852 LibGCryptIf gc;
853 hashLen = gc.hashLength(*dataHashType); 853 hashLen = gc.hashLength(*dataHashType);
854 if (hashLen == 0) 854 if (hashLen == 0)
855 return e_hashNotImpl; 855 return e_hashNotImpl;
856 break; 856 break;
857 } 857 }
858 default: 858 default:
859 return e_hashNotImpl; 859 return e_hashNotImpl;
860 } 860 }
861 *dataHash = ""; 861 *dataHash = "";
862 for (i = 0; i < hashLen; ++i) { 862 for (i = 0; i < hashLen; ++i) {
863 tmpRet = f->getch(); 863 tmpRet = f->getch();
864 if (tmpRet == -1) 864 if (tmpRet == -1)
865 return e_fileFormat; 865 return e_fileFormat;
866 dataHash->push_back(static_cast<char>(tmpRet)); 866 dataHash->push_back(static_cast<char>(tmpRet));
@@ -1054,629 +1054,637 @@ PwMerror PwMDoc::addCategory(const QString &category, unsigned int *categoryInde
1054 PwMCategoryItem item; 1054 PwMCategoryItem item;
1055 //US ENH: clear item to initialize with default values, or create a constructor 1055 //US ENH: clear item to initialize with default values, or create a constructor
1056 item.clear(); 1056 item.clear();
1057 1057
1058 item.name = category.latin1(); 1058 item.name = category.latin1();
1059 dti.dta.push_back(item); 1059 dti.dta.push_back(item);
1060 if (categoryIndex) 1060 if (categoryIndex)
1061 *categoryIndex = dti.dta.size() - 1; 1061 *categoryIndex = dti.dta.size() - 1;
1062 return e_success; 1062 return e_success;
1063} 1063}
1064 1064
1065bool PwMDoc::delEntry(const QString &category, unsigned int index, bool dontFlagDirty) 1065bool PwMDoc::delEntry(const QString &category, unsigned int index, bool dontFlagDirty)
1066{ 1066{
1067 unsigned int cat = 0; 1067 unsigned int cat = 0;
1068 1068
1069 if (!findCategory(category, &cat)) { 1069 if (!findCategory(category, &cat)) {
1070 BUG(); 1070 BUG();
1071 return false; 1071 return false;
1072 } 1072 }
1073 1073
1074 return delEntry(cat, index, dontFlagDirty); 1074 return delEntry(cat, index, dontFlagDirty);
1075} 1075}
1076 1076
1077bool PwMDoc::delEntry(unsigned int category, unsigned int index, bool dontFlagDirty) 1077bool PwMDoc::delEntry(unsigned int category, unsigned int index, bool dontFlagDirty)
1078{ 1078{
1079 if (isDeepLocked()) 1079 if (isDeepLocked())
1080 return false; 1080 return false;
1081 if (index > dti.dta[category].d.size() - 1) 1081 if (index > dti.dta[category].d.size() - 1)
1082 return false; 1082 return false;
1083 getDataChangedLock(); 1083 getDataChangedLock();
1084 if (!lockAt(category, index, false)) { 1084 if (!lockAt(category, index, false)) {
1085 putDataChangedLock(); 1085 putDataChangedLock();
1086 return false; 1086 return false;
1087 } 1087 }
1088 putDataChangedLock(); 1088 putDataChangedLock();
1089 int lvPos = dti.dta[category].d[index].listViewPos; 1089 int lvPos = dti.dta[category].d[index].listViewPos;
1090 1090
1091 // delete entry 1091 // delete entry
1092 dti.dta[category].d.erase(dti.dta[category].d.begin() + index); 1092 dti.dta[category].d.erase(dti.dta[category].d.begin() + index);
1093 1093
1094 unsigned int i, entries = numEntries(category); 1094 unsigned int i, entries = numEntries(category);
1095 if (!entries) { 1095 if (!entries) {
1096 // no more entries in this category, so 1096 // no more entries in this category, so
1097 // we can delete it, too. 1097 // we can delete it, too.
1098 BUG_ON(!delCategory(category)); 1098 BUG_ON(!delCategory(category));
1099 // delCategory() flags it dirty, so we need not to do so. 1099 // delCategory() flags it dirty, so we need not to do so.
1100 return true; 1100 return true;
1101 } 1101 }
1102 for (i = 0; i < entries; ++i) { 1102 for (i = 0; i < entries; ++i) {
1103 // decrement all listViewPositions that are greater than the deleted. 1103 // decrement all listViewPositions that are greater than the deleted.
1104 if (dti.dta[category].d[i].listViewPos > lvPos) 1104 if (dti.dta[category].d[i].listViewPos > lvPos)
1105 --dti.dta[category].d[i].listViewPos; 1105 --dti.dta[category].d[i].listViewPos;
1106 } 1106 }
1107 1107
1108 if (!dontFlagDirty) 1108 if (!dontFlagDirty)
1109 flagDirty(); 1109 flagDirty();
1110 return true; 1110 return true;
1111} 1111}
1112 1112
1113bool PwMDoc::editEntry(const QString &oldCategory, const QString &newCategory, 1113bool PwMDoc::editEntry(const QString &oldCategory, const QString &newCategory,
1114 unsigned int index, PwMDataItem *d, bool updateMeta) 1114 unsigned int index, PwMDataItem *d, bool updateMeta)
1115{ 1115{
1116 PWM_ASSERT(d); 1116 PWM_ASSERT(d);
1117 unsigned int oldCat = 0; 1117 unsigned int oldCat = 0;
1118 1118
1119 if (!findCategory(oldCategory, &oldCat)) { 1119 if (!findCategory(oldCategory, &oldCat)) {
1120 BUG(); 1120 BUG();
1121 return false; 1121 return false;
1122 } 1122 }
1123 1123
1124 return editEntry(oldCat, newCategory, index, d, updateMeta); 1124 return editEntry(oldCat, newCategory, index, d, updateMeta);
1125} 1125}
1126 1126
1127bool PwMDoc::editEntry(unsigned int oldCategory, const QString &newCategory, 1127bool PwMDoc::editEntry(unsigned int oldCategory, const QString &newCategory,
1128 unsigned int index, PwMDataItem *d, bool updateMeta) 1128 unsigned int index, PwMDataItem *d, bool updateMeta)
1129{ 1129{
1130 if (isDeepLocked()) 1130 if (isDeepLocked())
1131 return false; 1131 return false;
1132 if (updateMeta) { 1132 if (updateMeta) {
1133 d->meta.update = QDateTime::currentDateTime(); 1133 d->meta.update = QDateTime::currentDateTime();
1134 if (d->meta.create.isNull()) { 1134 if (d->meta.create.isNull()) {
1135 d->meta.create = d->meta.update; 1135 d->meta.create = d->meta.update;
1136 } 1136 }
1137 } 1137 }
1138 if (dti.dta[oldCategory].name != newCategory.latin1()) { 1138 if (dti.dta[oldCategory].name != newCategory.latin1()) {
1139 // the user changed the category. 1139 // the user changed the category.
1140 PwMerror ret; 1140 PwMerror ret;
1141 d->rev = 0; 1141 d->rev = 0;
1142 ret = addEntry(newCategory, d, true, false); 1142 ret = addEntry(newCategory, d, true, false);
1143 if (ret != e_success) 1143 if (ret != e_success)
1144 return false; 1144 return false;
1145 if (!delEntry(oldCategory, index, true)) 1145 if (!delEntry(oldCategory, index, true))
1146 return false; 1146 return false;
1147 } else { 1147 } else {
1148 d->rev = dti.dta[oldCategory].d[index].rev + 1; // increment revision counter. 1148 d->rev = dti.dta[oldCategory].d[index].rev + 1; // increment revision counter.
1149 dti.dta[oldCategory].d[index] = *d; 1149 dti.dta[oldCategory].d[index] = *d;
1150 } 1150 }
1151 flagDirty(); 1151 flagDirty();
1152 return true; 1152 return true;
1153} 1153}
1154 1154
1155unsigned int PwMDoc::numEntries(const QString &category) 1155unsigned int PwMDoc::numEntries(const QString &category)
1156{ 1156{
1157 unsigned int cat = 0; 1157 unsigned int cat = 0;
1158 1158
1159 if (!findCategory(category, &cat)) { 1159 if (!findCategory(category, &cat)) {
1160 BUG(); 1160 BUG();
1161 return 0; 1161 return 0;
1162 } 1162 }
1163 1163
1164 return numEntries(cat); 1164 return numEntries(cat);
1165} 1165}
1166 1166
1167bool PwMDoc::serializeDta(string *d) 1167bool PwMDoc::serializeDta(string *d)
1168{ 1168{
1169 PWM_ASSERT(d); 1169 PWM_ASSERT(d);
1170 Serializer ser; 1170 Serializer ser;
1171 if (!ser.serialize(dti)) 1171 if (!ser.serialize(dti))
1172 return false; 1172 return false;
1173 d->assign(ser.getXml()); 1173 d->assign(ser.getXml());
1174 if (!d->size()) 1174 if (!d->size())
1175 return false; 1175 return false;
1176 return true; 1176 return true;
1177} 1177}
1178 1178
1179bool PwMDoc::deSerializeDta(const string *d, bool entriesLocked) 1179bool PwMDoc::deSerializeDta(const string *d, bool entriesLocked)
1180{ 1180{
1181 PWM_ASSERT(d); 1181 PWM_ASSERT(d);
1182#ifndef PWM_EMBEDDED 1182#ifndef PWM_EMBEDDED
1183 try { 1183 try {
1184 1184
1185 Serializer ser(d->c_str()); 1185 Serializer ser(d->c_str());
1186 ser.setDefaultLockStat(entriesLocked); 1186 ser.setDefaultLockStat(entriesLocked);
1187 if (!ser.deSerialize(&dti)) 1187 if (!ser.deSerialize(&dti))
1188 return false; 1188 return false;
1189 } catch (PwMException) { 1189 } catch (PwMException) {
1190 return false; 1190 return false;
1191 } 1191 }
1192#else 1192#else
1193 Serializer ser(d->c_str()); 1193 Serializer ser(d->c_str());
1194 ser.setDefaultLockStat(entriesLocked); 1194 ser.setDefaultLockStat(entriesLocked);
1195 if (!ser.deSerialize(&dti)) 1195 if (!ser.deSerialize(&dti))
1196 return false; 1196 return false;
1197#endif 1197#endif
1198 1198
1199 emitDataChanged(this); 1199 emitDataChanged(this);
1200 return true; 1200 return true;
1201} 1201}
1202 1202
1203bool PwMDoc::getEntry(const QString &category, unsigned int index, 1203bool PwMDoc::getEntry(const QString &category, unsigned int index,
1204 PwMDataItem * d, bool unlockIfLocked) 1204 PwMDataItem * d, bool unlockIfLocked)
1205{ 1205{
1206 PWM_ASSERT(d); 1206 PWM_ASSERT(d);
1207 unsigned int cat = 0; 1207 unsigned int cat = 0;
1208 1208
1209 if (!findCategory(category, &cat)) { 1209 if (!findCategory(category, &cat)) {
1210 BUG(); 1210 BUG();
1211 return false; 1211 return false;
1212 } 1212 }
1213 1213
1214 return getEntry(cat, index, d, unlockIfLocked); 1214 return getEntry(cat, index, d, unlockIfLocked);
1215} 1215}
1216 1216
1217bool PwMDoc::getEntry(unsigned int category, unsigned int index, 1217bool PwMDoc::getEntry(unsigned int category, unsigned int index,
1218 PwMDataItem *d, bool unlockIfLocked) 1218 PwMDataItem *d, bool unlockIfLocked)
1219{ 1219{
1220 if (index > dti.dta[category].d.size() - 1) 1220 if (index > dti.dta[category].d.size() - 1)
1221 return false; 1221 return false;
1222 1222
1223 bool locked = isLocked(category, index); 1223 bool locked = isLocked(category, index);
1224 if (locked) { 1224 if (locked) {
1225 /* this entry is locked. We don't return a password, 1225 /* this entry is locked. We don't return a password,
1226 * until it's unlocked by the user by inserting 1226 * until it's unlocked by the user by inserting
1227 * chipcard or entering the mpw 1227 * chipcard or entering the mpw
1228 */ 1228 */
1229 if (unlockIfLocked) { 1229 if (unlockIfLocked) {
1230 if (!lockAt(category, index, false)) { 1230 if (!lockAt(category, index, false)) {
1231 return false; 1231 return false;
1232 } 1232 }
1233 locked = false; 1233 locked = false;
1234 } 1234 }
1235 } 1235 }
1236 1236
1237 *d = dti.dta[category].d[index]; 1237 *d = dti.dta[category].d[index];
1238 if (locked) 1238 if (locked)
1239 d->pw = LOCKED_STRING.latin1(); 1239 d->pw = LOCKED_STRING.latin1();
1240 1240
1241 return true; 1241 return true;
1242} 1242}
1243 1243
1244PwMerror PwMDoc::getCommentByLvp(const QString &category, int listViewPos, 1244PwMerror PwMDoc::getCommentByLvp(const QString &category, int listViewPos,
1245 string *foundComment) 1245 string *foundComment)
1246{ 1246{
1247 PWM_ASSERT(foundComment); 1247 PWM_ASSERT(foundComment);
1248 unsigned int cat = 0; 1248 unsigned int cat = 0;
1249 1249
1250 if (!findCategory(category, &cat)) 1250 if (!findCategory(category, &cat))
1251 return e_invalidArg; 1251 return e_invalidArg;
1252 1252
1253 unsigned int i, entries = numEntries(cat); 1253 unsigned int i, entries = numEntries(cat);
1254 for (i = 0; i < entries; ++i) { 1254 for (i = 0; i < entries; ++i) {
1255 if (dti.dta[cat].d[i].listViewPos == listViewPos) { 1255 if (dti.dta[cat].d[i].listViewPos == listViewPos) {
1256 *foundComment = dti.dta[cat].d[i].comment; 1256 *foundComment = dti.dta[cat].d[i].comment;
1257 if (dti.dta[cat].d[i].binary) 1257 if (dti.dta[cat].d[i].binary)
1258 return e_binEntry; 1258 return e_binEntry;
1259 return e_normalEntry; 1259 return e_normalEntry;
1260 } 1260 }
1261 } 1261 }
1262 BUG(); 1262 BUG();
1263 return e_generic; 1263 return e_generic;
1264} 1264}
1265 1265
1266bool PwMDoc::compressDta(string *d, char algo) 1266bool PwMDoc::compressDta(string *d, char algo)
1267{ 1267{
1268 PWM_ASSERT(d); 1268 PWM_ASSERT(d);
1269 switch (algo) { 1269 switch (algo) {
1270 case PWM_COMPRESS_GZIP: { 1270 case PWM_COMPRESS_GZIP: {
1271 CompressGzip comp; 1271 CompressGzip comp;
1272 return comp.compress(d); 1272 return comp.compress(d);
1273 } 1273 }
1274#ifndef PWM_EMBEDDED 1274#ifndef PWM_EMBEDDED
1275 case PWM_COMPRESS_BZIP2: { 1275 case PWM_COMPRESS_BZIP2: {
1276 CompressBzip2 comp; 1276 CompressBzip2 comp;
1277 return comp.compress(d); 1277 return comp.compress(d);
1278 } 1278 }
1279#endif 1279#endif
1280 case PWM_COMPRESS_NONE: { 1280 case PWM_COMPRESS_NONE: {
1281 return true; 1281 return true;
1282 } default: { 1282 } default: {
1283 BUG(); 1283 BUG();
1284 } 1284 }
1285 } 1285 }
1286 return false; 1286 return false;
1287} 1287}
1288 1288
1289bool PwMDoc::decompressDta(string *d, char algo) 1289bool PwMDoc::decompressDta(string *d, char algo)
1290{ 1290{
1291 PWM_ASSERT(d); 1291 PWM_ASSERT(d);
1292 switch (algo) { 1292 switch (algo) {
1293 case PWM_COMPRESS_GZIP: { 1293 case PWM_COMPRESS_GZIP: {
1294 CompressGzip comp; 1294 CompressGzip comp;
1295 return comp.decompress(d); 1295 return comp.decompress(d);
1296 } 1296 }
1297#ifndef PWM_EMBEDDED 1297#ifndef PWM_EMBEDDED
1298 case PWM_COMPRESS_BZIP2: { 1298 case PWM_COMPRESS_BZIP2: {
1299 CompressBzip2 comp; 1299 CompressBzip2 comp;
1300 return comp.decompress(d); 1300 return comp.decompress(d);
1301 } 1301 }
1302#endif 1302#endif
1303 case PWM_COMPRESS_NONE: { 1303 case PWM_COMPRESS_NONE: {
1304 return true; 1304 return true;
1305 } 1305 }
1306 } 1306 }
1307 return false; 1307 return false;
1308} 1308}
1309 1309
1310PwMerror PwMDoc::encrypt(string *d, const QString *pw, QFile *f, char algo) 1310PwMerror PwMDoc::encrypt(string *d, const QString *pw, QFile *f, char algo,
1311 char hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
1312)
1311{ 1313{
1312 PWM_ASSERT(d); 1314 PWM_ASSERT(d);
1313 PWM_ASSERT(pw); 1315 PWM_ASSERT(pw);
1314 PWM_ASSERT(f); 1316 PWM_ASSERT(f);
1315 1317
1316 size_t encSize; 1318 size_t encSize;
1317 byte *encrypted = 0; 1319 byte *encrypted = 0;
1318 1320
1319 switch (algo) { 1321 switch (algo) {
1320 case PWM_CRYPT_BLOWFISH: { 1322 case PWM_CRYPT_BLOWFISH: {
1321 Blowfish::padNull(d); 1323 Blowfish::padNull(d);
1322 encSize = d->length(); 1324 encSize = d->length();
1323 encrypted = new byte[encSize]; 1325 encrypted = new byte[encSize];
1324 Blowfish bf; 1326 Blowfish bf;
1325 if (bf.bf_setkey((byte *) pw->latin1(), pw->length())) { 1327 if (bf.bf_setkey((byte *) pw->latin1(), pw->length())) {
1326 delete [] encrypted; 1328 delete [] encrypted;
1327 return e_weakPw; 1329 return e_weakPw;
1328 } 1330 }
1329 bf.bf_encrypt((byte *) encrypted, (byte *) d->c_str(), encSize); 1331 bf.bf_encrypt((byte *) encrypted, (byte *) d->c_str(), encSize);
1330 break; 1332 break;
1331 } 1333 }
1332 case PWM_CRYPT_AES128: 1334 case PWM_CRYPT_AES128:
1333 /*... fall through */ 1335 /*... fall through */
1334 case PWM_CRYPT_AES192: 1336 case PWM_CRYPT_AES192:
1335 case PWM_CRYPT_AES256: 1337 case PWM_CRYPT_AES256:
1336 case PWM_CRYPT_3DES: 1338 case PWM_CRYPT_3DES:
1337 case PWM_CRYPT_TWOFISH: 1339 case PWM_CRYPT_TWOFISH:
1338 case PWM_CRYPT_TWOFISH128: { 1340 case PWM_CRYPT_TWOFISH128: {
1339 if (!LibGCryptIf::available()) 1341 if (!LibGCryptIf::available())
1340 return e_cryptNotImpl; 1342 return e_cryptNotImpl;
1341 LibGCryptIf gc; 1343 LibGCryptIf gc;
1342 PwMerror err; 1344 PwMerror err;
1343 unsigned char *plain = new unsigned char[d->length() + 1024]; 1345 unsigned char *plain = new unsigned char[d->length() + 1024];
1344 memcpy(plain, d->c_str(), d->length()); 1346 memcpy(plain, d->c_str(), d->length());
1345 err = gc.encrypt(&encrypted, 1347 err = gc.encrypt(&encrypted,
1346 &encSize, 1348 &encSize,
1347 plain, 1349 plain,
1348 d->length(), 1350 d->length(),
1349 reinterpret_cast<const unsigned char *>(pw->latin1()), 1351 reinterpret_cast<const unsigned char *>(pw->latin1()),
1350 pw->length(), 1352 pw->length(),
1351 algo); 1353 algo,
1354 hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
1355 );
1352 delete [] plain; 1356 delete [] plain;
1353 if (err != e_success) 1357 if (err != e_success)
1354 return e_cryptNotImpl; 1358 return e_cryptNotImpl;
1355 break; 1359 break;
1356 } 1360 }
1357 default: { 1361 default: {
1358 delete_ifnot_null_array(encrypted); 1362 delete_ifnot_null_array(encrypted);
1359 return e_cryptNotImpl; 1363 return e_cryptNotImpl;
1360 } } 1364 } }
1361 1365
1362 // write encrypted data to file 1366 // write encrypted data to file
1363 if (f->writeBlock(reinterpret_cast<const char *>(encrypted), 1367 if (f->writeBlock(reinterpret_cast<const char *>(encrypted),
1364 static_cast<Q_ULONG>(encSize)) 1368 static_cast<Q_ULONG>(encSize))
1365 != static_cast<Q_LONG>(encSize)) { 1369 != static_cast<Q_LONG>(encSize)) {
1366 delete_ifnot_null_array(encrypted); 1370 delete_ifnot_null_array(encrypted);
1367 return e_writeFile; 1371 return e_writeFile;
1368 } 1372 }
1369 delete_ifnot_null_array(encrypted); 1373 delete_ifnot_null_array(encrypted);
1370 return e_success; 1374 return e_success;
1371} 1375}
1372 1376
1373PwMerror PwMDoc::decrypt(string *d, unsigned int pos, const QString *pw, 1377PwMerror PwMDoc::decrypt(string *d, unsigned int pos, const QString *pw,
1374 char algo, QFile *f) 1378 char algo,
1379 char hashalgo, //US BUG: pass _hashalgo because we need it in hashPassphrase
1380 QFile *f)
1375{ 1381{
1376 PWM_ASSERT(d); 1382 PWM_ASSERT(d);
1377 PWM_ASSERT(pw); 1383 PWM_ASSERT(pw);
1378 PWM_ASSERT(f); 1384 PWM_ASSERT(f);
1379 1385
1380 unsigned int cryptLen = f->size() - pos; 1386 unsigned int cryptLen = f->size() - pos;
1381 byte *encrypted = new byte[cryptLen]; 1387 byte *encrypted = new byte[cryptLen];
1382 byte *decrypted = new byte[cryptLen]; 1388 byte *decrypted = new byte[cryptLen];
1383 1389
1384 f->at(pos); 1390 f->at(pos);
1385#ifndef PWM_EMBEDDED 1391#ifndef PWM_EMBEDDED
1386 if (f->readBlock(reinterpret_cast<char *>(encrypted), 1392 if (f->readBlock(reinterpret_cast<char *>(encrypted),
1387 static_cast<Q_ULONG>(cryptLen)) 1393 static_cast<Q_ULONG>(cryptLen))
1388 != static_cast<Q_LONG>(cryptLen)) { 1394 != static_cast<Q_LONG>(cryptLen)) {
1389 delete [] encrypted; 1395 delete [] encrypted;
1390 delete [] decrypted; 1396 delete [] decrypted;
1391 return e_readFile; 1397 return e_readFile;
1392 } 1398 }
1393#else 1399#else
1394 if (f->readBlock((char *)(encrypted), 1400 if (f->readBlock((char *)(encrypted),
1395 (unsigned long)(cryptLen)) 1401 (unsigned long)(cryptLen))
1396 != (long)(cryptLen)) { 1402 != (long)(cryptLen)) {
1397 delete [] encrypted; 1403 delete [] encrypted;
1398 delete [] decrypted; 1404 delete [] decrypted;
1399 return e_readFile; 1405 return e_readFile;
1400 } 1406 }
1401#endif 1407#endif
1402 switch (algo) { 1408 switch (algo) {
1403 case PWM_CRYPT_BLOWFISH: { 1409 case PWM_CRYPT_BLOWFISH: {
1404 Blowfish bf; 1410 Blowfish bf;
1405 bf.bf_setkey((byte *) pw->latin1(), pw->length()); 1411 bf.bf_setkey((byte *) pw->latin1(), pw->length());
1406 bf.bf_decrypt(decrypted, encrypted, cryptLen); 1412 bf.bf_decrypt(decrypted, encrypted, cryptLen);
1407 break; 1413 break;
1408 } 1414 }
1409 case PWM_CRYPT_AES128: 1415 case PWM_CRYPT_AES128:
1410 /*... fall through */ 1416 /*... fall through */
1411 case PWM_CRYPT_AES192: 1417 case PWM_CRYPT_AES192:
1412 case PWM_CRYPT_AES256: 1418 case PWM_CRYPT_AES256:
1413 case PWM_CRYPT_3DES: 1419 case PWM_CRYPT_3DES:
1414 case PWM_CRYPT_TWOFISH: 1420 case PWM_CRYPT_TWOFISH:
1415 case PWM_CRYPT_TWOFISH128: { 1421 case PWM_CRYPT_TWOFISH128: {
1416 if (!LibGCryptIf::available()) 1422 if (!LibGCryptIf::available())
1417 return e_cryptNotImpl; 1423 return e_cryptNotImpl;
1418 LibGCryptIf gc; 1424 LibGCryptIf gc;
1419 PwMerror err; 1425 PwMerror err;
1420 err = gc.decrypt(&decrypted, 1426 err = gc.decrypt(&decrypted,
1421 &cryptLen, 1427 &cryptLen,
1422 encrypted, 1428 encrypted,
1423 cryptLen, 1429 cryptLen,
1424 reinterpret_cast<const unsigned char *>(pw->latin1()), 1430 reinterpret_cast<const unsigned char *>(pw->latin1()),
1425 pw->length(), 1431 pw->length(),
1426 algo); 1432 algo,
1433 hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
1434);
1427 if (err != e_success) { 1435 if (err != e_success) {
1428 delete [] encrypted; 1436 delete [] encrypted;
1429 delete [] decrypted; 1437 delete [] decrypted;
1430 return e_cryptNotImpl; 1438 return e_cryptNotImpl;
1431 } 1439 }
1432 break; 1440 break;
1433 } 1441 }
1434 default: { 1442 default: {
1435 delete [] encrypted; 1443 delete [] encrypted;
1436 delete [] decrypted; 1444 delete [] decrypted;
1437 return e_cryptNotImpl; 1445 return e_cryptNotImpl;
1438 } } 1446 } }
1439 delete [] encrypted; 1447 delete [] encrypted;
1440#ifndef PWM_EMBEDDED 1448#ifndef PWM_EMBEDDED
1441 d->assign(reinterpret_cast<const char *>(decrypted), 1449 d->assign(reinterpret_cast<const char *>(decrypted),
1442 static_cast<string::size_type>(cryptLen)); 1450 static_cast<string::size_type>(cryptLen));
1443#else 1451#else
1444 d->assign((const char *)(decrypted), 1452 d->assign((const char *)(decrypted),
1445 (string::size_type)(cryptLen)); 1453 (string::size_type)(cryptLen));
1446#endif 1454#endif
1447 delete [] decrypted; 1455 delete [] decrypted;
1448 if (algo == PWM_CRYPT_BLOWFISH) { 1456 if (algo == PWM_CRYPT_BLOWFISH) {
1449 if (!Blowfish::unpadNull(d)) { 1457 if (!Blowfish::unpadNull(d)) {
1450 BUG(); 1458 BUG();
1451 return e_readFile; 1459 return e_readFile;
1452 } 1460 }
1453 } 1461 }
1454 return e_success; 1462 return e_success;
1455} 1463}
1456 1464
1457PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash, 1465PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash,
1458 const string *dataStream) 1466 const string *dataStream)
1459{ 1467{
1460 PWM_ASSERT(dataHash); 1468 PWM_ASSERT(dataHash);
1461 PWM_ASSERT(dataStream); 1469 PWM_ASSERT(dataStream);
1462 switch(dataHashType) { 1470 switch(dataHashType) {
1463 case PWM_HASH_SHA1: { 1471 case PWM_HASH_SHA1: {
1464 Sha1 hash; 1472 Sha1 hash;
1465 hash.sha1_write((byte*)dataStream->c_str(), dataStream->length()); 1473 hash.sha1_write((byte*)dataStream->c_str(), dataStream->length());
1466 string ret = hash.sha1_read(); 1474 string ret = hash.sha1_read();
1467 if (ret != *dataHash) 1475 if (ret != *dataHash)
1468 return e_fileCorrupt; 1476 return e_fileCorrupt;
1469 break; 1477 break;
1470 } 1478 }
1471 case PWM_HASH_SHA256: 1479 case PWM_HASH_SHA256:
1472 /*... fall through */ 1480 /*... fall through */
1473 case PWM_HASH_SHA384: 1481 case PWM_HASH_SHA384:
1474 case PWM_HASH_SHA512: 1482 case PWM_HASH_SHA512:
1475 case PWM_HASH_MD5: 1483 case PWM_HASH_MD5:
1476 case PWM_HASH_RMD160: 1484 case PWM_HASH_RMD160:
1477 case PWM_HASH_TIGER: { 1485 case PWM_HASH_TIGER: {
1478 if (!LibGCryptIf::available()) 1486 if (!LibGCryptIf::available())
1479 return e_hashNotImpl; 1487 return e_hashNotImpl;
1480 LibGCryptIf gc; 1488 LibGCryptIf gc;
1481 PwMerror err; 1489 PwMerror err;
1482 unsigned char *buf; 1490 unsigned char *buf;
1483 size_t hashLen; 1491 size_t hashLen;
1484 err = gc.hash(&buf, 1492 err = gc.hash(&buf,
1485 &hashLen, 1493 &hashLen,
1486 reinterpret_cast<const unsigned char *>(dataStream->c_str()), 1494 reinterpret_cast<const unsigned char *>(dataStream->c_str()),
1487 dataStream->length(), 1495 dataStream->length(),
1488 dataHashType); 1496 dataHashType);
1489 if (err != e_success) 1497 if (err != e_success)
1490 return e_hashNotImpl; 1498 return e_hashNotImpl;
1491 string calcHash(reinterpret_cast<const char *>(buf), 1499 string calcHash(reinterpret_cast<const char *>(buf),
1492 static_cast<string::size_type>(hashLen)); 1500 static_cast<string::size_type>(hashLen));
1493 delete [] buf; 1501 delete [] buf;
1494 if (calcHash != *dataHash) 1502 if (calcHash != *dataHash)
1495 return e_fileCorrupt; 1503 return e_fileCorrupt;
1496 break; 1504 break;
1497 } 1505 }
1498 default: 1506 default:
1499 return e_hashNotImpl; 1507 return e_hashNotImpl;
1500 } 1508 }
1501 return e_success; 1509 return e_success;
1502} 1510}
1503 1511
1504bool PwMDoc::lockAt(unsigned int category, unsigned int index, 1512bool PwMDoc::lockAt(unsigned int category, unsigned int index,
1505 bool lock) 1513 bool lock)
1506{ 1514{
1507 if (index >= numEntries(category)) { 1515 if (index >= numEntries(category)) {
1508 BUG(); 1516 BUG();
1509 return false; 1517 return false;
1510 } 1518 }
1511 if (lock == dti.dta[category].d[index].lockStat) 1519 if (lock == dti.dta[category].d[index].lockStat)
1512 return true; 1520 return true;
1513 1521
1514 if (!lock && currentPw != "") { 1522 if (!lock && currentPw != "") {
1515 // "unlocking" and "password is already set" 1523 // "unlocking" and "password is already set"
1516 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) { 1524 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
1517 // unlocking without pw not allowed 1525 // unlocking without pw not allowed
1518 QString pw; 1526 QString pw;
1519 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1527 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1520 if (pw != "") { 1528 if (pw != "") {
1521 if (pw != currentPw) { 1529 if (pw != currentPw) {
1522 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1530 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1523 return false; 1531 return false;
1524 } else { 1532 } else {
1525 timer()->start(DocTimer::id_mpwTimer); 1533 timer()->start(DocTimer::id_mpwTimer);
1526 } 1534 }
1527 } else { 1535 } else {
1528 return false; 1536 return false;
1529 } 1537 }
1530 } else { 1538 } else {
1531 timer()->start(DocTimer::id_mpwTimer); 1539 timer()->start(DocTimer::id_mpwTimer);
1532 } 1540 }
1533 } 1541 }
1534 1542
1535 dti.dta[category].d[index].lockStat = lock; 1543 dti.dta[category].d[index].lockStat = lock;
1536 dti.dta[category].d[index].rev++; // increment revision counter. 1544 dti.dta[category].d[index].rev++; // increment revision counter.
1537 1545
1538 emitDataChanged(this); 1546 emitDataChanged(this);
1539 if (!lock) 1547 if (!lock)
1540 timer()->start(DocTimer::id_autoLockTimer); 1548 timer()->start(DocTimer::id_autoLockTimer);
1541 1549
1542 return true; 1550 return true;
1543 1551
1544} 1552}
1545 1553
1546bool PwMDoc::lockAt(const QString &category,unsigned int index, 1554bool PwMDoc::lockAt(const QString &category,unsigned int index,
1547 bool lock) 1555 bool lock)
1548{ 1556{
1549 unsigned int cat = 0; 1557 unsigned int cat = 0;
1550 1558
1551 if (!findCategory(category, &cat)) { 1559 if (!findCategory(category, &cat)) {
1552 BUG(); 1560 BUG();
1553 return false; 1561 return false;
1554 } 1562 }
1555 1563
1556 return lockAt(cat, index, lock); 1564 return lockAt(cat, index, lock);
1557} 1565}
1558 1566
1559bool PwMDoc::lockAll(bool lock) 1567bool PwMDoc::lockAll(bool lock)
1560{ 1568{
1561 if (!lock && isDeepLocked()) { 1569 if (!lock && isDeepLocked()) {
1562 PwMerror ret; 1570 PwMerror ret;
1563 ret = deepLock(false); 1571 ret = deepLock(false);
1564 if (ret != e_success) 1572 if (ret != e_success)
1565 return false; 1573 return false;
1566 return true; 1574 return true;
1567 } 1575 }
1568 if (isDocEmpty()) { 1576 if (isDocEmpty()) {
1569 return true; 1577 return true;
1570 } 1578 }
1571 if (!lock && currentPw != "") { 1579 if (!lock && currentPw != "") {
1572 // unlocking and password is already set 1580 // unlocking and password is already set
1573 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) { 1581 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
1574 // unlocking without pw not allowed 1582 // unlocking without pw not allowed
1575 QString pw; 1583 QString pw;
1576 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1584 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1577 if (pw != "") { 1585 if (pw != "") {
1578 if (pw != currentPw) { 1586 if (pw != currentPw) {
1579 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1587 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1580 return false; 1588 return false;
1581 } else { 1589 } else {
1582 timer()->start(DocTimer::id_mpwTimer); 1590 timer()->start(DocTimer::id_mpwTimer);
1583 } 1591 }
1584 } else { 1592 } else {
1585 return false; 1593 return false;
1586 } 1594 }
1587 } else { 1595 } else {
1588 timer()->start(DocTimer::id_mpwTimer); 1596 timer()->start(DocTimer::id_mpwTimer);
1589 } 1597 }
1590 } 1598 }
1591 1599
1592 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), 1600 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
1593 catEnd = dti.dta.end(), 1601 catEnd = dti.dta.end(),
1594 catI = catBegin; 1602 catI = catBegin;
1595 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; 1603 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
1596 while (catI != catEnd) { 1604 while (catI != catEnd) {
1597 entrBegin = catI->d.begin(); 1605 entrBegin = catI->d.begin();
1598 entrEnd = catI->d.end(); 1606 entrEnd = catI->d.end();
1599 entrI = entrBegin; 1607 entrI = entrBegin;
1600 while (entrI != entrEnd) { 1608 while (entrI != entrEnd) {
1601 entrI->lockStat = lock; 1609 entrI->lockStat = lock;
1602 entrI->rev++; // increment revision counter. 1610 entrI->rev++; // increment revision counter.
1603 ++entrI; 1611 ++entrI;
1604 } 1612 }
1605 ++catI; 1613 ++catI;
1606 } 1614 }
1607 1615
1608 emitDataChanged(this); 1616 emitDataChanged(this);
1609 if (lock) 1617 if (lock)
1610 timer()->stop(DocTimer::id_autoLockTimer); 1618 timer()->stop(DocTimer::id_autoLockTimer);
1611 else 1619 else
1612 timer()->start(DocTimer::id_autoLockTimer); 1620 timer()->start(DocTimer::id_autoLockTimer);
1613 1621
1614 return true; 1622 return true;
1615} 1623}
1616 1624
1617bool PwMDoc::isLocked(const QString &category, unsigned int index) 1625bool PwMDoc::isLocked(const QString &category, unsigned int index)
1618{ 1626{
1619 unsigned int cat = 0; 1627 unsigned int cat = 0;
1620 1628
1621 if (!findCategory(category, &cat)) { 1629 if (!findCategory(category, &cat)) {
1622 BUG(); 1630 BUG();
1623 return false; 1631 return false;
1624 } 1632 }
1625 1633
1626 return isLocked(cat, index); 1634 return isLocked(cat, index);
1627} 1635}
1628 1636
1629bool PwMDoc::unlockAll_tempoary(bool revert) 1637bool PwMDoc::unlockAll_tempoary(bool revert)
1630{ 1638{
1631 static vector< vector<bool> > *oldLockStates = 0; 1639 static vector< vector<bool> > *oldLockStates = 0;
1632 static bool wasDeepLocked; 1640 static bool wasDeepLocked;
1633 1641
1634 if (revert) {// revert the unlocking 1642 if (revert) {// revert the unlocking
1635 if (oldLockStates) { 1643 if (oldLockStates) {
1636 /* we actually _have_ unlocked something, because 1644 /* we actually _have_ unlocked something, because
1637 * we have allocated space for the oldLockStates. 1645 * we have allocated space for the oldLockStates.
1638 * So, go on and revert them! 1646 * So, go on and revert them!
1639 */ 1647 */
1640 if (wasDeepLocked) { 1648 if (wasDeepLocked) {
1641 PwMerror ret = deepLock(true); 1649 PwMerror ret = deepLock(true);
1642 if (ret == e_success) { 1650 if (ret == e_success) {
1643 /* deep-lock succeed. We are save. 1651 /* deep-lock succeed. We are save.
1644 * (but if it failed, just go on 1652 * (but if it failed, just go on
1645 * lock them normally) 1653 * lock them normally)
1646 */ 1654 */
1647 delete_and_null(oldLockStates); 1655 delete_and_null(oldLockStates);
1648 timer()->start(DocTimer::id_autoLockTimer); 1656 timer()->start(DocTimer::id_autoLockTimer);
1649 printDebug("tempoary unlocking of dta " 1657 printDebug("tempoary unlocking of dta "
1650 "reverted by deep-locking."); 1658 "reverted by deep-locking.");
1651 return true; 1659 return true;
1652 } 1660 }
1653 printDebug("deep-lock failed while reverting! " 1661 printDebug("deep-lock failed while reverting! "
1654 "Falling back to normal-lock."); 1662 "Falling back to normal-lock.");
1655 } 1663 }
1656 if (unlikely(!wasDeepLocked && 1664 if (unlikely(!wasDeepLocked &&
1657 numCategories() != oldLockStates->size())) { 1665 numCategories() != oldLockStates->size())) {
1658 /* DOH! We have modified "dta" while 1666 /* DOH! We have modified "dta" while
1659 * it was unlocked tempoary. DON'T DO THIS! 1667 * it was unlocked tempoary. DON'T DO THIS!
1660 */ 1668 */
1661 BUG(); 1669 BUG();
1662 delete_and_null(oldLockStates); 1670 delete_and_null(oldLockStates);
1663 timer()->start(DocTimer::id_autoLockTimer); 1671 timer()->start(DocTimer::id_autoLockTimer);
1664 return false; 1672 return false;
1665 } 1673 }
1666 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), 1674 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
1667 catEnd = dti.dta.end(), 1675 catEnd = dti.dta.end(),
1668 catI = catBegin; 1676 catI = catBegin;
1669 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; 1677 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
1670 vector< vector<bool> >::iterator oldCatStatI = oldLockStates->begin(); 1678 vector< vector<bool> >::iterator oldCatStatI = oldLockStates->begin();
1671 vector<bool>::iterator oldEntrStatBegin, 1679 vector<bool>::iterator oldEntrStatBegin,
1672 oldEntrStatEnd, 1680 oldEntrStatEnd,
1673 oldEntrStatI; 1681 oldEntrStatI;
1674 while (catI != catEnd) { 1682 while (catI != catEnd) {
1675 entrBegin = catI->d.begin(); 1683 entrBegin = catI->d.begin();
1676 entrEnd = catI->d.end(); 1684 entrEnd = catI->d.end();
1677 entrI = entrBegin; 1685 entrI = entrBegin;
1678 if (likely(!wasDeepLocked)) { 1686 if (likely(!wasDeepLocked)) {
1679 oldEntrStatBegin = oldCatStatI->begin(); 1687 oldEntrStatBegin = oldCatStatI->begin();
1680 oldEntrStatEnd = oldCatStatI->end(); 1688 oldEntrStatEnd = oldCatStatI->end();
1681 oldEntrStatI = oldEntrStatBegin; 1689 oldEntrStatI = oldEntrStatBegin;
1682 if (unlikely(catI->d.size() != oldCatStatI->size())) { 1690 if (unlikely(catI->d.size() != oldCatStatI->size())) {
diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h
index 138dd3d..9fcdda7 100644
--- a/pwmanager/pwmanager/pwmdoc.h
+++ b/pwmanager/pwmanager/pwmdoc.h
@@ -483,345 +483,349 @@ public:
483 bool delEntry(const QString &category, unsigned int index, bool dontFlagDirty = false); 483 bool delEntry(const QString &category, unsigned int index, bool dontFlagDirty = false);
484 /** delete entry */ 484 /** delete entry */
485 bool delEntry(unsigned int category, unsigned int index, bool dontFlagDirty = false); 485 bool delEntry(unsigned int category, unsigned int index, bool dontFlagDirty = false);
486 /** edit entry */ 486 /** edit entry */
487 bool editEntry(const QString &oldCategory, const QString &newCategory, 487 bool editEntry(const QString &oldCategory, const QString &newCategory,
488 unsigned int index, PwMDataItem *d, bool updateMeta = true); 488 unsigned int index, PwMDataItem *d, bool updateMeta = true);
489 /** edit entry */ 489 /** edit entry */
490 bool editEntry(unsigned int oldCategory, const QString &newCategory, 490 bool editEntry(unsigned int oldCategory, const QString &newCategory,
491 unsigned int index, PwMDataItem *d, bool updateMeta = true); 491 unsigned int index, PwMDataItem *d, bool updateMeta = true);
492 /** finds the category with the "name" and return it's index */ 492 /** finds the category with the "name" and return it's index */
493 bool findCategory(const QString &name, unsigned int *index); 493 bool findCategory(const QString &name, unsigned int *index);
494 /** search for an entry "find" and check while searching only for 494 /** search for an entry "find" and check while searching only for
495 * the data-fields specified by "searchIn". To set the "searchIn" 495 * the data-fields specified by "searchIn". To set the "searchIn"
496 * value, we may use one or more of the SEARCH_IN_* defines at 496 * value, we may use one or more of the SEARCH_IN_* defines at
497 * the top of this header-file. It returns the positions of all 497 * the top of this header-file. It returns the positions of all
498 * matched entries in "foundPositions". If "breakAfterFound" is true, 498 * matched entries in "foundPositions". If "breakAfterFound" is true,
499 * the function terminates after the first occurence of the entry 499 * the function terminates after the first occurence of the entry
500 * and doesn't go on searching. So foundPositions->size() is never 500 * and doesn't go on searching. So foundPositions->size() is never
501 * > 1 if breakAfterFound is true. 501 * > 1 if breakAfterFound is true.
502 */ 502 */
503 void findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn, 503 void findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn,
504 vector<unsigned int> *foundPositions, bool breakAfterFound = false, 504 vector<unsigned int> *foundPositions, bool breakAfterFound = false,
505 bool caseSensitive = true, bool exactWordMatch = true, 505 bool caseSensitive = true, bool exactWordMatch = true,
506 bool sortByLvp = false); 506 bool sortByLvp = false);
507 /** see the above funtion. This function allows to set the category by name. */ 507 /** see the above funtion. This function allows to set the category by name. */
508 void findEntry(const QString &category, PwMDataItem find, unsigned int searchIn, 508 void findEntry(const QString &category, PwMDataItem find, unsigned int searchIn,
509 vector<unsigned int> *foundPositions, bool breakAfterFound = false, 509 vector<unsigned int> *foundPositions, bool breakAfterFound = false,
510 bool caseSensitive = true, bool exactWordMatch = true, 510 bool caseSensitive = true, bool exactWordMatch = true,
511 bool sortByLvp = false); 511 bool sortByLvp = false);
512 /** returns number of entries */ 512 /** returns number of entries */
513 unsigned int numEntries(const QString &category); 513 unsigned int numEntries(const QString &category);
514 unsigned int numEntries(unsigned int category) 514 unsigned int numEntries(unsigned int category)
515 { return dti.dta[category].d.size(); } 515 { return dti.dta[category].d.size(); }
516 /** returns number of categories */ 516 /** returns number of categories */
517 unsigned int numCategories() 517 unsigned int numCategories()
518 { return dti.dta.size(); } 518 { return dti.dta.size(); }
519 /** returns the name of the category at "index" */ 519 /** returns the name of the category at "index" */
520 const string* getCategory(unsigned int index) 520 const string* getCategory(unsigned int index)
521 { return (&(dti.dta[index].name)); } 521 { return (&(dti.dta[index].name)); }
522 522
523 /** returns the data of item at "index". 523 /** returns the data of item at "index".
524 * It unlocks the entry if it's locked and unlockIfLocked is true. 524 * It unlocks the entry if it's locked and unlockIfLocked is true.
525 * If the entry is locked, but unlockIfLocked is false, it'll not return 525 * If the entry is locked, but unlockIfLocked is false, it'll not return
526 * the pw. 526 * the pw.
527 */ 527 */
528 bool getEntry(const QString &category, unsigned int index, 528 bool getEntry(const QString &category, unsigned int index,
529 PwMDataItem *d, bool unlockIfLocked = false); 529 PwMDataItem *d, bool unlockIfLocked = false);
530 bool getEntry(unsigned int category, unsigned int index, 530 bool getEntry(unsigned int category, unsigned int index,
531 PwMDataItem *d, bool unlockIfLocked = false); 531 PwMDataItem *d, bool unlockIfLocked = false);
532 /** returns the comment-string by looking at the category 532 /** returns the comment-string by looking at the category
533 * and the listViewPos 533 * and the listViewPos
534 */ 534 */
535 PwMerror getCommentByLvp(const QString &category, int listViewPos, 535 PwMerror getCommentByLvp(const QString &category, int listViewPos,
536 string *foundComment); 536 string *foundComment);
537 /** checks if a password is already available. (currentPw) */ 537 /** checks if a password is already available. (currentPw) */
538 bool isPwAvailable() 538 bool isPwAvailable()
539 { return (currentPw != ""); } 539 { return (currentPw != ""); }
540 /** un/lock entry at "index". If needed, ask for password. */ 540 /** un/lock entry at "index". If needed, ask for password. */
541 bool lockAt(const QString &category, unsigned int index, 541 bool lockAt(const QString &category, unsigned int index,
542 bool lock = true); 542 bool lock = true);
543 bool lockAt(unsigned int category, unsigned int index, 543 bool lockAt(unsigned int category, unsigned int index,
544 bool lock = true); 544 bool lock = true);
545 /** returns the lock-status at "index" */ 545 /** returns the lock-status at "index" */
546 bool isLocked(const QString &category, unsigned int index); 546 bool isLocked(const QString &category, unsigned int index);
547 bool isLocked(unsigned int category, unsigned int index) 547 bool isLocked(unsigned int category, unsigned int index)
548 { return dti.dta[category].d[index].lockStat; } 548 { return dti.dta[category].d[index].lockStat; }
549 /** returns the deeplock status */ 549 /** returns the deeplock status */
550 bool isDeepLocked() 550 bool isDeepLocked()
551 { return getDocStatFlag(DOC_STAT_DEEPLOCKED); } 551 { return getDocStatFlag(DOC_STAT_DEEPLOCKED); }
552 /** (un)lock all entries */ 552 /** (un)lock all entries */
553 bool lockAll(bool lock); 553 bool lockAll(bool lock);
554 /** unlocks all entries tempoarly. 554 /** unlocks all entries tempoarly.
555 * 1st NOTE: Be very careful with this function! :) 555 * 1st NOTE: Be very careful with this function! :)
556 * 2nd NOTE: After you have called unlockAll_Tempoary(); , 556 * 2nd NOTE: After you have called unlockAll_Tempoary(); ,
557 * please DON'T forget to call unlockAll_Tempoary(true); 557 * please DON'T forget to call unlockAll_Tempoary(true);
558 * _before_ the user (or someone else) is able to change 558 * _before_ the user (or someone else) is able to change
559 * the document! 559 * the document!
560 * 3rd NOTE: Please DON'T change "dta" while the data is tempoary 560 * 3rd NOTE: Please DON'T change "dta" while the data is tempoary
561 * unlocked! This will cause corruption. 561 * unlocked! This will cause corruption.
562 */ 562 */
563 bool unlockAll_tempoary(bool revert = false); 563 bool unlockAll_tempoary(bool revert = false);
564 /** deep-(un)locks the document. 564 /** deep-(un)locks the document.
565 * deep-locking writes all data to the file, deletes all data 565 * deep-locking writes all data to the file, deletes all data
566 * in memory, but doesn't close the document. 566 * in memory, but doesn't close the document.
567 * deep-locking is only available, if the user previously saved 567 * deep-locking is only available, if the user previously saved
568 * the doc to a file (with a password). 568 * the doc to a file (with a password).
569 * If "saveToFile" is false, it does NOT write the data to the file! 569 * If "saveToFile" is false, it does NOT write the data to the file!
570 */ 570 */
571 PwMerror deepLock(bool lock = true, bool saveToFile = true); 571 PwMerror deepLock(bool lock = true, bool saveToFile = true);
572 /** is unlockable without pw? */ 572 /** is unlockable without pw? */
573 bool unlockWoPw() 573 bool unlockWoPw()
574 { return getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); } 574 { return getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); }
575 /** get the "currentPassword" */ 575 /** get the "currentPassword" */
576 const QString& getCurrentPw() 576 const QString& getCurrentPw()
577 { return currentPw; } 577 { return currentPw; }
578 /** open a window and request the user to change the mpw */ 578 /** open a window and request the user to change the mpw */
579 void changeCurrentPw(); 579 void changeCurrentPw();
580 /** set the "listViewPos" variable of "dta" */ 580 /** set the "listViewPos" variable of "dta" */
581 void setListViewPos(const QString &category, unsigned int index, 581 void setListViewPos(const QString &category, unsigned int index,
582 int pos); 582 int pos);
583 /** set the "listViewPos" variable of "dta" */ 583 /** set the "listViewPos" variable of "dta" */
584 void setListViewPos(unsigned int category, unsigned int index, 584 void setListViewPos(unsigned int category, unsigned int index,
585 int pos); 585 int pos);
586 /** get the "listViewPos" variable of "dta" */ 586 /** get the "listViewPos" variable of "dta" */
587 int getListViewPos(const QString &category, unsigned int index); 587 int getListViewPos(const QString &category, unsigned int index);
588 /** set the maximum number of entries allowed */ 588 /** set the maximum number of entries allowed */
589 void setMaxNumEntries(unsigned int num = DEFAULT_MAX_ENTRIES) 589 void setMaxNumEntries(unsigned int num = DEFAULT_MAX_ENTRIES)
590 { maxEntries = num; } 590 { maxEntries = num; }
591 /** get the maximum number of entries allowed */ 591 /** get the maximum number of entries allowed */
592 unsigned int getMaxNumEntries() 592 unsigned int getMaxNumEntries()
593 { return maxEntries; } 593 { return maxEntries; }
594 /** ensure all listViewPos of all dta items are set. (are ! -1). 594 /** ensure all listViewPos of all dta items are set. (are ! -1).
595 * If there are some undefined entries, add them to the end of 595 * If there are some undefined entries, add them to the end of
596 * the listViewPos(itions). */ 596 * the listViewPos(itions). */
597 void ensureLvp(); 597 void ensureLvp();
598 /** execute the "launcher" of this entry */ 598 /** execute the "launcher" of this entry */
599 bool execLauncher(const QString &category, unsigned int entryIndex); 599 bool execLauncher(const QString &category, unsigned int entryIndex);
600 /** see above */ 600 /** see above */
601 bool execLauncher(unsigned int category, unsigned int entryIndex); 601 bool execLauncher(unsigned int category, unsigned int entryIndex);
602 /** open a browser with the URL-section of the given entry */ 602 /** open a browser with the URL-section of the given entry */
603 bool goToURL(const QString &category, unsigned int entryIndex); 603 bool goToURL(const QString &category, unsigned int entryIndex);
604 /** see above */ 604 /** see above */
605 bool goToURL(unsigned int category, unsigned int entryIndex); 605 bool goToURL(unsigned int category, unsigned int entryIndex);
606 /** returns true if there is no entry present in the document. 606 /** returns true if there is no entry present in the document.
607 * Note: The "default" Category is present everytime, so 607 * Note: The "default" Category is present everytime, so
608 * it's checked for it's entries. 608 * it's checked for it's entries.
609 */ 609 */
610 bool isDocEmpty() 610 bool isDocEmpty()
611 { 611 {
612 if (numCategories() > 1) 612 if (numCategories() > 1)
613 return false; 613 return false;
614 if (numEntries(0)) 614 if (numEntries(0))
615 return false; 615 return false;
616 return true; 616 return true;
617 } 617 }
618 /** returns the filename of this doc */ 618 /** returns the filename of this doc */
619 const QString& getFilename() 619 const QString& getFilename()
620 { return filename; } 620 { return filename; }
621 /** returns the title of the doc */ 621 /** returns the title of the doc */
622 QString getTitle(); 622 QString getTitle();
623 /** sets the list-view-pointer hold in the doc */ 623 /** sets the list-view-pointer hold in the doc */
624 void setListViewPointer(PwMView *_listView) 624 void setListViewPointer(PwMView *_listView)
625 { listView = _listView; } 625 { listView = _listView; }
626 /** returns the list-view-pointer */ 626 /** returns the list-view-pointer */
627 PwMView * getListViewPointer() 627 PwMView * getListViewPointer()
628 { return listView; } 628 { return listView; }
629 /** try to delete the doc. The user may be asked to save 629 /** try to delete the doc. The user may be asked to save
630 * the data. The user may cancel the whole operation. 630 * the data. The user may cancel the whole operation.
631 * false is returned, then. 631 * false is returned, then.
632 */ 632 */
633 bool tryDelete(); 633 bool tryDelete();
634 /** is the doc deleted? (with tryDelete() ) */ 634 /** is the doc deleted? (with tryDelete() ) */
635 bool isDeleted() 635 bool isDeleted()
636 { return deleted; } 636 { return deleted; }
637 /** returns the document timer object */ 637 /** returns the document timer object */
638 DocTimer * timer() 638 DocTimer * timer()
639 { return _timer; } 639 { return _timer; }
640 /** get a lock on the dataChanged signal. 640 /** get a lock on the dataChanged signal.
641 * If someone is holding a lock, the signal is not emitted. 641 * If someone is holding a lock, the signal is not emitted.
642 */ 642 */
643 void getDataChangedLock() 643 void getDataChangedLock()
644 { ++dataChangedLock; } 644 { ++dataChangedLock; }
645 /** put the dataChanged lock */ 645 /** put the dataChanged lock */
646 void putDataChangedLock() 646 void putDataChangedLock()
647 { --dataChangedLock; } 647 { --dataChangedLock; }
648 /** returns the revision count of the item at cat/index */ 648 /** returns the revision count of the item at cat/index */
649 unsigned int getEntryRevCnt(unsigned int category, unsigned int index) 649 unsigned int getEntryRevCnt(unsigned int category, unsigned int index)
650 { return dti.dta[category].d[index].rev; } 650 { return dti.dta[category].d[index].rev; }
651 /** returns a const pointer to the entries meta */ 651 /** returns a const pointer to the entries meta */
652 const PwMMetaData * getEntryMeta(unsigned int category, unsigned int index) 652 const PwMMetaData * getEntryMeta(unsigned int category, unsigned int index)
653 { return &(dti.dta[category].d[index].meta); } 653 { return &(dti.dta[category].d[index].meta); }
654 /** is the entry at "category" "index" a binary entry? */ 654 /** is the entry at "category" "index" a binary entry? */
655 bool isBinEntry(unsigned int category, unsigned int index) 655 bool isBinEntry(unsigned int category, unsigned int index)
656 { return dti.dta[category].d[index].binary; } 656 { return dti.dta[category].d[index].binary; }
657 657
658public slots: 658public slots:
659 /** wrapper for PwMTray */ 659 /** wrapper for PwMTray */
660 void _deepUnlock(); 660 void _deepUnlock();
661 661
662signals: 662signals:
663 /** the data of the document has changed and must be updated 663 /** the data of the document has changed and must be updated
664 * in all views. 664 * in all views.
665 * NOTE: use emitDataChanged(PwMDoc *document) to emit this signal! 665 * NOTE: use emitDataChanged(PwMDoc *document) to emit this signal!
666 */ 666 */
667 void dataChanged(PwMDoc *document); 667 void dataChanged(PwMDoc *document);
668 /** the document class is going to close. This signal may be 668 /** the document class is going to close. This signal may be
669 * used to nofify all views, that the user closed the document, 669 * used to nofify all views, that the user closed the document,
670 * so the views can go down, too. 670 * so the views can go down, too.
671 */ 671 */
672 void docClosed(PwMDoc *document); 672 void docClosed(PwMDoc *document);
673 /** somebody just opened the document */ 673 /** somebody just opened the document */
674 void docOpened(PwMDoc *document); 674 void docOpened(PwMDoc *document);
675 /** this document object just got created */ 675 /** this document object just got created */
676 void docCreated(PwMDoc *document); 676 void docCreated(PwMDoc *document);
677 677
678public: 678public:
679 /** emit the dataChanged signal after checking for a lock */ 679 /** emit the dataChanged signal after checking for a lock */
680 void emitDataChanged(PwMDoc *document) 680 void emitDataChanged(PwMDoc *document)
681 { 681 {
682 if (!dataChangedLock) 682 if (!dataChangedLock)
683 emit dataChanged(document); 683 emit dataChanged(document);
684 } 684 }
685 685
686protected: 686protected:
687 /** current file for this doc */ 687 /** current file for this doc */
688 QString filename; 688 QString filename;
689//US ENH: we need a place where we keep the syncentries. So I invented 689//US ENH: we need a place where we keep the syncentries. So I invented
690// struct PwMItem, that has a vector of PwMCategoryItem and vector of PwMSyncItem 690// struct PwMItem, that has a vector of PwMCategoryItem and vector of PwMSyncItem
691 /** holds all data */ 691 /** holds all data */
692 PwMItem dti; 692 PwMItem dti;
693 /** maximum number of entries */ 693 /** maximum number of entries */
694 unsigned int maxEntries; 694 unsigned int maxEntries;
695 /** currently used password to encrypt data */ 695 /** currently used password to encrypt data */
696 QString currentPw; 696 QString currentPw;
697 /** current global document status flags */ 697 /** current global document status flags */
698 unsigned int curDocStat; 698 unsigned int curDocStat;
699 /** browser process for goToURL() */ 699 /** browser process for goToURL() */
700 KProcess browserProc; 700 KProcess browserProc;
701 /** pointer to the list-view, using this document. 701 /** pointer to the list-view, using this document.
702 * As there can only be one list-view per doc, we 702 * As there can only be one list-view per doc, we
703 * don't need a list here. 703 * don't need a list here.
704 */ 704 */
705 PwMView *listView; 705 PwMView *listView;
706 /** unnamedNum is used to store the "unnamed counter" 706 /** unnamedNum is used to store the "unnamed counter"
707 * for this document, while it's unnamed. If it's 0, 707 * for this document, while it's unnamed. If it's 0,
708 * we have to get a new unique one. 708 * we have to get a new unique one.
709 */ 709 */
710 unsigned int unnamedNum; 710 unsigned int unnamedNum;
711 /** is this doc going to be deleted (executing in destructor context) */ 711 /** is this doc going to be deleted (executing in destructor context) */
712 bool deleted; 712 bool deleted;
713 /** document timer */ 713 /** document timer */
714 DocTimer *_timer; 714 DocTimer *_timer;
715 /** lock counter for the "dataChanged" signal */ 715 /** lock counter for the "dataChanged" signal */
716 unsigned int dataChangedLock; 716 unsigned int dataChangedLock;
717 717
718 /** list of all open documents */ 718 /** list of all open documents */
719 static PwMDocList openDocList; 719 static PwMDocList openDocList;
720 720
721protected: 721protected:
722 /** serialize "dta" and return it in "d". */ 722 /** serialize "dta" and return it in "d". */
723 bool serializeDta(string *d); 723 bool serializeDta(string *d);
724 /** de-serialize "d" and overwrite "dta" */ 724 /** de-serialize "d" and overwrite "dta" */
725 bool deSerializeDta(const string *d, bool entriesLocked); 725 bool deSerializeDta(const string *d, bool entriesLocked);
726 /** write header to file */ 726 /** write header to file */
727 PwMerror writeFileHeader(char keyHash, char dataHash, char crypt, char compress, 727 PwMerror writeFileHeader(char keyHash, char dataHash, char crypt, char compress,
728 QString *pw, QFile *f); 728 QString *pw, QFile *f);
729 /** write data-hash to file */ 729 /** write data-hash to file */
730 PwMerror writeDataHash(char dataHash, string *d, QFile *f); 730 PwMerror writeDataHash(char dataHash, string *d, QFile *f);
731 /** check header. Read header info and verify key-hash and filever. 731 /** check header. Read header info and verify key-hash and filever.
732 * returns length of header in "headerLength" */ 732 * returns length of header in "headerLength" */
733 PwMerror checkHeader(char *cryptAlgo, QString *pw, char *compress, 733 PwMerror checkHeader(char *cryptAlgo, QString *pw, char *compress,
734 unsigned int *headerLength, char *dataHashType, 734 unsigned int *headerLength, char *dataHashType,
735 string *dataHash, QFile *f); 735 string *dataHash, QFile *f);
736 /** check the data-hash */ 736 /** check the data-hash */
737 PwMerror checkDataHash(char dataHashType, const string *dataHash, const string *dataStream); 737 PwMerror checkDataHash(char dataHashType, const string *dataHash, const string *dataStream);
738 /** encrypt data "d" and write to "filename" */ 738 /** encrypt data "d" and write to "filename" */
739 PwMerror encrypt(string *d, const QString *pw, QFile *f, char algo); 739 PwMerror encrypt(string *d, const QString *pw, QFile *f, char algo,
740 char _hashalgo //US BUG: pass _hashalgo because we need it in hashPassphrase
741);
740 /** read data from file beginning at "pos", decrypt and return it */ 742 /** read data from file beginning at "pos", decrypt and return it */
741 PwMerror decrypt(string *d, unsigned int pos, const QString *pw, char algo, QFile *f); 743 PwMerror decrypt(string *d, unsigned int pos, const QString *pw, char algo,
744 char _hashalgo, //US BUG: pass _hashalgo because we need it in hashPassphrase
745QFile *f);
742 /** compress the data */ 746 /** compress the data */
743 bool compressDta(string *d, char algo); 747 bool compressDta(string *d, char algo);
744 /** uncompress the data */ 748 /** uncompress the data */
745 bool decompressDta(string *d, char algo); 749 bool decompressDta(string *d, char algo);
746 /** internal import function for a text-file generated by PwM. 750 /** internal import function for a text-file generated by PwM.
747 * If this is not a valid PwM-exported file, it returns e_fileFormat */ 751 * If this is not a valid PwM-exported file, it returns e_fileFormat */
748 PwMerror importText_PwM(const QString *file); 752 PwMerror importText_PwM(const QString *file);
749 /** PwM-text-import helper function to extract the name/pw/comment out 753 /** PwM-text-import helper function to extract the name/pw/comment out
750 * of one entry-line */ 754 * of one entry-line */
751 bool textExtractEntry_PwM(const char *in, ssize_t in_size, string *out); 755 bool textExtractEntry_PwM(const char *in, ssize_t in_size, string *out);
752 /** compare two strings */ 756 /** compare two strings */
753 bool compareString(const string &s1, const string &s2, bool caseSensitive, 757 bool compareString(const string &s1, const string &s2, bool caseSensitive,
754 bool exactWordMatch); 758 bool exactWordMatch);
755 /** clears all document-data */ 759 /** clears all document-data */
756 void clearDoc(); 760 void clearDoc();
757 /** delete all empty categories */ 761 /** delete all empty categories */
758 void delAllEmptyCat(bool dontFlagDirty); 762 void delAllEmptyCat(bool dontFlagDirty);
759 /** set a document status flag */ 763 /** set a document status flag */
760 void setDocStatFlag(unsigned int statFlag) 764 void setDocStatFlag(unsigned int statFlag)
761 { curDocStat |= statFlag; } 765 { curDocStat |= statFlag; }
762 /** unset a document status flag */ 766 /** unset a document status flag */
763 void unsetDocStatFlag(unsigned int statFlag) 767 void unsetDocStatFlag(unsigned int statFlag)
764 { curDocStat &= ~statFlag; } 768 { curDocStat &= ~statFlag; }
765 /** get a document status flag */ 769 /** get a document status flag */
766 bool getDocStatFlag(unsigned int statFlag) const 770 bool getDocStatFlag(unsigned int statFlag) const
767 { return (curDocStat & statFlag); } 771 { return (curDocStat & statFlag); }
768 /** set the "currentPassword" */ 772 /** set the "currentPassword" */
769 void setCurrentPw(const QString &pw) 773 void setCurrentPw(const QString &pw)
770 { 774 {
771 currentPw = pw; 775 currentPw = pw;
772 setDocStatFlag(DOC_STAT_DISK_DIRTY); 776 setDocStatFlag(DOC_STAT_DISK_DIRTY);
773 } 777 }
774 /** make a backup-copy of the given file */ 778 /** make a backup-copy of the given file */
775 bool backupFile(const QString &filePath); 779 bool backupFile(const QString &filePath);
776 /** copy a file from src to dst */ 780 /** copy a file from src to dst */
777 bool copyFile(const QString &src, const QString &dst); 781 bool copyFile(const QString &src, const QString &dst);
778 782
779 783
780 public: 784 public:
781#ifdef PWM_EMBEDDED 785#ifdef PWM_EMBEDDED
782 //US ENH: this is the magic function that syncronizes the local doc with the remote doc. 786 //US ENH: this is the magic function that syncronizes the local doc with the remote doc.
783 PwMerror syncronize(KSyncManager* manager, PwMDoc* syncLocal, PwMDoc* syncRemote, int mode ); 787 PwMerror syncronize(KSyncManager* manager, PwMDoc* syncLocal, PwMDoc* syncRemote, int mode );
784 788
785 //takePwMDataItem returns the following values 789 //takePwMDataItem returns the following values
786 // 0 equal 790 // 0 equal
787 // 1 take local 791 // 1 take local
788 // 2 take remote 792 // 2 take remote
789 // 3 cancel 793 // 3 cancel
790 int takePwMDataItem( PwMDataItem* local, PwMDataItem* remote, QDateTime lastSync, int mode , bool full ); 794 int takePwMDataItem( PwMDataItem* local, PwMDataItem* remote, QDateTime lastSync, int mode , bool full );
791 795
792 //the following methods are the overwritten callbackmethods from the syncinterface 796 //the following methods are the overwritten callbackmethods from the syncinterface
793 virtual bool sync(KSyncManager* manager, QString filename, int mode); 797 virtual bool sync(KSyncManager* manager, QString filename, int mode);
794 virtual void removeSyncInfo( QString syncProfile); 798 virtual void removeSyncInfo( QString syncProfile);
795 799
796#endif 800#endif
797 //US ENH: helpermethods to return a whole category entry 801 //US ENH: helpermethods to return a whole category entry
798 /** returns a pointer to the categoryitem */ 802 /** returns a pointer to the categoryitem */
799 PwMCategoryItem* getCategoryEntry(unsigned int index) 803 PwMCategoryItem* getCategoryEntry(unsigned int index)
800 { return &(dti.dta[index]); } 804 { return &(dti.dta[index]); }
801 805
802 private: 806 private:
803 //US ENH: helpermethods to access the sync data for a certain syncname. 807 //US ENH: helpermethods to access the sync data for a certain syncname.
804 // It returns the syncdatas index 808 // It returns the syncdatas index
805 bool findSyncData(const QString &syncname, unsigned int *index); 809 bool findSyncData(const QString &syncname, unsigned int *index);
806 810
807 /** add new syncdataentry */ 811 /** add new syncdataentry */
808 PwMerror addSyncDataEntry(PwMSyncItem *d, bool dontFlagDirty = false); 812 PwMerror addSyncDataEntry(PwMSyncItem *d, bool dontFlagDirty = false);
809 813
810 /** returns a pointer to the syncdata */ 814 /** returns a pointer to the syncdata */
811 PwMSyncItem* getSyncDataEntry(unsigned int index) 815 PwMSyncItem* getSyncDataEntry(unsigned int index)
812 { return &(dti.syncDta[index]); } 816 { return &(dti.syncDta[index]); }
813 817
814 /** delete entry */ 818 /** delete entry */
815 bool delSyncDataEntry(unsigned int index, bool dontFlagDirty = false); 819 bool delSyncDataEntry(unsigned int index, bool dontFlagDirty = false);
816 820
817 /** returns number of categories */ 821 /** returns number of categories */
818 unsigned int numSyncDataEntries() 822 unsigned int numSyncDataEntries()
819 { return dti.syncDta.size(); } 823 { return dti.syncDta.size(); }
820 824
821 PwMDataItem* findEntryByID(const QString &uid, unsigned int *category, unsigned int *index); 825 PwMDataItem* findEntryByID(const QString &uid, unsigned int *category, unsigned int *index);
822 826
823 QStringList getIDEntryList(); 827 QStringList getIDEntryList();
824 828
825}; 829};
826 830
827#endif 831#endif