netsnmp 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module NETSNMP
3
4
  module Encryption
4
5
  class AES
@@ -7,7 +8,7 @@ module NETSNMP
7
8
  @local = local
8
9
  end
9
10
 
10
- def encrypt(decrypted_data, engine_boots: , engine_time: )
11
+ def encrypt(decrypted_data, engine_boots:, engine_time:)
11
12
  cipher = OpenSSL::Cipher::AES128.new(:CFB)
12
13
 
13
14
  iv, salt = generate_encryption_key(engine_boots, engine_time)
@@ -24,12 +25,11 @@ module NETSNMP
24
25
  NETSNMP.debug { "encrypted:\n#{Hexdump.dump(encrypted_data)}" }
25
26
 
26
27
  [encrypted_data, salt]
27
-
28
28
  end
29
29
 
30
- def decrypt(encrypted_data, salt: , engine_boots: , engine_time: )
31
- raise Error, "invalid priv salt received" unless salt.length % 8 == 0
32
- raise Error, "invalid encrypted PDU received" unless encrypted_data.length % 8 == 0
30
+ def decrypt(encrypted_data, salt:, engine_boots:, engine_time:)
31
+ raise Error, "invalid priv salt received" unless (salt.length % 8).zero?
32
+ raise Error, "invalid encrypted PDU received" unless (encrypted_data.length % 8).zero?
33
33
 
34
34
  cipher = OpenSSL::Cipher::AES128.new(:CFB)
35
35
  cipher.padding = 0
@@ -40,13 +40,14 @@ module NETSNMP
40
40
  cipher.key = des_key
41
41
  cipher.iv = iv
42
42
  decrypted_data = cipher.update(encrypted_data) + cipher.final
43
- NETSNMP.debug {"decrypted:\n#{Hexdump.dump(decrypted_data)}" }
43
+ NETSNMP.debug { "decrypted:\n#{Hexdump.dump(decrypted_data)}" }
44
44
 
45
45
  hlen, bodylen = OpenSSL::ASN1.traverse(decrypted_data) { |_, _, x, y, *| break x, y }
46
- decrypted_data.byteslice(0, hlen+bodylen)
46
+ decrypted_data.byteslice(0, hlen + bodylen)
47
47
  end
48
48
 
49
49
  private
50
+
50
51
  # 8.1.1.1
51
52
  def generate_encryption_key(boots, time)
