| 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 |  |  |  |  |  |  |  |