line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::Tel::Passwd; |
2
|
|
|
|
|
|
|
|
3
|
10
|
|
|
10
|
|
101622
|
use strict; |
|
10
|
|
|
|
|
25
|
|
|
10
|
|
|
|
|
266
|
|
4
|
10
|
|
|
10
|
|
54
|
use warnings; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
314
|
|
5
|
10
|
|
|
10
|
|
53
|
use Carp; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
697
|
|
6
|
10
|
|
|
10
|
|
3468
|
use Module::Load; |
|
10
|
|
|
|
|
4566
|
|
|
10
|
|
|
|
|
61
|
|
7
|
10
|
|
|
10
|
|
3829
|
use POSIX qw(); # For isatty |
|
10
|
|
|
|
|
31473
|
|
|
10
|
|
|
|
|
240
|
|
8
|
10
|
|
|
10
|
|
3289
|
use IO::Stty; |
|
10
|
|
|
|
|
25216
|
|
|
10
|
|
|
|
|
1236
|
|
9
|
|
|
|
|
|
|
require Exporter; |
10
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
11
|
|
|
|
|
|
|
our @EXPORT = qw(); |
12
|
|
|
|
|
|
|
our @EXPORT_OK = qw ( keyring input_password ); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
App::Tel::Passwd - Methods for managing App::Tel::Passwd:: modules |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=cut |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
my $plugins = [ 'KeePass', 'PWSafe', 'Pass' ]; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head2 load_module |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
my $name = App::Tel::Passwd::load_module($password_module, $file, $passwd); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
Loads the module for the specified password store type. Returns the module's |
27
|
|
|
|
|
|
|
namespace. |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=cut |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
sub load_module { |
32
|
2
|
|
|
2
|
1
|
1113
|
my ($type, $file, $passwd) = @_; |
33
|
10
|
|
|
10
|
|
75
|
no warnings 'uninitialized'; |
|
10
|
|
|
|
|
18
|
|
|
10
|
|
|
|
|
5591
|
|
34
|
2
|
|
|
|
|
7
|
my $mod = 'App::Tel::Passwd::'. $type; |
35
|
2
|
|
|
|
|
4
|
my $load = eval { |
36
|
2
|
|
|
|
|
10
|
Module::Load::load $mod; |
37
|
0
|
|
|
|
|
0
|
$mod->new(file => $file, passwd => $passwd); |
38
|
|
|
|
|
|
|
}; |
39
|
2
|
50
|
|
|
|
1510
|
croak "Something went wrong with our load of passwd module $type:\n$@" if ($@); |
40
|
0
|
|
|
|
|
|
return $load; |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head2 input_password |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
my $password = input_password($prompt); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
Prompts the user for a password then disables local echo on STDIN, reads a |
48
|
|
|
|
|
|
|
line and returns it. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=cut |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub input_password { |
54
|
0
|
|
|
0
|
1
|
|
my $prompt = shift; |
55
|
0
|
|
0
|
|
|
|
$prompt ||= ''; |
56
|
0
|
0
|
|
|
|
|
die 'STDIN not a tty' if (!POSIX::isatty(\*STDIN)); |
57
|
0
|
|
|
|
|
|
my $old_mode=IO::Stty::stty(\*STDIN,'-g'); |
58
|
0
|
|
|
|
|
|
print "Enter password for $prompt: "; |
59
|
0
|
|
|
|
|
|
IO::Stty::stty(\*STDIN,'-echo'); |
60
|
0
|
|
|
|
|
|
chomp(my $password=<STDIN>); |
61
|
0
|
|
|
|
|
|
IO::Stty::stty(\*STDIN,$old_mode); |
62
|
0
|
|
|
|
|
|
return $password; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head2 keyring |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
my $password = keyring($user, $domain, $group); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Reads a password from a keyring using Passwd::Keyring::Auto if it's available. |
70
|
|
|
|
|
|
|
If the password isn't found the user is prompted to enter a password, then we |
71
|
|
|
|
|
|
|
try to store it in the keyring. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=cut |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub keyring { |
76
|
0
|
|
|
0
|
1
|
|
my ($user, $domain, $group) = @_; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# TODO: needs to warn on some kind of failure? |
79
|
0
|
|
|
|
|
|
eval { |
80
|
0
|
|
|
|
|
|
load Passwd::Keyring::Auto, 'get_keyring'; |
81
|
0
|
|
|
|
|
|
my $keyring = get_keyring(app=>"tel script", group=>$group); |
82
|
0
|
|
|
|
|
|
my $pass = $keyring->get_password($user, $domain); |
83
|
0
|
0
|
|
|
|
|
if (!$pass) { |
84
|
0
|
|
|
|
|
|
$pass = input_password($domain); |
85
|
0
|
|
|
|
|
|
$keyring->set_password($user, $pass, $domain); |
86
|
|
|
|
|
|
|
} |
87
|
0
|
|
|
|
|
|
return $pass; |
88
|
|
|
|
|
|
|
}; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head2 load_from_profile |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
my $pass = load_from_profile($profile); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Given an App::Tel profile, see if it contains entries for Passwd modules. If |
96
|
|
|
|
|
|
|
it does attempt to load them and return the password associated. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
I'm not too happy with the flexibility of this, but I think it will get the |
99
|
|
|
|
|
|
|
job done for right now. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=cut |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub load_from_profile { |
104
|
0
|
|
|
0
|
1
|
|
my $profile = shift; |
105
|
|
|
|
|
|
|
|
106
|
0
|
|
|
|
|
|
foreach my $plugin (@$plugins) { |
107
|
0
|
|
|
|
|
|
my $type = lc($plugin); |
108
|
0
|
0
|
|
|
|
|
if (defined($profile->{$type .'_file'})) { |
109
|
0
|
|
|
|
|
|
my $file = $type . '_file'; |
110
|
0
|
|
|
|
|
|
my $entry = $type . '_entry'; |
111
|
0
|
|
|
|
|
|
my $safe_password = $profile->{$type . '_passwd'}; |
112
|
|
|
|
|
|
|
|
113
|
0
|
0
|
|
|
|
|
if ($safe_password eq 'KEYRING') { |
114
|
0
|
|
|
|
|
|
$safe_password = keyring($type,$type,$type); |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
|
my $mod = load_module $plugin, $profile->{$file}, $safe_password; |
118
|
0
|
|
|
|
|
|
my $e = $mod->passwd($profile->{$entry}); |
119
|
0
|
0
|
|
|
|
|
return $e if $e; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|