File Coverage

blib/lib/Net/SNMP/Security.pm
Criterion Covered Total %
statement 21 64 32.8
branch 4 42 9.5
condition 3 8 37.5
subroutine 7 17 41.1
pod 0 11 0.0
total 35 142 24.6


line stmt bran cond sub pod time code
1             # -*- mode: perl -*-
2             # ============================================================================
3              
4             package Net::SNMP::Security;
5              
6             # $Id: Security.pm,v 2.0 2009/09/09 15:05:33 dtown Rel $
7              
8             # Base object that implements the Net::SNMP Security Models.
9              
10             # Copyright (c) 2001-2009 David M. Town
11             # All rights reserved.
12              
13             # This program is free software; you may redistribute it and/or modify it
14             # under the same terms as the Perl 5 programming language system itself.
15              
16             # ============================================================================
17              
18 2     2   705 use strict;
  2         4  
  2         231  
19              
20 2         472 use Net::SNMP::Message qw(
21             :securityLevels :securityModels :versions TRUE FALSE
22 2     2   28 );
  2         4  
23              
24             ## Version of the Net::SNMP::Security module
25              
26             our $VERSION = v2.0.0;
27              
28             ## Handle importing/exporting of symbols
29              
30 2     2   10 use base qw( Exporter );
  2         4  
  2         2478  