52
53
  salt = [0xff & (@local >> 56),
@@ -62,23 +63,22 @@ module NETSNMP
62
63
  iv = generate_decryption_key(boots, time, salt)
63
64
 
64
65
  [iv, salt]
65
- end
66
-
67
- def generate_decryption_key(boots, time, salt)
68
- [0xff & (boots >> 24),
69
- 0xff & (boots >> 16),
70
- 0xff & (boots >> 8),
71
- 0xff & boots,
72
- 0xff & (time >> 24),
73
- 0xff & (time >> 16),
74
- 0xff & (time >> 8),
75
- 0xff & time].pack("c*") + salt
76
- end
77
-
78
- def des_key
79
- @priv_key[0,16]
80
66
  end
81
67
 
68
+ def generate_decryption_key(boots, time, salt)
69
+ [0xff & (boots >> 24),
70
+ 0xff & (boots >> 16),
71
+ 0xff & (boots >> 8),
72
+ 0xff & boots,
73
+ 0xff & (time >> 24),
74
+ 0xff & (time >> 16),
75
+ 0xff & (time >> 8),
76
+ 0xff & time].pack("c*") + salt
77
+ end
78
+
79
+ def des_key
80
+ @priv_key[0, 16]
81
+ end
82
82
  end
83
83
  end
84
84
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module NETSNMP
3
4
  module Encryption
4
5
  using StringExtensions
@@ -9,8 +10,7 @@ module NETSNMP
9
10
  @local = local
10
11
  end
11
12
 
12
-
13
- def encrypt(decrypted_data, engine_boots: , engine_time: nil)
13
+ def encrypt(decrypted_data, engine_boots:, **)
14
14
  cipher = OpenSSL::Cipher::DES.new(:CBC)
15
15
 
16
16
  iv, salt = generate_encryption_key(engine_boots)
@@ -23,15 +23,14 @@ module NETSNMP
23
23
  decrypted_data << ("\x00" * (8 - diff))
24
24
  end
25
25
 
26
-
27
26
  encrypted_data = cipher.update(decrypted_data) + cipher.final
28
- NETSNMP.debug {"encrypted:\n#{Hexdump.dump(encrypted_data)}" }
27
+ NETSNMP.debug { "encrypted:\n#{Hexdump.dump(encrypted_data)}" }
29
28
  [encrypted_data, salt]
30
29
  end
31
30
 
32
- def decrypt(encrypted_data, salt: , engine_boots: nil, engine_time: nil)
33
- raise Error, "invalid priv salt received" unless salt.length % 8 == 0
34
- raise Error, "invalid encrypted PDU received" unless encrypted_data.length % 8 == 0
31
+ def decrypt(encrypted_data, salt:, **)
32
+ raise Error, "invalid priv salt received" unless (salt.length % 8).zero?
33
+ raise Error, "invalid encrypted PDU received" unless (encrypted_data.length % 8).zero?
35
34
 
36
35
  cipher = OpenSSL::Cipher::DES.new(:CBC)
37
36
  cipher.padding = 0
@@ -42,17 +41,17 @@ module NETSNMP
42
41
  cipher.key = des_key
43
42
  cipher.iv = iv
44
43
  decrypted_data = cipher.update(encrypted_data) + cipher.final
45
- NETSNMP.debug {"decrypted:\n#{Hexdump.dump(decrypted_data)}" }
44
+ NETSNMP.debug { "decrypted:\n#{Hexdump.dump(decrypted_data)}" }
46
45
 
47
46
  hlen, bodylen = OpenSSL::ASN1.traverse(decrypted_data) { |_, _, x, y, *| break x, y }
48
- decrypted_data.byteslice(0, hlen+bodylen)
47
+ decrypted_data.byteslice(0, hlen + bodylen)
49
48
  end
50
49
 
51
-
52
50
  private
51
+
53
52
  # 8.1.1.1
54
53
  def generate_encryption_key(boots)
55
- pre_iv = @priv_key[8,8]
54
+ pre_iv = @priv_key[8, 8]
56
55
  salt = [0xff & (boots >> 24),
57
56
  0xff & (boots >> 16),
58
57
  0xff & (boots >> 8),
@@ -61,19 +60,19 @@ module NETSNMP
61
60
  0xff & (@local >> 16),
62
61
  0xff & (@local >> 8),
63
62
  0xff & @local].pack("c*")
64
- @local = @local == 0xffffffff ? 0 : @local + 1
63
+ @local = @local == 0xffffffff ? 0 : @local + 1
65
64
 
66
- iv = pre_iv.xor(salt)
67
- [iv, salt]
68
- end
65
+ iv = pre_iv.xor(salt)
66
+ [iv, salt]
67
+ end
69
68
 
70
- def generate_decryption_key(salt)
71
- pre_iv = @priv_key[8,8]
72
- pre_iv.xor(salt)
73
- end
69
+ def generate_decryption_key(salt)
70
+ pre_iv = @priv_key[8, 8]
71
+ pre_iv.xor(salt)
72
+ end
74
73
 
75
- def des_key
76
- @priv_key[0,8]
74
+ def des_key
75
+ @priv_key[0, 8]
77
76
  end
78
77
  end
79
78
  end
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module NETSNMP
3
4
  module Encryption
4
5
  class None
5
-
6
- def initialize(*)
7
- end
6
+ def initialize(*); end
8
7
 
9
8
  def encrypt(pdu)
10
9
  pdu.send(:to_asn)
11
10
  end
11
+
12
12
  def decrypt(stream, *)
13
13
  stream
14
14
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module NETSNMP
3
4
  Error = Class.new(StandardError)
4
5
  ConnectionFailed = Class.new(Error)
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module NETSNMP
3
4
  # Factory for the SNMP v3 Message format
4
5
  module Message
5
- extend self
6
+ module_function
7
+
6
8
  AUTHNONE = OpenSSL::ASN1::OctetString.new("\x00" * 12)
7
9
  PRIVNONE = OpenSSL::ASN1::OctetString.new("")
8
10
  MSG_MAX_SIZE = OpenSSL::ASN1::Integer.new(65507)
9
- MSG_SECURITY_MODEL = OpenSSL::ASN1::Integer.new(3) # usmSecurityModel
11
+ MSG_SECURITY_MODEL = OpenSSL::ASN1::Integer.new(3) # usmSecurityModel
10
12
  MSG_VERSION = OpenSSL::ASN1::Integer.new(3)
11
13
  MSG_REPORTABLE = 4
12
14
 
@@ -15,25 +17,25 @@ module NETSNMP
15
17
  #
16
18
  # @return [NETSNMP::ScopedPDU] the decoded PDU
17
19
  #
18
- def decode(stream, security_parameters: )
20
+ def decode(stream, security_parameters:)
19
21
  asn_tree = OpenSSL::ASN1.decode(stream)
20
- version, headers, sec_params, pdu_payload = asn_tree.value
22
+ _version, _headers, sec_params, pdu_payload = asn_tree.value
21
23
 
22
24
  sec_params_asn = OpenSSL::ASN1.decode(sec_params.value).value
23
25
 
24
- engine_id, engine_boots, engine_time, username, auth_param, priv_param = sec_params_asn.map(&:value)
26
+ engine_id, engine_boots, engine_time, _username, auth_param, priv_param = sec_params_asn.map(&:value)
25
27
 
26
28
  # validate_authentication
27
29
  security_parameters.verify(stream.sub(auth_param, AUTHNONE.value), auth_param)
28
30
 
29
- engine_boots=engine_boots.to_i
30
- engine_time =engine_time.to_i
31
+ engine_boots = engine_boots.to_i
32
+ engine_time = engine_time.to_i
31
33
 
32
34
  encoded_pdu = security_parameters.decode(pdu_payload, salt: priv_param,
33
35
  engine_boots: engine_boots,
34
36
  engine_time: engine_time)
35
-
36
- pdu = ScopedPDU.decode(encoded_pdu)
37
+
38
+ pdu = ScopedPDU.decode(encoded_pdu)
37
39
  [pdu, engine_id, engine_boots, engine_time]
38
40
  end
39
41
 
@@ -42,33 +44,33 @@ module NETSNMP
42
44
  #
43
45
  # @return [String] the byte representation of an SNMP v3 Message
44
46
  #
45
- def encode(pdu, security_parameters: , engine_boots: 0, engine_time: 0)
46
- scoped_pdu, salt_param = security_parameters.encode(pdu, salt: PRIVNONE,
47
- engine_boots: engine_boots,
47
+ def encode(pdu, security_parameters:, engine_boots: 0, engine_time: 0)
48
+ scoped_pdu, salt_param = security_parameters.encode(pdu, salt: PRIVNONE,
49
+ engine_boots: engine_boots,
48
50
  engine_time: engine_time)
49
51
 
50
52
  sec_params = OpenSSL::ASN1::Sequence.new([
51
- OpenSSL::ASN1::OctetString.new(security_parameters.engine_id),
52
- OpenSSL::ASN1::Integer.new(engine_boots),
53
- OpenSSL::ASN1::Integer.new(engine_time),
54
- OpenSSL::ASN1::OctetString.new(security_parameters.username),
55
- AUTHNONE,
56
- salt_param
57
- ])
53
+ OpenSSL::ASN1::OctetString.new(security_parameters.engine_id),
54
+ OpenSSL::ASN1::Integer.new(engine_boots),
55
+ OpenSSL::ASN1::Integer.new(engine_time),
56
+ OpenSSL::ASN1::OctetString.new(security_parameters.username),
57
+ AUTHNONE,
58
+ salt_param
59
+ ])
58
60
  message_flags = MSG_REPORTABLE | security_parameters.security_level
