summaryrefslogtreecommitdiffstats
path: root/t/srs.t
blob: b6482b49a18ce4209ae0fd874b521e3efe896198 (plain)
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
use strict;
use warnings;

use Test::More tests => 35;
use Test::Exception;
use Test::MockModule;

BEGIN {
    use_ok 'Spline::Srs', qw(
        check_exclude
    ) or BAIL_OUT;
}

# Testing ignores
is(check_exclude('test@example.com',['example.com']), 1, 'Ignore matching domain');
is(check_exclude('test@example.de', ['example.com']), 0, 'Do not ignore non-matching domain');
is(check_exclude('test@test.example.com', ['example.com']), 0, 'Do not ignore sub-domain');
is(check_exclude('test@test.example.com', ['.example.com']), 1, 'Ignore sub-domain if requested');

# Try without config
my %config = ();
throws_ok { new Spline::Srs(\%config) } qr/configure.*secret/, 'Secret required';
$config{secret} = 'abc';
throws_ok { new Spline::Srs(\%config) } qr/configure.*secret/, 'Long secret required';
$config{secret} = '12345678901234567890';
throws_ok { new Spline::Srs(\%config) } qr/configure.*alias/, 'Alias required';
$config{alias} = 'something';
lives_ok { new Spline::Srs(\%config) } 'Config complete';

# Testing ignores with config
$config{alias} = 'domain.invalid';
{
    my $srs = new Spline::Srs(\%config);
    is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
        'Exclude alias domain by default');
    isnt($srs->forward('test@example.com'), 'test@example.com',
        'Not excluding something other');
}

$config{excludes} = ['example.com'];
{
    my $srs = new Spline::Srs(\%config);
    is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
        'Exclude alias domain by default');
    is($srs->forward('test@example.com'), 'test@example.com',
        'Exclude is working');
    isnt($srs->forward('test@test.example.com'), 'test@test.example.com',
        'Excluded domain should not match subdomain');
}

$config{excludes} = ['.example.com'];
{
    my $srs = new Spline::Srs(\%config);
    is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
        'Exclude alias domain by default');
    is($srs->forward('test@test.example.com'), 'test@test.example.com',
        'Exclude subdomains');
    isnt($srs->forward('test@example.com'), 'test@example.com',
        'Excluded subdomain should not match domain');
}

$config{excludes} = ['example.com', '.example.com'];
{
    my $srs = new Spline::Srs(\%config);
    is($srs->forward('test@domain.invalid'), 'test@domain.invalid',
        'Exclude alias domain by default');
    is($srs->forward('test@test.example.com'), 'test@test.example.com',
        'Multiple excludes');
    is($srs->forward('test@example.com'), 'test@example.com',
        'Multiple excludes');
}

# SRS Forward
$config{secret} = '12345678901234567890';
$config{alias} = 'domain.invalid';
$config{excludes} = undef;
$config{hash_length} = 6;
my ($old_srs_address, $broken);
{
    my $srs = new Spline::Srs(\%config);
    my $result = $srs->forward('alex@example.com');
    isnt($result, undef, 'Not undef');
    isnt($result, 'alex@example.com', 'Not rewritten');
    like($result, qr/^SRS0[+=-]/, 'SRS0 Prefix');
    like($result, qr/\@domain\.invalid$/, 'Rewrite to alias-Domain');

    # Check SRS forward an backwards
    my $address = 'alex@example.com';
    my $srs_address = $srs->forward($address);
    isnt($srs_address, undef, 'Forward works');
    isnt($srs_address, $address, 'Forward works');
    is($srs->reverse($srs_address), $address, 'Reverse maps back to original');

    # Some checks requires a fixed time for deterministic output
    {
        no warnings 'redefine';
        my $timestamp_create = \&Mail::SRS::timestamp_create;
        local *Mail::SRS::timestamp_create = sub {
            my $self = shift;
            $timestamp_create->($self, 1);
        };

        $old_srs_address = $srs->forward($address);
        isnt($old_srs_address, $srs_address, 'Time should have changed');
        is($old_srs_address, 'SRS0=R0OuN1=AA=example.com=alex@domain.invalid',
            'exakt match with fixed time');

        # Hash with broken chars
        $broken = $srs->forward('nk@example.com');
        is($broken, 'SRS0=s/6g+P=AA=example.com=nk@domain.invalid',
            'srs address is as expected');
    }

    # Timestamp should timeout (but old timestamps can be ignored)
    throws_ok { $srs->reverse($old_srs_address) } qr/Invalid timestamp/,
        'Timestamp should be to old';
}

$config{'ignore_time'} = 1;
{
    my $srs = new Spline::Srs(\%config);
    lives_ok { $srs->reverse($old_srs_address) } 'Ignore old timestamp';

    # libsrs_alt uses different base64 chars and should also work
    lives_ok { $srs->reverse($broken) } 'Reverse with special chars';
    $broken = 'SRS0=s.6g_P=AA=example.com=nk@domain.invalid';
    throws_ok { $srs->reverse($broken) } qr/Invalid hash/,
        'Reverse with legacy chars';
}

$config{'srsalt_fallback'} = 1;
{
    my $srs = new Spline::Srs(\%config);
    is($srs->reverse($broken), 'nk@example.com', 'Reverse with legacy chars');
}

# vim: set et ts=4: