File Coverage

blib/lib/App/Tel/Passwd/Pass.pm
Criterion Covered Total %
statement 67 72 93.0
branch 12 18 66.6
condition 5 11 45.4
subroutine 10 10 100.0
pod 2 2 100.0
total 96 113 84.9


line stmt bran cond sub pod time code
1             package App::Tel::Passwd::Pass;
2              
3             =head1 name
4              
5             App::Tel::Passwd::Pass - Tel Passwd module for Pass
6              
7             =cut
8              
9 1     1   449 use strict;
  1         1  
  1         21  
10 1     1   3 use warnings;
  1         1  
  1         18  
11 1     1   467 use IO::Handle;
  1         4693  
  1         33  
12 1     1   429 use IO::File;
  1         1407  
  1         84  
13 1     1   5 use Carp;
  1         0  
  1         33  
14 1     1   3 use Module::Load;
  1         1  
  1         4  
15              
16             our $_debug = 0;
17              
18             =head1 METHODS
19              
20             A note on private subroutines in this file: Anything with two underscores
21             proceeding it is a private non-method sub.
22              
23             =head2 new
24              
25             my $passwd = App::Tel::Passwd::Pass->new( file => $filename, passwd => $password );
26              
27             This will return a Passwd::Pass Object if the module exists and return undef if it doesn't.
28              
29             Requires filename and password for the file.
30              
31             =cut
32              
33             sub new {
34 7     7 1 3746 my $proto = shift;
35 7   33     54 my $class = ref($proto) || $proto;
36 7         27 my %args = @_;
37              
38 7         24 my $self = { debug => $_debug,
39             %args
40             };
41 7         24 $self->{file} = __find_password_store($self->{file});
42 7 50 33     47 $self->{gpg} ||= ($^O=~/(freebsd|openbsd|netbsd|solaris)/) ? '/usr/local/bin/gpg' : '/usr/bin/gpg';
43              
44 7 50       112 if (! -x $self->{gpg}) {
45 0         0 croak "$class: gpg executable not found.";
46             }
47              
48 7 100 66     91 if (!defined($self->{file}) || ! -r $self->{file} ) {
49 1   50     9 $self->{file} ||= '';
50 1         27 croak "$class: Can't read file $self->{file}";
51             }
52              
53 6         10 $self->{gnupg} = eval {
54 6         28 load GnuPG::Interface;
55 6         631 return GnuPG::Interface->new();
56             };
57              
58 6 50       3268 if ($@) {
59 0         0 croak $@;
60             }
61              
62 6         11 bless( $self, $class );
63 6         18 $self->{pass} = $self->_run($self->{gpg}, $self->{file}, $self->{passwd});
64 5         93 return $self;
65             }
66              
67             sub _run {
68 6     6   9 my ($self, $call, $file, $passphrase) = @_;
69              
70 6         10 my $gnupg = $self->{gnupg};
71 6         81 $gnupg->call($call);
72 6         142 $gnupg->options->no_greeting(1);
73 6         10154 $gnupg->options->quiet(1);
74 6         679 $gnupg->options->batch(1);
75              
76             # This time we'll catch the standard error for our perusing
77             # as well as passing in the passphrase manually
78             # as well as the status information given by GnuPG
79 6         655 my ( $input, $output, $error, $passphrase_fh, $status_fh )
80             = ( IO::Handle->new(),
81             IO::Handle->new(),
82             IO::Handle->new(),
83             IO::Handle->new(),
84             IO::Handle->new(),
85             );
86              
87 6         424 my $handles = GnuPG::Handles->new( stdin => $input,
88             stdout => $output,
89             stderr => $error,
90             passphrase => $passphrase_fh,
91             status => $status_fh,
92             );
93              
94             # this time we'll also demonstrate decrypting
95             # a file written to disk
96             # Make sure you "use IO::File" if you use this module!
97 6         7728 my $cipher_file = IO::File->new( $file );
98              
99             # this sets up the communication
100 6         407 my $pid = $gnupg->decrypt( handles => $handles );
101              
102             # This passes in the passphrase
103 6         17810 print $passphrase_fh $passphrase;
104 6         41 close $passphrase_fh;
105              
106             # this passes in the plaintext
107 6         280 print $input $_ while <$cipher_file>;
108              
109             # this closes the communication channel,
110             # indicating we are done
111 6         55 close $input;
112 6         22 close $cipher_file;
113              
114 6         103959 my @plaintext = <$output>; # reading the output
115 6         83 my @error_output = <$error>; # reading the error
116 6         91 my @status_info = <$status_fh>; # read the status info
117 6         18 chomp(@plaintext);
118              
119 6         27 for (@status_info) {
120 39 100       153 croak @error_output if (/BAD_PASSPHRASE|DECRYPTION_FAILED/);
121             }
122              
123             # clean up...
124 5         57 close $output;
125 5         21 close $error;
126 5         19 close $status_fh;
127              
128 5         74 waitpid $pid, 0; # clean up the finished GnuPG process
129 5         172 return $plaintext[0];
130             }
131              
132             sub __find_password_store {
133 7     7   22 my $file = shift;
134              
135 7 100       27 return if (!defined($file));
136 6 100       37 if ($file !~ /.gpg$/) {
137 1         7 $file .= '.gpg';
138             }
139             # if it's an absolute path then treat it as-is.
140 6 50       30 return $file if ($file =~ m#^/#);
141              
142 0 0       0 if (defined($ENV{PASSWORD_STORE_DIR})) {
143 0         0 return "$ENV{PASSWORD_STORE_DIR}/$file";
144             }
145              
146 0         0 return "$ENV{HOME}/.password-store/$file";
147             }
148              
149             =head2 passwd
150              
151             $passwd->passwd($entry);
152              
153             This requires a password for the router. It will return a blank line if not
154             found.
155              
156             =cut
157              
158             sub passwd {
159 2     2 1 820 $_[0]->{pass};
160             }
161              
162             1;