59
61
  message_id = OpenSSL::ASN1::Integer.new(SecureRandom.random_number(2147483647))
60
62
  headers = OpenSSL::ASN1::Sequence.new([
61
- message_id, MSG_MAX_SIZE,
62
- OpenSSL::ASN1::OctetString.new( [String(message_flags)].pack("h*") ),
63
- MSG_SECURITY_MODEL
64
- ])
63
+ message_id, MSG_MAX_SIZE,
64
+ OpenSSL::ASN1::OctetString.new([String(message_flags)].pack("h*")),
65
+ MSG_SECURITY_MODEL
66
+ ])
65
67
 
66
- encoded = OpenSSL::ASN1::Sequence([
67
- MSG_VERSION,
68
- headers,
69
- OpenSSL::ASN1::OctetString.new(sec_params.to_der),
70
- scoped_pdu
71
- ]).to_der
68
+ encoded = OpenSSL::ASN1::Sequence([
69
+ MSG_VERSION,
70
+ headers,
71
+ OpenSSL::ASN1::OctetString.new(sec_params.to_der),
72
+ scoped_pdu
73
+ ]).to_der
72
74
  signature = security_parameters.sign(encoded)
73
75
  if signature
74
76
  auth_salt = OpenSSL::ASN1::OctetString.new(signature)
