Class: NETSNMP::SecurityParameters

Inherits:
Object
  • Object
show all
Defined in:
lib/netsnmp/security_parameters.rb

Overview

This module encapsulates the public API for encrypting/decrypting and signing/verifying.

It doesn’t interact with other layers from the library, rather it is used and passed all the arguments (consisting mostly of primitive types). It also provides validation of the security options passed with a client is initialized in v3 mode.

Constant Summary collapse

IPAD =
"\x36" * 64
OPAD =
"\x5c" * 64

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(username:, engine_id: "", security_level: nil, auth_protocol: nil, auth_password: nil, priv_protocol: nil, priv_password: nil) ⇒ SecurityParameters

Note:

if security level is set to :no_auth_no_priv, all other parameters are optional; if :auth_no_priv, :auth_protocol will be coerced to :md5 (if not explicitly set), and :auth_password is mandatory; if :auth_priv, the sentence before applies, and :priv_protocol will be coerced to :des (if not explicitly set), and :priv_password becomes mandatory.

Returns a new instance of SecurityParameters.

Parameters:

  • username (String)

    the snmp v3 username

  • engine_id (String) (defaults to: "")

    the device engine id (initialized to ” for report)

  • security_level (Symbol, integer) (defaults to: nil)

    allowed snmp v3 security level (:auth_priv, :auh_no_priv, etc)

  • auth_protocol (Symbol, nil) (defaults to: nil)

    a supported authentication protocol (currently supported: :md5, :sha)

  • priv_protocol (Symbol, nil) (defaults to: nil)

    a supported privacy protocol (currently supported: :des, :aes)

  • auth_password (String, nil) (defaults to: nil)

    the authentication password

  • priv_password (String, nil) (defaults to: nil)

    the privacy password



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/netsnmp/security_parameters.rb', line 30

def initialize(
               username: , 
               engine_id: "",
               security_level: nil, 
               auth_protocol: nil, 
               auth_password: nil, 
               priv_protocol: nil, 
               priv_password: nil)
  @security_level = security_level
  @username = username
  @engine_id = engine_id
  @auth_protocol = auth_protocol.to_sym unless auth_protocol.nil?
  @priv_protocol = priv_protocol.to_sym unless priv_protocol.nil?
  @auth_password = auth_password
  @priv_password = priv_password
  check_parameters
  @auth_pass_key = passkey(@auth_password) unless @auth_password.nil?
  @priv_pass_key = passkey(@priv_password) unless @priv_password.nil?
end

Instance Attribute Details

#engine_idObject

Returns the value of attribute engine_id.



15
16
17
# File 'lib/netsnmp/security_parameters.rb', line 15

def engine_id
  @engine_id
end

#security_levelObject (readonly)

Returns the value of attribute security_level.



14
15
16
# File 'lib/netsnmp/security_parameters.rb', line 14

def security_level
  @security_level
end

#usernameObject (readonly)

Returns the value of attribute username.



14
15
16
# File 'lib/netsnmp/security_parameters.rb', line 14

def username
  @username
end

Instance Method Details

#decode(der, salt:, engine_time:, engine_boots:) ⇒ Object

Parameters:

  • der (String)

    the encoded der to be decoded

  • salt (String)

    the salt from the incoming der

  • engine_time (Integer)

    the reported engine time

  • engine_boots (Integer)

    the reported engine boots



72
73
74
75
76
77
78
79
80
81
# File 'lib/netsnmp/security_parameters.rb', line 72

def decode(der, salt: , engine_time: , engine_boots: )
  asn = OpenSSL::ASN1.decode(der)
  if encryption
    encrypted_pdu = asn.value
    pdu_der = encryption.decrypt(encrypted_pdu, salt: salt, engine_time: engine_time, engine_boots: engine_boots)
    OpenSSL::ASN1.decode(pdu_der)      
  else
    asn
  end
end

#encode(pdu, salt:, engine_time:, engine_boots:) ⇒ Array

Returns a pair, where the first argument in the asn structure with the encoded pdu, and the second is the calculated salt (if it has been encrypted).

Parameters:

  • pdu (#to_asn, #to_der)

    the pdu to encode (must quack like a asn1 type)

  • salt (String)

    the salt to use

  • engine_time (Integer)

    the reported engine time

  • engine_boots (Integer)

    the reported boots time

Returns:

  • (Array)

    a pair, where the first argument in the asn structure with the encoded pdu, and the second is the calculated salt (if it has been encrypted)



58
59
60
61
62
63
64
65
66
# File 'lib/netsnmp/security_parameters.rb', line 58

def encode(pdu, salt: , engine_time: , engine_boots: )
  if encryption
    encrypted_pdu, salt = encryption.encrypt(pdu.to_der, engine_boots: engine_boots, 
                                                         engine_time: engine_time)
    [OpenSSL::ASN1::OctetString.new(encrypted_pdu), OpenSSL::ASN1::OctetString.new(salt) ]
  else
    [ pdu.to_asn, salt ]
  end
end

#sign(message) ⇒ String

Note:

this method is used in the process of authenticating a message

Returns the digest signature of the message payload.

Parameters:

  • message (String)

    the already encoded snmp v3 message

Returns:

  • (String)

    the digest signature of the message payload



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/netsnmp/security_parameters.rb', line 87

def sign(message)
  # don't sign unless you have to
  return nil if not @auth_protocol

  key = auth_key.dup

  key << "\x00" * (@auth_protocol == :md5 ? 48 : 44)
  k1 = key.xor(IPAD)
  k2 = key.xor(OPAD)

  digest.reset
  digest << ( k1 + message )
  d1 = digest.digest

  digest.reset
  digest << ( k2 + d1 )
  digest.digest[0,12]
end

#verify(stream, salt) ⇒ Object

Parameters:

  • stream (String)

    the encoded incoming payload

  • salt (String)

    the incoming payload”s salt

Raises:

  • (NETSNMP::Error)

    if the message’s integration has been violated



110
111
112
113
114
# File 'lib/netsnmp/security_parameters.rb', line 110

def verify(stream, salt)
  return if @security_level < 1
  verisalt = sign(stream)
  raise Error, "invalid message authentication salt" unless verisalt == salt
end