# -*- mode: perl -*- # ============================================================================ package Net::SNMP::Security::Community; # $Id: Community.pm,v 1.5 2005/07/20 13:53:07 dtown Rel $ # Object that implements the SNMPv1/v2c Community-based Security Model. # Copyright (c) 2001-2005 David M. Town # All rights reserved. # This program is free software; you may redistribute it and/or modify it # under the same terms as Perl itself. # ============================================================================ use strict; use Net::SNMP::Security qw( SECURITY_MODEL_SNMPV1 SECURITY_MODEL_SNMPV2C ); use Net::SNMP::Message qw( OCTET_STRING SEQUENCE INTEGER SNMP_VERSION_1 SNMP_VERSION_2C TRUE ); ## Version of the Net::SNMP::Security::Community module our $VERSION = v1.1.1; ## Handle importing/exporting of symbols use Exporter(); our @ISA = qw( Net::SNMP::Security Exporter ); sub import { Net::SNMP::Security->export_to_level(1, @_); } ## RFC 3584 - snmpCommunityName::=OCTET STRING sub COMMUNITY_DEFAULT() { 'public' } # [public methods] ----------------------------------------------------------- sub new { my ($class, %argv) = @_; # Create a new data structure for the object my $this = bless { '_error' => undef, # Error message '_version' => SNMP_VERSION_1, # SNMP version '_community' => COMMUNITY_DEFAULT # Community name }, $class; # Now validate the passed arguments foreach (keys %argv) { if (/^-?community$/i) { $this->_community($argv{$_}); } elsif (/^-?debug$/i) { $this->debug($argv{$_}); } elsif (/^-?version$/i) { $this->_version($argv{$_}); } else { $this->_error("Invalid argument '%s'", $_); } if (defined($this->{_error})) { return wantarray ? (undef, $this->{_error}) : undef; } } # Return the object and an empty error message (in list context) wantarray ? ($this, '') : $this; } sub generate_request_msg { my ($this, $pdu, $msg) = @_; # Clear any previous errors $this->_error_clear; return $this->_error('Required PDU and/or Message missing') unless (@_ == 3); if ($pdu->version != $this->{_version}) { return $this->_error('Invalid version [%d]', $pdu->version); } # Append the PDU if (!defined($msg->append($pdu->copy))) { return $this->_error($msg->error); } # community::=OCTET STRING if (!defined($msg->prepare(OCTET_STRING, $this->{_community}))) { return $this->_error($msg->error); } # version::=INTEGER if (!defined($msg->prepare(INTEGER, $this->{_version}))) { return $this->_error($msg->error); } # message::=SEQUENCE if (!defined($msg->prepare(SEQUENCE))) { return $this->_error($msg->error); } # Return the message $msg; } sub process_incoming_msg { my ($this, $msg) = @_; # Clear any previous errors $this->_error_clear; return $this->_error('Required Message missing') unless (@_ == 2); if ($msg->security_name ne $this->{_community}) { return $this->_error('Bad incoming community [%s]', $msg->security_name); } TRUE; } sub community { $_[0]->{_community}; } sub security_model { my ($this) = @_; # RFC 3411 - SnmpSecurityModel::=TEXTUAL-CONVENTION if ($this->{_version} == SNMP_VERSION_2C) { SECURITY_MODEL_SNMPV2C; } else { SECURITY_MODEL_SNMPV1; } } sub security_name { $_[0]->{_community}; } # [private methods] ---------------------------------------------------------- sub _community { my ($this, $community) = @_; return $this->_error('Community not defined') unless defined($community); $this->{_community} = $community; } sub _version { my ($this, $version) = @_; if (($version != SNMP_VERSION_1) && ($version != SNMP_VERSION_2C)) { return $this->_error('Invalid SNMP version specified [%s]', $version); } $this->{_version} = $version; } sub DEBUG_INFO { return unless $Net::SNMP::Security::DEBUG; printf( sprintf('debug: [%d] %s(): ', (caller(0))[2], (caller(1))[3]) . ((@_ > 1) ? shift(@_) : '%s') . "\n", @_ ); $Net::SNMP::Security::DEBUG; } # ============================================================================ 1; # [end Net::SNMP::Security::Community]