@@ -76,6 +78,5 @@ module NETSNMP
76
78
  end
77
79
  encoded
78
80
  end
79
-
80
81
  end
81
82
  end
data/lib/netsnmp/oid.rb CHANGED
@@ -1,19 +1,20 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module NETSNMP
3
4
  # Abstracts the OID structure
4
5
  #
5
6
  module OID
6
7
  OIDREGEX = /^[\d\.]*$/
7
8
 
8
- extend self
9
+ module_function
9
10
 
10
11
  def build(o)
11
12
  case o
12
13
  when OID then o
13
14
  when Array
14
- o.join('.')
15
+ o.join(".")
15
16
  when OIDREGEX
16
- o = o[1..-1] if o.start_with?('.')
17
+ o = o[1..-1] if o.start_with?(".")
17
18
  o
18
19
  # TODO: MIB to OID
19
20
  else raise Error, "can't convert #{o} to OID"
@@ -28,7 +29,7 @@ module NETSNMP
28
29
  # @return [true, false] whether the given OID belongs to the sub-tree
29
30
  #
30
31
  def parent?(parent_oid, child_oid)
31
- child_oid.match(%r/\A#{parent_oid}\./)
32
+ child_oid.match(/\A#{parent_oid}\./)
32
33
  end
33
34
  end
34
35
  end
data/lib/netsnmp/pdu.rb CHANGED
@@ -1,21 +1,21 @@
1
1
  # frozen_string_literal: true
2
- require 'forwardable'
2
+
3
+ require "forwardable"
3
4
  module NETSNMP
4
5
  # Abstracts the PDU base structure into a ruby object. It gives access to its varbinds.
5
6
  #
6
7
  class PDU
7
- MAXREQUESTID=2147483647
8
+ MAXREQUESTID = 2147483647
8
9
  class << self
9
-
10
10
  def decode(der)
11
11
  asn_tree = case der
12
- when String
13
- OpenSSL::ASN1.decode(der)
14
- when OpenSSL::ASN1::ASN1Data
15
- der
16
- else
17
- raise "#{der}: unexpected data"
18
- end
12
+ when String
13
+ OpenSSL::ASN1.decode(der)
14
+ when OpenSSL::ASN1::ASN1Data
15
+ der
16
+ else
17
+ raise "#{der}: unexpected data"
18
+ end
19
19
 
20
20
  *headers, request = asn_tree.value
21
21
 
@@ -25,34 +25,34 @@ module NETSNMP
25
25
 
26
26
  *request_headers, varbinds = request.value
27
27
 
28
- request_id, error_status, error_index = request_headers.map(&:value).map(&:to_i)
28
+ request_id, error_status, error_index = request_headers.map(&:value).map(&:to_i)
29
29
 
30
30
  varbs = varbinds.value.map do |varbind|
31
- oid_asn, val_asn = varbind.value
31
+ oid_asn, val_asn = varbind.value
32
32
  oid = oid_asn.value
33
33
  { oid: oid, value: val_asn }
34
34
  end
35
35
 
36
36
  new(type: type, headers: [version, community],
37
- error_status: error_status,
38
- error_index: error_index,
39
- request_id: request_id,
40
- varbinds: varbs)
37
+ error_status: error_status,
38
+ error_index: error_index,
39
+ request_id: request_id,
40
+ varbinds: varbs)
41
41
  end
42
42
 
43
43
  # factory method that abstracts initialization of the pdu types that the library supports.
44
- #
44
+ #
45
45
  # @param [Symbol] type the type of pdu structure to build
46
- #
46
+ #
47
47
  def build(type, **args)
48
48
  typ = case type
49
- when :get then 0
50
- when :getnext then 1
51
- # when :getbulk then 5
52
- when :set then 3
53
- when :response then 2
54
- else raise Error, "#{type} is not supported as type"
55
- end
49
+ when :get then 0
50
+ when :getnext then 1
51
+ # when :getbulk then 5
52
+ when :set then 3
53
+ when :response then 2
54
+ else raise Error, "#{type} is not supported as type"
55
+ end
56
56
  new(args.merge(type: typ))
57
57
  end
58
58
  end
@@ -61,11 +61,11 @@ module NETSNMP
61
61
 
62
62
  attr_reader :version, :community, :request_id
63
63
 
64
- def initialize(type: , headers: ,
65
- request_id: nil,
66
- error_status: 0,
67
- error_index: 0,
68
- varbinds: [])
64
+ def initialize(type:, headers:,
65
+ request_id: nil,
66
+ error_status: 0,
67
+ error_index: 0,
68
+ varbinds: [])
69
69
  @version, @community = headers
70
70
  @version = @version.to_i
71
71
  @error_status = error_status
@@ -79,70 +79,67 @@ module NETSNMP
79
79
  check_error_status(@error_status)
80
80
  end
81
81
 
82
-
83
82
  def to_der
84
83
  to_asn.to_der
85
84
  end
86
85
 
87
86
  # Adds a request varbind to the pdu
88
- #
87
+ #
89
88
  # @param [OID] oid a valid oid
90
89
  # @param [Hash] options additional request varbind options
91
90
  # @option options [Object] :value the value for the oid
92
- def add_varbind(oid: , **options)
91
+ def add_varbind(oid:, **options)
93
92
  @varbinds << Varbind.new(oid, **options)
94
93
  end
95
- alias_method :<<, :add_varbind
96
-
94
+ alias << add_varbind
97
95
 
98
96
  def to_asn
99
- request_id_asn = OpenSSL::ASN1::Integer.new( @request_id )
100
- error_asn = OpenSSL::ASN1::Integer.new( @error_status )
101
- error_index_asn = OpenSSL::ASN1::Integer.new( @error_index )
97
+ request_id_asn = OpenSSL::ASN1::Integer.new(@request_id)
98
+ error_asn = OpenSSL::ASN1::Integer.new(@error_status)
99
+ error_index_asn = OpenSSL::ASN1::Integer.new(@error_index)
102
100
 
103
- varbind_asns = OpenSSL::ASN1::Sequence.new( @varbinds.map(&:to_asn) )
101
+ varbind_asns = OpenSSL::ASN1::Sequence.new(@varbinds.map(&:to_asn))
104
102
 
105
- request_asn = OpenSSL::ASN1::ASN1Data.new( [request_id_asn,
106
- error_asn, error_index_asn,
107
- varbind_asns], @type,
108
- :CONTEXT_SPECIFIC )
103
+ request_asn = OpenSSL::ASN1::ASN1Data.new([request_id_asn,
104
+ error_asn, error_index_asn,
105
+ varbind_asns], @type,
106
+ :CONTEXT_SPECIFIC)
109
107
 
110
- OpenSSL::ASN1::Sequence.new( [ *encode_headers_asn, request_asn ] )
108
+ OpenSSL::ASN1::Sequence.new([*encode_headers_asn, request_asn])
111
109
  end
112
110
 
113
111
  private
114
112
 
115
113
  def encode_headers_asn
116
- [ OpenSSL::ASN1::Integer.new( @version ),
117
- OpenSSL::ASN1::OctetString.new( @community ) ]
114
+ [OpenSSL::ASN1::Integer.new(@version),
115
+ OpenSSL::ASN1::OctetString.new(@community)]
118
116
  end
119
117
 
120
-
121
118
  # http://www.tcpipguide.com/free/t_SNMPVersion2SNMPv2MessageFormats-5.htm#Table_219
122
119
  def check_error_status(status)
123
- return if status == 0
120
+ return if status.zero?
124
121
  message = case status
125
- when 1 then "Response-PDU too big"
126
- when 2 then "No such name"
127
- when 3 then "Bad value"
128
- when 4 then "Read Only"
129
- when 5 then "General Error"
130
- when 6 then "Access denied"
131
- when 7 then "Wrong type"
132
- when 8 then "Wrong length"
133
- when 9 then "Wrong encoding"
134
- when 10 then "Wrong value"
135
- when 11 then "No creation"
136
- when 12 then "Inconsistent value"
137
- when 13 then "Resource unavailable"
138
- when 14 then "Commit failed"
139
- when 15 then "Undo Failed"
140
- when 16 then "Authorization Error"
141
- when 17 then "Not Writable"
142
- when 18 then "Inconsistent Name"
143
- else
144
- "Unknown Error: (#{status})"
145
- end
122
+ when 1 then "Response-PDU too big"
123
+ when 2 then "No such name"
124
+ when 3 then "Bad value"
125
+ when 4 then "Read Only"
126
+ when 5 then "General Error"
127
+ when 6 then "Access denied"
128
+ when 7 then "Wrong type"
129
+ when 8 then "Wrong length"
130
+ when 9 then "Wrong encoding"
131
+ when 10 then "Wrong value"
132
+ when 11 then "No creation"
133
+ when 12 then "Inconsistent value"
134
+ when 13 then "Resource unavailable"
135
+ when 14 then "Commit failed"
136
+ when 15 then "Undo Failed"
137
+ when 16 then "Authorization Error"
138
+ when 17 then "Not Writable"
139
+ when 18 then "Inconsistent Name"
140
+ else
141
+ "Unknown Error: (#{status})"
142
+ end
146
143
  raise Error, message
147
144
  end
148
145
  end
@@ -1,19 +1,17 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module NETSNMP
3
4
  class ScopedPDU < PDU
4
-
5
-
6
5
  attr_reader :engine_id
7
6
 
8
- def initialize(type: , headers:, **options)
7
+ def initialize(type:, headers:, **options)
9
8
  @engine_id, @context = headers
10
9
  super(type: type, headers: [3, nil], **options)
11
10
  end
12
11
 
13
12
  def encode_headers_asn
14
- [ OpenSSL::ASN1::OctetString.new(@engine_id || ""),
15
- OpenSSL::ASN1::OctetString.new(@context || "") ]
16
- end
17
-
13
+ [OpenSSL::ASN1::OctetString.new(@engine_id || ""),
14
+ OpenSSL::ASN1::OctetString.new(@context || "")]
15
+ end
18
16
  end
19
17
  end