scashin133-net-ldap 0.1.2

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.
data/lib/net/ldif.rb ADDED
@@ -0,0 +1,34 @@
1
+ # $Id$
2
+ #
3
+ # Net::LDIF for Ruby
4
+ #
5
+ #
6
+ #
7
+ # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
8
+ #
9
+ # Gmail: garbagecat10
10
+ #
11
+ # This program is free software; you can redistribute it and/or modify
12
+ # it under the terms of the GNU General Public License as published by
13
+ # the Free Software Foundation; either version 2 of the License, or
14
+ # (at your option) any later version.
15
+ #
16
+ # This program is distributed in the hope that it will be useful,
17
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ # GNU General Public License for more details.
20
+ #
21
+ # You should have received a copy of the GNU General Public License
22
+ # along with this program; if not, write to the Free Software
23
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
+ #
25
+ #
26
+
27
+ # THIS FILE IS A STUB.
28
+
29
+ module Net
30
+ class LDIF
31
+ end
32
+ end
33
+
34
+
data/lib/net/snmp.rb ADDED
@@ -0,0 +1,295 @@
1
+ # $Id$
2
+ #
3
+ # NET::SNMP
4
+ #
5
+ #----------------------------------------------------------------------------
6
+ #
7
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
8
+ #
9
+ # Gmail: garbagecat10
10
+ #
11
+ # This program is free software; you can redistribute it and/or modify
12
+ # it under the terms of the GNU General Public License as published by
13
+ # the Free Software Foundation; either version 2 of the License, or
14
+ # (at your option) any later version.
15
+ #
16
+ # This program is distributed in the hope that it will be useful,
17
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ # GNU General Public License for more details.
20
+ #
21
+ # You should have received a copy of the GNU General Public License
22
+ # along with this program; if not, write to the Free Software
23
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
+ #
25
+ #---------------------------------------------------------------------------
26
+ #
27
+ #
28
+
29
+ module Net
30
+
31
+ class SNMP
32
+ VERSION = '0.1.0'
33
+
34
+ AsnSyntax = Net::BER.compile_syntax({
35
+ :application => {
36
+ :primitive => {
37
+ 1 => :integer, # Counter32, (RFC2578 sec 2)
38
+ 2 => :integer, # Gauge32 or Unsigned32, (RFC2578 sec 2)
39
+ 3 => :integer # TimeTicks32, (RFC2578 sec 2)
40
+ },
41
+ :constructed => {
42
+ }
43
+ },
44
+ :context_specific => {
45
+ :primitive => {
46
+ },
47
+ :constructed => {
48
+ 0 => :array, # GetRequest PDU (RFC1157 pgh 4.1.2)
49
+ 1 => :array, # GetNextRequest PDU (RFC1157 pgh 4.1.3)
50
+ 2 => :array # GetResponse PDU (RFC1157 pgh 4.1.4)
51
+ }
52
+ }
53
+ })
54
+
55
+ # SNMP 32-bit counter.
56
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
57
+ # A 32-bit counter is an ASN.1 application [1] implicit unsigned integer
58
+ # with a range from 0 to 2^^32 - 1.
59
+ class Counter32
60
+ def initialize value
61
+ @value = value
62
+ end
63
+ def to_ber
64
+ @value.to_ber_application(1)
65
+ end
66
+ end
67
+
68
+ # SNMP 32-bit gauge.
69
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
70
+ # A 32-bit counter is an ASN.1 application [2] implicit unsigned integer.
71
+ # This is also indistinguishable from Unsigned32. (Need to alias them.)
72
+ class Gauge32
73
+ def initialize value
74
+ @value = value
75
+ end
76
+ def to_ber
77
+ @value.to_ber_application(2)
78
+ end
79
+ end
80
+
81
+ # SNMP 32-bit timer-ticks.
82
+ # Defined in RFC1155 (Structure of Mangement Information), section 6.
83
+ # A 32-bit counter is an ASN.1 application [3] implicit unsigned integer.
84
+ class TimeTicks32
85
+ def initialize value
86
+ @value = value
87
+ end
88
+ def to_ber
89
+ @value.to_ber_application(3)
90
+ end
91
+ end
92
+ end
93
+
94
+ class SnmpPdu
95
+ class Error < StandardError; end
96
+
97
+ PduTypes = [
98
+ :get_request,
99
+ :get_next_request,
100
+ :get_response,
101
+ :set_request,
102
+ :trap
103
+ ]
104
+ ErrorStatusCodes = { # Per RFC1157, pgh 4.1.1
105
+ 0 => "noError",
106
+ 1 => "tooBig",
107
+ 2 => "noSuchName",
108
+ 3 => "badValue",
109
+ 4 => "readOnly",
110
+ 5 => "genErr"
111
+ }
112
+
113
+ class << self
114
+ def parse ber_object
115
+ n = new
116
+ n.send :parse, ber_object
117
+ n
118
+ end
119
+ end
120
+
121
+ attr_reader :version, :community, :pdu_type, :variables, :error_status
122
+ attr_accessor :request_id, :error_index
123
+
124
+
125
+ def initialize args={}
126
+ @version = args[:version] || 0
127
+ @community = args[:community] || "public"
128
+ @pdu_type = args[:pdu_type] # leave nil unless specified; there's no reasonable default value.
129
+ @error_status = args[:error_status] || 0
130
+ @error_index = args[:error_index] || 0
131
+ @variables = args[:variables] || []
132
+ end
133
+
134
+ #--
135
+ def parse ber_object
136
+ begin
137
+ parse_ber_object ber_object
138
+ rescue Error
139
+ # Pass through any SnmpPdu::Error instances
140
+ raise $!
141
+ rescue
142
+ # Wrap any basic parsing error so it becomes a PDU-format error
143
+ raise Error.new( "snmp-pdu format error" )
144
+ end
145
+ end
146
+ private :parse
147
+
148
+ def parse_ber_object ber_object
149
+ send :version=, ber_object[0].to_i
150
+ send :community=, ber_object[1].to_s
151
+
152
+ data = ber_object[2]
153
+ case (app_tag = data.ber_identifier & 31)
154
+ when 0
155
+ send :pdu_type=, :get_request
156
+ parse_get_request data
157
+ when 1
158
+ send :pdu_type=, :get_next_request
159
+ # This PDU is identical to get-request except for the type.
160
+ parse_get_request data
161
+ when 2
162
+ send :pdu_type=, :get_response
163
+ # This PDU is identical to get-request except for the type,
164
+ # the error_status and error_index values are meaningful,
165
+ # and the fact that the variable bindings will be non-null.
166
+ parse_get_response data
167
+ else
168
+ raise Error.new( "unknown snmp-pdu type: #{app_tag}" )
169
+ end
170
+ end
171
+ private :parse_ber_object
172
+
173
+ #--
174
+ # Defined in RFC1157, pgh 4.1.2.
175
+ def parse_get_request data
176
+ send :request_id=, data[0].to_i
177
+ # data[1] is error_status, always zero.
178
+ # data[2] is error_index, always zero.
179
+ send :error_status=, 0
180
+ send :error_index=, 0
181
+ data[3].each {|n,v|
182
+ # A variable-binding, of which there may be several,
183
+ # consists of an OID and a BER null.
184
+ # We're ignoring the null, we might want to verify it instead.
185
+ unless v.is_a?(Net::BER::BerIdentifiedNull)
186
+ raise Error.new(" invalid variable-binding in get-request" )
187
+ end
188
+ add_variable_binding n, nil
189
+ }
190
+ end
191
+ private :parse_get_request
192
+
193
+ #--
194
+ # Defined in RFC1157, pgh 4.1.4
195
+ def parse_get_response data
196
+ send :request_id=, data[0].to_i
197
+ send :error_status=, data[1].to_i
198
+ send :error_index=, data[2].to_i
199
+ data[3].each {|n,v|
200
+ # A variable-binding, of which there may be several,
201
+ # consists of an OID and a BER null.
202
+ # We're ignoring the null, we might want to verify it instead.
203
+ add_variable_binding n, v
204
+ }
205
+ end
206
+ private :parse_get_response
207
+
208
+
209
+ def version= ver
210
+ unless [0,2].include?(ver)
211
+ raise Error.new("unknown snmp-version: #{ver}")
212
+ end
213
+ @version = ver
214
+ end
215
+
216
+ def pdu_type= t
217
+ unless PduTypes.include?(t)
218
+ raise Error.new("unknown pdu-type: #{t}")
219
+ end
220
+ @pdu_type = t
221
+ end
222
+
223
+ def error_status= es
224
+ unless ErrorStatusCodes.has_key?(es)
225
+ raise Error.new("unknown error-status: #{es}")
226
+ end
227
+ @error_status = es
228
+ end
229
+
230
+ def community= c
231
+ @community = c.to_s
232
+ end
233
+
234
+ #--
235
+ # Syntactic sugar
236
+ def add_variable_binding name, value=nil
237
+ @variables ||= []
238
+ @variables << [name, value]
239
+ end
240
+
241
+ def to_ber_string
242
+ [
243
+ version.to_ber,
244
+ community.to_ber,
245
+ pdu_to_ber_string
246
+ ].to_ber_sequence
247
+ end
248
+
249
+ #--
250
+ # Helper method that returns a PDU payload in BER form,
251
+ # depending on the PDU type.
252
+ def pdu_to_ber_string
253
+ case pdu_type
254
+ when :get_request
255
+ [
256
+ request_id.to_ber,
257
+ error_status.to_ber,
258
+ error_index.to_ber,
259
+ [
260
+ @variables.map {|n,v|
261
+ [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
262
+ }
263
+ ].to_ber_sequence
264
+ ].to_ber_contextspecific(0)
265
+ when :get_next_request
266
+ [
267
+ request_id.to_ber,
268
+ error_status.to_ber,
269
+ error_index.to_ber,
270
+ [
271
+ @variables.map {|n,v|
272
+ [n.to_ber_oid, Net::BER::BerIdentifiedNull.new.to_ber].to_ber_sequence
273
+ }
274
+ ].to_ber_sequence
275
+ ].to_ber_contextspecific(1)
276
+ when :get_response
277
+ [
278
+ request_id.to_ber,
279
+ error_status.to_ber,
280
+ error_index.to_ber,
281
+ [
282
+ @variables.map {|n,v|
283
+ [n.to_ber_oid, v.to_ber].to_ber_sequence
284
+ }
285
+ ].to_ber_sequence
286
+ ].to_ber_contextspecific(2)
287
+ else
288
+ raise Error.new( "unknown pdu-type: #{pdu_type}" )
289
+ end
290
+ end
291
+ private :pdu_to_ber_string
292
+
293
+ end
294
+ end
295
+
data/lib/net-ldap.rb ADDED
@@ -0,0 +1 @@
1
+ require 'net/ldap'
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ require 'net/ldap'
4
+
5
+ describe "BER serialisation (SSL)" do
6
+ # Transmits str to #to and reads it back from #from.
7
+ #
8
+ def transmit(str)
9
+ to.write(str)
10
+ to.close
11
+
12
+ from.read
13
+ end
14
+
15
+ attr_reader :to, :from
16
+ before(:each) do
17
+ @from, @to = IO.pipe
18
+
19
+ flexmock(OpenSSL::SSL::SSLSocket).
20
+ new_instances.should_receive(:connect => nil)
21
+
22
+ @to = Net::LDAP::Connection.wrap_with_ssl(to)
23
+ @from = Net::LDAP::Connection.wrap_with_ssl(from)
24
+ end
25
+
26
+ it "should transmit strings" do
27
+ transmit('foo').should == 'foo'
28
+ end
29
+ it "should correctly transmit numbers" do
30
+ to.write 1234.to_ber
31
+ from.read_ber.should == 1234
32
+ end
33
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,6 @@
1
+ require 'net/ldap'
2
+ require 'rubygems'
3
+
4
+ Spec::Runner.configure do |config|
5
+ config.mock_with :flexmock
6
+ end
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ require 'net/ber'
4
+ require 'net/ldap'
5
+
6
+ describe "BER encoding of" do
7
+ def properly_encode_and_decode
8
+ simple_matcher('properly encode and decode') do |given|
9
+ given.to_ber.read_ber.should == given
10
+ end
11
+ end
12
+
13
+ context "arrays" do
14
+ it "should properly encode/decode []" do
15
+ [].should properly_encode_and_decode
16
+ end
17
+ it "should properly encode/decode [1,2,3]" do
18
+ ary = [1,2,3]
19
+ encoded_ary = ary.map { |el| el.to_ber }.to_ber
20
+
21
+ encoded_ary.read_ber.should == ary
22
+ end
23
+ end
24
+ context "booleans" do
25
+ it "should encode true" do
26
+ true.to_ber.should == "\x01\x01\x01"
27
+ end
28
+ it "should encode false" do
29
+ false.to_ber.should == "\x01\x01\x00"
30
+ end
31
+ end
32
+ context "numbers" do
33
+ # Sample based
34
+ {
35
+ 0 => "\x02\x01\x00",
36
+ 1 => "\x02\x01\x01",
37
+ 127 => "\x02\x01\x7F",
38
+ 128 => "\x02\x01\x80",
39
+ 255 => "\x02\x01\xFF",
40
+ 256 => "\x02\x02\x01\x00",
41
+ 65535 => "\x02\x02\xFF\xFF",
42
+ 65536 => "\x02\x03\x01\x00\x00",
43
+ 16_777_215 => "\x02\x03\xFF\xFF\xFF",
44
+ 0x01000000 => "\x02\x04\x01\x00\x00\x00",
45
+ 0x3FFFFFFF => "\x02\x04\x3F\xFF\xFF\xFF",
46
+ 0x4FFFFFFF => "\x02\x04\x4F\xFF\xFF\xFF",
47
+
48
+ # Some odd samples...
49
+ 5 => "\002\001\005",
50
+ 500 => "\002\002\001\364",
51
+ 50_000 => "\x02\x02\xC3P",
52
+ 5_000_000_000 => "\002\005\001*\005\362\000"
53
+ }.each do |number, expected_encoding|
54
+ it "should encode #{number} as #{expected_encoding.inspect}" do
55
+ number.to_ber.should == expected_encoding
56
+ end
57
+ end
58
+
59
+ # Round-trip encoding: This is mostly to be sure to cover Bignums well.
60
+ context "when decoding with #read_ber" do
61
+ it "should correctly handle powers of two" do
62
+ 100.times do |p|
63
+ n = 2 << p
64
+
65
+ n.should properly_encode_and_decode
66
+ end
67
+ end
68
+ it "should correctly handle powers of ten" do
69
+ 100.times do |p|
70
+ n = 5 * 10**p
71
+
72
+ n.should properly_encode_and_decode
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "BER decoding of" do
80
+ context "numbers" do
81
+ it "should decode #{"\002\001\006".inspect} (6)" do
82
+ "\002\001\006".read_ber(Net::LDAP::AsnSyntax).should == 6
83
+ end
84
+ it "should decode #{"\004\007testing".inspect} ('testing')" do
85
+ "\004\007testing".read_ber(Net::LDAP::AsnSyntax).should == 'testing'
86
+ end
87
+ it "should decode an ldap bind request" do
88
+ "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus".
89
+ read_ber(Net::LDAP::AsnSyntax).should ==
90
+ [1, [3, "Administrator", "ad_is_bogus"]]
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'metaid'
3
+
4
+ describe String, "when extended with BER core extensions" do
5
+ describe "<- #read_ber! (consuming read_ber method)" do
6
+ context "when passed an ldap bind request and some extra data" do
7
+ attr_reader :str, :result
8
+ before(:each) do
9
+ @str = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus UNCONSUMED"
10
+ @result = str.read_ber!(Net::LDAP::AsnSyntax)
11
+ end
12
+
13
+ it "should correctly parse the ber message" do
14
+ result.should == [1, [3, "Administrator", "ad_is_bogus"]]
15
+ end
16
+ it "should leave unconsumed part of message in place" do
17
+ str.should == " UNCONSUMED"
18
+ end
19
+
20
+ context "if an exception occurs during #read_ber" do
21
+ attr_reader :initial_value
22
+ before(:each) do
23
+ stub_exception_class = Class.new(StandardError)
24
+
25
+ @initial_value = "0$\002\001\001`\037\002\001\003\004\rAdministrator\200\vad_is_bogus"
26
+ @str = initial_value.dup
27
+
28
+ # Defines a string
29
+ io = StringIO.new(initial_value)
30
+ io.meta_def :read_ber do |syntax|
31
+ read
32
+ raise stub_exception_class
33
+ end
34
+ flexmock(StringIO).should_receive(:new).and_return(io)
35
+
36
+ begin
37
+ str.read_ber!(Net::LDAP::AsnSyntax)
38
+ rescue stub_exception_class
39
+ # EMPTY ON PURPOSE
40
+ else
41
+ raise "The stub code should raise an exception!"
42
+ end
43
+ end
44
+
45
+ it "should not modify string" do
46
+ str.should == initial_value
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::LDAP::Entry do
4
+ attr_reader :entry
5
+ before(:each) do
6
+ @entry = Net::LDAP::Entry.from_single_ldif_string(
7
+ %Q{dn: something
8
+ foo: foo
9
+ barAttribute: bar
10
+ }
11
+ )
12
+ end
13
+
14
+ describe "entry access" do
15
+ it "should always respond to #dn" do
16
+ entry.should respond_to(:dn)
17
+ end
18
+
19
+ context "<- #foo" do
20
+ it "should respond_to?" do
21
+ entry.should respond_to(:foo)
22
+ end
23
+ it "should return 'foo'" do
24
+ entry.foo.should == ['foo']
25
+ end
26
+ end
27
+ context "<- #Foo" do
28
+ it "should respond_to?" do
29
+ entry.should respond_to(:Foo)
30
+ end
31
+ it "should return 'foo'" do
32
+ entry.foo.should == ['foo']
33
+ end
34
+ end
35
+ context "<- #foo=" do
36
+ it "should respond_to?" do
37
+ entry.should respond_to(:foo=)
38
+ end
39
+ it "should set 'foo'" do
40
+ entry.foo= 'bar'
41
+ entry.foo.should == ['bar']
42
+ end
43
+ end
44
+ context "<- #fOo=" do
45
+ it "should return 'foo'" do
46
+ entry.fOo= 'bar'
47
+ entry.fOo.should == ['bar']
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::LDAP::Filter do
4
+ describe "<- .ex(attr, value)" do
5
+ context "('foo', 'bar')" do
6
+ attr_reader :filter
7
+ before(:each) do
8
+ @filter = Net::LDAP::Filter.ex('foo', 'bar')
9
+ end
10
+ it "should convert to 'foo:=bar'" do
11
+ filter.to_s.should == '(foo:=bar)'
12
+ end
13
+ it "should survive roundtrip via to_s/from_rfc2254" do
14
+ Net::LDAP::Filter.from_rfc2254(filter.to_s).should == filter
15
+ end
16
+ it "should survive roundtrip conversion to/from ber" do
17
+ ber = filter.to_ber
18
+ Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should ==
19
+ filter
20
+ end
21
+ end
22
+ context "various legal inputs" do
23
+ [
24
+ '(o:dn:=Ace Industry)',
25
+ '(:dn:2.4.8.10:=Dino)',
26
+ '(cn:dn:1.2.3.4.5:=John Smith)',
27
+ '(sn:dn:2.4.6.8.10:=Barbara Jones)',
28
+ ].each do |filter_str|
29
+ context "from_rfc2254(#{filter_str.inspect})" do
30
+ attr_reader :filter
31
+ before(:each) do
32
+ @filter = Net::LDAP::Filter.from_rfc2254(filter_str)
33
+ end
34
+
35
+ it "should decode into a Net::LDAP::Filter" do
36
+ filter.should be_an_instance_of(Net::LDAP::Filter)
37
+ end
38
+ it "should survive roundtrip conversion to/from ber" do
39
+ ber = filter.to_ber
40
+ Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should ==
41
+ filter
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::LDAP::Connection do
4
+ describe "initialize" do
5
+ context "when host is not responding" do
6
+ before(:each) do
7
+ flexmock(TCPSocket).
8
+ should_receive(:new).and_raise(Errno::ECONNREFUSED)
9
+ end
10
+
11
+ it "should raise LdapError" do
12
+ lambda {
13
+ Net::LDAP::Connection.new(
14
+ :server => 'test.mocked.com',
15
+ :port => 636)
16
+ }.should raise_error(Net::LDAP::LdapError)
17
+ end
18
+ end
19
+ context "when host is blocking the port" do
20
+ before(:each) do
21
+ flexmock(TCPSocket).
22
+ should_receive(:new).and_raise(SocketError)
23
+ end
24
+
25
+ it "should raise LdapError" do
26
+ lambda {
27
+ Net::LDAP::Connection.new(
28
+ :server => 'test.mocked.com',
29
+ :port => 636)
30
+ }.should raise_error(Net::LDAP::LdapError)
31
+ end
32
+ end
33
+ context "on other exceptions" do
34
+ before(:each) do
35
+ flexmock(TCPSocket).
36
+ should_receive(:new).and_raise(NameError)
37
+ end
38
+
39
+ it "should rethrow the exception" do
40
+ lambda {
41
+ Net::LDAP::Connection.new(
42
+ :server => 'test.mocked.com',
43
+ :port => 636)
44
+ }.should raise_error(NameError)
45
+ end
46
+ end
47
+ end
48
+ end
data/test/common.rb ADDED
@@ -0,0 +1,3 @@
1
+ # Add 'lib' to load path.
2
+ require 'test/unit'
3
+ require 'net/ldap'