File Coverage

blib/lib/Net/SSH/Perl/Config.pm
Criterion Covered Total %
statement 68 92 73.9
branch 27 60 45.0
condition 9 21 42.8
subroutine 17 18 94.4
pod 5 5 100.0
total 126 196 64.2


line stmt bran cond sub pod time code
1             package Net::SSH::Perl::Config;
2 5     5   37 use strict;
  5         9  
  5         147  
3 5     5   25 use warnings;
  5         9  
  5         144  
4              
5 5     5   24 use Net::SSH::Perl::Constants qw( :protocol :kex );
  5         8  
  5         29  
6 5     5   34 use vars qw( %DIRECTIVES $AUTOLOAD );
  5         18  
  5         278  
7 5     5   31 use Carp qw( croak );
  5         9  
  5         9295  
8              
9             %DIRECTIVES = (
10             BindAddress => [ \&_set_str, 'bind_address' ],
11             Host => [ \&_host ],
12             BatchMode => [ \&_batch_mode ],
13             ChallengeResponseAuthentication => [ \&_set_yesno, 'auth_ch_res' ],
14             CheckHostIP => [ \&_set_yesno, 'check_host_ip' ],
15             Cipher => [ \&_cipher ],
16             Ciphers => [ \&_set_str, 'ciphers', KEX_DEFAULT_ENCRYPT, KEX_ALL_ENCRYPT ],
17             Compression => [ \&_set_yesno, 'compression' ],
18             CompressionLevel => [ \&_set_str, 'compression_level' ],
19             DSAAuthentication => [ \&_set_yesno, 'auth_dsa' ],
20             FingerprintHash => [ \&_set_str, 'fingerprint_hash' ],
21             GlobalKnownHostsFile => [ \&_set_str, 'global_known_hosts' ],
22             HashKnownHosts => [ \&_set_yesno, 'hash_known_hosts' ],
23             HostKeyAlgorithms => [ \&_set_str, 'host_key_algorithms', KEX_DEFAULT_PK_ALG, KEX_ALL_PK_ALG ],
24             HostName => [ \&_set_str, 'hostname' ],
25             IdentityFile => [ \&_identity_file ],
26             IdentitiesOnly => [ \&_set_yesno, 'identities_only' ],
27             KexAlgorithms => [ \&_set_str, 'kex_algorithms', KEX_DEFAULT_KEX, KEX_ALL_KEX ],
28             MACs => [ \&_set_str, 'macs', KEX_DEFAULT_MAC, KEX_ALL_MAC ],
29             NumberOfPasswordPrompts => [ \&_set_str, 'number_of_password_prompts' ],
30             PasswordAuthentication => [ \&_set_yesno, 'auth_password' ],
31             PasswordPromptHost => [ \&_set_yesno, 'password_prompt_host' ],
32             PasswordPromptLogin => [ \&_set_yesno, 'password_prompt_login' ],
33             Port => [ \&_set_str, 'port' ],
34             Protocol => [ \&_protocol ],
35             RhostsAuthentication => [ \&_set_yesno, 'auth_rhosts' ],
36             RhostsRSAAuthentication => [ \&_set_yesno, 'auth_rhosts_rsa' ],
37             RSAAuthentication => [ \&_set_yesno, 'auth_rsa' ],
38             StrictHostKeyChecking => [ \&_set_str, 'strict_host_key_checking' ],
39             UpdateHostKeys => [ \&_set_str, 'update_host_keys' ],
40             UsePrivilegedPort => [ \&_set_yesno, 'privileged' ],
41             User => [ \&_set_str, 'user' ],
42             UserKnownHostsFile => [ \&_set_str, 'user_known_hosts' ],
43             );
44              
45             sub new {
46 8     8 1 5981 my $class = shift;
47 8         27 my $host = shift;
48 8         66 bless { host => $host, o => { @_ } }, $class;
49             }
50              
51 66     66 1 1003 sub get { $_[0]->{o}{ $_[1] } }
52              
53             sub set {
54 35     35 1 90 my($cfg, $key) = @_;
55 35 50       105 $cfg->{o}{$key} = $_[2] if @_ == 3;
56 35         90 $cfg->{o}{$key};
57             }
58              
59             sub read_config {
60 13     13 1 2218 my($cfg, $conf_file) = @_;
61              
62 13         60 local $cfg->{_state} = { host => $cfg->{host}, host_matched => 1 };
63              
64 13         50 local($_, $/);
65 13         33 $/ = "\n";
66 13 100       566 open my $fh, '<', $conf_file or return;
67 6         170 while (<$fh>) {
68 54 100 66     283 next if !/\S/ || /^#/;
69 48         217 my($key, $args) = $_ =~ /^\s*(\S+)\s+(.+)$/;
70 48 50 33     165 next unless $key && $args;
71 48 100 100     208 next unless $cfg->{_state}{host_matched} || $key eq "Host";
72              
73 34 50       81 my $code = $DIRECTIVES{$key}[0] or next;
74 34         75 $code->($cfg, $key, $args);
75             }
76 6 50       130 close $fh or warn qq{Could not close "$conf_file": $!\n};
77             }
78              
79             sub merge_directive {
80 6     6 1 2906 my($cfg, $line) = @_;
81 6         42 my($key, $args) = $line =~ /^\s*(\S+)\s+(.+)$/;
82 6 50 33     32 return unless $key && $args;
83              
84 6 50       29 my $code = $DIRECTIVES{$key}[0] or return;
85 6         24 $code->($cfg, $key, $args);
86             }
87              
88             sub _host {
89 12     12   35 my($cfg, $key, $host) = @_;
90 12         29 (my $hostre = $host) =~ s/\*/.*/g;
91 12         21 $hostre =~ s/\?/./g;
92 12 100 66     227 if ($host eq '*' || $cfg->{_state}{host} =~ /^$hostre$/) {
93 6         37 $cfg->{_state}{host_matched} = 1;
94             }
95             else {
96 6         29 $cfg->{_state}{host_matched} = 0;
97             }
98             }
99              
100             sub _batch_mode {
101 2     2   5 my($cfg, $key, $batch) = @_;
102 2 50       14 return if exists $cfg->{o}{interactive};
103 2 50       24 $cfg->{o}{interactive} = $batch eq "yes" ? 0 : 1;
104             }
105              
106             sub _identity_file {
107 10     10   25 my($cfg, $key, $id_file) = @_;
108             $cfg->{identity_files} = []
109 10 100       41 unless ref $cfg->{o}{identity_files} eq "ARRAY";
110 10         19 $id_file =~ s!~!$ENV{HOME}!;
111 10         19 push @{ $cfg->{o}{identity_files} }, $id_file;
  10         55  
112             }
113              
114             sub _protocol {
115 0     0   0 my($cfg, $key, $p_list) = @_;
116 0 0       0 return if exists $cfg->{o}{protocol};
117 0         0 for my $p (split /\s*,\s*/, $p_list) {
118 0 0 0     0 croak "Invalid protocol: must be 1 or 2"
119             unless $p == 1 || $p == 2;
120 0         0 $cfg->{o}{protocol} |= $p;
121 0 0 0     0 if ($p == PROTOCOL_SSH1 && !($cfg->{o}{protocol} & PROTOCOL_SSH2)) {
122 0         0 $cfg->{o}{protocol} |= PROTOCOL_SSH1_PREFERRED;
123             }
124             }
125             }
126              
127             sub _set_str {
128 13     13   28 my($cfg, $key, $value) = @_;
129 13 100       56 return if exists $cfg->{o}{ $DIRECTIVES{$key}[1] };
130 10 50       49 if ($value =~ s/^-//) {
    50          
131 0         0 my @list;
132 0         0 $value =~ s/\*/\.\*/g;
133 0 0       0 my $defaults = $DIRECTIVES{$key}[2] or return;
134 0         0 foreach (split(',', $defaults)) {
135 0 0       0 next if /^$value$/;
136 0         0 push @list, $_;
137             }
138 0         0 $value = join(',',@list);
139             }
140             elsif ($value =~ s/^\+//) {
141 0         0 my @list;
142 0         0 $value =~ s/\*/\.\*/g;
143 0 0       0 my $all = $DIRECTIVES{$key}[3] or return;
144 0         0 foreach (split(',', $all)) {
145 0 0       0 push @list, $_ if /^$value$/;
146             }
147 0         0 $value = join(',', $DIRECTIVES{$key}[2], @list);
148             }
149 10         65 $cfg->{o}{ $DIRECTIVES{$key}[1] } = $value;
150             }
151              
152             {
153             my %cipher_map = (
154             idea => 'IDEA',
155             none => 'None',
156             des => 'DES',
157             '3des' => 'DES3',
158             arcfour => 'RC4',
159             blowfish => 'Blowfish',
160             );
161              
162             sub _cipher {
163 1     1   4 my($cfg, $key, $value) = @_;
164 1 50       4 return if exists $cfg->{o}{cipher};
165 1         12 $cfg->{o}{cipher} = $cipher_map{$value};
166             }
167             }
168              
169             sub _set_yesno {
170 2     2   4 my($cfg, $key, $yesno) = @_;
171 2 50       12 return if exists $cfg->{o}{ $DIRECTIVES{$key}[1] };
172 2 50       10 if ($yesno eq "yes") {
    50          
173 0         0 $cfg->{o}{ $DIRECTIVES{$key}[1] } = 1;
174             }
175             elsif ($yesno eq "no") {
176 2         9 $cfg->{o}{ $DIRECTIVES{$key}[1] } = 0;
177             }
178             else {
179 0         0 warn "Configuration setting for '$key' must be 'yes' or 'no'";
180             }
181             }
182              
183             sub AUTOLOAD {
184 8     8   2285 my $cfg = shift;
185 8         42 (my $variable = $AUTOLOAD) =~ s/.*:://;
186 8 50       333 return if $variable eq 'DESTROY';
187              
188             croak "No such configuration option $variable"
189 0 0         unless exists $cfg->{o}{$variable};
190              
191 0 0         return @_ ? $cfg->set($variable, @_) : $cfg->get($variable);
192             }
193              
194             1;
195             __END__