rubinius-net-ldap 0.11

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.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rubocop.yml +5 -0
  4. data/.rubocop_todo.yml +462 -0
  5. data/.travis.yml +19 -0
  6. data/CONTRIBUTING.md +54 -0
  7. data/Contributors.rdoc +24 -0
  8. data/Gemfile +2 -0
  9. data/Hacking.rdoc +63 -0
  10. data/History.rdoc +260 -0
  11. data/License.rdoc +29 -0
  12. data/README.rdoc +65 -0
  13. data/Rakefile +17 -0
  14. data/lib/net-ldap.rb +2 -0
  15. data/lib/net/ber.rb +320 -0
  16. data/lib/net/ber/ber_parser.rb +182 -0
  17. data/lib/net/ber/core_ext.rb +55 -0
  18. data/lib/net/ber/core_ext/array.rb +96 -0
  19. data/lib/net/ber/core_ext/false_class.rb +10 -0
  20. data/lib/net/ber/core_ext/integer.rb +74 -0
  21. data/lib/net/ber/core_ext/string.rb +66 -0
  22. data/lib/net/ber/core_ext/true_class.rb +11 -0
  23. data/lib/net/ldap.rb +1229 -0
  24. data/lib/net/ldap/connection.rb +702 -0
  25. data/lib/net/ldap/dataset.rb +168 -0
  26. data/lib/net/ldap/dn.rb +225 -0
  27. data/lib/net/ldap/entry.rb +193 -0
  28. data/lib/net/ldap/error.rb +38 -0
  29. data/lib/net/ldap/filter.rb +778 -0
  30. data/lib/net/ldap/instrumentation.rb +23 -0
  31. data/lib/net/ldap/password.rb +38 -0
  32. data/lib/net/ldap/pdu.rb +297 -0
  33. data/lib/net/ldap/version.rb +5 -0
  34. data/lib/net/snmp.rb +264 -0
  35. data/rubinius-net-ldap.gemspec +37 -0
  36. data/script/install-openldap +112 -0
  37. data/script/package +7 -0
  38. data/script/release +16 -0
  39. data/test/ber/core_ext/test_array.rb +22 -0
  40. data/test/ber/core_ext/test_string.rb +25 -0
  41. data/test/ber/test_ber.rb +99 -0
  42. data/test/fixtures/cacert.pem +20 -0
  43. data/test/fixtures/openldap/memberof.ldif +33 -0
  44. data/test/fixtures/openldap/retcode.ldif +76 -0
  45. data/test/fixtures/openldap/slapd.conf.ldif +67 -0
  46. data/test/fixtures/seed.ldif +374 -0
  47. data/test/integration/test_add.rb +28 -0
  48. data/test/integration/test_ber.rb +30 -0
  49. data/test/integration/test_bind.rb +34 -0
  50. data/test/integration/test_delete.rb +31 -0
  51. data/test/integration/test_open.rb +88 -0
  52. data/test/integration/test_return_codes.rb +38 -0
  53. data/test/integration/test_search.rb +77 -0
  54. data/test/support/vm/openldap/.gitignore +1 -0
  55. data/test/support/vm/openldap/README.md +32 -0
  56. data/test/support/vm/openldap/Vagrantfile +33 -0
  57. data/test/test_dn.rb +44 -0
  58. data/test/test_entry.rb +65 -0
  59. data/test/test_filter.rb +223 -0
  60. data/test/test_filter_parser.rb +20 -0
  61. data/test/test_helper.rb +66 -0
  62. data/test/test_ldap.rb +60 -0
  63. data/test/test_ldap_connection.rb +404 -0
  64. data/test/test_ldif.rb +104 -0
  65. data/test/test_password.rb +10 -0
  66. data/test/test_rename.rb +77 -0
  67. data/test/test_search.rb +39 -0
  68. data/test/test_snmp.rb +119 -0
  69. data/test/test_ssl_ber.rb +40 -0
  70. data/test/testdata.ldif +101 -0
  71. data/testserver/ldapserver.rb +210 -0
  72. data/testserver/testdata.ldif +101 -0
  73. metadata +204 -0
