File: keyring.t

package info (click to toggle)
webauth 4.7.0-8
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 7,932 kB
  • sloc: ansic: 28,341; sh: 12,031; perl: 8,361; xml: 6,856; makefile: 459; php: 7
file content (183 lines) | stat: -rwxr-xr-x 8,613 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/perl -w
#
# Test suite for keyring manipulation.
#
# Written by Russ Allbery <eagle@eyrie.org>
# Copyright 2011, 2012, 2013, 2014
#     The Board of Trustees of the Leland Stanford Junior University
#
# See LICENSE for licensing terms.

use strict;

use Test::More tests => 63;

use lib ('t/lib', 'lib', 'blib/arch');
use WebAuth qw(:const);
use WebAuth::Keyring;

# Do all tests in an eval block to catch otherwise-uncaught exceptions.
eval {
    my $wa = WebAuth->new;
    my $keyring = $wa->keyring_new (1);
    isa_ok ($keyring, 'WebAuth::Keyring');
    is (scalar ($keyring->entries), 0, '... and contains no keys');
    my @entries = $keyring->entries;
    is (scalar (@entries), 0, '... and no keys are returned');

    # Add a key to the keyring and then make sure the data matches.
    my $key = $wa->key_create (WA_KEY_AES, WA_AES_256);
    my $now = time - 20;
    eval { $keyring->add ($now, $now + 5, $key) };
    is ($@, '', 'Adding a key works');
    is (scalar ($keyring->entries), 1, '... and now there is one key');
    @entries = $keyring->entries;
    is (scalar (@entries), 1, '... which is returned in an array');
    is ($entries[0]->creation, $now, '... with the right creation');
    is ($entries[0]->valid_after, $now + 5, '... and the right valid time');
    is ($entries[0]->key->type, WA_KEY_AES, '... and right key type');
    is ($entries[0]->key->length, WA_AES_256, '... and right key length');
    is ($entries[0]->key->data, $key->data, '... and right key data');

    # Add a second key to test keyring resizing.
    my $key2 = $wa->key_create (WA_KEY_AES, WA_AES_256);
    $now = $now + 10;
    is ($keyring->add ($now, $now + 5, $key2), 1, 'Adding a second key works');
    is (scalar ($keyring->entries), 2, '... and now there are two keys');
    @entries = $keyring->entries;
    is ($entries[1]->creation, $now, 'The second key has the right creation');
    is ($entries[1]->valid_after, $now + 5, '... and the right valid time');
    is ($entries[1]->key->type, WA_KEY_AES, '... and right key type');
    is ($entries[1]->key->length, WA_AES_256, '... and right key length');
    is ($entries[1]->key->data, $key2->data, '... and right key data');

    # Test writing the keyring out and reading it back in again.
    eval { $keyring->write ('webauth_keyring') };
    is ($@, '', 'Writing the key out to a file works');
    ok (-f 'webauth_keyring', '... and the file exists');
    is ((stat 'webauth_keyring')[2] & 07777, 0600,
        '... and has the correct mode');
    my $keyring2 = eval { $wa->keyring_read ('webauth_keyring') };
    is ($@, '', 'Reading the keyring back in works');
    my @entries2 = $keyring2->entries;
    is (scalar (@entries2), scalar (@entries),
        '... and the keyrings are the same size');
    is ($entries2[0]->creation, $entries[0]->creation,
        'Creation of first keys match');
    is ($entries2[0]->valid_after, $entries[0]->valid_after,
        'Valid after of first keys match');
    is ($entries2[0]->key->type, $entries[0]->key->type,
        '... and right key type');
    is ($entries2[0]->key->length, $entries[0]->key->length,
        '... and right key length');
    is ($entries2[0]->key->data, $entries[0]->key->data,
        '... and right key data');
    is ($entries2[1]->creation, $entries[1]->creation,
        'Creation of second keys match');
    is ($entries2[1]->valid_after, $entries[1]->valid_after,
        'Valid after of second keys match');
    is ($entries2[1]->key->type, $entries[1]->key->type,
        '... and right key type');
    is ($entries2[1]->key->length, $entries[1]->key->length,
        '... and right key length');
    is ($entries2[1]->key->data, $entries[1]->key->data,
        '... and right key data');

    # Read in the encoded data and try decoding it.
    ok (open (KEYRING, '<', 'webauth_keyring'), 'Can open the saved file');
    my $data2;
    {
        local $/;
        $data2 = <KEYRING>;
    }
    close KEYRING;
    $keyring2 = eval { $wa->keyring_decode ($data2) };
    is ($@, '', 'Decoding the keyring works');
    @entries2 = $keyring2->entries;
    is (scalar (@entries2), scalar (@entries),
        '... and the keyrings are the same size');
    $keyring2 = eval { WebAuth::Keyring->decode ($wa, $data2) };
    is ($@, '', 'Decoding the keyring via WebAuth::Keyring helper works');
    @entries2 = $keyring2->entries;
    is (scalar (@entries2), scalar (@entries),
        '... and the keyrings are the same size');
    my $data = eval { $keyring->encode };
    is ($@, '', 'Encoding the keyring works');
    is ($data, $data2, '... and the encoded data matches');
    unlink ('webauth_keyring', 'webauth_keyring.lock');

    # Check whether we get back the correct key when we ask for the best
    # key for the "current" time.  This should be the first key, since the
    # second key wasn't created until five minutes from "now."
    is ($keyring->best_key (0, $now - 5)->data, $entries[0]->key->data,
        'Best key is the first');

    # But if we ask for encryption, we want the one created most recently
    # that's valid, so that's the second key.
    is ($keyring->best_key (1, $now - 5)->data, $entries[1]->key->data,
        'Best encryption key is the second');

    # If we make the timestamp later, after the valid time for the second
    # key, we'll get that one for decryption as well.
    is ($keyring->best_key (0, $now + 10)->data, $entries[1]->key->data,
        'Best future key is the second');

    # Test removing keys from the keyring.
    eval { $keyring->remove (0) };
    is ($@, '', 'Removing the first key of the keyring works');
    is (scalar ($keyring->entries), 1, '... and the entry count is 1');
    @entries2 = $keyring->entries;
    is ($entries2[0]->creation, $entries[1]->creation,
        'The remaining key has the expecte creation');
    is ($entries2[0]->valid_after, $entries[1]->valid_after,
        '... and valid after');

    # Test the alternative constructors for keyrings.
    $keyring = WebAuth::Keyring->new ($wa, 1);
    isa_ok ($keyring, 'WebAuth::Keyring');
    is (scalar ($keyring->entries), 0, '... and contains no keys');
    $key = $wa->key_create (WA_KEY_AES, WA_AES_256);
    $keyring = WebAuth::Keyring->new ($wa, $key);
    isa_ok ($keyring, 'WebAuth::Keyring');
    is (scalar ($keyring->entries), 1, '... and contains one key');

    # Write it to a file and then test reading it back in.
    eval { $keyring->write ('webauth_keyring') };
    is ($@, '', 'Writing the key out to a file works');
    $keyring2 = eval { WebAuth::Keyring->read ($wa, 'webauth_keyring') };
    is ($@, '', 'Reading the keyring back in works');
    unlink ('webauth_keyring', 'webauth_keyring.lock');
    is (scalar ($keyring2->entries), 1, '... and contains one key');
};
is ($@, '', 'No unexpected exceptions');

