File Coverage

blib/lib/Authen/NZRealMe/LogonStrength.pm
Criterion Covered Total %
statement 50 50 100.0
branch 16 18 88.8
condition 8 9 88.8
subroutine 12 12 100.0
pod 4 4 100.0
total 90 93 96.7


line stmt bran cond sub pod time code
1             package Authen::NZRealMe::LogonStrength;
2             {
3             $Authen::NZRealMe::LogonStrength::VERSION = '1.16';
4             }
5              
6 1     1   3 use strict;
  1         2  
  1         23  
7 1     1   4 use warnings;
  1         1  
  1         19  
8 1     1   3 use Carp;
  1         1  
  1         64  
9              
10 1     1   4 use constant URN_PREFIX => 'urn:nzl:govt:ict:stds:authn:deployment:GLS:SAML:2.0:ac:classes:';
  1         1  
  1         64  
11              
12 1     1   3 use constant STRENGTH_LOW => URN_PREFIX . 'LowStrength';
  1         6  
  1         50  
13 1     1   4 use constant STRENGTH_MODERATE => URN_PREFIX . 'ModStrength';
  1         1  
  1         42  
14 1     1   3 use constant STRENGTH_MODERATE_SID => URN_PREFIX . 'ModStrength::OTP:Token:SID';
  1         1  
  1         40  
15 1     1   4 use constant STRENGTH_MODERATE_SMS => URN_PREFIX . 'ModStrength::OTP:Token:SMS';
  1         1  
  1         309  
16              
17              
18             my %word_to_urn = (
19             low => STRENGTH_LOW,
20             mod => STRENGTH_MODERATE,
21             moderate => STRENGTH_MODERATE,
22             );
23              
24             my %strength_score = (
25             &STRENGTH_LOW => 10,
26             &STRENGTH_MODERATE => 20,
27             &STRENGTH_MODERATE_SID => 20,
28             &STRENGTH_MODERATE_SMS => 20,
29             );
30              
31              
32             sub new {
33 34     34 1 2119 my $class = shift;
34 34   100     75 my $urn = shift || 'low';
35              
36 34 100       69 $urn = $word_to_urn{$urn} if $word_to_urn{$urn};
37              
38 34 100       55 if(not exists $strength_score{$urn}) {
39 15         186 my @match = grep /\Q$urn\E$/i, keys %strength_score;
40 15 50       32 croak "Can't find a match for logon strength '$urn'" if @match == 0;
41 15 50       24 croak "Ambiguous logon strength '$urn'" if @match > 1;
42 15         21 $urn = $match[0];
43             }
44              
45 34         89 return bless { urn => $urn }, $class;
46             }
47              
48              
49 59     59 1 580 sub urn { shift->{urn}; }
50 35     35 1 48 sub score { $strength_score{ shift->{urn} }; }
51              
52              
53             sub assert_match {
54 27     27 1 7076 my $self = shift;
55 27   50     57 my $required = shift || 'low';
56 27   100     39 my $match = shift || 'minimum';
57              
58 27         31 my $class = ref($self);
59 27         41 $required = $class->new($required);
60              
61 27         40 my $provided_urn = $self->urn;
62 27         49 my $required_urn = $required->urn;
63 27 100       68 return if $required_urn eq $provided_urn;
64              
65 17         20 my $provided_score = $self->score;
66 17         18 my $required_score = $required->score;
67 17 100 100     47 return if $required_urn eq STRENGTH_MODERATE and $provided_score == 20;
68              
69 13 100       28 if($match eq 'minimum') {
    100          
70 5 100       15 return if $provided_score > $required_score;
71             }
72             elsif($match ne 'exact') {
73 1         9 die "Unrecognised password strength match type: '$match'";
74             }
75              
76 9         62 die "Invalid logon strength.\n"
77             . "Required: $required_urn\n"
78             . "Provided: $provided_urn\n"
79             . "Comparison: $match\n";
80             }
81              
82             1;
83              
84             __END__