@@ -0,0 +1,23 @@
1
+ module Net::LDAP::Instrumentation
2
+ attr_reader :instrumentation_service
3
+ private :instrumentation_service
4
+
5
+ # Internal: Instrument a block with the defined instrumentation service.
6
+ #
7
+ # Yields the event payload if a block is given.
8
+ #
9
+ # Skips instrumentation if no service is set.
10
+ #
11
+ # Returns the return value of the block.
12
+ def instrument(event, payload = {})
13
+ payload = (payload || {}).dup
14
+ if instrumentation_service
15
+ instrumentation_service.instrument(event, payload) do |payload|
16
+ payload[:result] = yield(payload) if block_given?
17
+ end
18
+ else
19
+ yield(payload) if block_given?
20
+ end
21
+ end
22
+ private :instrument
23
+ end
@@ -0,0 +1,38 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+ require 'digest/sha1'
3
+ require 'digest/md5'
4
+ require 'base64'
5
+ require 'securerandom'
6
+
7
+ class Net::LDAP::Password
8
+ class << self
9
+ # Generate a password-hash suitable for inclusion in an LDAP attribute.
10
+ # Pass a hash type as a symbol (:md5, :sha, :ssha) and a plaintext
11
+ # password. This function will return a hashed representation.
12
+ #
13
+ #--
14
+ # STUB: This is here to fulfill the requirements of an RFC, which
15
+ # one?
16
+ #
17
+ # TODO:
18
+ # * maybe salted-md5
19
+ # * Should we provide sha1 as a synonym for sha1? I vote no because then
20
+ # should you also provide ssha1 for symmetry?
21
+ #
22
+ attribute_value = ""
23
+ def generate(type, str)
24
+ case type
25
+ when :md5
26
+ attribute_value = '{MD5}' + Base64.encode64(Digest::MD5.digest(str)).chomp!
27
+ when :sha
28
+ attribute_value = '{SHA}' + Base64.encode64(Digest::SHA1.digest(str)).chomp!
29
+ when :ssha
30
+ salt = SecureRandom.random_bytes(16)
31
+ attribute_value = '{SSHA}' + Base64.encode64(Digest::SHA1.digest(str + salt) + salt).chomp!
32
+ else
33
+ raise Net::LDAP::HashTypeUnsupportedError, "Unsupported password-hash type (#{type})"
34
+ end
35
+ return attribute_value
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,297 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+ require 'ostruct'
3
+
4
+ ##
5
+ # Defines the Protocol Data Unit (PDU) for LDAP. An LDAP PDU always looks
6
+ # like a BER SEQUENCE with at least two elements: an INTEGER message ID
7
+ # number and an application-specific SEQUENCE. Some LDAPv3 packets also
8
+ # include an optional third element, a sequence of "controls" (see RFC 2251
9
+ # section 4.1.12 for more information).
10
+ #
11
+ # The application-specific tag in the sequence tells us what kind of packet
12
+ # it is, and each kind has its own format, defined in RFC-1777.
13
+ #
14
+ # Observe that many clients (such as ldapsearch) do not necessarily enforce
15
+ # the expected application tags on received protocol packets. This
16
+ # implementation does interpret the RFC strictly in this regard, and it
17
+ # remains to be seen whether there are servers out there that will not work
18
+ # well with our approach.
19
+ #
20
+ # Currently, we only support controls on SearchResult.
21
+ #
22
+ # http://tools.ietf.org/html/rfc4511#section-4.1.1
23
+ # http://tools.ietf.org/html/rfc4511#section-4.1.9
24
+ class Net::LDAP::PDU
25
+ class Error < RuntimeError; end
26
+
27
+ # http://tools.ietf.org/html/rfc4511#section-4.2
28
+ BindRequest = 0
29
+ # http://tools.ietf.org/html/rfc4511#section-4.2.2
30
+ BindResult = 1
31
+ # http://tools.ietf.org/html/rfc4511#section-4.3
32
+ UnbindRequest = 2
33
+ # http://tools.ietf.org/html/rfc4511#section-4.5.1
34
+ SearchRequest = 3
35
+ # http://tools.ietf.org/html/rfc4511#section-4.5.2
36
+ SearchReturnedData = 4
37
+ SearchResult = 5
38
+ # see also SearchResultReferral (19)
39
+ # http://tools.ietf.org/html/rfc4511#section-4.6
40
+ ModifyRequest = 6
41
+ ModifyResponse = 7
42
+ # http://tools.ietf.org/html/rfc4511#section-4.7
43
+ AddRequest = 8
44
+ AddResponse = 9
45
+ # http://tools.ietf.org/html/rfc4511#section-4.8
46
+ DeleteRequest = 10
47
+ DeleteResponse = 11
48
+ # http://tools.ietf.org/html/rfc4511#section-4.9
49
+ ModifyRDNRequest = 12
50
+ ModifyRDNResponse = 13
51
+ # http://tools.ietf.org/html/rfc4511#section-4.10
52
+ CompareRequest = 14
53
+ CompareResponse = 15
54
+ # http://tools.ietf.org/html/rfc4511#section-4.11
55
+ AbandonRequest = 16
56
+ # http://tools.ietf.org/html/rfc4511#section-4.5.2
57
+ SearchResultReferral = 19
58
+ # http://tools.ietf.org/html/rfc4511#section-4.12
59
+ ExtendedRequest = 23
60
+ ExtendedResponse = 24
61
+ # unused: http://tools.ietf.org/html/rfc4511#section-4.13
62
+ IntermediateResponse = 25
63
+
64
+ ##
65
+ # The LDAP packet message ID.
66
+ attr_reader :message_id
67
+ alias_method :msg_id, :message_id
68
+
69
+ ##
70
+ # The application protocol format tag.
71
+ attr_reader :app_tag
72
+
73
+ attr_reader :search_entry
74
+ attr_reader :search_referrals
75
+ attr_reader :search_parameters
76
+ attr_reader :bind_parameters
77
+
78
+ ##
79
+ # Returns RFC-2251 Controls if any.
80
+ attr_reader :ldap_controls
81
+ alias_method :result_controls, :ldap_controls
82
+ # Messy. Does this functionality belong somewhere else?
83
+
84
+ def initialize(ber_object)
85
+ begin
86
+ @message_id = ber_object[0].to_i
87
+ # Grab the bottom five bits of the identifier so we know which type of
88
+ # PDU this is.
89
+ #
90
+ # This is safe enough in LDAP-land, but it is recommended that other
91
+ # approaches be taken for other protocols in the case that there's an
92
+ # app-specific tag that has both primitive and constructed forms.
93
+ @app_tag = ber_object[1].ber_identifier & 0x1f
94
+ @ldap_controls = []
95
+ rescue Exception => ex
96
+ raise Net::LDAP::PDU::Error, "LDAP PDU Format Error: #{ex.message}"
97
+ end
98
+
99
+ case @app_tag
100
+ when BindResult
101
+ parse_bind_response(ber_object[1])
102
+ when SearchReturnedData
103
+ parse_search_return(ber_object[1])
104
+ when SearchResultReferral
105
+ parse_search_referral(ber_object[1])
106
+ when SearchResult
107
+ parse_ldap_result(ber_object[1])
108
+ when ModifyResponse
109
+ parse_ldap_result(ber_object[1])
110
+ when AddResponse
111
+ parse_ldap_result(ber_object[1])
112
+ when DeleteResponse
113
+ parse_ldap_result(ber_object[1])
114
+ when ModifyRDNResponse
115
+ parse_ldap_result(ber_object[1])
116
+ when SearchRequest
117
+ parse_ldap_search_request(ber_object[1])
118
+ when BindRequest
119
+ parse_bind_request(ber_object[1])
120
+ when UnbindRequest
121
+ parse_unbind_request(ber_object[1])
122
+ when ExtendedResponse
123
+ parse_ldap_result(ber_object[1])
124
+ else
125
+ raise LdapPduError.new("unknown pdu-type: #{@app_tag}")
126
+ end
127
+
128
+ parse_controls(ber_object[2]) if ber_object[2]
129
+ end
130
+
131
+ ##
132
+ # Returns a hash which (usually) defines the members :resultCode,
133
+ # :errorMessage, and :matchedDN. These values come directly from an LDAP
134
+ # response packet returned by the remote peer. Also see #result_code.
135
+ def result
136
+ @ldap_result || {}
137
+ end
138
+
139
+ def error_message
140
+ result[:errorMessage] || ""
141
+ end
142
+
143
+ ##
144
+ # This returns an LDAP result code taken from the PDU, but it will be nil
145
+ # if there wasn't a result code. That can easily happen depending on the
146
+ # type of packet.
147
+ def result_code(code = :resultCode)
148
+ @ldap_result and @ldap_result[code]
149
+ end
150
+
151
+ def status
152
+ Net::LDAP::ResultCodesNonError.include?(result_code) ? :success : :failure
153
+ end
154
+
155
+ def success?
156
+ status == :success
157
+ end
158
+
159
+ def failure?
160
+ !success?
161
+ end
162
+
163
+ ##
164
+ # Return serverSaslCreds, which are only present in BindResponse packets.
165
+ #--
166
+ # Messy. Does this functionality belong somewhere else? We ought to
167
+ # refactor the accessors of this class before they get any kludgier.
168
+ def result_server_sasl_creds
169
+ @ldap_result && @ldap_result[:serverSaslCreds]
170
+ end
171
+
172
+ def parse_ldap_result(sequence)
173
+ sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP result length."
174
+ @ldap_result = {
175
+ :resultCode => sequence[0],
176
+ :matchedDN => sequence[1],
177
+ :errorMessage => sequence[2]
178
+ }
179
+ parse_search_referral(sequence[3]) if @ldap_result[:resultCode] == Net::LDAP::ResultCodeReferral
180
+ end
181
+ private :parse_ldap_result
182
+
183
+ ##
184
+ # A Bind Response may have an additional field, ID [7], serverSaslCreds,
185
+ # per RFC 2251 pgh 4.2.3.
186
+ def parse_bind_response(sequence)
187
+ sequence.length >= 3 or raise Net::LDAP::PDU::Error, "Invalid LDAP Bind Response length."
188
+ parse_ldap_result(sequence)
189
+ @ldap_result[:serverSaslCreds] = sequence[3] if sequence.length >= 4
190
+ @ldap_result
191
+ end
192
+ private :parse_bind_response
193
+
194
+ # Definition from RFC 1777 (we're handling application-4 here).
195
+ #
196
+ # Search Response ::=
197
+ # CHOICE {
198
+ # entry [APPLICATION 4] SEQUENCE {
199
+ # objectName LDAPDN,
200
+ # attributes SEQUENCE OF SEQUENCE {
201
+ # AttributeType,
202
+ # SET OF AttributeValue
203
+ # }
204
+ # },
205
+ # resultCode [APPLICATION 5] LDAPResult
206
+ # }
207
+ #
208
+ # We concoct a search response that is a hash of the returned attribute
209
+ # values.
210
+ #
211
+ # NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES.
212
+ #
213
+ # This is to make them more predictable for user programs, but it may not
214
+ # be a good idea. Maybe this should be configurable.
215
+ def parse_search_return(sequence)
216
+ sequence.length >= 2 or raise Net::LDAP::PDU::Error, "Invalid Search Response length."
217
+ @search_entry = Net::LDAP::Entry.new(sequence[0])
218
+ sequence[1].each { |seq| @search_entry[seq[0]] = seq[1] }
219
+ end
220
+ private :parse_search_return
221
+
222
+ ##
223
+ # A search referral is a sequence of one or more LDAP URIs. Any number of
224
+ # search-referral replies can be returned by the server, interspersed with
225
+ # normal replies in any order.
226
+ #--
227
+ # Until I can think of a better way to do this, we'll return the referrals
228
+ # as an array. It'll be up to higher-level handlers to expose something
229
+ # reasonable to the client.
230
+ def parse_search_referral(uris)
231
+ @search_referrals = uris
232
+ end
233
+ private :parse_search_referral
234
+
235
+ ##
236
+ # Per RFC 2251, an LDAP "control" is a sequence of tuples, each consisting
237
+ # of an OID, a boolean criticality flag defaulting FALSE, and an OPTIONAL
238
+ # Octet String. If only two fields are given, the second one may be either
239
+ # criticality or data, since criticality has a default value. Someday we
240
+ # may want to come back here and add support for some of more-widely used
241
+ # controls. RFC-2696 is a good example.
242
+ def parse_controls(sequence)
243
+ @ldap_controls = sequence.map do |control|
244
+ o = OpenStruct.new
245
+ o.oid, o.criticality, o.value = control[0], control[1], control[2]
246
+ if o.criticality and o.criticality.is_a?(String)
247
+ o.value = o.criticality
248
+ o.criticality = false
249
+ end
250
+ o
251
+ end
252
+ end
253
+ private :parse_controls
254
+
255
+ # (provisional, must document)
256
+ def parse_ldap_search_request(sequence)
257
+ s = OpenStruct.new
258
+ s.base_object, s.scope, s.deref_aliases, s.size_limit, s.time_limit,
259
+ s.types_only, s.filter, s.attributes = sequence
260
+ @search_parameters = s
261
+ end
262
+ private :parse_ldap_search_request
263
+
264
+ # (provisional, must document)
265
+ def parse_bind_request sequence
266
+ s = OpenStruct.new
267
+ s.version, s.name, s.authentication = sequence
268
+ @bind_parameters = s
269
+ end
270
+ private :parse_bind_request
271
+
272
+ # (provisional, must document)
273
+ # UnbindRequest has no content so this is a no-op.
274
+ def parse_unbind_request(sequence)
275
+ nil
276
+ end
277
+ private :parse_unbind_request
278
+ end
279
+
280
+ module Net
281
+ ##
282
+ # Handle renamed constants Net::LdapPdu (Net::LDAP::PDU) and
283
+ # Net::LdapPduError (Net::LDAP::PDU::Error).
284
+ def self.const_missing(name) #:nodoc:
285
+ case name.to_s
286
+ when "LdapPdu"
287
+ warn "Net::#{name} has been deprecated. Use Net::LDAP::PDU instead."
288
+ Net::LDAP::PDU
289
+ when "LdapPduError"
290
+ warn "Net::#{name} has been deprecated. Use Net::LDAP::PDU::Error instead."
291
+ Net::LDAP::PDU::Error
292
+ when 'LDAP'
293
+ else
294
+ super
295
+ end
296
+ end
297
+ end # module Net
@@ -0,0 +1,5 @@
1
+ module Net
2
+ class LDAP
3
+ VERSION = "0.11"
4
+ end
5
+ end
data/lib/net/snmp.rb ADDED
@@ -0,0 +1,264 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+ require 'net/ldap/version'
3
+
4
+ # :stopdoc:
5
+ module Net
6
+ class SNMP
7
+ VERSION = Net::LDAP::VERSION
8
+ AsnSyntax = Net::BER.compile_syntax({
9
+ :application => {
10
+ :primitive => {
11
+ 1 => :integer, # Counter32, (RFC2578 sec 2)
12
+ 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2)
13
+ 3 => :integer # TimeTicks32, (RFC2578 sec 2)
14
+ },
15
+ :constructed => {}
16
+ },
17
+ :context_specific => {
18
+ :primitive => {},
19
+ :constructed => {
20
+ 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2)
21
+ 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3)
22
+ 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4)
23
+ }
24
+ }
25
+ })
26
+
27
+ # SNMP 32-bit counter.
28
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
29
+ # A 32-bit counter is an ASN.1 application [1] implicit unsigned integer
30
+ # with a range from 0 to 2^^32 - 1.
31
+ class Counter32
32
+ def initialize value
33
+ @value = value
34
+ end
35
+ def to_ber
36
+ @value.to_ber_application(1)
37
+ end
38
+ end
39
+
40
+ # SNMP 32-bit gauge.
41
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
42
+ # A 32-bit counter is an ASN.1 application [2] implicit unsigned integer.
43
+ # This is also indistinguishable from Unsigned32. (Need to alias them.)
44
+ class Gauge32
45
+ def initialize value
46
+ @value = value
47
+ end
48
+ def to_ber
49
+ @value.to_ber_application(2)
50
+ end
51
+ end
52
+
53
+ # SNMP 32-bit timer-ticks.
54
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
55
+ # A 32-bit counter is an ASN.1 application [3] implicit unsigned integer.
56
+ class TimeTicks32
57
+ def initialize value
58
+ @value = value
59
+ end
60
+ def to_ber
61
+ @value.to_ber_application(3)
62
+ end
63
+ end
64
+ end
65
+
66
+ class SnmpPdu
67
+ class Error < StandardError; end
68
+ PduTypes = [
69
+ :get_request,
70
+ :get_next_request,
71
+ :get_response,
72
+ :set_request,
73
+ :trap
74
+ ]
75
+ ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1
76
+ 0 => "noError",
77
+ 1 => "tooBig",
78
+ 2 => "noSuchName",
79
+ 3 => "badValue",
80
+ 4 => "readOnly",
81
+ 5 => "genErr"
82
+ }
83
+
84
+ class << self
85
+ def parse ber_object
86
+ n = new
87
+ n.send :parse, ber_object
88
+ n
89
+ end
90
+ end
91
+
92
+ attr_reader :version, :community, :pdu_type, :variables, :error_status
93
+ attr_accessor :request_id, :error_index
94
+
95
+ def initialize args={}
96
+ @version = args[:version] || 0
97
+ @community = args[:community] || "public"
98
+ @pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value.
99
+ @error_status = args[:error_status] || 0
100
+ @error_index = args[:error_index] || 0
101
+ @variables = args[:variables] || []
102
+ end
103
+
104
+ #--
105
+ def parse ber_object
106
+ begin
107
+ parse_ber_object ber_object
108
+ rescue Error
109
+ # Pass through any SnmpPdu::Error instances
110
+ raise $!
111
+ rescue
112
+ # Wrap any basic parsing error so it becomes a PDU-format error
113
+ raise Error.new( "snmp-pdu format error" )
114
+ end
115
+ end
116
+ private :parse
117
+
118
+ def parse_ber_object ber_object
119
+ send :version=, ber_object[0].to_i
120
+ send :community=, ber_object[1].to_s
121
+
122
+ data = ber_object[2]
123
+ case (app_tag = data.ber_identifier & 31)
124
+ when 0
125
+ send :pdu_type=, :get_request
126
+ parse_get_request data
127
+ when 1
128
+ send :pdu_type=, :get_next_request
129
+ # This PDU is identical to get-request except for the type.
130
+ parse_get_request data
131
+ when 2
132
+ send :pdu_type=, :get_response
133
+ # This PDU is identical to get-request except for the type,
134
+ # the error_status and error_index values are meaningful,
135
+ # and the fact that the variable bindings will be non-null.
136
+ parse_get_response data
137
+ else
138
+ raise Error.new( "unknown snmp-pdu type: #{app_tag}" )
139
+ end
140
+ end
141
+ private :parse_ber_object
142
+
143
+ #--
144
+ # Defined in RFC1157, pgh 4.1.2.
145
+ def parse_get_request data
146
+ send :request_id=, data[0].to_i
147
+ # data[1] is error_status, always zero.
148
+ # data[2] is error_index, always zero.
149
+ send :error_status=, 0
150
+ send :error_index=, 0
151
+ data[3].each do |n,v|
152
+ # A variable-binding, of which there may be several,
153
+ # consists of an OID and a BER null.
154
+ # We're ignoring the null, we might want to verify it instead.
155
+ unless v.is_a?(Net::BER::BerIdentifiedNull)
156
+ raise Error.new(" invalid variable-binding in get-request" )
157
+ end
158
+ add_variable_binding n, nil
159
+ end
160
+ end
161
+ private :parse_get_request
162
+
163
+ #--
164
+ # Defined in RFC1157, pgh 4.1.4
165
+ def parse_get_response data
166
+ send :request_id=, data[0].to_i
167
+ send :error_status=, data[1].to_i
168
+ send :error_index=, data[2].to_i
169
+ data[3].each do |n,v|
170
+ # A variable-binding, of which there may be several,
171
+ # consists of an OID and a BER null.
172
+ # We're ignoring the null, we might want to verify it instead.
173
+ add_variable_binding n, v
174
+ end
175
+ end
176
+ private :parse_get_response
177
+
178
+
179
+ def version= ver
180
+ unless [0,2].include?(ver)
181
+ raise Error.new("unknown snmp-version: #{ver}")
182
+ end
183
+ @version = ver
184
+ end
185
+
186
+ def pdu_type= t
187
+ unless PduTypes.include?(t)
188
+ raise Error.new("unknown pdu-type: #{t}")
189
+ end
190
+ @pdu_type = t
191
+ end
192
+
193
+ def error_status= es
194
+ unless ErrorStatusCodes.has_key?(es)
195
+ raise Error.new("unknown error-status: #{es}")
196
+ end
197
+ @error_status = es
198
+ end
199
+
200
+ def community= c
201
+ @community = c.to_s
202
+ end
203
+
204
+ #--
205
+ # Syntactic sugar
206
+ def add_variable_binding name, value=nil
207
+ @variables ||= []
208
+ @variables << [name, value]
209
+ end
210
+
211
+ def to_ber_string
212
+ [
213
+ version.to_ber,
214
+ community.to_ber,
215
+ pdu_to_ber_string,
216
+ ].to_ber_sequence
217
+ end
218
+
219
+ #--
220
+ # Helper method that returns a PDU payload in BER form,
221
+ # depending on the PDU type.
222
+ def pdu_to_ber_string
223
+ case pdu_type
224
+ when :get_request
225
+ [
226
+ request_id.to_ber,
227
+ error_status.to_ber,
228
+ error_index.to_ber,
229
+ [
230
+ @variables.map {|n,v|
231
+ [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
232
+ }
233
+ ].to_ber_sequence
234
+ ].to_ber_contextspecific(0)
235
+ when :get_next_request
236
+ [
237
+ request_id.to_ber,
238
+ error_status.to_ber,
239
+ error_index.to_ber,
240
+ [
241
+ @variables.map {|n,v|
242
+ [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
243
+ }
244
+ ].to_ber_sequence
245
+ ].to_ber_contextspecific(1)
246
+ when :get_response
247
+ [
248
+ request_id.to_ber,
249
+ error_status.to_ber,
250
+ error_index.to_ber,
251
+ [
252
+ @variables.map {|n,v|
253
+ [n.to_ber_oid, v.to_ber].to_ber_sequence
254
+ }
255
+ ].to_ber_sequence
256
+ ].to_ber_contextspecific(2)
257
+ else
258
+ raise Error.new( "unknown pdu-type: #{pdu_type}" )
259
+ end
260
+ end
261
+ private :pdu_to_ber_string
262
+ end
263
+ end
264
+ # :startdoc: