]> Dogcows Code - chaz/p5-File-KDBX/blob - t/yubikey.t
multiplex IO to prevent deadlocks
[chaz/p5-File-KDBX] / t / yubikey.t
1 #!/usr/bin/env perl
2
3 use warnings;
4 use strict;
5
6 use lib 't/lib';
7 use TestCommon;
8
9 use Config;
10 use File::KDBX::Key::YubiKey;
11 use Test::More;
12
13 $^O eq 'MSWin32' and plan skip_all => 'Non-Windows required to test YubiKeys';
14
15 @ENV{qw(YKCHALRESP YKCHALRESP_FLAGS)} = ($Config{perlpath}, testfile(qw{bin ykchalresp}));
16 @ENV{qw(YKINFO YKINFO_FLAGS)} = ($Config{perlpath}, testfile(qw{bin ykinfo}));
17
18 {
19 my ($pre, $post);
20 my $key = File::KDBX::Key::YubiKey->new(
21 pre_challenge => sub { ++$pre },
22 post_challenge => sub { ++$post },
23 );
24 my $resp;
25 is exception { $resp = $key->challenge('foo') }, undef, 'Do not throw during non-blocking response';
26 is $resp, "\xf0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 'Get a non-blocking challenge response';
27 is length($resp), 20, 'Response is the proper length';
28 is $pre, 1, 'The pre-challenge callback is called';
29 is $post, 1, 'The post-challenge callback is called';
30 }
31
32 {
33 my $key = File::KDBX::Key::YubiKey->new;
34 local $ENV{YKCHALRESP_MOCK} = 'error';
35 like exception { $key->challenge('foo') }, qr/Yubikey core error:/i,
36 'Throw if challenge-response program errored out';
37 }
38
39 {
40 my $key = File::KDBX::Key::YubiKey->new;
41 local $ENV{YKCHALRESP_MOCK} = 'usberror';
42 like exception { $key->challenge('foo') }, qr/USB error:/i,
43 'Throw if challenge-response program had a USB error';
44 }
45
46 {
47 my $key = File::KDBX::Key::YubiKey->new(timeout => 0, device => 3, slot => 2);
48 local $ENV{YKCHALRESP_MOCK} = 'block';
49
50 like exception { $key->challenge('foo') }, qr/operation would block/i,
51 'Throw if challenge would block but we do not want to wait';
52
53 $key->timeout(1);
54 like exception { $key->challenge('foo') }, qr/timed out/i,
55 'Timeout while waiting for response';
56
57 $key->timeout(-1);
58 my $resp;
59 is exception { $resp = $key->challenge('foo') }, undef,
60 'Do not throw during blocking response';
61 is $resp, "\xf0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 'Get a blocking challenge response';
62 }
63
64 {
65 my $key = File::KDBX::Key::YubiKey->new(device => 0, slot => 1);
66 is $key->name, 'YubiKey NEO FIDO v2.0.0 [123] (slot #1)',
67 'Get name for a new, unscanned key';
68 is $key->serial, 123, 'Get the serial number of the new key';
69 }
70
71 {
72 my ($key, @other) = File::KDBX::Key::YubiKey->scan;
73 is $key->name, 'YubiKey 4/5 OTP v3.0.1 [456] (slot #2)',
74 'Find expected YubiKey';
75 is $key->serial, 456, 'Get the serial number of the scanned key';
76 is scalar @other, 0, 'Do not find any other YubiKeys';
77 }
78
79 {
80 local $ENV{YKCHALRESP} = testfile(qw{bin nonexistent});
81 local $ENV{YKCHALRESP_FLAGS} = undef;
82 my $key = File::KDBX::Key::YubiKey->new;
83 like exception { $key->challenge('foo') }, qr/failed to run|failed to receive challenge response/i,
84 'Throw if the program failed to run';
85 }
86
87 done_testing;
This page took 0.036018 seconds and 4 git commands to generate.