31              
32             our @EXPORT_OK = qw( DEBUG_INFO );
33              
34             our %EXPORT_TAGS = (
35             levels => [
36             qw( SECURITY_LEVEL_NOAUTHNOPRIV SECURITY_LEVEL_AUTHNOPRIV
37             SECURITY_LEVEL_AUTHPRIV )
38             ],
39             models => [
40             qw( SECURITY_MODEL_ANY SECURITY_MODEL_SNMPV1 SECURITY_MODEL_SNMPV2C
41             SECURITY_MODEL_USM )
42             ]
43             );
44              
45             Exporter::export_ok_tags( qw( levels models ) );
46              
47             $EXPORT_TAGS{ALL} = [ @EXPORT_OK ];
48              
49             ## Package variables
50              
51             our $DEBUG = FALSE; # Debug flag
52              
53             our $AUTOLOAD; # Used by the AUTOLOAD method
54              
55             #perl2exe_include Net::SNMP::Security::USM
56              
57             # [public methods] -----------------------------------------------------------
58              
59             sub new
60             {
61 1     1 0 4 my ($class, %argv) = @_;
62              
63 1         4 my $version = SNMP_VERSION_1;
64              
65             # See if a SNMP version has been passed
66 1         3 for (keys %argv) {
67 1 50       11 if (/^-?version$/i) {
68 1 50 33     4 if (($argv{$_} == SNMP_VERSION_1) ||
      33        
69             ($argv{$_} == SNMP_VERSION_2C) ||
70             ($argv{$_} == SNMP_VERSION_3))
71             {
72 1         3 $version = $argv{$_};
73             }
74             }
75             }
76              
77             # Return the appropriate object based upon the SNMP version. To
78             # avoid consuming unnecessary resources, only load the appropriate
79             # module when requested. The Net::SNMP::Security::USM module
80             # requires four non-core modules. If any of these modules are not
81             # present, we gracefully return an error.
82              
83 1 50       15 if ($version == SNMP_VERSION_3) {
84              
85 0 0       0 if (defined(my $error = load_module('Net::SNMP::Security::USM'))) {
86 0         0 $error = 'SNMPv3 support is unavailable ' . $error;
87 0 0       0 return wantarray ? (undef, $error) : undef;
88             }
89              
90 0         0 return Net::SNMP::Security::USM->new(%argv);
91             }
92              
93             # Load the default Security module without eval protection.
94              
95 1         738 require Net::SNMP::Security::Community;
96 1         7 return Net::SNMP::Security::Community->new(%argv);
97             }
98              
99             sub version
100             {
101 0     0 0 0 my ($this) = @_;
102              
103 0 0       0 if (@_ > 1) {
104 0         0 $this->_error_clear();
105 0         0 return $this->_error('The SNMP version is not modifiable');
106             }
107              
108 0         0 return $this->{_version};
109             }
110              
111             sub discovered
112             {
113 0     0 0 0 return TRUE;
114             }
115              
116             sub security_model
117             {
118             # RFC 3411 - SnmpSecurityModel::=TEXTUAL-CONVENTION
119              
120 0     0 0 0 return SECURITY_MODEL_ANY;
121             }
122              
123             sub security_level
124             {
125             # RFC 3411 - SnmpSecurityLevel::=TEXTUAL-CONVENTION
126              
127 0     0 0 0 return SECURITY_LEVEL_NOAUTHNOPRIV;
128             }
129              
130             sub security_name
131             {
132 0     0 0 0 return q{};
133             }
134              
135             sub debug
136             {
137 0 0   0 0 0 return (@_ == 2) ? $DEBUG = ($_[1]) ? TRUE : FALSE : $DEBUG;
    0          
138             }
139              
140             sub error
141             {
142 2   50 2 0 11 return $_[0]->{_error} || q{};
143             }
144              
145             sub AUTOLOAD
146             {
147 0     0   0 my ($this) = @_;
148              
149 0 0       0 return if $AUTOLOAD =~ /::DESTROY$/;
150              
151 0         0 $AUTOLOAD =~ s/.*://;
152              
153 0 0       0 if (ref $this) {
154 0         0 $this->_error_clear();
155 0         0 return $this->_error(
156             'The method "%s" is not supported by this Security Model', $AUTOLOAD
157             );
158             } else {
159 0         0 require Carp;
160 0         0 Carp::croak(sprintf 'The function "%s" is not supported', $AUTOLOAD);
161             }
162              
163             # Never get here.
164 0         0 return;
165             }
166              
167             # [private methods] ----------------------------------------------------------
168              
169             sub _error
170             {
171 0     0   0 my $this = shift;
172              
173 0 0       0 if (!defined $this->{_error}) {
174 0 0       0 $this->{_error} = (@_ > 1) ? sprintf(shift(@_), @_) : $_[0];
175 0 0       0 if ($this->debug()) {
176 0         0 printf "error: [%d] %s(): %s\n",
177             (caller 0)[2], (caller 1)[3], $this->{_error};
178             }
179             }
180              
181 0         0 return;
182             }
183              
184             sub _error_clear
185             {
186 7     7   20 return $_[0]->{_error} = undef;
187             }
188              
189             {
190             my %modules;
191              
192             sub load_module
193             {
194 0     0 0 0 my ($module) = @_;
195              
196             # We attempt to load the required module under the protection of an
197             # eval statement. If there is a failure, typically it is due to a
198             # missing module required by the requested module and we attempt to
199             # simplify the error message by just listing that module. We also
200             # need to track failures since require() only produces an error on
201             # the first attempt to load the module.
202              
203             # NOTE: Contrary to our typical convention, a return value of "undef"
204             # actually means success and a defined value means error.
205              
206 0 0       0 return $modules{$module} if exists $modules{$module};
207              
208 0 0       0 if (!eval "require $module") {
209 0 0       0 if ($@ =~ m/locate (\S+\.pm)/) {
    0          
210 0         0 $modules{$module} = err_msg('(Required module %s not found)', $1);
211             } elsif ($@ =~ m/(.*)\n/) {
212 0         0 $modules{$module} = err_msg('(%s)', $1);
213             } else {
214 0         0 $modules{$module} = err_msg('(%s)', $@);
215             }
216             } else {
217 0         0 $modules{$module} = undef;
218             }
219              
220 0         0 return $modules{$module};
221             }
222             }
223              
224             sub err_msg
225             {
226 0 0   0 0 0 my $msg = (@_ > 1) ? sprintf(shift(@_), @_) : $_[0];
227              
228 0 0       0 if ($DEBUG) {
229 0         0 printf "error: [%d] %s(): %s\n", (caller 0)[2], (caller 1)[3], $msg;
230             }
231              
232 0         0 return $msg;
233             }
234              
235             sub DEBUG_INFO
236             {
237 12 50   12 0 34 return if (!$DEBUG);
238              
239 0 0         return printf
240             sprintf('debug: [%d] %s(): ', (caller 0)[2], (caller 1)[3]) .
241             ((@_ > 1) ? shift(@_) : '%s') .
242             "\n",
243             @_;
244             }
245              
246             # ============================================================================
247             1; # [end Net::SNMP::Security]
248