]> Dogcows Code - chaz/p5-File-KDBX/blob - lib/File/KDBX.pm
e5fcb27c91919ace7eff6f38ae4294acfefd0d74
[chaz/p5-File-KDBX] / lib / File / KDBX.pm
1 package File::KDBX;
2 # ABSTRACT: Encrypted databases to store secret text and files
3
4 use warnings;
5 use strict;
6
7 use Crypt::PRNG qw(random_bytes);
8 use Devel::GlobalDestruction;
9 use File::KDBX::Constants qw(:all);
10 use File::KDBX::Error;
11 use File::KDBX::Safe;
12 use File::KDBX::Util qw(:empty erase generate_uuid search simple_expression_query snakify);
13 use Hash::Util::FieldHash qw(fieldhashes);
14 use List::Util qw(any);
15 use Ref::Util qw(is_ref is_arrayref is_plain_hashref);
16 use Scalar::Util qw(blessed);
17 use Time::Piece;
18 use boolean;
19 use namespace::clean;
20
21 our $VERSION = '999.999'; # VERSION
22 our $WARNINGS = 1;
23
24 fieldhashes \my (%SAFE, %KEYS);
25
26 =method new
27
28 $kdbx = File::KDBX->new(%attributes);
29 $kdbx = File::KDBX->new($kdbx); # copy constructor
30
31 Construct a new L<File::KDBX>.
32
33 =cut
34
35 sub new {
36 my $class = shift;
37
38 # copy constructor
39 return $_[0]->clone if @_ == 1 && blessed $_[0] && $_[0]->isa($class);
40
41 my $self = bless {}, $class;
42 $self->init(@_);
43 $self->_set_default_attributes if empty $self;
44 return $self;
45 }
46
47 sub DESTROY { local ($., $@, $!, $^E, $?); !in_global_destruction and $_[0]->reset }
48
49 =method init
50
51 $kdbx = $kdbx->init(%attributes);
52
53 Initialize a L<File::KDBX> with a new set of attributes. Returns itself to allow method chaining.
54
55 This is called by L</new>.
56
57 =cut
58
59 sub init {
60 my $self = shift;
61 my %args = @_;
62
63 @$self{keys %args} = values %args;
64
65 return $self;
66 }
67
68 =method reset
69
70 $kdbx = $kdbx->reset;
71
72 Set a L<File::KDBX> to an empty state, ready to load a KDBX file or build a new one. Returns itself to allow
73 method chaining.
74
75 =cut
76
77 sub reset {
78 my $self = shift;
79 erase $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
80 erase $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
81 erase $self->{raw};
82 %$self = ();
83 $self->_remove_safe;
84 return $self;
85 }
86
87 =method clone
88
89 $kdbx_copy = $kdbx->clone;
90 $kdbx_copy = File::KDBX->new($kdbx);
91
92 Clone a L<File::KDBX>. The clone will be an exact copy and completely independent of the original.
93
94 =cut
95
96 sub clone {
97 my $self = shift;
98 require Storable;
99 return Storable::dclone($self);
100 }
101
102 sub STORABLE_freeze {
103 my $self = shift;
104 my $cloning = shift;
105
106 my $copy = {%$self};
107
108 return '', $copy, $KEYS{$self} // (), $SAFE{$self} // ();
109 }
110
111 sub STORABLE_thaw {
112 my $self = shift;
113 my $cloning = shift;
114 shift;
115 my $clone = shift;
116 my $key = shift;
117 my $safe = shift;
118
119 @$self{keys %$clone} = values %$clone;
120 $KEYS{$self} = $key;
121 $SAFE{$self} = $safe;
122
123 for my $object (@{$self->all_groups}, @{$self->all_entries(history => 1)}) {
124 $object->kdbx($self);
125 }
126 }
127
128 ##############################################################################
129
130 =method load
131
132 =method load_string
133
134 =method load_file
135
136 =method load_handle
137
138 $kdbx = KDBX::File->load(\$string, $key);
139 $kdbx = KDBX::File->load(*IO, $key);
140 $kdbx = KDBX::File->load($filepath, $key);
141 $kdbx->load(...); # also instance method
142
143 $kdbx = File::KDBX->load_string($string, $key);
144 $kdbx = File::KDBX->load_string(\$string, $key);
145 $kdbx->load_string(...); # also instance method
146
147 $kdbx = File::KDBX->load_file($filepath, $key);
148 $kdbx->load_file(...); # also instance method
149
150 $kdbx = File::KDBX->load_handle($fh, $key);
151 $kdbx = File::KDBX->load_handle(*IO, $key);
152 $kdbx->load_handle(...); # also instance method
153
154 Load a KDBX file from a string buffer, IO handle or file from a filesystem.
155
156 L<File::KDBX::Loader> does the heavy lifting.
157
158 =cut
159
160 sub load { shift->_loader->load(@_) }
161 sub load_string { shift->_loader->load_string(@_) }
162 sub load_file { shift->_loader->load_file(@_) }
163 sub load_handle { shift->_loader->load_handle(@_) }
164
165 sub _loader {
166 my $self = shift;
167 $self = $self->new if !ref $self;
168 require File::KDBX::Loader;
169 File::KDBX::Loader->new(kdbx => $self);
170 }
171
172 =method dump
173
174 =method dump_string
175
176 =method dump_file
177
178 =method dump_handle
179
180 $kdbx->dump(\$string, $key);
181 $kdbx->dump(*IO, $key);
182 $kdbx->dump($filepath, $key);
183
184 $kdbx->dump_string(\$string, $key);
185 \$string = $kdbx->dump_string($key);
186
187 $kdbx->dump_file($filepath, $key);
188
189 $kdbx->dump_handle($fh, $key);
190 $kdbx->dump_handle(*IO, $key);
191
192 Dump a KDBX file to a string buffer, IO handle or file in a filesystem.
193
194 L<File::KDBX::Dumper> does the heavy lifting.
195
196 =cut
197
198 sub dump { shift->_dumper->dump(@_) }
199 sub dump_string { shift->_dumper->dump_string(@_) }
200 sub dump_file { shift->_dumper->dump_file(@_) }
201 sub dump_handle { shift->_dumper->dump_handle(@_) }
202
203 sub _dumper {
204 my $self = shift;
205 $self = $self->new if !ref $self;
206 require File::KDBX::Dumper;
207 File::KDBX::Dumper->new(kdbx => $self);
208 }
209
210 ##############################################################################
211
212 =method user_agent_string
213
214 $string = $kdbx->user_agent_string;
215
216 Get a text string identifying the database client software.
217
218 =cut
219
220 sub user_agent_string {
221 require Config;
222 sprintf('%s/%s (%s/%s; %s/%s; %s)',
223 __PACKAGE__, $VERSION, @Config::Config{qw(package version osname osvers archname)});
224 }
225
226 =attr sig1
227
228 =attr sig2
229
230 =attr version
231
232 =attr headers
233
234 =attr inner_headers
235
236 =attr meta
237
238 =attr binaries
239
240 =attr deleted_objects
241
242 =attr raw
243
244 $value = $kdbx->$attr;
245 $kdbx->$attr($value);
246
247 Get and set attributes.
248
249 =cut
250
251 my %ATTRS = (
252 sig1 => KDBX_SIG1,
253 sig2 => KDBX_SIG2_2,
254 version => KDBX_VERSION_3_1,
255 headers => sub { +{} },
256 inner_headers => sub { +{} },
257 meta => sub { +{} },
258 binaries => sub { +{} },
259 deleted_objects => sub { +{} },
260 raw => undef,
261 );
262 my %ATTRS_HEADERS = (
263 HEADER_COMMENT() => '',
264 HEADER_CIPHER_ID() => CIPHER_UUID_CHACHA20,
265 HEADER_COMPRESSION_FLAGS() => COMPRESSION_GZIP,
266 HEADER_MASTER_SEED() => sub { random_bytes(32) },
267 # HEADER_TRANSFORM_SEED() => sub { random_bytes(32) },
268 # HEADER_TRANSFORM_ROUNDS() => 100_000,
269 HEADER_ENCRYPTION_IV() => sub { random_bytes(16) },
270 # HEADER_INNER_RANDOM_STREAM_KEY() => sub { random_bytes(32) }, # 64?
271 HEADER_STREAM_START_BYTES() => sub { random_bytes(32) },
272 # HEADER_INNER_RANDOM_STREAM_ID() => STREAM_ID_CHACHA20,
273 HEADER_KDF_PARAMETERS() => sub {
274 +{
275 KDF_PARAM_UUID() => KDF_UUID_AES,
276 KDF_PARAM_AES_ROUNDS() => $_[0]->headers->{+HEADER_TRANSFORM_ROUNDS} // KDF_DEFAULT_AES_ROUNDS,
277 KDF_PARAM_AES_SEED() => $_[0]->headers->{+HEADER_TRANSFORM_SEED} // random_bytes(32),
278 };
279 },
280 # HEADER_PUBLIC_CUSTOM_DATA() => sub { +{} },
281 );
282 my %ATTRS_META = (
283 generator => '',
284 header_hash => '',
285 database_name => '',
286 database_name_changed => sub { gmtime },
287 database_description => '',
288 database_description_changed => sub { gmtime },
289 default_username => '',
290 default_username_changed => sub { gmtime },
291 maintenance_history_days => 0,
292 color => '',
293 master_key_changed => sub { gmtime },
294 master_key_change_rec => -1,
295 master_key_change_force => -1,
296 # memory_protection => sub { +{} },
297 custom_icons => sub { +{} },
298 recycle_bin_enabled => true,
299 recycle_bin_uuid => "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
300 recycle_bin_changed => sub { gmtime },
301 entry_templates_group => "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
302 entry_templates_group_changed => sub { gmtime },
303 last_selected_group => "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
304 last_top_visible_group => "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
305 history_max_items => HISTORY_DEFAULT_MAX_ITEMS,
306 history_max_size => HISTORY_DEFAULT_MAX_SIZE,
307 settings_changed => sub { gmtime },
308 # binaries => sub { +{} },
309 # custom_data => sub { +{} },
310 );
311 my %ATTRS_MEMORY_PROTECTION = (
312 protect_title => false,
313 protect_username => false,
314 protect_password => true,
315 protect_url => false,
316 protect_notes => false,
317 auto_enable_visual_hiding => false,
318 );
319
320 sub _update_group_uuid {
321 my $self = shift;
322 my $old_uuid = shift // return;
323 my $new_uuid = shift;
324
325 my $meta = $self->meta;
326 $self->recycle_bin_uuid($new_uuid) if $old_uuid eq ($meta->{recycle_bin_uuid} // '');
327 $self->entry_templates_group($new_uuid) if $old_uuid eq ($meta->{entry_templates_group} // '');
328 $self->last_selected_group($new_uuid) if $old_uuid eq ($meta->{last_selected_group} // '');
329 $self->last_top_visible_group($new_uuid) if $old_uuid eq ($meta->{last_top_visible_group} // '');
330
331 for my $group (@{$self->all_groups}) {
332 $group->last_top_visible_entry($new_uuid) if $old_uuid eq ($group->{last_top_visible_entry} // '');
333 $group->previous_parent_group($new_uuid) if $old_uuid eq ($group->{previous_parent_group} // '');
334 }
335 for my $entry (@{$self->all_entries}) {
336 $entry->previous_parent_group($new_uuid) if $old_uuid eq ($entry->{previous_parent_group} // '');
337 }
338 }
339
340 sub _update_entry_uuid {
341 my $self = shift;
342 my $old_uuid = shift // return;
343 my $new_uuid = shift;
344
345 for my $entry (@{$self->all_entries}) {
346 $entry->previous_parent_group($new_uuid) if $old_uuid eq ($entry->{previous_parent_group} // '');
347 }
348 }
349
350 while (my ($attr, $default) = each %ATTRS) {
351 no strict 'refs'; ## no critic (ProhibitNoStrict)
352 *{$attr} = sub {
353 my $self = shift;
354 $self->{$attr} = shift if @_;
355 $self->{$attr} //= (ref $default eq 'CODE') ? $default->($self) : $default;
356 };
357 }
358 while (my ($attr, $default) = each %ATTRS_HEADERS) {
359 no strict 'refs'; ## no critic (ProhibitNoStrict)
360 *{$attr} = sub {
361 my $self = shift;
362 $self->headers->{$attr} = shift if @_;
363 $self->headers->{$attr} //= (ref $default eq 'CODE') ? $default->($self) : $default;
364 };
365 }
366 while (my ($attr, $default) = each %ATTRS_META) {
367 no strict 'refs'; ## no critic (ProhibitNoStrict)
368 *{$attr} = sub {
369 my $self = shift;
370 $self->meta->{$attr} = shift if @_;
371 $self->meta->{$attr} //= (ref $default eq 'CODE') ? $default->($self) : $default;
372 };
373 }
374 while (my ($attr, $default) = each %ATTRS_MEMORY_PROTECTION) {
375 no strict 'refs'; ## no critic (ProhibitNoStrict)
376 *{$attr} = sub {
377 my $self = shift;
378 $self->meta->{$attr} = shift if @_;
379 $self->meta->{$attr} //= (ref $default eq 'CODE') ? $default->($self) : $default;
380 };
381 }
382
383 my @ATTRS_OTHER = (
384 HEADER_TRANSFORM_SEED,
385 HEADER_TRANSFORM_ROUNDS,
386 HEADER_INNER_RANDOM_STREAM_KEY,
387 HEADER_INNER_RANDOM_STREAM_ID,
388 );
389 sub _set_default_attributes {
390 my $self = shift;
391 $self->$_ for keys %ATTRS, keys %ATTRS_HEADERS, keys %ATTRS_META, keys %ATTRS_MEMORY_PROTECTION,
392 @ATTRS_OTHER;
393 }
394
395 =method memory_protection
396
397 \%settings = $kdbx->memory_protection
398 $kdbx->memory_protection(\%settings);
399
400 $bool = $kdbx->memory_protection($string_key);
401 $kdbx->memory_protection($string_key => $bool);
402
403 Get or set memory protection settings. This globally (for the whole database) configures whether and which of
404 the standard strings should be memory-protected. The default setting is to memory-protect only I<Password>
405 strings.
406
407 Memory protection can be toggled individually for each entry string, and individual settings take precedence
408 over these global settings.
409
410 =cut
411
412 sub memory_protection {
413 my $self = shift;
414 $self->{meta}{memory_protection} = shift if @_ == 1 && is_plain_hashref($_[0]);
415 return $self->{meta}{memory_protection} //= {} if !@_;
416
417 my $string_key = shift;
418 my $key = 'protect_' . lc($string_key);
419
420 $self->meta->{memory_protection}{$key} = shift if @_;
421 $self->meta->{memory_protection}{$key};
422 }
423
424 =method minimum_version
425
426 $version = $kdbx->minimum_version;
427
428 Determine the minimum file version required to save a database losslessly. Using certain databases features
429 might increase this value. For example, setting the KDF to Argon2 will increase the minimum version to at
430 least C<KDBX_VERSION_4_0> (i.e. C<0x00040000>) because Argon2 was introduced with KDBX4.
431
432 This method never returns less than C<KDBX_VERSION_3_1> (i.e. C<0x00030001>). That file version is so
433 ubiquitious and well-supported, there are seldom reasons to dump in a lesser format nowadays.
434
435 B<WARNING:> If you dump a database with a minimum version higher than the current L</version>, the dumper will
436 typically issue a warning and automatically upgrade the database. This seems like the safest behavior in order
437 to avoid data loss, but lower versions have the benefit of being compatible with more software. It is possible
438 to prevent auto-upgrades by explicitly telling the dumper which version to use, but you do run the risk of
439 data loss. A database will never be automatically downgraded.
440
441 =cut
442
443 sub minimum_version {
444 my $self = shift;
445
446 return KDBX_VERSION_4_1 if any {
447 nonempty $_->{last_modification_time}
448 } values %{$self->custom_data};
449
450 return KDBX_VERSION_4_1 if any {
451 nonempty $_->{name} || nonempty $_->{last_modification_time}
452 } values %{$self->custom_icons};
453
454 return KDBX_VERSION_4_1 if any {
455 nonempty $_->previous_parent_group || nonempty $_->tags ||
456 any { nonempty $_->{last_modification_time} } values %{$_->custom_data}
457 } @{$self->all_groups};
458
459 return KDBX_VERSION_4_1 if any {
460 nonempty $_->previous_parent_group || (defined $_->quality_check && !$_->quality_check) ||
461 any { nonempty $_->{last_modification_time} } values %{$_->custom_data}
462 } @{$self->all_entries(history => 1)};
463
464 return KDBX_VERSION_4_0 if $self->kdf->uuid ne KDF_UUID_AES;
465
466 return KDBX_VERSION_4_0 if nonempty $self->public_custom_data;
467
468 return KDBX_VERSION_4_0 if any {
469 nonempty $_->custom_data
470 } @{$self->all_groups}, @{$self->all_entries(history => 1)};
471
472 return KDBX_VERSION_3_1;
473 }
474
475 ##############################################################################
476
477 =method add_group
478
479 $kdbx->add_group($group, %options);
480 $kdbx->add_group(%group_attributes, %options);
481
482 Add a group to a database. This is equivalent to identifying a parent group and calling
483 L<File::KDBX::Group/add_group> on the parent group, forwarding the arguments. Available options:
484
485 =for :list
486 * C<group> (aka C<parent>) - Group (object or group UUID) to add the group to (default: root group)
487
488 =cut
489
490 sub add_group {
491 my $self = shift;
492 my $group = @_ % 2 == 1 ? shift : undef;
493 my %args = @_;
494
495 # find the right group to add the group to
496 my $parent = delete $args{group} // delete $args{parent} // $self->root;
497 ($parent) = $self->find_groups({uuid => $parent}) if !ref $parent;
498 $parent or throw 'Invalid group';
499
500 return $parent->add_group(defined $group ? $group : (), %args, kdbx => $self);
501 }
502
503 sub _wrap_group {
504 my $self = shift;
505 my $group = shift;
506 require File::KDBX::Group;
507 return File::KDBX::Group->wrap($group, $self);
508 }
509
510 =method root
511
512 $group = $kdbx->root;
513 $kdbx->root($group);
514
515 Get or set a database's root group. You don't necessarily need to explicitly create or set a root group
516 because it autovivifies when adding entries and groups to the database.
517
518 Every database has only a single root group at a time. Some old KDB files might have multiple root groups.
519 When reading such files, a single implicit root group is created to contain the other explicit groups. When
520 writing to such a format, if the root group looks like it was implicitly created then it won't be written and
521 the resulting file might have multiple root groups. This allows working with older files without changing
522 their written internal structure while still adhering to the modern restrictions while the database is opened.
523
524 B<WARNING:> The root group of a KDBX database contains all of the database's entries and other groups. If you
525 replace the root group, you are essentially replacing the entire database contents with something else.
526
527 =cut
528
529 sub root {
530 my $self = shift;
531 if (@_) {
532 $self->{root} = $self->_wrap_group(@_);
533 $self->{root}->kdbx($self);
534 }
535 $self->{root} //= $self->_implicit_root;
536 return $self->_wrap_group($self->{root});
537 }
538
539 sub _kpx_groups {
540 my $self = shift;
541 return [] if !$self->{root};
542 return $self->_has_implicit_root ? $self->root->groups : [$self->root];
543 }
544
545 sub _has_implicit_root {
546 my $self = shift;
547 my $root = $self->root;
548 my $temp = __PACKAGE__->_implicit_root;
549 # If an implicit root group has been changed in any significant way, it is no longer implicit.
550 return $root->name eq $temp->name &&
551 $root->is_expanded ^ $temp->is_expanded &&
552 $root->notes eq $temp->notes &&
553 !@{$root->entries} &&
554 !defined $root->custom_icon_uuid &&
555 !keys %{$root->custom_data} &&
556 $root->icon_id == $temp->icon_id &&
557 $root->expires ^ $temp->expires &&
558 $root->default_auto_type_sequence eq $temp->default_auto_type_sequence &&
559 !defined $root->enable_auto_type &&
560 !defined $root->enable_searching;
561 }
562
563 sub _implicit_root {
564 my $self = shift;
565 require File::KDBX::Group;
566 return File::KDBX::Group->new(
567 name => 'Root',
568 is_expanded => true,
569 notes => 'Added as an implicit root group by '.__PACKAGE__.'.',
570 ref $self ? (kdbx => $self) : (),
571 );
572 }
573
574 =method all_groups
575
576 \@groups = $kdbx->all_groups(%options);
577 \@groups = $kdbx->all_groups($base_group, %options);
578
579 Get all groups deeply in a database, or all groups within a specified base group, in a flat array. Supported
580 options:
581
582 =for :list
583 * C<base> - Only include groups within a base group (same as C<$base_group>) (default: root)
584 * C<include_base> - Include the base group in the results (default: true)
585
586 =cut
587
588 sub all_groups {
589 my $self = shift;
590 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
591 my $base = $args{base} // $self->root;
592
593 my @groups = $args{include_base} // 1 ? $self->_wrap_group($base) : ();
594
595 for my $subgroup (@{$base->{groups} || []}) {
596 my $more = $self->all_groups($subgroup);
597 push @groups, @$more;
598 }
599
600 return \@groups;
601 }
602
603 =method trace_lineage
604
605 \@lineage = $kdbx->trace_lineage($group);
606 \@lineage = $kdbx->trace_lineage($group, $base_group);
607 \@lineage = $kdbx->trace_lineage($entry);
608 \@lineage = $kdbx->trace_lineage($entry, $base_group);
609
610 Get the direct line of ancestors from C<$base_group> (default: the root group) to a group or entry. The
611 lineage includes the base group but I<not> the target group or entry. Returns C<undef> if the target is not in
612 the database structure.
613
614 =cut
615
616 sub trace_lineage {
617 my $self = shift;
618 my $object = shift;
619 return $object->lineage(@_);
620 }
621
622 sub _trace_lineage {
623 my $self = shift;
624 my $object = shift;
625 my @lineage = @_;
626
627 push @lineage, $self->root if !@lineage;
628 my $base = $lineage[-1] or return [];
629
630 my $uuid = $object->uuid;
631 return \@lineage if any { $_->uuid eq $uuid } @{$base->groups || []}, @{$base->entries || []};
632
633 for my $subgroup (@{$base->groups || []}) {
634 my $result = $self->_trace_lineage($object, @lineage, $subgroup);
635 return $result if $result;
636 }
637 }
638
639 =method find_groups
640
641 @groups = $kdbx->find_groups($query, %options);
642
643 Find all groups deeply that match to a query. Options are the same as for L</all_groups>.
644
645 See L</QUERY> for a description of what C<$query> can be.
646
647 =cut
648
649 sub find_groups {
650 my $self = shift;
651 my $query = shift or throw 'Must provide a query';
652 my %args = @_;
653 my %all_groups = (
654 base => $args{base},
655 include_base => $args{include_base},
656 );
657 return @{search($self->all_groups(%all_groups), is_arrayref($query) ? @$query : $query)};
658 }
659
660 sub remove {
661 my $self = shift;
662 my $object = shift;
663 }
664
665 ##############################################################################
666
667 =method add_entry
668
669 $kdbx->add_entry($entry, %options);
670 $kdbx->add_entry(%entry_attributes, %options);
671
672 Add a entry to a database. This is equivalent to identifying a parent group and calling
673 L<File::KDBX::Group/add_entry> on the parent group, forwarding the arguments. Available options:
674
675 =for :list
676 * C<group> (aka C<parent>) - Group (object or group UUID) to add the entry to (default: root group)
677
678 =cut
679
680 sub add_entry {
681 my $self = shift;
682 my $entry = @_ % 2 == 1 ? shift : undef;
683 my %args = @_;
684
685 # find the right group to add the entry to
686 my $parent = delete $args{group} // delete $args{parent} // $self->root;
687 ($parent) = $self->find_groups({uuid => $parent}) if !ref $parent;
688 $parent or throw 'Invalid group';
689
690 return $parent->add_entry(defined $entry ? $entry : (), %args, kdbx => $self);
691 }
692
693 sub _wrap_entry {
694 my $self = shift;
695 my $entry = shift;
696 require File::KDBX::Entry;
697 return File::KDBX::Entry->wrap($entry, $self);
698 }
699
700 =method all_entries
701
702 \@entries = $kdbx->all_entries(%options);
703 \@entries = $kdbx->all_entries($base_group, %options);
704
705 Get entries deeply in a database, in a flat array. Supported options:
706
707 =for :list
708 * C<base> - Only include entries within a base group (same as C<$base_group>) (default: root)
709 * C<auto_type> - Only include entries with auto-type enabled (default: false, include all)
710 * C<search> - Only include entries within groups with search enabled (default: false, include all)
711 * C<history> - Also include historical entries (default: false, include only active entries)
712
713 =cut
714
715 sub all_entries {
716 my $self = shift;
717 my %args = @_ % 2 == 0 ? @_ : (base => shift, @_);
718
719 my $base = $args{base} // $self->root;
720 my $history = $args{history};
721 my $search = $args{search};
722 my $auto_type = $args{auto_type};
723
724 my $enable_auto_type = $base->{enable_auto_type} // true;
725 my $enable_searching = $base->{enable_searching} // true;
726
727 my @entries;
728 if ((!$search || $enable_searching) && (!$auto_type || $enable_auto_type)) {
729 push @entries,
730 map { $self->_wrap_entry($_) }
731 grep { !$auto_type || $_->{auto_type}{enabled} }
732 map { $_, $history ? @{$_->{history} || []} : () }
733 @{$base->{entries} || []};
734 }
735
736 for my $subgroup (@{$base->{groups} || []}) {
737 my $more = $self->all_entries($subgroup,
738 auto_type => $auto_type,
739 search => $search,
740 history => $history,
741 );
742 push @entries, @$more;
743 }
744
745 return \@entries;
746 }
747
748 =method find_entries
749
750 =method find_entries_simple
751
752 @entries = $kdbx->find_entries($query, %options);
753
754 @entries = $kdbx->find_entries_simple($expression, \@fields, %options);
755 @entries = $kdbx->find_entries_simple($expression, $operator, \@fields, %options);
756
757 Find all entries deeply that match a query. Options are the same as for L</all_entries>.
758
759 See L</QUERY> for a description of what C<$query> can be.
760
761 =cut
762
763 sub find_entries {
764 my $self = shift;
765 my $query = shift or throw 'Must provide a query';
766 my %args = @_;
767 my %all_entries = (
768 base => $args{base},
769 auto_type => $args{auto_type},
770 search => $args{search},
771 history => $args{history},
772 );
773 return @{search($self->all_entries(%all_entries), is_arrayref($query) ? @$query : $query)};
774 }
775
776 sub find_entries_simple {
777 my $self = shift;
778 my $text = shift;
779 my $op = @_ && !is_ref($_[0]) ? shift : undef;
780 my $fields = shift;
781 is_arrayref($fields) or throw q{Usage: find_entries_simple($expression, [$op,] \@fields)};
782 return $self->find_entries([\$text, $op, $fields], @_);
783 }
784
785 ##############################################################################
786
787 =method custom_icon
788
789 \%icon = $kdbx->custom_icon($uuid);
790 $kdbx->custom_icon($uuid => \%icon);
791 $kdbx->custom_icon(%icon);
792 $kdbx->custom_icon(uuid => $value, %icon);
793
794
795 =cut
796
797 sub custom_icon {
798 my $self = shift;
799 my %args = @_ == 2 ? (uuid => shift, value => shift)
800 : @_ % 2 == 1 ? (uuid => shift, @_) : @_;
801
802 if (!$args{key} && !$args{value}) {
803 my %standard = (key => 1, value => 1, last_modification_time => 1);
804 my @other_keys = grep { !$standard{$_} } keys %args;
805 if (@other_keys == 1) {
806 my $key = $args{key} = $other_keys[0];
807 $args{value} = delete $args{$key};
808 }
809 }
810
811 my $key = $args{key} or throw 'Must provide a custom_icons key to access';
812
813 return $self->{meta}{custom_icons}{$key} = $args{value} if is_plain_hashref($args{value});
814
815 while (my ($field, $value) = each %args) {
816 $self->{meta}{custom_icons}{$key}{$field} = $value;
817 }
818 return $self->{meta}{custom_icons}{$key};
819 }
820
821 =method custom_icon_data
822
823 $image_data = $kdbx->custom_icon_data($uuid);
824
825 Get a custom icon.
826
827 =cut
828
829 sub custom_icon_data {
830 my $self = shift;
831 my $uuid = shift // return;
832 return if !exists $self->custom_icons->{$uuid};
833 return $self->custom_icons->{$uuid}{data};
834 }
835
836 =method add_custom_icon
837
838 $uuid = $kdbx->add_custom_icon($image_data, %attributes);
839
840 Add a custom icon and get its UUID. If not provided, a random UUID will be generated. Possible attributes:
841
842 =for :list
843 * C<uuid> - Icon UUID
844 * C<name> - Name of the icon (text, KDBX4.1+)
845 * C<last_modification_time> - Just what it says (datetime, KDBX4.1+)
846
847 =cut
848
849 sub add_custom_icon {
850 my $self = shift;
851 my $img = shift or throw 'Must provide image data';
852 my %args = @_;
853
854 my $uuid = $args{uuid} // generate_uuid(sub { !$self->custom_icons->{$_} });
855 $self->custom_icons->{$uuid} = {
856 @_,
857 uuid => $uuid,
858 data => $img,
859 };
860 return $uuid;
861 }
862
863 =method remove_custom_icon
864
865 $kdbx->remove_custom_icon($uuid);
866
867 Remove a custom icon.
868
869 =cut
870
871 sub remove_custom_icon {
872 my $self = shift;
873 my $uuid = shift;
874 delete $self->custom_icons->{$uuid};
875 }
876
877 ##############################################################################
878
879 =method custom_data
880
881 \%all_data = $kdbx->custom_data;
882 $kdbx->custom_data(\%all_data);
883
884 \%data = $kdbx->custom_data($key);
885 $kdbx->custom_data($key => \%data);
886 $kdbx->custom_data(%data);
887 $kdbx->custom_data(key => $value, %data);
888
889 Get and set custom data. Custom data is metadata associated with a database.
890
891 Each data item can have a few attributes associated with it.
892
893 =for :list
894 * C<key> - A unique text string identifier used to look up the data item (required)
895 * C<value> - A text string value (required)
896 * C<last_modification_time> (optional, KDBX4.1+)
897
898 =cut
899
900 sub custom_data {
901 my $self = shift;
902 $self->{meta}{custom_data} = shift if @_ == 1 && is_plain_hashref($_[0]);
903 return $self->{meta}{custom_data} //= {} if !@_;
904
905 my %args = @_ == 2 ? (key => shift, value => shift)
906 : @_ % 2 == 1 ? (key => shift, @_) : @_;
907
908 if (!$args{key} && !$args{value}) {
909 my %standard = (key => 1, value => 1, last_modification_time => 1);
910 my @other_keys = grep { !$standard{$_} } keys %args;
911 if (@other_keys == 1) {
912 my $key = $args{key} = $other_keys[0];
913 $args{value} = delete $args{$key};
914 }
915 }
916
917 my $key = $args{key} or throw 'Must provide a custom_data key to access';
918
919 return $self->{meta}{custom_data}{$key} = $args{value} if is_plain_hashref($args{value});
920
921 while (my ($field, $value) = each %args) {
922 $self->{meta}{custom_data}{$key}{$field} = $value;
923 }
924 return $self->{meta}{custom_data}{$key};
925 }
926
927 =method custom_data_value
928
929 $value = $kdbx->custom_data_value($key);
930
931 Exactly the same as L</custom_data> except returns just the custom data's value rather than a structure of
932 attributes. This is a shortcut for:
933
934 my $data = $kdbx->custom_data($key);
935 my $value = defined $data ? $data->{value} : undef;
936
937 =cut
938
939 sub custom_data_value {
940 my $self = shift;
941 my $data = $self->custom_data(@_) // return;
942 return $data->{value};
943 }
944
945 =method public_custom_data
946
947 \%all_data = $kdbx->public_custom_data;
948 $kdbx->public_custom_data(\%all_data);
949
950 $value = $kdbx->public_custom_data($key);
951 $kdbx->public_custom_data($key => $value);
952
953 Get and set public custom data. Public custom data is similar to custom data but different in some important
954 ways. Public custom data:
955
956 =for :list
957 * can store strings, booleans and up to 64-bit integer values (custom data can only store text values)
958 * is NOT encrypted within a KDBX file (hence the "public" part of the name)
959 * is a flat hash/dict of key-value pairs (no other associated fields like modification times)
960
961 =cut
962
963 sub public_custom_data {
964 my $self = shift;
965 $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} = shift if @_ == 1 && is_plain_hashref($_[0]);
966 return $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA} //= {} if !@_;
967
968 my $key = shift or throw 'Must provide a public_custom_data key to access';
969 $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA}{$key} = shift if @_;
970 return $self->{headers}{+HEADER_PUBLIC_CUSTOM_DATA}{$key};
971 }
972
973 ##############################################################################
974
975 # TODO
976
977 # sub merge_to {
978 # my $self = shift;
979 # my $other = shift;
980 # my %options = @_; # prefer_old / prefer_new
981 # $other->merge_from($self);
982 # }
983
984 # sub merge_from {
985 # my $self = shift;
986 # my $other = shift;
987
988 # die 'Not implemented';
989 # }
990
991 ##############################################################################
992
993 =method resolve_reference
994
995 $string = $kdbx->resolve_reference($reference);
996 $string = $kdbx->resolve_reference($wanted, $search_in, $expression);
997
998 Resolve a L<field reference|https://keepass.info/help/base/fieldrefs.html>. A field reference is a kind of
999 string placeholder. You can use a field reference to refer directly to a standard field within an entry. Field
1000 references are resolved automatically while expanding entry strings (i.e. replacing placeholders), but you can
1001 use this method to resolve on-the-fly references that aren't part of any actual string in the database.
1002
1003 If the reference does not resolve to any field, C<undef> is returned. If the reference resolves to multiple
1004 fields, only the first one is returned (in the same order as L</all_entries>). To avoid ambiguity, you can
1005 refer to a specific entry by its UUID.
1006
1007 The syntax of a reference is: C<< {REF:<WantedField>@<SearchIn>:<Text>} >>. C<Text> is a
1008 L</"Simple Expression">. C<WantedField> and C<SearchIn> are both single character codes representing a field:
1009
1010 =for :list
1011 * C<T> - Title
1012 * C<U> - UserName
1013 * C<P> - Password
1014 * C<A> - URL
1015 * C<N> - Notes
1016 * C<I> - UUID
1017 * C<O> - Other custom strings
1018
1019 Since C<O> does not represent any specific field, it cannot be used as the C<WantedField>.
1020
1021 Examples:
1022
1023 To get the value of the I<UserName> string of the first entry with "My Bank" in the title:
1024
1025 my $username = $kdbx->resolve_reference('{REF:U@T:"My Bank"}');
1026 # OR the {REF:...} wrapper is optional
1027 my $username = $kdbx->resolve_reference('U@T:"My Bank"');
1028 # OR separate the arguments
1029 my $username = $kdbx->resolve_reference(U => T => '"My Bank"');
1030
1031 Note how the text is a L</"Simple Expression">, so search terms with spaces must be surrounded in double
1032 quotes.
1033
1034 To get the I<Password> string of a specific entry (identified by its UUID):
1035
1036 my $password = $kdbx->resolve_reference('{REF:P@I:46C9B1FFBD4ABC4BBB260C6190BAD20C}');
1037
1038 =cut
1039
1040 sub resolve_reference {
1041 my $self = shift;
1042 my $wanted = shift // return;
1043 my $search_in = shift;
1044 my $text = shift;
1045
1046 if (!defined $text) {
1047 $wanted =~ s/^\{REF:([^\}]+)\}$/$1/i;
1048 ($wanted, $search_in, $text) = $wanted =~ /^([TUPANI])\@([TUPANIO]):(.*)$/i;
1049 }
1050 $wanted && $search_in && nonempty($text) or return;
1051
1052 my %fields = (
1053 T => 'expanded_title',
1054 U => 'expanded_username',
1055 P => 'expanded_password',
1056 A => 'expanded_url',
1057 N => 'expanded_notes',
1058 I => 'id',
1059 O => 'other_strings',
1060 );
1061 $wanted = $fields{$wanted} or return;
1062 $search_in = $fields{$search_in} or return;
1063
1064 my $query = simple_expression_query($text, ($search_in eq 'id' ? 'eq' : '=~'), $search_in);
1065
1066 my ($entry) = $self->find_entries($query);
1067 $entry or return;
1068
1069 return $entry->$wanted;
1070 }
1071
1072 our %PLACEHOLDERS = (
1073 # placeholder => sub { my ($entry, $arg) = @_; ... };
1074 'TITLE' => sub { $_[0]->expanded_title },
1075 'USERNAME' => sub { $_[0]->expanded_username },
1076 'PASSWORD' => sub { $_[0]->expanded_password },
1077 'NOTES' => sub { $_[0]->expanded_notes },
1078 'S:' => sub { $_[0]->string_value($_[1]) },
1079 'URL' => sub { $_[0]->expanded_url },
1080 'URL:RMVSCM' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
1081 'URL:WITHOUTSCHEME' => sub { local $_ = $_[0]->url; s!^[^:/\?\#]+://!!; $_ },
1082 'URL:SCM' => sub { (split_url($_[0]->url))[0] },
1083 'URL:SCHEME' => sub { (split_url($_[0]->url))[0] }, # non-standard
1084 'URL:HOST' => sub { (split_url($_[0]->url))[2] },
1085 'URL:PORT' => sub { (split_url($_[0]->url))[3] },
1086 'URL:PATH' => sub { (split_url($_[0]->url))[4] },
1087 'URL:QUERY' => sub { (split_url($_[0]->url))[5] },
1088 'URL:HASH' => sub { (split_url($_[0]->url))[6] }, # non-standard
1089 'URL:FRAGMENT' => sub { (split_url($_[0]->url))[6] }, # non-standard
1090 'URL:USERINFO' => sub { (split_url($_[0]->url))[1] },
1091 'URL:USERNAME' => sub { (split_url($_[0]->url))[7] },
1092 'URL:PASSWORD' => sub { (split_url($_[0]->url))[8] },
1093 'UUID' => sub { local $_ = format_uuid($_[0]->uuid); s/-//g; $_ },
1094 'REF:' => sub { $_[0]->kdbx->resolve_reference($_[1]) },
1095 'INTERNETEXPLORER' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('iexplore') },
1096 'FIREFOX' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('firefox') },
1097 'GOOGLECHROME' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('google-chrome') },
1098 'OPERA' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('opera') },
1099 'SAFARI' => sub { load_optional('IPC::Cmd'); IPC::Cmd::can_run('safari') },
1100 'APPDIR' => sub { load_optional('FindBin'); $FindBin::Bin },
1101 'GROUP' => sub { my $p = $_[0]->parent; $p ? $p->name : undef },
1102 'GROUP_PATH' => sub { $_[0]->path },
1103 'GROUP_NOTES' => sub { my $p = $_[0]->parent; $p ? $p->notes : undef },
1104 # 'GROUP_SEL'
1105 # 'GROUP_SEL_PATH'
1106 # 'GROUP_SEL_NOTES'
1107 # 'DB_PATH'
1108 # 'DB_DIR'
1109 # 'DB_NAME'
1110 # 'DB_BASENAME'
1111 # 'DB_EXT'
1112 'ENV:' => sub { $ENV{$_[1]} },
1113 'ENV_DIRSEP' => sub { load_optional('File::Spec')->catfile('', '') },
1114 'ENV_PROGRAMFILES_X86' => sub { $ENV{'ProgramFiles(x86)'} || $ENV{'ProgramFiles'} },
1115 # 'T-REPLACE-RX:'
1116 # 'T-CONV:'
1117 'DT_SIMPLE' => sub { localtime->strftime('%Y%m%d%H%M%S') },
1118 'DT_YEAR' => sub { localtime->strftime('%Y') },
1119 'DT_MONTH' => sub { localtime->strftime('%m') },
1120 'DT_DAY' => sub { localtime->strftime('%d') },
1121 'DT_HOUR' => sub { localtime->strftime('%H') },
1122 'DT_MINUTE' => sub { localtime->strftime('%M') },
1123 'DT_SECOND' => sub { localtime->strftime('%S') },
1124 'DT_UTC_SIMPLE' => sub { gmtime->strftime('%Y%m%d%H%M%S') },
1125 'DT_UTC_YEAR' => sub { gmtime->strftime('%Y') },
1126 'DT_UTC_MONTH' => sub { gmtime->strftime('%m') },
1127 'DT_UTC_DAY' => sub { gmtime->strftime('%d') },
1128 'DT_UTC_HOUR' => sub { gmtime->strftime('%H') },
1129 'DT_UTC_MINUTE' => sub { gmtime->strftime('%M') },
1130 'DT_UTC_SECOND' => sub { gmtime->strftime('%S') },
1131 # 'PICKCHARS'
1132 # 'PICKCHARS:'
1133 # 'PICKFIELD'
1134 # 'NEWPASSWORD'
1135 # 'NEWPASSWORD:'
1136 # 'PASSWORD_ENC'
1137 'HMACOTP' => sub { $_[0]->hmac_otp },
1138 'TIMEOTP' => sub { $_[0]->time_otp },
1139 'C:' => sub { '' }, # comment
1140 # 'BASE'
1141 # 'BASE:'
1142 # 'CLIPBOARD'
1143 # 'CLIPBOARD-SET:'
1144 # 'CMD:'
1145 );
1146
1147 ##############################################################################
1148
1149 =method lock
1150
1151 $kdbx->lock;
1152
1153 Encrypt all protected strings in a database. The encrypted strings are stored in a L<File::KDBX::Safe>
1154 associated with the database and the actual strings will be replaced with C<undef> to indicate their protected
1155 state. Returns itself to allow method chaining.
1156
1157 =cut
1158
1159 sub _safe {
1160 my $self = shift;
1161 $SAFE{$self} = shift if @_;
1162 $SAFE{$self};
1163 }
1164
1165 sub _remove_safe { delete $SAFE{$_[0]} }
1166
1167 sub lock {
1168 my $self = shift;
1169
1170 $self->_safe and return $self;
1171
1172 my @strings;
1173
1174 my $entries = $self->all_entries(history => 1);
1175 for my $entry (@$entries) {
1176 push @strings, grep { $_->{protect} } values %{$entry->{strings} || {}};
1177 }
1178
1179 $self->_safe(File::KDBX::Safe->new(\@strings));
1180
1181 return $self;
1182 }
1183
1184 =method unlock
1185
1186 $kdbx->unlock;
1187
1188 Decrypt all protected strings in a database, replacing C<undef> placeholders with unprotected values. Returns
1189 itself to allow method chaining.
1190
1191 =cut
1192
1193 sub peek {
1194 my $self = shift;
1195 my $string = shift;
1196 my $safe = $self->_safe or return;
1197 return $safe->peek($string);
1198 }
1199
1200 sub unlock {
1201 my $self = shift;
1202 my $safe = $self->_safe or return $self;
1203
1204 $safe->unlock;
1205 $self->_remove_safe;
1206
1207 return $self;
1208 }
1209
1210 # sub unlock_scoped {
1211 # my $self = shift;
1212 # return if !$self->is_locked;
1213 # require Scope::Guard;
1214 # my $guard = Scope::Guard->new(sub { $self->lock });
1215 # $self->unlock;
1216 # return $guard;
1217 # }
1218
1219 =method is_locked
1220
1221 $bool = $kdbx->is_locked;
1222
1223 Get whether or not a database's strings are memory-protected. If this is true, then some or all of the
1224 protected strings within the database will be unavailable (literally have C<undef> values) until L</unlock> is
1225 called.
1226
1227 =cut
1228
1229 sub is_locked { $_[0]->_safe ? 1 : 0 }
1230
1231 ##############################################################################
1232
1233 =method randomize_seeds
1234
1235 $kdbx->randomize_seeds;
1236
1237 Set various keys, seeds and IVs to random values. These values are used by the cryptographic functions that
1238 secure the database when dumped. The attributes that will be randomized are:
1239
1240 =for :list
1241 * L</encryption_iv>
1242 * L</inner_random_stream_key>
1243 * L</master_seed>
1244 * L</stream_start_bytes>
1245 * L</transform_seed>
1246
1247 Randomizing these values has no effect on a loaded database. These are only used when a database is dumped.
1248 You normally do not need to call this method explicitly because the dumper does it explicitly by default.
1249
1250 =cut
1251
1252 sub randomize_seeds {
1253 my $self = shift;
1254 $self->encryption_iv(random_bytes(16));
1255 $self->inner_random_stream_key(random_bytes(64));
1256 $self->master_seed(random_bytes(32));
1257 $self->stream_start_bytes(random_bytes(32));
1258 $self->transform_seed(random_bytes(32));
1259 }
1260
1261 ##############################################################################
1262
1263 =method key
1264
1265 $key = $kdbx->key;
1266 $key = $kdbx->key($key);
1267 $key = $kdbx->key($primitive);
1268
1269 Get or set a L<File::KDBX::Key>. This is the master key (i.e. a password or a key file that can decrypt
1270 a database). See L<File::KDBX::Key/new> for an explanation of what the primitive can be.
1271
1272 You generally don't need to call this directly because you can provide the key directly to the loader or
1273 dumper when loading or saving a KDBX file.
1274
1275 =cut
1276
1277 sub key {
1278 my $self = shift;
1279 $KEYS{$self} = File::KDBX::Key->new(@_) if @_;
1280 $KEYS{$self};
1281 }
1282
1283 =method composite_key
1284
1285 $key = $kdbx->composite_key($key);
1286 $key = $kdbx->composite_key($primitive);
1287
1288 Construct a L<File::KDBX::Key::Composite> from a primitive. See L<File::KDBX::Key/new> for an explanation of
1289 what the primitive can be. If the primitive does not represent a composite key, it will be wrapped.
1290
1291 You generally don't need to call this directly. The parser and writer use it to transform a master key into
1292 a raw encryption key.
1293
1294 =cut
1295
1296 sub composite_key {
1297 my $self = shift;
1298 require File::KDBX::Key::Composite;
1299 return File::KDBX::Key::Composite->new(@_);
1300 }
1301
1302 =method kdf
1303
1304 $kdf = $kdbx->kdf(%options);
1305 $kdf = $kdbx->kdf(\%parameters, %options);
1306
1307 Get a L<File::KDBX::KDF> (key derivation function).
1308
1309 Options:
1310
1311 =for :list
1312 * C<params> - KDF parameters, same as C<\%parameters> (default: value of L</kdf_parameters>)
1313
1314 =cut
1315
1316 sub kdf {
1317 my $self = shift;
1318 my %args = @_ % 2 == 1 ? (params => shift, @_) : @_;
1319
1320 my $params = $args{params};
1321 my $compat = $args{compatible} // 1;
1322
1323 $params //= $self->kdf_parameters;
1324 $params = {%{$params || {}}};
1325
1326 if (empty $params || !defined $params->{+KDF_PARAM_UUID}) {
1327 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES;
1328 }
1329 if ($params->{+KDF_PARAM_UUID} eq KDF_UUID_AES) {
1330 # AES_CHALLENGE_RESPONSE is equivalent to AES if there are no challenge-response keys, and since
1331 # non-KeePassXC implementations don't support challenge-response keys anyway, there's no problem with
1332 # always using AES_CHALLENGE_RESPONSE for all KDBX4+ databases.
1333 # For compatibility, we should not *write* AES_CHALLENGE_RESPONSE, but the dumper handles that.
1334 if ($self->version >= KDBX_VERSION_4_0) {
1335 $params->{+KDF_PARAM_UUID} = KDF_UUID_AES_CHALLENGE_RESPONSE;
1336 }
1337 $params->{+KDF_PARAM_AES_SEED} //= $self->transform_seed;
1338 $params->{+KDF_PARAM_AES_ROUNDS} //= $self->transform_rounds;
1339 }
1340
1341 require File::KDBX::KDF;
1342 return File::KDBX::KDF->new(%$params);
1343 }
1344
1345 sub transform_seed {
1346 my $self = shift;
1347 $self->headers->{+HEADER_TRANSFORM_SEED} =
1348 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_SEED} = shift if @_;
1349 $self->headers->{+HEADER_TRANSFORM_SEED} =
1350 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_SEED} //= random_bytes(32);
1351 }
1352
1353 sub transform_rounds {
1354 my $self = shift;
1355 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
1356 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_ROUNDS} = shift if @_;
1357 $self->headers->{+HEADER_TRANSFORM_ROUNDS} =
1358 $self->headers->{+HEADER_KDF_PARAMETERS}{+KDF_PARAM_AES_ROUNDS} //= 100_000;
1359 }
1360
1361 =method cipher
1362
1363 $cipher = $kdbx->cipher(key => $key);
1364 $cipher = $kdbx->cipher(key => $key, iv => $iv, uuid => $uuid);
1365
1366 Get a L<File::KDBX::Cipher> capable of encrypting and decrypting the body of a database file.
1367
1368 A key is required. This should be a raw encryption key made up of a fixed number of octets (depending on the
1369 cipher), not a L<File::KDBX::Key> or primitive.
1370
1371 If not passed, the UUID comes from C<< $kdbx->headers->{cipher_id} >> and the encryption IV comes from
1372 C<< $kdbx->headers->{encryption_iv} >>.
1373
1374 You generally don't need to call this directly. The parser and writer use it to decrypt and encrypt KDBX
1375 files.
1376
1377 =cut
1378
1379 sub cipher {
1380 my $self = shift;
1381 my %args = @_;
1382
1383 $args{uuid} //= $self->headers->{+HEADER_CIPHER_ID};
1384 $args{iv} //= $self->headers->{+HEADER_ENCRYPTION_IV};
1385
1386 require File::KDBX::Cipher;
1387 return File::KDBX::Cipher->new(%args);
1388 }
1389
1390 =method random_stream
1391
1392 $cipher = $kdbx->random_stream;
1393 $cipher = $kdbx->random_stream(id => $stream_id, key => $key);
1394
1395 Get a L<File::KDBX::Cipher::Stream> for decrypting and encrypting protected values.
1396
1397 If not passed, the ID and encryption key comes from C<< $kdbx->headers->{inner_random_stream_id} >> and
1398 C<< $kdbx->headers->{inner_random_stream_key} >> (respectively) for KDBX3 files and from
1399 C<< $kdbx->inner_headers->{inner_random_stream_key} >> and
1400 C<< $kdbx->inner_headers->{inner_random_stream_id} >> (respectively) for KDBX4 files.
1401
1402 You generally don't need to call this directly. The parser and writer use it to scramble protected strings.
1403
1404 =cut
1405
1406 sub random_stream {
1407 my $self = shift;
1408 my %args = @_;
1409
1410 $args{stream_id} //= delete $args{id} // $self->inner_random_stream_id;
1411 $args{key} //= $self->inner_random_stream_key;
1412
1413 require File::KDBX::Cipher;
1414 File::KDBX::Cipher->new(%args);
1415 }
1416
1417 sub inner_random_stream_id {
1418 my $self = shift;
1419 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
1420 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} = shift if @_;
1421 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_ID}
1422 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_ID} //= do {
1423 my $version = $self->minimum_version;
1424 $version < KDBX_VERSION_4_0 ? STREAM_ID_SALSA20 : STREAM_ID_CHACHA20;
1425 };
1426 }
1427
1428 sub inner_random_stream_key {
1429 my $self = shift;
1430 if (@_) {
1431 # These are probably the same SvPV so erasing one will CoW, but erasing the second should do the
1432 # trick anyway.
1433 erase \$self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY};
1434 erase \$self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY};
1435 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1436 = $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} = shift;
1437 }
1438 $self->inner_headers->{+INNER_HEADER_INNER_RANDOM_STREAM_KEY}
1439 //= $self->headers->{+HEADER_INNER_RANDOM_STREAM_KEY} //= random_bytes(64); # 32
1440 }
1441
1442 #########################################################################################
1443
1444 sub check {
1445 # - Fixer tool. Can repair inconsistencies, including:
1446 # - Orphaned binaries... not really a thing anymore since we now distribute binaries amongst entries
1447 # - Unused custom icons (OFF, data loss)
1448 # - Duplicate icons
1449 # - All data types are valid
1450 # - date times are correct
1451 # - boolean fields
1452 # - All UUIDs refer to things that exist
1453 # - previous parent group
1454 # - recycle bin
1455 # - last selected group
1456 # - last visible group
1457 # - Enforce history size limits (ON)
1458 # - Check headers/meta (ON)
1459 # - Duplicate deleted objects (ON)
1460 # - Duplicate window associations (OFF)
1461 # - Only one root group (ON)
1462 # - Header UUIDs match known ciphers/KDFs?
1463 }
1464
1465 #########################################################################################
1466
1467 =attr comment
1468
1469 A text string associated with the database. Often unset.
1470
1471 =attr cipher_id
1472
1473 The UUID of a cipher used to encrypt the database when stored as a file.
1474
1475 See L</File::KDBX::Cipher>.
1476
1477 =attr compression_flags
1478
1479 Configuration for whether or not and how the database gets compressed. See
1480 L<File::KDBX::Constants/":compression">.
1481
1482 =attr master_seed
1483
1484 The master seed is a string of 32 random bytes that is used as salt in hashing the master key when loading
1485 and saving the database. If a challenge-response key is used in the master key, the master seed is also the
1486 challenge.
1487
1488 The master seed I<should> be changed each time the database is saved to file.
1489
1490 =attr transform_seed
1491
1492 The transform seed is a string of 32 random bytes that is used in the key derivation function, either as the
1493 salt or the key (depending on the algorithm).
1494
1495 The transform seed I<should> be changed each time the database is saved to file.
1496
1497 =attr transform_rounds
1498
1499 The number of rounds or iterations used in the key derivation function. Increasing this number makes loading
1500 and saving the database slower by design in order to make dictionary and brute force attacks more costly.
1501
1502 =attr encryption_iv
1503
1504 The initialization vector used by the cipher.
1505
1506 The encryption IV I<should> be changed each time the database is saved to file.
1507
1508 =attr inner_random_stream_key
1509
1510 The encryption key (possibly including the IV, depending on the cipher) used to encrypt the protected strings
1511 within the database.
1512
1513 =attr stream_start_bytes
1514
1515 A string of 32 random bytes written in the header and encrypted in the body. If the bytes do not match when
1516 loading a file then the wrong master key was used or the file is corrupt. Only KDBX 2 and KDBX 3 files use
1517 this. KDBX 4 files use an improved HMAC method to verify the master key and data integrity of the header and
1518 entire file body.
1519
1520 =attr inner_random_stream_id
1521
1522 A number indicating the cipher algorithm used to encrypt the protected strings within the database, usually
1523 Salsa20 or ChaCha20. See L<File::KDBX::Constants/":random_stream">.
1524
1525 =attr kdf_parameters
1526
1527 A hash/dict of key-value pairs used to configure the key derivation function. This is the KDBX4+ way to
1528 configure the KDF, superceding L</transform_seed> and L</transform_rounds>.
1529
1530 =attr generator
1531
1532 The name of the software used to generate the KDBX file.
1533
1534 =attr header_hash
1535
1536 The header hash used to verify that the file header is not corrupt. (KDBX 2 - KDBX 3.1, removed KDBX 4.0)
1537
1538 =attr database_name
1539
1540 Name of the database.
1541
1542 =attr database_name_changed
1543
1544 Timestamp indicating when the database name was last changed.
1545
1546 =attr database_description
1547
1548 Description of the database
1549
1550 =attr database_description_changed
1551
1552 Timestamp indicating when the database description was last changed.
1553
1554 =attr default_username
1555
1556 When a new entry is created, the I<UserName> string will be populated with this value.
1557
1558 =attr default_username_changed
1559
1560 Timestamp indicating when the default username was last changed.
1561
1562 =attr maintenance_history_days
1563
1564 TODO... not really sure what this is. 😀
1565
1566 =attr color
1567
1568 A color associated with the database (in the form C<#ffffff> where "f" is a hexidecimal digit). Some agents
1569 use this to help users visually distinguish between different databases.
1570
1571 =attr master_key_changed
1572
1573 Timestamp indicating when the master key was last changed.
1574
1575 =attr master_key_change_rec
1576
1577 Number of days until the agent should prompt to recommend changing the master key.
1578
1579 =attr master_key_change_force
1580
1581 Number of days until the agent should prompt to force changing the master key.
1582
1583 Note: This is purely advisory. It is up to the individual agent software to actually enforce it.
1584 C<File::KDBX> does NOT enforce it.
1585
1586 =attr recycle_bin_enabled
1587
1588 Boolean indicating whether removed groups and entries should go to a recycle bin or be immediately deleted.
1589
1590 =attr recycle_bin_uuid
1591
1592 The UUID of a group used to store thrown-away groups and entries.
1593
1594 =attr recycle_bin_changed
1595
1596 Timestamp indicating when the recycle bin was last changed.
1597
1598 =attr entry_templates_group
1599
1600 The UUID of a group containing template entries used when creating new entries.
1601
1602 =attr entry_templates_group_changed
1603
1604 Timestamp indicating when the entry templates group was last changed.
1605
1606 =attr last_selected_group
1607
1608 The UUID of the previously-selected group.
1609
1610 =attr last_top_visible_group
1611
1612 The UUID of the group visible at the top of the list.
1613
1614 =attr history_max_items
1615
1616 The maximum number of historical entries allowed to be saved for each entry.
1617
1618 =attr history_max_size
1619
1620 The maximum total size (in bytes) that each individual entry's history is allowed to grow.
1621
1622 =attr settings_changed
1623
1624 Timestamp indicating when the database settings were last updated.
1625
1626 =attr protect_title
1627
1628 Alias of the L</memory_protection> setting for the I<Title> string.
1629
1630 =attr protect_username
1631
1632 Alias of the L</memory_protection> setting for the I<UserName> string.
1633
1634 =attr protect_password
1635
1636 Alias of the L</memory_protection> setting for the I<Password> string.
1637
1638 =attr protect_url
1639
1640 Alias of the L</memory_protection> setting for the I<URL> string.
1641
1642 =attr protect_notes
1643
1644 Alias of the L</memory_protection> setting for the I<Notes> string.
1645
1646 =cut
1647
1648 #########################################################################################
1649
1650 sub TO_JSON { +{%{$_[0]}} }
1651
1652 1;
1653 __END__
1654
1655 =for Pod::Coverage STORABLE_freeze STORABLE_thaw TO_JSON
1656
1657 =head1 SYNOPSIS
1658
1659 use File::KDBX;
1660
1661 my $kdbx = File::KDBX->new;
1662
1663 my $group = $kdbx->add_group(
1664 name => 'Passwords',
1665 );
1666
1667 my $entry = $group->add_entry(
1668 title => 'My Bank',
1669 password => 's3cr3t',
1670 );
1671
1672 $kdbx->dump_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
1673
1674 $kdbx = File::KDBX->load_file('passwords.kdbx', 'M@st3rP@ssw0rd!');
1675
1676 for my $entry (@{ $kdbx->all_entries }) {
1677 say 'Entry: ', $entry->title;
1678 }
1679
1680 =head1 DESCRIPTION
1681
1682 B<File::KDBX> provides everything you need to work with a KDBX database. A KDBX database is a hierarchical
1683 object database which is commonly used to store secret information securely. It was developed for the KeePass
1684 password safe. See L</"KDBX Introduction"> for more information about KDBX.
1685
1686 This module lets you query entries, create new entries, delete entries and modify entries. The distribution
1687 also includes various parsers and generators for serializing and persisting databases.
1688
1689 This design of this software was influenced by the L<KeePassXC|https://github.com/keepassxreboot/keepassxc>
1690 implementation of KeePass as well as the L<File::KeePass> module. B<File::KeePass> is an alternative module
1691 that works well in most cases but has a small backlog of bugs and security issues and also does not work with
1692 newer KDBX version 4 files. If you're coming here from the B<File::KeePass> world, you might be interested in
1693 L<File::KeePass::KDBX> that is a drop-in replacement for B<File::KeePass> that uses B<File::KDBX> for storage.
1694
1695 =head2 KDBX Introduction
1696
1697 A KDBX database consists of a hierarchical I<group> of I<entries>. Entries can contain zero or more key-value
1698 pairs of I<strings> and zero or more I<binaries> (i.e. octet strings). Groups, entries, strings and binaries:
1699 that's the KDBX vernacular. A small amount of metadata (timestamps, etc.) is associated with each entry, group
1700 and the database as a whole.
1701
1702 You can think of a KDBX database kind of like a file system, where groups are directories, entries are files,
1703 and strings and binaries make up a file's contents.
1704
1705 Databases are typically persisted as a encrypted, compressed files. They are usually accessed directly (i.e.
1706 not over a network). The primary focus of this type of database is data security. It is ideal for storing
1707 relatively small amounts of data (strings and binaries) that must remain secret except to such individuals as
1708 have the correct I<master key>. Even if the database file were to be "leaked" to the public Internet, it
1709 should be virtually impossible to crack with a strong key. See L</SECURITY> for an overview of security
1710 considerations.
1711
1712 =head1 RECIPES
1713
1714 =head2 Create a new database
1715
1716 my $kdbx = File::KDBX->new;
1717
1718 my $group = $kdbx->add_group(name => 'Passwords);
1719 my $entry = $group->add_entry(
1720 title => 'WayneCorp',
1721 username => 'bwayne',
1722 password => 'iambatman',
1723 url => 'https://example.com/login'
1724 );
1725 $entry->add_auto_type_window_association('WayneCorp - Mozilla Firefox', '{PASSWORD}{ENTER}');
1726
1727 $kdbx->dump_file('mypasswords.kdbx', 'master password CHANGEME');
1728
1729 =head2 Read an existing database
1730
1731 my $kdbx = File::KDBX->load_file('mypasswords.kdbx', 'master password CHANGEME');
1732 $kdbx->unlock;
1733
1734 for my $entry (@{ $kdbx->all_entries }) {
1735 say 'Found password for ', $entry->title, ':';
1736 say ' Username: ', $entry->username;
1737 say ' Password: ', $entry->password;
1738 }
1739
1740 =head2 Search for entries
1741
1742 my @entries = $kdbx->find_entries({
1743 title => 'WayneCorp',
1744 }, search => 1);
1745
1746 See L</QUERY> for many more query examples.
1747
1748 =head2 Search for entries by auto-type window association
1749
1750 my @entry_key_sequences = $kdbx->find_entries_for_window('WayneCorp - Mozilla Firefox');
1751 for my $pair (@entry_key_sequences) {
1752 my ($entry, $key_sequence) = @$pair;
1753 say 'Entry title: ', $entry->title, ', key sequence: ', $key_sequence;
1754 }
1755
1756 Example output:
1757
1758 Entry title: WayneCorp, key sequence: {PASSWORD}{ENTER}
1759
1760 =head1 SECURITY
1761
1762 One of the biggest threats to your database security is how easily the encryption key can be brute-forced.
1763 Strong brute-force protection depends on a couple factors:
1764
1765 =for :list
1766 * Using unguessable passwords, passphrases and key files.
1767 * Using a brute-force resistent key derivation function.
1768
1769 The first factor is up to you. This module does not enforce strong master keys. It is up to you to pick or
1770 generate strong keys.
1771
1772 The KDBX format allows for the key derivation function to be tuned. The idea is that you want each single
1773 brute-foce attempt to be expensive (in terms of time, CPU usage or memory usage), so that making a lot of
1774 attempts (which would be required if you have a strong master key) gets I<really> expensive.
1775
1776 How expensive you want to make each attempt is up to you and can depend on the application.
1777
1778 This and other KDBX-related security issues are covered here more in depth:
1779 L<https://keepass.info/help/base/security.html>
1780
1781 Here are other security risks you should be thinking about:
1782
1783 =head2 Cryptography
1784
1785 This distribution uses the excellent L<CryptX> and L<Crypt::Argon2> packages to handle all crypto-related
1786 functions. As such, a lot of the security depends on the quality of these dependencies. Fortunately these
1787 modules are maintained and appear to have good track records.
1788
1789 The KDBX format has evolved over time to incorporate improved security practices and cryptographic functions.
1790 This package uses the following functions for authentication, hashing, encryption and random number
1791 generation:
1792
1793 =for :list
1794 * AES-128 (legacy)
1795 * AES-256
1796 * Argon2d & Argon2id
1797 * CBC block mode
1798 * HMAC-SHA256
1799 * SHA256
1800 * SHA512
1801 * Salsa20 & ChaCha20
1802 * Twofish
1803
1804 At the time of this writing, I am not aware of any successful attacks against any of these functions. These
1805 are among the most-analyzed and widely-adopted crypto functions available.
1806
1807 The KDBX format allows the body cipher and key derivation function to be configured. If a flaw is discovered
1808 in one of these functions, you can hopefully just switch to a better function without needing to update this
1809 software. A later software release may phase out the use of any functions which are no longer secure.
1810
1811 =head2 Memory Protection
1812
1813 It is not a good idea to keep secret information unencrypted in system memory for longer than is needed. The
1814 address space of your program can generally be read by a user with elevated privileges on the system. If your
1815 system is memory-constrained or goes into a hibernation mode, the contents of your address space could be
1816 written to a disk where it might be persisted for long time.
1817
1818 There might be system-level things you can do to reduce your risk, like using swap encryption and limiting
1819 system access to your program's address space while your program is running.
1820
1821 B<File::KDBX> helps minimize (but not eliminate) risk by keeping secrets encrypted in memory until accessed
1822 and zeroing out memory that holds secrets after they're no longer needed, but it's not a silver bullet.
1823
1824 For one thing, the encryption key is stored in the same address space. If core is dumped, the encryption key
1825 is available to be found out. But at least there is the chance that the encryption key and the encrypted
1826 secrets won't both be paged out while memory-constrained.
1827
1828 Another problem is that some perls (somewhat notoriously) copy around memory behind the scenes willy nilly,
1829 and it's difficult know when perl makes a copy of a secret in order to be able to zero it out later. It might
1830 be impossible. The good news is that perls with SvPV copy-on-write (enabled by default beginning with perl
1831 5.20) are much better in this regard. With COW, it's mostly possible to know what operations will cause perl
1832 to copy the memory of a scalar string, and the number of copies will be significantly reduced. There is a unit
1833 test named F<t/memory-protection.t> in this distribution that can be run on POSIX systems to determine how
1834 well B<File::KDBX> memory protection is working.
1835
1836 Memory protection also depends on how your application handles secrets. If your app code is handling scalar
1837 strings with secret information, it's up to you to make sure its memory is zeroed out when no longer needed.
1838 L<File::KDBX::Util/erase> et al. provide some tools to help accomplish this. Or if you're not too concerned
1839 about the risks memory protection is meant to mitigate, then maybe don't worry about it. The security policy
1840 of B<File::KDBX> is to try hard to keep secrets protected while in memory so that your app might claim a high
1841 level of security, in case you care about that.
1842
1843 There are some memory protection strategies that B<File::KDBX> does NOT use today but could in the future:
1844
1845 Many systems allow programs to mark unswappable pages. Secret information should ideally be stored in such
1846 pages. You could potentially use L<mlockall(2)> (or equivalent for your system) in your own application to
1847 prevent the entire address space from being swapped.
1848
1849 Some systems provide special syscalls for storing secrets in memory while keeping the encryption key outside
1850 of the program's address space, like C<CryptProtectMemory> for Windows. This could be a good option, though
1851 unfortunately not portable.
1852
1853 =head1 QUERY
1854
1855 Several methods take a I<query> as an argument (e.g. L</find_entries>). A query is just a subroutine that you
1856 can either write yourself or have generated for you based on either a simple expression or a declarative
1857 structure. It's easier to have your query generated, so I'll cover that first.
1858
1859 =head2 Simple Expression
1860
1861 A simple expression is mostly compatible with the KeePass 2 implementation
1862 L<described here|https://keepass.info/help/base/search.html#mode_se>.
1863
1864 An expression is a string with one or more space-separated terms. Terms with spaces can be enclosed in double
1865 quotes. Terms are negated if they are prefixed with a minus sign. A record must match every term on at least
1866 one of the given fields.
1867
1868 So a simple expression is something like what you might type into a search engine. You can generate a simple
1869 expression query using L<File::KDBX::Util/simple_expression_query> or by passing the simple expression as
1870 a B<string reference> to search methods like L</find_entries>.
1871
1872 To search for all entries in a database with the word "canyon" appearing anywhere in the title:
1873
1874 my @entries = $kdbx->find_entries([ \'canyon', qw(title) ]);
1875
1876 Notice the first argument is a B<stringref>. This diambiguates a simple expression from other types of queries
1877 covered below.
1878
1879 As mentioned, a simple expression can have multiple terms. This simple expression query matches any entry that
1880 has the words "red" B<and> "canyon" anywhere in the title:
1881
1882 my @entries = $kdbx->find_entries([ \'red canyon', qw(title) ]);
1883
1884 Each term in the simple expression must be found for an entry to match.
1885
1886 To search for entries with "red" in the title but B<not> "canyon", just prepend "canyon" with a minus sign:
1887
1888 my @entries = $kdbx->find_entries([ \'red -canyon', qw(title) ]);
1889
1890 To search over multiple fields simultaneously, just list them. To search for entries with "grocery" in the
1891 title or notes but not "Foodland":
1892
1893 my @entries = $kdbx->find_entries([ \'grocery -Foodland', qw(title notes) ]);
1894
1895 The default operator is a case-insensitive regexp match, which is fine for searching text loosely. You can use
1896 just about any binary comparison operator that perl supports. To specify an operator, list it after the simple
1897 expression. For example, to search for any entry that has been used at least five times:
1898
1899 my @entries = $kdbx->find_entries([ \5, '>=', qw(usage_count) ]);
1900
1901 It helps to read it right-to-left, like "usage_count is >= 5".
1902
1903 If you find the disambiguating structures to be confusing, you can also the L</find_entries_simple> method as
1904 a more intuitive alternative. The following example is equivalent to the previous:
1905
1906 my @entries = $kdbx->find_entries_simple(5, '>=', qw(usage_count));
1907
1908 =head2 Declarative Query
1909
1910 Structuring a declarative query is similar to L<SQL::Abstract/"WHERE CLAUSES">, but you don't have to be
1911 familiar with that module. Just learn by examples.
1912
1913 To search for all entries in a database titled "My Bank":
1914
1915 my @entries = $kdbx->find_entries({ title => 'My Bank' });
1916
1917 The query here is C<< { title => 'My Bank' } >>. A hashref can contain key-value pairs where the key is
1918 a attribute of the thing being searched for (in this case an entry) and the value is what you want the thing's
1919 attribute to be to consider it a match. In this case, the attribute we're using as our match criteria is
1920 L<File::KDBX::Entry/title>, a text field. If an entry has its title attribute equal to "My Bank", it's
1921 a match.
1922
1923 A hashref can contain multiple attributes. The search candidate will be a match if I<all> of the specified
1924 attributes are equal to their respective values. For example, to search for all entries with a particular URL
1925 B<AND> username:
1926
1927 my @entries = $kdbx->find_entries({
1928 url => 'https://example.com',
1929 username => 'neo',
1930 });
1931
1932 To search for entries matching I<any> criteria, just change the hashref to an arrayref. To search for entries
1933 with a particular URL B<OR> a particular username:
1934
1935 my @entries = $kdbx->find_entries([ # <-- square bracket
1936 url => 'https://example.com',
1937 username => 'neo',
1938 ]);
1939
1940 You can user different operators to test different types of attributes. The L<File::KDBX::Entry/icon_id>
1941 attribute is a number, so we should use a number comparison operator. To find entries using the smartphone
1942 icon:
1943
1944 my @entries = $kdbx->find_entries({
1945 icon_id => { '==', ICON_SMARTPHONE },
1946 });
1947
1948 Note: L<File::KDBX::Constants/ICON_SMARTPHONE> is just a constant from L<File::KDBX::Constants>. It isn't
1949 special to this example or to queries generally. We could have just used a literal number.
1950
1951 The important thing to notice here is how we wrapped the condition in another arrayref with a single key-pair
1952 where the key is the name of an operator and the value is the thing to match against. The supported operators
1953 are:
1954
1955 =for :list
1956 * C<eq> - String equal
1957 * C<ne> - String not equal
1958 * C<lt> - String less than
1959 * C<gt> - String greater than
1960 * C<le> - String less than or equal
1961 * C<ge> - String greater than or equal
1962 * C<==> - Number equal
1963 * C<!=> - Number not equal
1964 * C<< < >> - Number less than
1965 * C<< > >>> - Number greater than
1966 * C<< <= >> - Number less than or equal
1967 * C<< >= >> - Number less than or equal
1968 * C<=~> - String match regular expression
1969 * C<!~> - String does not match regular expression
1970 * C<!> - Boolean false
1971 * C<!!> - Boolean true
1972
1973 Other special operators:
1974
1975 =for :list
1976 * C<-true> - Boolean true
1977 * C<-false> - Boolean false
1978 * C<-not> - Boolean false (alias for C<-false>)
1979 * C<-defined> - Is defined
1980 * C<-undef> - Is not d efined
1981 * C<-empty> - Is empty
1982 * C<-nonempty> - Is not empty
1983 * C<-or> - Logical or
1984 * C<-and> - Logical and
1985
1986 Let's see another example using an explicit operator. To find all groups except one in particular (identified
1987 by its L<File::KDBX::Group/uuid>), we can use the C<ne> (string not equal) operator:
1988
1989 my ($group, @other) = $kdbx->find_groups({
1990 uuid => {
1991 'ne' => uuid('596f7520-6172-6520-7370-656369616c2e'),
1992 },
1993 });
1994 if (@other) { say "Problem: there can be only one!" }
1995
1996 Note: L<File::KDBX::Util/uuid> is a little helper function to convert a UUID in its pretty form into octets.
1997 This helper function isn't special to this example or to queries generally. It could have been written with
1998 a literal such as C<"\x59\x6f\x75\x20\x61...">, but that's harder to read.
1999
2000 Notice we searched for groups this time. Finding groups works exactly the same as it does for entries.
2001
2002 Testing the truthiness of an attribute is a little bit different because it isn't a binary operation. To find
2003 all entries with the password quality check disabled:
2004
2005 my @entries = $kdbx->find_entries({ '!' => 'quality_check' });
2006
2007 This time the string after the operator is the attribute name rather than a value to compare the attribute
2008 against. To test that a boolean value is true, use the C<!!> operator (or C<-true> if C<!!> seems a little too
2009 weird for your taste):
2010
2011 my @entries = $kdbx->find_entries({ '!!' => 'quality_check' });
2012 my @entries = $kdbx->find_entries({ -true => 'quality_check' });
2013
2014 Yes, there is also a C<-false> and a C<-not> if you prefer one of those over C<!>. C<-false> and C<-not>
2015 (along with C<-true>) are also special in that you can use them to invert the logic of a subquery. These are
2016 logically equivalent:
2017
2018 my @entries = $kdbx->find_entries([ -not => { title => 'My Bank' } ]);
2019 my @entries = $kdbx->find_entries({ title => { 'ne' => 'My Bank' } });
2020
2021 These special operators become more useful when combined with two more special operators: C<-and> and C<-or>.
2022 With these, it is possible to construct more interesting queries with groups of logic. For example:
2023
2024 my @entries = $kdbx->find_entries({
2025 title => { '=~', qr/bank/ },
2026 -not => {
2027 -or => {
2028 notes => { '=~', qr/business/ },
2029 icon_id => { '==', ICON_TRASHCAN_FULL },
2030 },
2031 },
2032 });
2033
2034 In English, find entries where the word "bank" appears anywhere in the title but also do not have either the
2035 word "business" in the notes or is using the full trashcan icon.
2036
2037 =head2 Subroutine Query
2038
2039 Lastly, as mentioned at the top, you can ignore all this and write your own subroutine. Your subroutine will
2040 be called once for each thing being searched over. The single argument is the search candidate. The subroutine
2041 should match the candidate against whatever criteria you want and return true if it matches. The C<find_*>
2042 methods collect all matching things and return them.
2043
2044 For example, to find all entries in the database titled "My Bank":
2045
2046 my @entries = $kdbx->find_entries(sub { shift->title eq 'My Bank' });
2047 # logically the same as this declarative structure:
2048 my @entries = $kdbx->find_entries({ title => 'My Bank' });
2049 # as well as this simple expression:
2050 my @entries = $kdbx->find_entries([ \'My Bank', 'eq', qw{title} ]);
2051
2052 This is a trivial example, but of course your subroutine can be arbitrarily complex.
2053
2054 All of these query mechanisms described in this section are just tools, each with its own set of limitations.
2055 If the tools are getting in your way, you can of course iterate over the contents of a database and implement
2056 your own query logic, like this:
2057
2058 for my $entry (@{ $kdbx->all_entries }) {
2059 if (wanted($entry)) {
2060 do_something($entry);
2061 }
2062 else {
2063 ...
2064 }
2065 }
2066
2067 =head1 ERRORS
2068
2069 Errors in this package are constructed as L<File::KDBX::Error> objects and propagated using perl's built-in
2070 mechanisms. Fatal errors are propagated using L<functions/die> and non-fatal errors (a.k.a. warnings) are
2071 propagated using L<functions/warn> while adhering to perl's L<warnings> system. If you're already familiar
2072 with these mechanisms, you can skip this section.
2073
2074 You can catch fatal errors using L<functions/eval> (or something like L<Try::Tiny>) and non-fatal errors using
2075 C<$SIG{__WARN__}> (see L<variables/%SIG>). Examples:
2076
2077 use File::KDBX::Error qw(error);
2078
2079 my $key = ''; # uh oh
2080 eval {
2081 $kdbx->load_file('whatever.kdbx', $key);
2082 };
2083 if (my $error = error($@)) {
2084 handle_missing_key($error) if $error->type eq 'key.missing';
2085 $error->throw;
2086 }
2087
2088 or using C<Try::Tiny>:
2089
2090 try {
2091 $kdbx->load_file('whatever.kdbx', $key);
2092 }
2093 catch {
2094 handle_error($_);
2095 };
2096
2097 Catching non-fatal errors:
2098
2099 my @warnings;
2100 local $SIG{__WARN__} = sub { push @warnings, $_[0] };
2101
2102 $kdbx->load_file('whatever.kdbx', $key);
2103
2104 handle_warnings(@warnings) if @warnings;
2105
2106 By default perl prints warnings to C<STDERR> if you don't catch them. If you don't want to catch them and also
2107 don't want them printed to C<STDERR>, you can suppress them lexically (perl v5.28 or higher required):
2108
2109 {
2110 no warnings 'File::KDBX';
2111 ...
2112 }
2113
2114 or locally:
2115
2116 {
2117 local $File::KDBX::WARNINGS = 0;
2118 ...
2119 }
2120
2121 or globally in your program:
2122
2123 $File::KDBX::WARNINGS = 0;
2124
2125 You cannot suppress fatal errors, and if you don't catch them your program will exit.
2126
2127 =head1 ENVIRONMENT
2128
2129 This software will alter its behavior depending on the value of certain environment variables:
2130
2131 =for :list
2132 * C<PERL_FILE_KDBX_XS> - Do not use L<File::KDBX::XS> if false (default: true)
2133 * C<PERL_ONLY> - Do not use L<File::KDBX::XS> if true (default: false)
2134 * C<NO_FORK> - Do not fork if true (default: false)
2135
2136 =head1 CAVEATS
2137
2138 Some features (e.g. parsing) require 64-bit perl. It should be possible and actually pretty easy to make it
2139 work using L<Math::BigInt>, but I need to build a 32-bit perl in order to test it and frankly I'm still
2140 figuring out how. I'm sure it's simple so I'll mark this one "TODO", but for now an exception will be thrown
2141 when trying to use such features with undersized IVs.
2142
2143 =head1 SEE ALSO
2144
2145 L<File::KeePass> is a much older alternative. It's good but has a backlog of bugs and lacks support for newer
2146 KDBX features.
2147
2148 =cut
This page took 0.189739 seconds and 3 git commands to generate.