# Check that sending WebAuth::Keyring different objects than it expect fails.
my $keyring = eval { WebAuth::Keyring::new('WebAuth::NotKeyring') };
like ($@, qr{^subclassing of WebAuth::Keyring is not supported}ms,
    'Trying to subclass WebAuth::Keyring fails');
$keyring = eval { WebAuth::Keyring::decode('WebAuth::NotKeyring') };
like ($@, qr{^subclassing of WebAuth::Keyring is not supported}ms,
    '... as does trying to subclass the decode function');
$keyring = eval { WebAuth::Keyring::read('WebAuth::NotKeyring') };
like ($@, qr{^subclassing of WebAuth::Keyring is not supported}ms,
    '... as does trying to subclass the read function');
$keyring = eval { WebAuth::Keyring->new('WebAuth::NotKeyring') };
like ($@, qr{^second argument must be a WebAuth object}ms,
    'Trying to give WebAuth::Keyring a non-WebAuth context fails');
$keyring = eval { WebAuth::Keyring->decode('WebAuth::NotKeyring') };
like ($@, qr{^second argument must be a WebAuth object}ms,
    '... as does trying to give one to the decode function');
$keyring = eval { WebAuth::Keyring->read('WebAuth::NotKeyring') };
like ($@, qr{^second argument must be a WebAuth object}ms,
    '... as does trying to give one to the read function');

# Check that passing in undef arguments to various functions implemented in
# Perl XS results in exceptions rather than segfaults.
$keyring = eval { WebAuth::keyring_new(undef, 1) };
like ($@, qr{^WebAuth object is undef in WebAuth::keyring_new}ms,
      'Calling keyring_new with an undef WebAuth object fails properly');
my $wa = WebAuth->new;
$keyring = $wa->keyring_new(1);
eval { $keyring->add(time, time + 60, undef) };
like ($@, qr{^WebAuth::Key object is undef in WebAuth::Keyring::add}ms,
      '... as does passing undef key to WebAuth::Keyring::add');