keepass 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +3 -0
- data/ext/extconf.rb +6 -0
- data/ext/keepass.c +611 -0
- data/test/entries.rb +19 -0
- data/test/groups.rb +54 -0
- data/test/open.rb +65 -0
- metadata +57 -0
data/README.rdoc
ADDED
data/ext/extconf.rb
ADDED
data/ext/keepass.c
ADDED
@@ -0,0 +1,611 @@
|
|
1
|
+
#include <ctype.h>
|
2
|
+
#include <ruby.h>
|
3
|
+
#include <kpass.h>
|
4
|
+
|
5
|
+
/*
|
6
|
+
* Document-module: Keepass
|
7
|
+
*
|
8
|
+
* A module containing classes related to processing
|
9
|
+
* a Keepass database.
|
10
|
+
*
|
11
|
+
*/
|
12
|
+
static VALUE mKeepass;
|
13
|
+
|
14
|
+
/*
|
15
|
+
* Document-class: Keepass::Database
|
16
|
+
*
|
17
|
+
* A class representing a Keepass database.
|
18
|
+
*
|
19
|
+
*/
|
20
|
+
static VALUE cDatabase;
|
21
|
+
|
22
|
+
/*
|
23
|
+
* Document-class: Keepass::Group
|
24
|
+
*
|
25
|
+
* A class representing a group of entries in a Keepass
|
26
|
+
* database.
|
27
|
+
*
|
28
|
+
*/
|
29
|
+
static VALUE cGroup;
|
30
|
+
|
31
|
+
/*
|
32
|
+
* Document-class: Keepass::Entry
|
33
|
+
*
|
34
|
+
* A class representing an entry in a Keepass
|
35
|
+
* database.
|
36
|
+
*
|
37
|
+
*/
|
38
|
+
static VALUE cEntry;
|
39
|
+
|
40
|
+
/*
|
41
|
+
* Document-class: Keepass::Exception
|
42
|
+
*
|
43
|
+
* An exception type for exceptions that occur when accessing a Keepass
|
44
|
+
* database.
|
45
|
+
*
|
46
|
+
*/
|
47
|
+
static VALUE eException_KeepassException;
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Document-class: Keepass::UnknownException
|
51
|
+
*
|
52
|
+
* An exception type for unknown errors.
|
53
|
+
*
|
54
|
+
*/
|
55
|
+
static VALUE eException_unknown;
|
56
|
+
|
57
|
+
/*
|
58
|
+
* Document-class: Keepass::DecryptDataException
|
59
|
+
*
|
60
|
+
* An exception type for when data decryption fails.
|
61
|
+
*
|
62
|
+
*/
|
63
|
+
static VALUE eException_kpass_decrypt_data_fail;
|
64
|
+
|
65
|
+
/*
|
66
|
+
* Document-class: Keepass::DecryptDbException
|
67
|
+
*
|
68
|
+
* An exception type for when data decryption fails.
|
69
|
+
*
|
70
|
+
*/
|
71
|
+
static VALUE eException_kpass_decrypt_db_fail;
|
72
|
+
|
73
|
+
/*
|
74
|
+
* Document-class: Keepass::HashPwException
|
75
|
+
*
|
76
|
+
* An exception type for when password hashing fails.
|
77
|
+
*
|
78
|
+
*/
|
79
|
+
static VALUE eException_kpass_hash_pw_fail;
|
80
|
+
|
81
|
+
/*
|
82
|
+
* Document-class: Keepass::PrepareKeyException
|
83
|
+
*
|
84
|
+
* An exception type for when key preparation fails.
|
85
|
+
*
|
86
|
+
*/
|
87
|
+
static VALUE eException_kpass_prepare_key_fail;
|
88
|
+
|
89
|
+
/*
|
90
|
+
* Document-class: Keepass::LoadDecryptedDataEntryException
|
91
|
+
*
|
92
|
+
* An exception type for when loading an entry fails.
|
93
|
+
*
|
94
|
+
*/
|
95
|
+
static VALUE eException_kpass_load_decrypted_data_entry_fail;
|
96
|
+
|
97
|
+
/*
|
98
|
+
* Document-class: Keepass::LoadDecryptedDataGroupException
|
99
|
+
*
|
100
|
+
* An exception type for when loading a groupo fails.
|
101
|
+
*
|
102
|
+
*/
|
103
|
+
static VALUE eException_kpass_load_decrypted_data_group_fail;
|
104
|
+
|
105
|
+
/*
|
106
|
+
* Document-class: Keepass::InitDbException
|
107
|
+
*
|
108
|
+
* An exception type for when initializing a database fails.
|
109
|
+
*
|
110
|
+
*/
|
111
|
+
static VALUE eException_kpass_init_db_fail;
|
112
|
+
|
113
|
+
/*
|
114
|
+
* Document-class: Keepass::EncryptDbException
|
115
|
+
*
|
116
|
+
* An exception type for when encrypting a database fails.
|
117
|
+
*
|
118
|
+
*/
|
119
|
+
static VALUE eException_kpass_encrypt_db_fail;
|
120
|
+
|
121
|
+
/*
|
122
|
+
* Document-class: Keepass::EncryptDataException
|
123
|
+
*
|
124
|
+
* An exception type for when encrypting a database fails.
|
125
|
+
*
|
126
|
+
*/
|
127
|
+
static VALUE eException_kpass_encrypt_data_fail;
|
128
|
+
|
129
|
+
/*
|
130
|
+
* Document-class: Keepass::PackDbException
|
131
|
+
*
|
132
|
+
* An exception type for when packing a database fails.
|
133
|
+
*
|
134
|
+
*/
|
135
|
+
static VALUE eException_kpass_pack_db_fail;
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Document-class: Keepass::VerificationException
|
139
|
+
*
|
140
|
+
* An exception type for when verifying a database fails.
|
141
|
+
*
|
142
|
+
*/
|
143
|
+
static VALUE eException_kpass_verification_fail;
|
144
|
+
|
145
|
+
/*
|
146
|
+
* Document-class: Keepass::UnsupportedFlagException
|
147
|
+
*
|
148
|
+
* An exception type for when an unsupported flag is used.
|
149
|
+
*
|
150
|
+
*/
|
151
|
+
static VALUE eException_kpass_unsupported_flag;
|
152
|
+
|
153
|
+
/*
|
154
|
+
* Document-class: Keepass::NotImplementedException
|
155
|
+
*
|
156
|
+
* An exception type for when unimplemented functionality is used.
|
157
|
+
*
|
158
|
+
*/
|
159
|
+
static VALUE eException_kpass_not_implemented;
|
160
|
+
|
161
|
+
static void raise_kp_exception(kpass_retval result)
|
162
|
+
{
|
163
|
+
#define throw_exception(type)\
|
164
|
+
case type:\
|
165
|
+
rb_raise(eException_##type, kpass_error_str[type]);\
|
166
|
+
break;
|
167
|
+
|
168
|
+
/* it's ok, so don't do anything */
|
169
|
+
if(result == kpass_success) {
|
170
|
+
return;
|
171
|
+
}
|
172
|
+
switch(result) {
|
173
|
+
throw_exception(kpass_decrypt_data_fail);
|
174
|
+
throw_exception(kpass_decrypt_db_fail);
|
175
|
+
throw_exception(kpass_hash_pw_fail);
|
176
|
+
throw_exception(kpass_prepare_key_fail);
|
177
|
+
throw_exception(kpass_load_decrypted_data_entry_fail);
|
178
|
+
throw_exception(kpass_load_decrypted_data_group_fail);
|
179
|
+
throw_exception(kpass_init_db_fail);
|
180
|
+
throw_exception(kpass_encrypt_db_fail);
|
181
|
+
throw_exception(kpass_encrypt_data_fail);
|
182
|
+
throw_exception(kpass_pack_db_fail);
|
183
|
+
throw_exception(kpass_verification_fail);
|
184
|
+
throw_exception(kpass_unsupported_flag);
|
185
|
+
throw_exception(kpass_not_implemented);
|
186
|
+
|
187
|
+
default:
|
188
|
+
rb_raise(eException_unknown, "An unknown error occurred");
|
189
|
+
}
|
190
|
+
#undef throw_exception
|
191
|
+
}
|
192
|
+
|
193
|
+
/*
|
194
|
+
* Document-method: initialize
|
195
|
+
*
|
196
|
+
* Opens up a Keepass database with the given filename and password.
|
197
|
+
*
|
198
|
+
* call-seq:
|
199
|
+
* Keepass::Database.new(filename, password)
|
200
|
+
*
|
201
|
+
*/
|
202
|
+
VALUE
|
203
|
+
rb_kp_db_initialize(VALUE self, VALUE rb_file, VALUE rb_password)
|
204
|
+
{
|
205
|
+
ID id_read;
|
206
|
+
VALUE bytes;
|
207
|
+
const char *c_bytes;
|
208
|
+
long c_length;
|
209
|
+
kpass_db *kdb = NULL;
|
210
|
+
VALUE kdb_object;
|
211
|
+
kpass_retval result;
|
212
|
+
uint8_t hashed_pass[32];
|
213
|
+
|
214
|
+
if(TYPE(rb_file) == T_STRING) {
|
215
|
+
VALUE rb_filename = rb_file;
|
216
|
+
ID id_new = rb_intern("open");
|
217
|
+
|
218
|
+
rb_file = rb_funcall(rb_cFile, id_new, 2, rb_filename,
|
219
|
+
rb_str_new_cstr("rb"));
|
220
|
+
}
|
221
|
+
|
222
|
+
Check_Type(rb_file, T_FILE); /* XXX looser type check? */
|
223
|
+
Check_Type(rb_password, T_STRING);
|
224
|
+
|
225
|
+
id_read = rb_intern("read");
|
226
|
+
bytes = rb_funcall(rb_file, id_read, 0);
|
227
|
+
c_length = RSTRING_LEN(bytes);
|
228
|
+
c_bytes = RSTRING_PTR(bytes);
|
229
|
+
|
230
|
+
kdb_object = Data_Make_Struct(cDatabase, kpass_db, 0, kpass_free_db, kdb);
|
231
|
+
|
232
|
+
result = kpass_init_db(kdb, c_bytes, c_length);
|
233
|
+
|
234
|
+
if(result != kpass_success) {
|
235
|
+
raise_kp_exception(result);
|
236
|
+
}
|
237
|
+
|
238
|
+
result = kpass_hash_pw(kdb, RSTRING_PTR(rb_password), hashed_pass);
|
239
|
+
|
240
|
+
if(result != kpass_success) {
|
241
|
+
raise_kp_exception(result);
|
242
|
+
}
|
243
|
+
|
244
|
+
result = kpass_decrypt_db(kdb, hashed_pass);
|
245
|
+
|
246
|
+
if(result != kpass_success) {
|
247
|
+
raise_kp_exception(result);
|
248
|
+
}
|
249
|
+
|
250
|
+
rb_ivar_set(self, rb_intern("@kdb"), kdb_object);
|
251
|
+
|
252
|
+
return Qnil;
|
253
|
+
}
|
254
|
+
|
255
|
+
/*
|
256
|
+
* Document-method: open
|
257
|
+
*
|
258
|
+
* Opens up a Keepass database with the given filename and password.
|
259
|
+
*
|
260
|
+
* call-seq:
|
261
|
+
* Keepass::Database.open(filename, password)
|
262
|
+
*
|
263
|
+
*/
|
264
|
+
VALUE
|
265
|
+
rb_kp_db_open(VALUE klass, VALUE rb_file, VALUE rb_password)
|
266
|
+
{
|
267
|
+
ID id_new;
|
268
|
+
|
269
|
+
id_new = rb_intern("new");
|
270
|
+
|
271
|
+
return rb_funcall(klass, id_new, 2, rb_file, rb_password);
|
272
|
+
}
|
273
|
+
|
274
|
+
static void
|
275
|
+
_set_time(VALUE object, const char *attr_name, uint8_t value[5])
|
276
|
+
{
|
277
|
+
struct tm time_value;
|
278
|
+
VALUE rb_time;
|
279
|
+
|
280
|
+
kpass_unpack_time(value, &time_value);
|
281
|
+
rb_time = rb_funcall(rb_cTime, rb_intern("gm"), 6,
|
282
|
+
INT2NUM(time_value.tm_year + 1900),
|
283
|
+
INT2NUM(time_value.tm_mon + 1),
|
284
|
+
INT2NUM(time_value.tm_mday),
|
285
|
+
INT2NUM(time_value.tm_hour),
|
286
|
+
INT2NUM(time_value.tm_min),
|
287
|
+
INT2NUM(time_value.tm_sec)
|
288
|
+
);
|
289
|
+
|
290
|
+
rb_ivar_set(object, rb_intern(attr_name), rb_time);
|
291
|
+
}
|
292
|
+
|
293
|
+
static VALUE
|
294
|
+
_create_ruby_group(VALUE kdb, kpass_group *group)
|
295
|
+
{
|
296
|
+
VALUE rb_group = rb_funcall(cGroup, rb_intern("new"), 0);
|
297
|
+
|
298
|
+
rb_ivar_set(rb_group, rb_intern("@kdb"), kdb);
|
299
|
+
rb_ivar_set(rb_group, rb_intern("@id"), INT2NUM(group->id));
|
300
|
+
rb_ivar_set(rb_group, rb_intern("@name"), rb_str_new_cstr(group->name));
|
301
|
+
_set_time(rb_group, "@mtime", group->mtime);
|
302
|
+
_set_time(rb_group, "@ctime", group->ctime);
|
303
|
+
_set_time(rb_group, "@atime", group->atime);
|
304
|
+
_set_time(rb_group, "@etime", group->etime);
|
305
|
+
|
306
|
+
return rb_group;
|
307
|
+
}
|
308
|
+
|
309
|
+
/*
|
310
|
+
* Document-method: groups
|
311
|
+
*
|
312
|
+
* Returns an Array of groups in this database.
|
313
|
+
*
|
314
|
+
*/
|
315
|
+
VALUE
|
316
|
+
rb_kp_db_groups(VALUE self)
|
317
|
+
{
|
318
|
+
VALUE kdb_object;
|
319
|
+
kpass_db *kdb = NULL;
|
320
|
+
VALUE groups;
|
321
|
+
uint32_t i;
|
322
|
+
|
323
|
+
kdb_object = rb_ivar_get(self, rb_intern("@kdb"));
|
324
|
+
Data_Get_Struct(kdb_object, kpass_db, kdb);
|
325
|
+
|
326
|
+
groups = rb_ary_new2(kdb->groups_len);
|
327
|
+
|
328
|
+
for(i = 0; i < kdb->groups_len; i++) {
|
329
|
+
VALUE rb_group = _create_ruby_group(self, kdb->groups[i]);
|
330
|
+
|
331
|
+
rb_ary_push(groups, rb_group);
|
332
|
+
}
|
333
|
+
|
334
|
+
return groups;
|
335
|
+
}
|
336
|
+
|
337
|
+
static VALUE
|
338
|
+
_create_ruby_entry(kpass_entry *entry)
|
339
|
+
{
|
340
|
+
VALUE rb_entry;
|
341
|
+
|
342
|
+
rb_entry = rb_funcall(cEntry, rb_intern("new"), 0);
|
343
|
+
|
344
|
+
rb_ivar_set(rb_entry, rb_intern("@name"), rb_str_new_cstr(entry->title));
|
345
|
+
rb_ivar_set(rb_entry, rb_intern("@password"), rb_str_new_cstr(entry->password));
|
346
|
+
_set_time(rb_entry, "@mtime", entry->mtime);
|
347
|
+
_set_time(rb_entry, "@ctime", entry->ctime);
|
348
|
+
_set_time(rb_entry, "@atime", entry->atime);
|
349
|
+
_set_time(rb_entry, "@etime", entry->etime);
|
350
|
+
|
351
|
+
return rb_entry;
|
352
|
+
}
|
353
|
+
|
354
|
+
/*
|
355
|
+
* Document-method: Keepass::Database#entries
|
356
|
+
*
|
357
|
+
* Returns an Array of entries in this database.
|
358
|
+
*
|
359
|
+
*/
|
360
|
+
VALUE
|
361
|
+
rb_kp_db_entries(VALUE self)
|
362
|
+
{
|
363
|
+
VALUE kdb_object;
|
364
|
+
kpass_db *kdb = NULL;
|
365
|
+
VALUE entries;
|
366
|
+
uint32_t i;
|
367
|
+
|
368
|
+
kdb_object = rb_ivar_get(self, rb_intern("@kdb"));
|
369
|
+
Data_Get_Struct(kdb_object, kpass_db, kdb);
|
370
|
+
|
371
|
+
entries = rb_ary_new();
|
372
|
+
|
373
|
+
for(i = 0; i < kdb->entries_len; i++) {
|
374
|
+
VALUE rb_entry;
|
375
|
+
kpass_entry *entry = kdb->entries[i];
|
376
|
+
|
377
|
+
if(! strcmp(entry->title, "Meta-Info")) {
|
378
|
+
continue;
|
379
|
+
}
|
380
|
+
|
381
|
+
rb_entry = _create_ruby_entry(entry);
|
382
|
+
|
383
|
+
rb_ary_push(entries, rb_entry);
|
384
|
+
}
|
385
|
+
|
386
|
+
return entries;
|
387
|
+
}
|
388
|
+
|
389
|
+
/*
|
390
|
+
* Document-method: name
|
391
|
+
*
|
392
|
+
* Returns the name of this group.
|
393
|
+
*
|
394
|
+
*/
|
395
|
+
VALUE
|
396
|
+
rb_kp_grp_name(VALUE self)
|
397
|
+
{
|
398
|
+
return rb_ivar_get(self, rb_intern("@name"));
|
399
|
+
}
|
400
|
+
|
401
|
+
/*
|
402
|
+
* Document-method: mtime
|
403
|
+
*
|
404
|
+
* Returns the modification time of this group.
|
405
|
+
*
|
406
|
+
*/
|
407
|
+
VALUE
|
408
|
+
rb_kp_grp_mtime(VALUE self)
|
409
|
+
{
|
410
|
+
return rb_ivar_get(self, rb_intern("@mtime"));
|
411
|
+
}
|
412
|
+
|
413
|
+
/*
|
414
|
+
* Document-method: ctime
|
415
|
+
*
|
416
|
+
* Returns the creation time of this group.
|
417
|
+
*
|
418
|
+
*/
|
419
|
+
VALUE
|
420
|
+
rb_kp_grp_ctime(VALUE self)
|
421
|
+
{
|
422
|
+
return rb_ivar_get(self, rb_intern("@ctime"));
|
423
|
+
}
|
424
|
+
|
425
|
+
/*
|
426
|
+
* Document-method: atime
|
427
|
+
*
|
428
|
+
* Returns the last access time of this group.
|
429
|
+
*
|
430
|
+
*/
|
431
|
+
VALUE
|
432
|
+
rb_kp_grp_atime(VALUE self)
|
433
|
+
{
|
434
|
+
return rb_ivar_get(self, rb_intern("@atime"));
|
435
|
+
}
|
436
|
+
|
437
|
+
/*
|
438
|
+
* Document-method: etime
|
439
|
+
*
|
440
|
+
* Returns the expire time of this group.
|
441
|
+
*
|
442
|
+
*/
|
443
|
+
VALUE
|
444
|
+
rb_kp_grp_etime(VALUE self)
|
445
|
+
{
|
446
|
+
return rb_ivar_get(self, rb_intern("@etime"));
|
447
|
+
}
|
448
|
+
|
449
|
+
/*
|
450
|
+
* Document-method: name
|
451
|
+
*
|
452
|
+
* Returns the name of this entry.
|
453
|
+
*
|
454
|
+
*/
|
455
|
+
VALUE
|
456
|
+
rb_kp_entry_name(VALUE self)
|
457
|
+
{
|
458
|
+
return rb_ivar_get(self, rb_intern("@name"));
|
459
|
+
}
|
460
|
+
|
461
|
+
/*
|
462
|
+
* Document-method: password
|
463
|
+
*
|
464
|
+
* Returns the password of this entry.
|
465
|
+
*
|
466
|
+
*/
|
467
|
+
VALUE
|
468
|
+
rb_kp_entry_password(VALUE self)
|
469
|
+
{
|
470
|
+
return rb_ivar_get(self, rb_intern("@password"));
|
471
|
+
}
|
472
|
+
|
473
|
+
/*
|
474
|
+
* Document-method: mtime
|
475
|
+
*
|
476
|
+
* Returns the modification time of this entry.
|
477
|
+
*
|
478
|
+
*/
|
479
|
+
VALUE
|
480
|
+
rb_kp_entry_mtime(VALUE self)
|
481
|
+
{
|
482
|
+
return rb_ivar_get(self, rb_intern("@mtime"));
|
483
|
+
}
|
484
|
+
|
485
|
+
/*
|
486
|
+
* Document-method: ctime
|
487
|
+
*
|
488
|
+
* Returns the creation time of this entry.
|
489
|
+
*
|
490
|
+
*/
|
491
|
+
VALUE
|
492
|
+
rb_kp_entry_ctime(VALUE self)
|
493
|
+
{
|
494
|
+
return rb_ivar_get(self, rb_intern("@ctime"));
|
495
|
+
}
|
496
|
+
|
497
|
+
/*
|
498
|
+
* Document-method: atime
|
499
|
+
*
|
500
|
+
* Returns the last access time of this entry.
|
501
|
+
*
|
502
|
+
*/
|
503
|
+
VALUE
|
504
|
+
rb_kp_entry_atime(VALUE self)
|
505
|
+
{
|
506
|
+
return rb_ivar_get(self, rb_intern("@atime"));
|
507
|
+
}
|
508
|
+
|
509
|
+
/*
|
510
|
+
* Document-method: etime
|
511
|
+
*
|
512
|
+
* Returns the expire time of this entry.
|
513
|
+
*
|
514
|
+
*/
|
515
|
+
VALUE
|
516
|
+
rb_kp_entry_etime(VALUE self)
|
517
|
+
{
|
518
|
+
return rb_ivar_get(self, rb_intern("@etime"));
|
519
|
+
}
|
520
|
+
|
521
|
+
/*
|
522
|
+
* Document-method: Keepass::Group#entries
|
523
|
+
*
|
524
|
+
* Returns the entries contained within this group.
|
525
|
+
*
|
526
|
+
*/
|
527
|
+
VALUE
|
528
|
+
rb_kp_grp_entries(VALUE self)
|
529
|
+
{
|
530
|
+
VALUE kdb_object;
|
531
|
+
kpass_db *kdb;
|
532
|
+
VALUE entries;
|
533
|
+
uint32_t i;
|
534
|
+
uint32_t group_id;
|
535
|
+
|
536
|
+
kdb_object = rb_ivar_get(self, rb_intern("@kdb")); /* fetch the Keepass::Database */
|
537
|
+
kdb_object = rb_ivar_get(kdb_object, rb_intern("@kdb")); /* fetch the wrapper object */
|
538
|
+
Data_Get_Struct(kdb_object, kpass_db, kdb);
|
539
|
+
|
540
|
+
group_id = NUM2INT(rb_ivar_get(self, rb_intern("@id")));
|
541
|
+
|
542
|
+
entries = rb_ary_new();
|
543
|
+
|
544
|
+
for(i = 0; i < kdb->entries_len; i++) {
|
545
|
+
kpass_entry *entry = kdb->entries[i];
|
546
|
+
VALUE rb_entry;
|
547
|
+
|
548
|
+
if(entry->group_id != group_id) {
|
549
|
+
continue;
|
550
|
+
}
|
551
|
+
|
552
|
+
if(! strcmp(entry->title, "Meta-Info")) {
|
553
|
+
continue;
|
554
|
+
}
|
555
|
+
|
556
|
+
rb_entry = _create_ruby_entry(entry);
|
557
|
+
|
558
|
+
rb_ary_push(entries, rb_entry);
|
559
|
+
}
|
560
|
+
|
561
|
+
return entries;
|
562
|
+
}
|
563
|
+
|
564
|
+
void
|
565
|
+
Init_keepass(void)
|
566
|
+
{
|
567
|
+
/* Module Initialization */
|
568
|
+
mKeepass = rb_define_module("Keepass");
|
569
|
+
cDatabase = rb_define_class_under(mKeepass, "Database",
|
570
|
+
rb_cObject);
|
571
|
+
cGroup = rb_define_class_under(mKeepass, "Group", rb_cObject);
|
572
|
+
cEntry = rb_define_class_under(mKeepass, "Entry", rb_cObject);
|
573
|
+
|
574
|
+
eException_KeepassException = rb_define_class_under(mKeepass, "Exception", rb_eStandardError);
|
575
|
+
eException_unknown = rb_define_class_under(mKeepass, "UnknownException", eException_KeepassException);
|
576
|
+
eException_kpass_decrypt_data_fail = rb_define_class_under(mKeepass, "DecryptDataException", eException_KeepassException);
|
577
|
+
eException_kpass_decrypt_db_fail = rb_define_class_under(mKeepass, "DecryptDbException", eException_KeepassException);
|
578
|
+
eException_kpass_hash_pw_fail = rb_define_class_under(mKeepass, "HashPwException", eException_KeepassException);
|
579
|
+
eException_kpass_prepare_key_fail = rb_define_class_under(mKeepass, "PrepareKeyException", eException_KeepassException);
|
580
|
+
eException_kpass_load_decrypted_data_entry_fail = rb_define_class_under(mKeepass, "LoadDecryptedDataEntryException", eException_KeepassException);
|
581
|
+
eException_kpass_load_decrypted_data_group_fail = rb_define_class_under(mKeepass, "LoadDecryptedDataGroupException", eException_KeepassException);
|
582
|
+
eException_kpass_init_db_fail = rb_define_class_under(mKeepass, "InitDbException", eException_KeepassException);
|
583
|
+
eException_kpass_encrypt_db_fail = rb_define_class_under(mKeepass, "EncryptDbException", eException_KeepassException);
|
584
|
+
eException_kpass_encrypt_data_fail = rb_define_class_under(mKeepass, "EncryptDataException", eException_KeepassException);
|
585
|
+
eException_kpass_pack_db_fail = rb_define_class_under(mKeepass, "PackDbException", eException_KeepassException);
|
586
|
+
eException_kpass_verification_fail = rb_define_class_under(mKeepass, "VerificationException", eException_KeepassException);
|
587
|
+
eException_kpass_unsupported_flag = rb_define_class_under(mKeepass, "UnsupportedFlagException", eException_KeepassException);
|
588
|
+
eException_kpass_not_implemented = rb_define_class_under(mKeepass, "NotImplementedException", eException_KeepassException);
|
589
|
+
|
590
|
+
/* Database Methods */
|
591
|
+
rb_define_singleton_method(cDatabase, "open", rb_kp_db_open, 2);
|
592
|
+
rb_define_method(cDatabase, "initialize", rb_kp_db_initialize, 2);
|
593
|
+
rb_define_method(cDatabase, "groups", rb_kp_db_groups, 0);
|
594
|
+
rb_define_method(cDatabase, "entries", rb_kp_db_entries, 0);
|
595
|
+
|
596
|
+
/* Group Methods */
|
597
|
+
rb_define_method(cGroup, "name", rb_kp_grp_name, 0);
|
598
|
+
rb_define_method(cGroup, "mtime", rb_kp_grp_mtime, 0);
|
599
|
+
rb_define_method(cGroup, "ctime", rb_kp_grp_ctime, 0);
|
600
|
+
rb_define_method(cGroup, "atime", rb_kp_grp_atime, 0);
|
601
|
+
rb_define_method(cGroup, "etime", rb_kp_grp_etime, 0);
|
602
|
+
rb_define_method(cGroup, "entries", rb_kp_grp_entries, 0);
|
603
|
+
|
604
|
+
/* Entry Methods */
|
605
|
+
rb_define_method(cEntry, "name", rb_kp_entry_name, 0);
|
606
|
+
rb_define_method(cEntry, "password", rb_kp_entry_password, 0);
|
607
|
+
rb_define_method(cEntry, "mtime", rb_kp_entry_mtime, 0);
|
608
|
+
rb_define_method(cEntry, "ctime", rb_kp_entry_ctime, 0);
|
609
|
+
rb_define_method(cEntry, "atime", rb_kp_entry_atime, 0);
|
610
|
+
rb_define_method(cEntry, "etime", rb_kp_entry_etime, 0);
|
611
|
+
}
|
data/test/entries.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'keepass'
|
3
|
+
|
4
|
+
KP_FILE = 'test/example.kdb'
|
5
|
+
CORRECT_PASSWORD = 'abc123'
|
6
|
+
TIME_METHODS = [ :ctime, :mtime, :atime, :etime ]
|
7
|
+
|
8
|
+
class TestKeepass_Entries < MiniTest::Unit::TestCase
|
9
|
+
def test_time_methods
|
10
|
+
kdb = Keepass::Database.open KP_FILE, CORRECT_PASSWORD
|
11
|
+
entry = kdb.entries[0]
|
12
|
+
|
13
|
+
times = TIME_METHODS.collect do |method|
|
14
|
+
(entry.send method).class
|
15
|
+
end
|
16
|
+
|
17
|
+
assert_equal times, [ Time ] * TIME_METHODS.length
|
18
|
+
end
|
19
|
+
end
|
data/test/groups.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'keepass'
|
3
|
+
|
4
|
+
KP_FILE = 'test/example.kdb'
|
5
|
+
CORRECT_PASSWORD = 'abc123'
|
6
|
+
TIME_METHODS = [ :ctime, :mtime, :atime, :etime ]
|
7
|
+
|
8
|
+
class TestKeepass_Groups < MiniTest::Unit::TestCase
|
9
|
+
def test_group_names
|
10
|
+
kdb = Keepass::Database.open KP_FILE, CORRECT_PASSWORD
|
11
|
+
seen_groups = []
|
12
|
+
|
13
|
+
kdb.groups.each do |group|
|
14
|
+
seen_groups << group.name
|
15
|
+
end
|
16
|
+
|
17
|
+
assert_equal seen_groups, %w(Test1 Test2)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_time_methods
|
21
|
+
kdb = Keepass::Database.open KP_FILE, CORRECT_PASSWORD
|
22
|
+
group = kdb.groups[0]
|
23
|
+
|
24
|
+
times = TIME_METHODS.collect do |method|
|
25
|
+
(group.send method).class
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_equal times, [ Time ] * TIME_METHODS.length
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_entries
|
32
|
+
kdb = Keepass::Database.open KP_FILE, CORRECT_PASSWORD
|
33
|
+
group = kdb.groups[0]
|
34
|
+
entries = group.entries
|
35
|
+
|
36
|
+
seen_entries = []
|
37
|
+
|
38
|
+
entries.each do |entry|
|
39
|
+
seen_entries << {
|
40
|
+
:name => entry.name,
|
41
|
+
:password => entry.password,
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
seen_entries.sort! do |a, b|
|
46
|
+
a[:name] <=> b[:name]
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_equal seen_entries, [
|
50
|
+
{ :name => 'Test1', :password => '12345' },
|
51
|
+
{ :name => 'Test2', :password => 'abcde' },
|
52
|
+
]
|
53
|
+
end
|
54
|
+
end
|
data/test/open.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'keepass'
|
3
|
+
|
4
|
+
KP_FILE = 'test/example.kdb'
|
5
|
+
CORRECT_PASSWORD = 'abc123'
|
6
|
+
INCORRECT_PASSWORD = '123abc'
|
7
|
+
OPEN_METHODS = [ :open, :new ]
|
8
|
+
|
9
|
+
class TestKeepass_Open < MiniTest::Unit::TestCase
|
10
|
+
def assert_no_exception
|
11
|
+
begin
|
12
|
+
yield
|
13
|
+
pass
|
14
|
+
rescue Exception => e
|
15
|
+
flunk "Unexpected exception: #{e}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def assert_exception ex_type
|
20
|
+
begin
|
21
|
+
yield
|
22
|
+
flunk 'No exception was seen'
|
23
|
+
rescue ex_type => e
|
24
|
+
pass
|
25
|
+
rescue Exception => e
|
26
|
+
flunk "Unexpected exception: #{e}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_open_string_ok
|
31
|
+
OPEN_METHODS.each do |method|
|
32
|
+
assert_no_exception do
|
33
|
+
kdb = Keepass::Database.send method, KP_FILE, CORRECT_PASSWORD
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_open_file_ok
|
39
|
+
OPEN_METHODS.each do |method|
|
40
|
+
f = File.open(KP_FILE, 'rb')
|
41
|
+
|
42
|
+
assert_no_exception do
|
43
|
+
kdb = Keepass::Database.send method, f, CORRECT_PASSWORD
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_open_string_with_bad_password
|
49
|
+
OPEN_METHODS.each do |method|
|
50
|
+
assert_exception Keepass::DecryptDataException do
|
51
|
+
kdb = Keepass::Database.send method, KP_FILE, INCORRECT_PASSWORD
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_open_file_with_bad_password
|
57
|
+
OPEN_METHODS.each do |method|
|
58
|
+
f = File.open(KP_FILE, 'rb')
|
59
|
+
|
60
|
+
assert_exception Keepass::DecryptDataException do
|
61
|
+
kdb = Keepass::Database.send method, f, INCORRECT_PASSWORD
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: keepass
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Rob Hoelz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-11 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A Ruby library for accessing Keepass password databases
|
15
|
+
email: rob@hoelz.ro
|
16
|
+
executables: []
|
17
|
+
extensions:
|
18
|
+
- ext/extconf.rb
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.rdoc
|
21
|
+
files:
|
22
|
+
- ext/keepass.c
|
23
|
+
- README.rdoc
|
24
|
+
- test/entries.rb
|
25
|
+
- test/open.rb
|
26
|
+
- test/groups.rb
|
27
|
+
- ext/extconf.rb
|
28
|
+
homepage: https://github.com/hoelzro/ruby-keepass
|
29
|
+
licenses:
|
30
|
+
- MIT
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- ext
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements:
|
48
|
+
- libkpass
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 1.8.24
|
51
|
+
signing_key:
|
52
|
+
specification_version: 3
|
53
|
+
summary: Ruby bindings for libkpass
|
54
|
+
test_files:
|
55
|
+
- test/entries.rb
|
56
|
+
- test/open.rb
|
57
|
+
- test/groups.rb
|