File Coverage

blib/lib/Passwd/Keyring/OSXKeychain/PasswordTranslate.pm
Criterion Covered Total %
statement 23 23 100.0
branch 4 4 100.0
condition 2 3 66.6
subroutine 5 5 100.0
pod 1 1 100.0
total 35 36 97.2


line stmt bran cond sub pod time code
1             package Passwd::Keyring::OSXKeychain::PasswordTranslate;
2              
3 12     12   145491 use warnings;
  12         20  
  12         522  
4 12     12   62 use strict;
  12         20  
  12         339  
5 12     12   58 use base 'Exporter';
  12         19  
  12         1583  
6             our @EXPORT_OK = qw(read_security_encoded_passwd);
7              
8 12     12   8220 use Encode;
  12         132150  
  12         4447  
9              
10             =head1 NAME
11              
12             Passwd::Keyring::OSXKeychain::PasswordTranslate
13              
14             =head1 DESCRIPTION
15              
16             Helper routines, responsible for encoding and decoding passwords from
17             MacOS/X security escaped forms. Used internally inside Passwd::Keyring::OSXKeychain.
18              
19             =head2 read_security_encoded_passwd
20              
21             Tries to decode password given by security -w, handling known escaping schemes.
22              
23             =cut
24              
25             sub read_security_encoded_passwd {
26 16     16 1 11310 my ($encoded_password) = @_;
27              
28             # See discussion from #1 (especially comments by Maroš Kollár).
29             # We must detect whether password is plaintext or hex-encoded,
30             # and possibly truncate it.
31              
32 16 100       123 unless($encoded_password =~ /^(?:[0-9a-f][0-9a-f])+$/ix) {
33             # surely plaintext as non-hex is there
34 4         27 return $encoded_password;
35             }
36              
37             # Heuristics suggested by Maroš, and slightly extended by me to handle
38             # additinal cases.
39 12 100 66     121 if($encoded_password =~ /00$/
40             || $encoded_password =~ /ffffff.*ffffff/
41             # || length($encoded_password) > 30
42             ) {
43             # Hex
44 10         70 my $binary = pack('H*', $encoded_password);
45 10         48 $binary =~ s{\xFF{3}}{}g;
46 10         23 $binary =~ s/\x00.*$//; # Cutting post binary zero part
47 10         33 my $text = decode_utf8($binary);
48 10         307 $text =~ s{\n.*}{}; # Cuttint newline broken part
49 10         65 return $text;
50             }
51              
52             # By default we assume plain text
53 2         11 return $encoded_password;
54             }
55              
56              
57              
58              
59             1;