| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Passwd::Keyring::Auto::Chooser; |
|
2
|
7
|
|
|
7
|
|
3749
|
use Moo 1.001000; |
|
|
7
|
|
|
|
|
88705
|
|
|
|
7
|
|
|
|
|
37
|
|
|
3
|
7
|
|
|
7
|
|
8609
|
use Carp; |
|
|
7
|
|
|
|
|
10
|
|
|
|
7
|
|
|
|
|
379
|
|
|
4
|
7
|
|
|
7
|
|
2673
|
use Passwd::Keyring::Auto::Config; |
|
|
7
|
|
|
|
|
18
|
|
|
|
7
|
|
|
|
|
243
|
|
|
5
|
7
|
|
|
7
|
|
53
|
use namespace::clean; |
|
|
7
|
|
|
|
|
8
|
|
|
|
7
|
|
|
|
|
43
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 NAME |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Passwd::Keyring::Auto::Chooser - actual implementation of keyring picking algorithm |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Internal object, not intended to be used directly. |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Implements prioritizing keyrings and finding the best suitable. |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
See L<Passwd::Keyring::Auto> for algorithm description. |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=cut |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
has 'app' => (is=>'ro', default=>"Passwd::Keyring"); |
|
23
|
|
|
|
|
|
|
has 'group' => (is=>'ro', default=>"Passwd::Keyring passwords"); |
|
24
|
|
|
|
|
|
|
has 'config' => (is=>'ro'); |
|
25
|
|
|
|
|
|
|
has 'force' => (is=>'ro'); |
|
26
|
|
|
|
|
|
|
has 'prefer' => (is=>'ro'); |
|
27
|
|
|
|
|
|
|
has 'forbid' => (is=>'ro'); |
|
28
|
|
|
|
|
|
|
has 'backend_args' => (is=>'ro'); |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub BUILDARGS { |
|
31
|
7
|
|
|
7
|
0
|
5622
|
my ($class, %args) = @_; |
|
32
|
7
|
|
|
|
|
13
|
my %backend_args; |
|
33
|
7
|
|
|
|
|
22
|
foreach my $arg_name (keys %args) { |
|
34
|
14
|
100
|
|
|
|
69
|
unless($arg_name =~ /^(app|group|config|force|prefer|forbid)$/) { |
|
35
|
7
|
|
|
|
|
16
|
$backend_args{$arg_name} = $args{$arg_name}; |
|
36
|
7
|
|
|
|
|
18
|
delete $args{$arg_name}; |
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
} |
|
39
|
7
|
|
|
|
|
19
|
$args{backend_args} = \%backend_args; |
|
40
|
7
|
|
|
|
|
149
|
return \%args; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
has '_config' => ( |
|
44
|
|
|
|
|
|
|
is=>'lazy', builder=> sub { |
|
45
|
7
|
|
|
7
|
|
1550
|
my $self = shift; |
|
46
|
7
|
|
|
|
|
129
|
return Passwd::Keyring::Auto::Config->new(location=>$self->config, |
|
47
|
|
|
|
|
|
|
debug=>$self->debug); |
|
48
|
|
|
|
|
|
|
}); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
has 'debug' => (is=>'lazy', builder=>sub { |
|
51
|
7
|
50
|
|
7
|
|
1622
|
return $ENV{PASSWD_KEYRING_DEBUG} ? 1 : 0; |
|
52
|
|
|
|
|
|
|
}); |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub get_keyring { |
|
55
|
7
|
|
|
7
|
0
|
14
|
my ($self) = @_; |
|
56
|
|
|
|
|
|
|
|
|
57
|
7
|
|
|
|
|
68
|
my $debug = $self->debug; |
|
58
|
7
|
|
|
|
|
26
|
my $app = $self->app; |
|
59
|
7
|
|
|
|
|
17
|
my $group = $self->group; |
|
60
|
|
|
|
|
|
|
|
|
61
|
7
|
|
|
|
|
63
|
my $config = $self->_config; |
|
62
|
|
|
|
|
|
|
|
|
63
|
7
|
|
33
|
|
|
4028
|
my $force = $self->force |
|
64
|
|
|
|
|
|
|
|| $ENV{PASSWD_KEYRING_FORCE} |
|
65
|
|
|
|
|
|
|
|| $config->force($app); |
|
66
|
|
|
|
|
|
|
|
|
67
|
7
|
50
|
|
|
|
25
|
if($debug) { |
|
68
|
0
|
|
0
|
|
|
0
|
print STDERR "[Passwd::Keyring] Calculated param: force=", $force || '', "\n"; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
################################################################# |
|
72
|
|
|
|
|
|
|
# Fast path for force |
|
73
|
|
|
|
|
|
|
################################################################# |
|
74
|
|
|
|
|
|
|
|
|
75
|
7
|
50
|
|
|
|
16
|
if($force) { |
|
76
|
0
|
|
|
|
|
0
|
my $keyring = $self->_try_backend($force); |
|
77
|
0
|
0
|
|
|
|
0
|
return $keyring if $keyring; |
|
78
|
0
|
|
|
|
|
0
|
croak "Can not load enforced keyring $force"; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
################################################################# |
|
82
|
|
|
|
|
|
|
# Remaining params |
|
83
|
|
|
|
|
|
|
################################################################# |
|
84
|
|
|
|
|
|
|
|
|
85
|
7
|
|
50
|
|
|
58
|
my $forbid = $self->forbid |
|
86
|
|
|
|
|
|
|
|| [ split(/\s+/x, $ENV{PASSWD_KEYRING_FORBID} |
|
87
|
|
|
|
|
|
|
|| $config->forbid($app) |
|
88
|
|
|
|
|
|
|
|| '') ]; |
|
89
|
7
|
|
50
|
|
|
68
|
my $prefer = $self->prefer |
|
90
|
|
|
|
|
|
|
|| [ split(/\s+/x, $ENV{PASSWD_KEYRING_PREFER} |
|
91
|
|
|
|
|
|
|
|| $config->prefer($app) |
|
92
|
|
|
|
|
|
|
|| '') ]; |
|
93
|
|
|
|
|
|
|
|
|
94
|
7
|
50
|
|
|
|
22
|
unless(ref($forbid)) { |
|
95
|
0
|
|
|
|
|
0
|
$forbid = [$forbid]; |
|
96
|
|
|
|
|
|
|
} |
|
97
|
7
|
50
|
|
|
|
17
|
unless(ref($prefer)) { |
|
98
|
0
|
|
|
|
|
0
|
$prefer = [$prefer]; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
7
|
50
|
|
|
|
18
|
if($debug) { |
|
102
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Calculated param: forbid=[", join(", ", @$forbid), "]\n"; |
|
103
|
|
|
|
|
|
|
} |
|
104
|
7
|
50
|
|
|
|
20
|
if($debug) { |
|
105
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Calculated param: prefer=[", join(", ", @$prefer), "]\n"; |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
################################################################# |
|
109
|
|
|
|
|
|
|
# Selection and scoring of possible options. |
|
110
|
|
|
|
|
|
|
################################################################# |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# Note: we prefer to check possibly wrong module than to miss some. |
|
113
|
|
|
|
|
|
|
|
|
114
|
7
|
|
|
|
|
28
|
my %candidates =( # name â score, score > 0 means possible |
|
115
|
|
|
|
|
|
|
'Gnome' => 0, |
|
116
|
|
|
|
|
|
|
'KDEWallet' => 0, |
|
117
|
|
|
|
|
|
|
'OSXKeychain' => 0, |
|
118
|
|
|
|
|
|
|
'Memory' => 1, |
|
119
|
|
|
|
|
|
|
); |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Scoring: +HUGE for preferred, +100 for session-related, +10 for |
|
122
|
|
|
|
|
|
|
# sensible, +1 for possible |
|
123
|
|
|
|
|
|
|
|
|
124
|
7
|
50
|
|
|
|
28
|
if($^O eq 'darwin') { |
|
125
|
0
|
|
|
|
|
0
|
$candidates{'OSXKeychain'} += 100; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
7
|
50
|
33
|
|
|
35
|
if( $ENV{DISPLAY} || $ENV{DESKTOP_SESSION} ) { |
|
129
|
0
|
|
|
|
|
0
|
$candidates{'KDEWallet'} += 11; # To give it some boost, more portable |
|
130
|
0
|
|
|
|
|
0
|
$candidates{'Gnome'} += 10; |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
|
|
133
|
7
|
50
|
|
|
|
19
|
if($ENV{GNOME_KEYRING_CONTROL}) { |
|
134
|
0
|
|
|
|
|
0
|
$candidates{'Gnome'} += 100; |
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
|
|
137
|
7
|
50
|
|
|
|
15
|
if($ENV{DBUS_SESSION_BUS_ADDRESS}) { |
|
138
|
0
|
|
|
|
|
0
|
$candidates{'KDEWallet'} += 10; |
|
139
|
|
|
|
|
|
|
} |
|
140
|
|
|
|
|
|
|
|
|
141
|
7
|
|
|
|
|
9
|
my $prefer_bonus = 1_000_000; |
|
142
|
7
|
|
|
|
|
24
|
foreach (@$prefer) { |
|
143
|
0
|
|
|
|
|
0
|
$candidates{$_} += $prefer_bonus; |
|
144
|
0
|
|
|
|
|
0
|
$prefer_bonus -= 1_000; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
7
|
|
|
|
|
12
|
delete $candidates{$_} foreach (@$forbid); |
|
148
|
|
|
|
|
|
|
|
|
149
|
7
|
|
|
|
|
18
|
my @attempts = grep { $candidates{$_} > 0 } keys %candidates; |
|
|
28
|
|
|
|
|
48
|
|
|
150
|
|
|
|
|
|
|
|
|
151
|
7
|
0
|
|
|
|
14
|
@attempts = sort { ($candidates{$b} <=> $candidates{$a}) |
|
|
0
|
|
|
|
|
0
|
|
|
152
|
|
|
|
|
|
|
|| |
|
153
|
|
|
|
|
|
|
($a cmp $b) |
|
154
|
|
|
|
|
|
|
} @attempts; |
|
155
|
|
|
|
|
|
|
|
|
156
|
7
|
50
|
|
|
|
13
|
if($debug) { |
|
157
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Selected candidates(score): ", |
|
158
|
0
|
|
|
|
|
0
|
join(", ", map { "$_($candidates{$_})" } @attempts), "\n"; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
7
|
|
|
|
|
16
|
foreach my $keyring_name (@attempts) { |
|
162
|
7
|
|
|
|
|
17
|
my $keyring = $self->_try_backend($keyring_name); |
|
163
|
7
|
50
|
|
|
|
125
|
return $keyring if $keyring; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
0
|
croak "Could not load any keyring backend (attempted: " . join(", ", @attempts) . ")"; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub _get_env { |
|
170
|
0
|
|
|
0
|
|
0
|
my ($self, $name) = @_; |
|
171
|
0
|
|
|
|
|
0
|
my $full_name = "PASSWD_KEYRING_" . $name; |
|
172
|
0
|
0
|
|
|
|
0
|
if(exists $ENV{$full_name}) { |
|
173
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Found (and using) environment variable $full_name: $ENV{$full_name}\n"; |
|
174
|
0
|
|
|
|
|
0
|
return $ENV{$full_name}; |
|
175
|
|
|
|
|
|
|
} |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Loads module of given name or returns undef if it does not work |
|
179
|
|
|
|
|
|
|
sub _try_backend { |
|
180
|
7
|
|
|
7
|
|
10
|
my ($self, $backend_name) = @_; |
|
181
|
|
|
|
|
|
|
|
|
182
|
7
|
|
|
|
|
144
|
my $debug = $self->debug; |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# Sanity check |
|
185
|
7
|
50
|
|
|
|
67
|
unless($backend_name =~ /^[A-Za-z][A-Za-z0-9_]*$/) { |
|
186
|
0
|
0
|
|
|
|
0
|
if($debug) { |
|
187
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Ignoring illegal backend name: $backend_name\n"; |
|
188
|
|
|
|
|
|
|
} |
|
189
|
0
|
|
|
|
|
0
|
return undef; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
7
|
|
|
|
|
120
|
my @options = ( |
|
193
|
|
|
|
|
|
|
app => $self->app, |
|
194
|
|
|
|
|
|
|
group => $self->group, |
|
195
|
7
|
|
|
|
|
31
|
%{ $self->_config->backend_args($self->app, $backend_name) }, |
|
196
|
7
|
|
|
|
|
29
|
%{ $self->backend_args } |
|
197
|
|
|
|
|
|
|
); |
|
198
|
|
|
|
|
|
|
|
|
199
|
7
|
|
|
|
|
21
|
my $keyring; |
|
200
|
7
|
|
|
|
|
15
|
my $require = "Passwd/Keyring/$backend_name.pm"; |
|
201
|
7
|
|
|
|
|
13
|
my $module = "Passwd::Keyring::$backend_name"; |
|
202
|
7
|
50
|
|
|
|
17
|
if($debug) { |
|
203
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Trying to load $module and setup it with (" . join(", ", @options) . ")\n"; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
7
|
|
|
|
|
10
|
eval { |
|
206
|
7
|
|
|
|
|
2253
|
require $require; |
|
207
|
7
|
|
|
|
|
1720
|
$keyring = $module->new(@options); |
|
208
|
|
|
|
|
|
|
}; |
|
209
|
7
|
50
|
|
|
|
116
|
if($debug) { |
|
210
|
0
|
0
|
|
|
|
0
|
unless($@) { |
|
211
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Succesfully initiated $module, returning it\n"; |
|
212
|
|
|
|
|
|
|
} else { |
|
213
|
0
|
|
|
|
|
0
|
print STDERR "[Passwd::Keyring] Attempt to use $module failed, error: $@\n"; |
|
214
|
|
|
|
|
|
|
} |
|
215
|
|
|
|
|
|
|
} |
|
216
|
7
|
|
|
|
|
19
|
return $keyring; |
|
217
|
|
|
|
|
|
|
} |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
1; |