net-ldap 0.8.0 → 0.9.0
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.
Potentially problematic release.
This version of net-ldap might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +7 -0
- data/.travis.yml +19 -1
- data/CONTRIBUTING.md +54 -0
- data/Hacking.rdoc +2 -4
- data/History.rdoc +37 -0
- data/Manifest.txt +0 -4
- data/README.rdoc +8 -0
- data/Rakefile +1 -3
- data/lib/net/ber/core_ext.rb +5 -5
- data/lib/net/ber/core_ext/string.rb +7 -7
- data/lib/net/ber/core_ext/true_class.rb +2 -3
- data/lib/net/ldap.rb +134 -620
- data/lib/net/ldap/connection.rb +692 -0
- data/lib/net/ldap/dataset.rb +18 -4
- data/lib/net/ldap/entry.rb +1 -1
- data/lib/net/ldap/filter.rb +7 -7
- data/lib/net/ldap/password.rb +11 -11
- data/lib/net/ldap/pdu.rb +28 -4
- data/lib/net/ldap/version.rb +1 -1
- data/lib/net/snmp.rb +235 -241
- data/net-ldap.gemspec +7 -33
- data/script/install-openldap +47 -0
- data/script/package +7 -0
- data/script/release +16 -0
- data/test/ber/core_ext/test_array.rb +22 -0
- data/test/ber/core_ext/test_string.rb +25 -0
- data/test/ber/test_ber.rb +126 -0
- data/test/fixtures/openldap/memberof.ldif +33 -0
- data/test/fixtures/openldap/retcode.ldif +76 -0
- data/test/fixtures/openldap/slapd.conf.ldif +67 -0
- data/test/fixtures/seed.ldif +374 -0
- data/test/integration/test_add.rb +28 -0
- data/test/integration/test_ber.rb +30 -0
- data/test/integration/test_bind.rb +22 -0
- data/test/integration/test_delete.rb +31 -0
- data/test/integration/test_open.rb +88 -0
- data/test/integration/test_return_codes.rb +38 -0
- data/test/integration/test_search.rb +77 -0
- data/test/support/vm/openldap/.gitignore +1 -0
- data/test/support/vm/openldap/README.md +32 -0
- data/test/support/vm/openldap/Vagrantfile +33 -0
- data/test/test_dn.rb +44 -0
- data/test/test_entry.rb +62 -56
- data/test/test_filter.rb +98 -2
- data/test/test_filter_parser.rb +16 -0
- data/test/test_helper.rb +54 -0
- data/test/test_ldap.rb +60 -0
- data/test/test_ldap_connection.rb +382 -2
- data/test/test_ldif.rb +26 -1
- data/test/test_password.rb +3 -10
- data/test/test_rename.rb +2 -2
- data/test/test_search.rb +39 -0
- data/test/test_snmp.rb +1 -1
- data/test/test_ssl_ber.rb +40 -0
- metadata +70 -75
- data/.autotest +0 -11
- data/.gemtest +0 -0
- data/.rspec +0 -2
- data/autotest/discover.rb +0 -1
- data/spec/integration/ssl_ber_spec.rb +0 -39
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -28
- data/spec/unit/ber/ber_spec.rb +0 -141
- data/spec/unit/ber/core_ext/array_spec.rb +0 -24
- data/spec/unit/ber/core_ext/string_spec.rb +0 -51
- data/spec/unit/ldap/dn_spec.rb +0 -80
- data/spec/unit/ldap/entry_spec.rb +0 -51
- data/spec/unit/ldap/filter_parser_spec.rb +0 -26
- data/spec/unit/ldap/filter_spec.rb +0 -115
- data/spec/unit/ldap/search_spec.rb +0 -49
- data/spec/unit/ldap_spec.rb +0 -223
- data/test/common.rb +0 -3
data/test/test_filter.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative 'test_helper'
|
2
2
|
|
3
3
|
class TestFilter < Test::Unit::TestCase
|
4
4
|
Filter = Net::LDAP::Filter
|
@@ -28,7 +28,7 @@ class TestFilter < Test::Unit::TestCase
|
|
28
28
|
assert_equal("(uid=\\2A)", Filter.equals("uid", "*").to_s)
|
29
29
|
assert_equal("(uid=\\28*)", Filter.begins("uid", "(").to_s)
|
30
30
|
assert_equal("(uid=*\\29)", Filter.ends("uid", ")").to_s)
|
31
|
-
assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s)
|
31
|
+
assert_equal("(uid=*\\5C*)", Filter.contains("uid", "\\").to_s)
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_c2
|
@@ -120,3 +120,99 @@ class TestFilter < Test::Unit::TestCase
|
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
123
|
+
|
124
|
+
# tests ported over from rspec. Not sure if these overlap with the above
|
125
|
+
# https://github.com/ruby-ldap/ruby-net-ldap/pull/121
|
126
|
+
class TestFilterRSpec < Test::Unit::TestCase
|
127
|
+
def test_ex_convert
|
128
|
+
assert_equal '(foo:=bar)', Net::LDAP::Filter.ex('foo', 'bar').to_s
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_ex_rfc2254_roundtrip
|
132
|
+
filter = Net::LDAP::Filter.ex('foo', 'bar')
|
133
|
+
assert_equal filter, Net::LDAP::Filter.from_rfc2254(filter.to_s)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_ber_conversion
|
137
|
+
filter = Net::LDAP::Filter.ex('foo', 'bar')
|
138
|
+
ber = filter.to_ber
|
139
|
+
assert_equal filter, Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax))
|
140
|
+
end
|
141
|
+
|
142
|
+
[
|
143
|
+
'(o:dn:=Ace Industry)',
|
144
|
+
'(:dn:2.4.8.10:=Dino)',
|
145
|
+
'(cn:dn:1.2.3.4.5:=John Smith)',
|
146
|
+
'(sn:dn:2.4.6.8.10:=Barbara Jones)',
|
147
|
+
'(&(sn:dn:2.4.6.8.10:=Barbara Jones))'
|
148
|
+
].each_with_index do |filter_str, index|
|
149
|
+
define_method "test_decode_filter_#{index}" do
|
150
|
+
filter = Net::LDAP::Filter.from_rfc2254(filter_str)
|
151
|
+
assert_kind_of Net::LDAP::Filter, filter
|
152
|
+
end
|
153
|
+
|
154
|
+
define_method "test_ber_conversion_#{index}" do
|
155
|
+
filter = Net::LDAP::Filter.from_rfc2254(filter_str)
|
156
|
+
ber = Net::LDAP::Filter.from_rfc2254(filter_str).to_ber
|
157
|
+
assert_equal filter, Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax))
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_apostrophes
|
162
|
+
assert_equal "(uid=O'Keefe)", Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_equals
|
166
|
+
assert_equal Net::LDAP::Filter.eq('dn', 'f\2Aoo'), Net::LDAP::Filter.equals('dn', 'f*oo')
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_begins
|
170
|
+
assert_equal Net::LDAP::Filter.eq('dn', 'f\2Aoo*'), Net::LDAP::Filter.begins('dn', 'f*oo')
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_ends
|
174
|
+
assert_equal Net::LDAP::Filter.eq('dn', '*f\2Aoo'), Net::LDAP::Filter.ends('dn', 'f*oo')
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_contains
|
178
|
+
assert_equal Net::LDAP::Filter.eq('dn', '*f\2Aoo*'), Net::LDAP::Filter.contains('dn', 'f*oo')
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_escape
|
182
|
+
# escapes nul, *, (, ) and \\
|
183
|
+
assert_equal "\\00\\2A\\28\\29\\5C", Net::LDAP::Filter.escape("\0*()\\")
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_well_known_ber_string
|
187
|
+
ber = "\xa4\x2d" \
|
188
|
+
"\x04\x0b" "objectclass" \
|
189
|
+
"\x30\x1e" \
|
190
|
+
"\x80\x08" "foo" "*\\" "bar" \
|
191
|
+
"\x81\x08" "foo" "*\\" "bar" \
|
192
|
+
"\x82\x08" "foo" "*\\" "bar".b
|
193
|
+
|
194
|
+
[
|
195
|
+
"foo" "\\2A\\5C" "bar",
|
196
|
+
"foo" "\\2a\\5c" "bar",
|
197
|
+
"foo" "\\2A\\5c" "bar",
|
198
|
+
"foo" "\\2a\\5C" "bar"
|
199
|
+
].each do |escaped|
|
200
|
+
# unescapes escaped characters
|
201
|
+
filter = Net::LDAP::Filter.eq("objectclass", "#{escaped}*#{escaped}*#{escaped}")
|
202
|
+
assert_equal ber, filter.to_ber
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_parse_ber_escapes_characters
|
207
|
+
ber = "\xa4\x2d" \
|
208
|
+
"\x04\x0b" "objectclass" \
|
209
|
+
"\x30\x1e" \
|
210
|
+
"\x80\x08" "foo" "*\\" "bar" \
|
211
|
+
"\x81\x08" "foo" "*\\" "bar" \
|
212
|
+
"\x82\x08" "foo" "*\\" "bar".b
|
213
|
+
|
214
|
+
escaped = Net::LDAP::Filter.escape("foo" "*\\" "bar")
|
215
|
+
filter = Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax))
|
216
|
+
assert_equal "(objectclass=#{escaped}*#{escaped}*#{escaped})", filter.to_s
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require_relative 'test_helper'
|
3
|
+
|
4
|
+
class TestFilterParser < Test::Unit::TestCase
|
5
|
+
def test_ascii
|
6
|
+
assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(cn=name)")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_multibyte_characters
|
10
|
+
assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(cn=名前)")
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_colons
|
14
|
+
assert_kind_of Net::LDAP::Filter, Net::LDAP::Filter::FilterParser.parse("(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)")
|
15
|
+
end
|
16
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Add 'lib' to load path.
|
2
|
+
require 'test/unit'
|
3
|
+
require 'net/ldap'
|
4
|
+
require 'flexmock/test_unit'
|
5
|
+
|
6
|
+
# Whether integration tests should be run.
|
7
|
+
INTEGRATION = ENV.fetch("INTEGRATION", "skip") != "skip"
|
8
|
+
|
9
|
+
if RUBY_VERSION < "2.0"
|
10
|
+
class String
|
11
|
+
def b
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class MockInstrumentationService
|
18
|
+
def initialize
|
19
|
+
@events = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def instrument(event, payload)
|
23
|
+
result = yield(payload)
|
24
|
+
@events[event] ||= []
|
25
|
+
@events[event] << [payload, result]
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
def subscribe(event)
|
30
|
+
@events[event] ||= []
|
31
|
+
@events[event]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class LDAPIntegrationTestCase < Test::Unit::TestCase
|
36
|
+
# If integration tests aren't enabled, noop these tests.
|
37
|
+
if !INTEGRATION
|
38
|
+
def run(*)
|
39
|
+
self
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def setup
|
44
|
+
@service = MockInstrumentationService.new
|
45
|
+
@ldap = Net::LDAP.new \
|
46
|
+
host: ENV.fetch('INTEGRATION_HOST', 'localhost'),
|
47
|
+
port: 389,
|
48
|
+
admin_user: 'uid=admin,dc=rubyldap,dc=com',
|
49
|
+
admin_password: 'passworD1',
|
50
|
+
search_domains: %w(dc=rubyldap,dc=com),
|
51
|
+
uid: 'uid',
|
52
|
+
instrumentation_service: @service
|
53
|
+
end
|
54
|
+
end
|
data/test/test_ldap.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestLDAPInstrumentation < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@connection = flexmock(:connection, :close => true)
|
6
|
+
flexmock(Net::LDAP::Connection).should_receive(:new).and_return(@connection)
|
7
|
+
|
8
|
+
@service = MockInstrumentationService.new
|
9
|
+
@subject = Net::LDAP.new \
|
10
|
+
:host => "test.mocked.com", :port => 636,
|
11
|
+
:force_no_page => true, # so server capabilities are not queried
|
12
|
+
:instrumentation_service => @service
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_instrument_bind
|
16
|
+
events = @service.subscribe "bind.net_ldap"
|
17
|
+
|
18
|
+
bind_result = flexmock(:bind_result, :success? => true)
|
19
|
+
flexmock(@connection).should_receive(:bind).with(Hash).and_return(bind_result)
|
20
|
+
|
21
|
+
assert @subject.bind
|
22
|
+
|
23
|
+
payload, result = events.pop
|
24
|
+
assert result
|
25
|
+
assert_equal bind_result, payload[:bind]
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_instrument_search
|
29
|
+
events = @service.subscribe "search.net_ldap"
|
30
|
+
|
31
|
+
flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => Net::LDAP::ResultCodeSuccess))
|
32
|
+
flexmock(@connection).should_receive(:search).with(Hash, Proc).
|
33
|
+
yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")).
|
34
|
+
and_return(flexmock(:search_result, :success? => true, :result_code => Net::LDAP::ResultCodeSuccess))
|
35
|
+
|
36
|
+
refute_nil @subject.search(:filter => "(uid=user1)")
|
37
|
+
|
38
|
+
payload, result = events.pop
|
39
|
+
assert_equal [entry], result
|
40
|
+
assert_equal [entry], payload[:result]
|
41
|
+
assert_equal "(uid=user1)", payload[:filter]
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_instrument_search_with_size
|
45
|
+
events = @service.subscribe "search.net_ldap"
|
46
|
+
|
47
|
+
flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => Net::LDAP::ResultCodeSuccess))
|
48
|
+
flexmock(@connection).should_receive(:search).with(Hash, Proc).
|
49
|
+
yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")).
|
50
|
+
and_return(flexmock(:search_result, :success? => true, :result_code => Net::LDAP::ResultCodeSizeLimitExceeded))
|
51
|
+
|
52
|
+
refute_nil @subject.search(:filter => "(uid=user1)", :size => 1)
|
53
|
+
|
54
|
+
payload, result = events.pop
|
55
|
+
assert_equal [entry], result
|
56
|
+
assert_equal [entry], payload[:result]
|
57
|
+
assert_equal "(uid=user1)", payload[:filter]
|
58
|
+
assert_equal result.size, payload[:size]
|
59
|
+
end
|
60
|
+
end
|
@@ -1,6 +1,27 @@
|
|
1
|
-
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class TestLDAPConnection < Test::Unit::TestCase
|
4
|
+
def test_unresponsive_host
|
5
|
+
assert_raise Net::LDAP::LdapError do
|
6
|
+
Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_blocked_port
|
11
|
+
flexmock(TCPSocket).should_receive(:new).and_raise(SocketError)
|
12
|
+
assert_raise Net::LDAP::LdapError do
|
13
|
+
Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_raises_unknown_exceptions
|
18
|
+
error = Class.new(StandardError)
|
19
|
+
flexmock(TCPSocket).should_receive(:new).and_raise(error)
|
20
|
+
assert_raise error do
|
21
|
+
Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636)
|
22
|
+
end
|
23
|
+
end
|
2
24
|
|
3
|
-
class TestLDAP < Test::Unit::TestCase
|
4
25
|
def test_modify_ops_delete
|
5
26
|
args = { :operations => [ [ :delete, "mail" ] ] }
|
6
27
|
result = Net::LDAP::Connection.modify_ops(args[:operations])
|
@@ -21,4 +42,363 @@ class TestLDAP < Test::Unit::TestCase
|
|
21
42
|
expected = [ "0#\n\x01\x020\x1E\x04\x04mail1\x16\x04\x14testuser@example.com" ]
|
22
43
|
assert_equal(expected, result)
|
23
44
|
end
|
45
|
+
|
46
|
+
def test_write
|
47
|
+
mock = flexmock("socket")
|
48
|
+
mock.should_receive(:write).with([1.to_ber, "request"].to_ber_sequence).and_return(true)
|
49
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
50
|
+
conn.send(:write, "request")
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_write_with_controls
|
54
|
+
mock = flexmock("socket")
|
55
|
+
mock.should_receive(:write).with([1.to_ber, "request", "controls"].to_ber_sequence).and_return(true)
|
56
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
57
|
+
conn.send(:write, "request", "controls")
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_write_increments_msgid
|
61
|
+
mock = flexmock("socket")
|
62
|
+
mock.should_receive(:write).with([1.to_ber, "request1"].to_ber_sequence).and_return(true)
|
63
|
+
mock.should_receive(:write).with([2.to_ber, "request2"].to_ber_sequence).and_return(true)
|
64
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
65
|
+
conn.send(:write, "request1")
|
66
|
+
conn.send(:write, "request2")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class TestLDAPConnectionSocketReads < Test::Unit::TestCase
|
71
|
+
def make_message(message_id, options = {})
|
72
|
+
options = {
|
73
|
+
app_tag: Net::LDAP::PDU::SearchResult,
|
74
|
+
code: Net::LDAP::ResultCodeSuccess,
|
75
|
+
matched_dn: "",
|
76
|
+
error_message: ""
|
77
|
+
}.merge(options)
|
78
|
+
result = Net::BER::BerIdentifiedArray.new([options[:code], options[:matched_dn], options[:error_message]])
|
79
|
+
result.ber_identifier = options[:app_tag]
|
80
|
+
[message_id, result]
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_queued_read_drains_queue_before_read
|
84
|
+
result1a = make_message(1, error_message: "one")
|
85
|
+
result1b = make_message(1, error_message: "two")
|
86
|
+
|
87
|
+
mock = flexmock("socket")
|
88
|
+
mock.should_receive(:read_ber).and_return(result1b)
|
89
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
90
|
+
|
91
|
+
conn.message_queue[1].push Net::LDAP::PDU.new(result1a)
|
92
|
+
|
93
|
+
assert msg1 = conn.queued_read(1)
|
94
|
+
assert msg2 = conn.queued_read(1)
|
95
|
+
|
96
|
+
assert_equal 1, msg1.message_id
|
97
|
+
assert_equal "one", msg1.error_message
|
98
|
+
assert_equal 1, msg2.message_id
|
99
|
+
assert_equal "two", msg2.error_message
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_queued_read_reads_until_message_id_match
|
103
|
+
result1 = make_message(1)
|
104
|
+
result2 = make_message(2)
|
105
|
+
|
106
|
+
mock = flexmock("socket")
|
107
|
+
mock.should_receive(:read_ber).
|
108
|
+
and_return(result1).
|
109
|
+
and_return(result2)
|
110
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
111
|
+
|
112
|
+
assert result = conn.queued_read(2)
|
113
|
+
assert_equal 2, result.message_id
|
114
|
+
assert_equal 1, conn.queued_read(1).message_id
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_queued_read_modify
|
118
|
+
result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult)
|
119
|
+
result2 = make_message(2, app_tag: Net::LDAP::PDU::ModifyResponse)
|
120
|
+
|
121
|
+
mock = flexmock("socket")
|
122
|
+
mock.should_receive(:read_ber).
|
123
|
+
and_return(result1).
|
124
|
+
and_return(result2)
|
125
|
+
mock.should_receive(:write)
|
126
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
127
|
+
|
128
|
+
conn.next_msgid # simulates ongoing query
|
129
|
+
|
130
|
+
conn.instance_variable_get("@msgid")
|
131
|
+
|
132
|
+
assert result = conn.modify(dn: "uid=modified-user1,ou=People,dc=rubyldap,dc=com",
|
133
|
+
operations: [[:add, :mail, "modified-user1@example.com"]])
|
134
|
+
assert result.success?
|
135
|
+
assert_equal 2, result.message_id
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_queued_read_add
|
139
|
+
result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult)
|
140
|
+
result2 = make_message(2, app_tag: Net::LDAP::PDU::AddResponse)
|
141
|
+
|
142
|
+
mock = flexmock("socket")
|
143
|
+
mock.should_receive(:read_ber).
|
144
|
+
and_return(result1).
|
145
|
+
and_return(result2)
|
146
|
+
mock.should_receive(:write)
|
147
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
148
|
+
|
149
|
+
conn.next_msgid # simulates ongoing query
|
150
|
+
|
151
|
+
assert result = conn.add(dn: "uid=added-user1,ou=People,dc=rubyldap,dc=com")
|
152
|
+
assert result.success?
|
153
|
+
assert_equal 2, result.message_id
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_queued_read_rename
|
157
|
+
result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult)
|
158
|
+
result2 = make_message(2, app_tag: Net::LDAP::PDU::ModifyRDNResponse)
|
159
|
+
|
160
|
+
mock = flexmock("socket")
|
161
|
+
mock.should_receive(:read_ber).
|
162
|
+
and_return(result1).
|
163
|
+
and_return(result2)
|
164
|
+
mock.should_receive(:write)
|
165
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
166
|
+
|
167
|
+
conn.next_msgid # simulates ongoing query
|
168
|
+
|
169
|
+
assert result = conn.rename(
|
170
|
+
olddn: "uid=renamable-user1,ou=People,dc=rubyldap,dc=com",
|
171
|
+
newrdn: "uid=renamed-user1"
|
172
|
+
)
|
173
|
+
assert result.success?
|
174
|
+
assert_equal 2, result.message_id
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_queued_read_delete
|
178
|
+
result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult)
|
179
|
+
result2 = make_message(2, app_tag: Net::LDAP::PDU::DeleteResponse)
|
180
|
+
|
181
|
+
mock = flexmock("socket")
|
182
|
+
mock.should_receive(:read_ber).
|
183
|
+
and_return(result1).
|
184
|
+
and_return(result2)
|
185
|
+
mock.should_receive(:write)
|
186
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
187
|
+
|
188
|
+
conn.next_msgid # simulates ongoing query
|
189
|
+
|
190
|
+
assert result = conn.delete(dn: "uid=deletable-user1,ou=People,dc=rubyldap,dc=com")
|
191
|
+
assert result.success?
|
192
|
+
assert_equal 2, result.message_id
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_queued_read_setup_encryption_with_start_tls
|
196
|
+
result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult)
|
197
|
+
result2 = make_message(2, app_tag: Net::LDAP::PDU::ExtendedResponse)
|
198
|
+
|
199
|
+
mock = flexmock("socket")
|
200
|
+
mock.should_receive(:read_ber).
|
201
|
+
and_return(result1).
|
202
|
+
and_return(result2)
|
203
|
+
mock.should_receive(:write)
|
204
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
205
|
+
flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock).
|
206
|
+
and_return(mock)
|
207
|
+
|
208
|
+
conn.next_msgid # simulates ongoing query
|
209
|
+
|
210
|
+
assert result = conn.setup_encryption(method: :start_tls)
|
211
|
+
assert_equal mock, result
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_queued_read_bind_simple
|
215
|
+
result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult)
|
216
|
+
result2 = make_message(2, app_tag: Net::LDAP::PDU::BindResult)
|
217
|
+
|
218
|
+
mock = flexmock("socket")
|
219
|
+
mock.should_receive(:read_ber).
|
220
|
+
and_return(result1).
|
221
|
+
and_return(result2)
|
222
|
+
mock.should_receive(:write)
|
223
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
224
|
+
|
225
|
+
conn.next_msgid # simulates ongoing query
|
226
|
+
|
227
|
+
assert result = conn.bind(
|
228
|
+
method: :simple,
|
229
|
+
username: "uid=user1,ou=People,dc=rubyldap,dc=com",
|
230
|
+
password: "passworD1")
|
231
|
+
assert result.success?
|
232
|
+
assert_equal 2, result.message_id
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_queued_read_bind_sasl
|
236
|
+
result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult)
|
237
|
+
result2 = make_message(2, app_tag: Net::LDAP::PDU::BindResult)
|
238
|
+
|
239
|
+
mock = flexmock("socket")
|
240
|
+
mock.should_receive(:read_ber).
|
241
|
+
and_return(result1).
|
242
|
+
and_return(result2)
|
243
|
+
mock.should_receive(:write)
|
244
|
+
conn = Net::LDAP::Connection.new(:socket => mock)
|
245
|
+
|
246
|
+
conn.next_msgid # simulates ongoing query
|
247
|
+
|
248
|
+
assert result = conn.bind(
|
249
|
+
method: :sasl,
|
250
|
+
mechanism: "fake",
|
251
|
+
initial_credential: "passworD1",
|
252
|
+
challenge_response: flexmock("challenge proc"))
|
253
|
+
assert result.success?
|
254
|
+
assert_equal 2, result.message_id
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
class TestLDAPConnectionErrors < Test::Unit::TestCase
|
259
|
+
def setup
|
260
|
+
@tcp_socket = flexmock(:connection)
|
261
|
+
@tcp_socket.should_receive(:write)
|
262
|
+
flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket)
|
263
|
+
@connection = Net::LDAP::Connection.new(:host => 'test.mocked.com', :port => 636)
|
264
|
+
end
|
265
|
+
|
266
|
+
def test_error_failed_operation
|
267
|
+
ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeUnwillingToPerform, "", "The provided password value was rejected by a password validator: The provided password did not contain enough characters from the character set 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. The minimum number of characters from that set that must be present in user passwords is 1"])
|
268
|
+
ber.ber_identifier = Net::LDAP::PDU::ModifyResponse
|
269
|
+
@tcp_socket.should_receive(:read_ber).and_return([1, ber])
|
270
|
+
|
271
|
+
result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]])
|
272
|
+
assert result.failure?, "should be failure"
|
273
|
+
assert_equal "The provided password value was rejected by a password validator: The provided password did not contain enough characters from the character set 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. The minimum number of characters from that set that must be present in user passwords is 1", result.error_message
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_no_error_on_success
|
277
|
+
ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""])
|
278
|
+
ber.ber_identifier = Net::LDAP::PDU::ModifyResponse
|
279
|
+
@tcp_socket.should_receive(:read_ber).and_return([1, ber])
|
280
|
+
|
281
|
+
result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]])
|
282
|
+
assert result.success?, "should be success"
|
283
|
+
assert_equal "", result.error_message
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
class TestLDAPConnectionInstrumentation < Test::Unit::TestCase
|
288
|
+
def setup
|
289
|
+
@tcp_socket = flexmock(:connection)
|
290
|
+
@tcp_socket.should_receive(:write)
|
291
|
+
flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket)
|
292
|
+
|
293
|
+
@service = MockInstrumentationService.new
|
294
|
+
@connection = Net::LDAP::Connection.new \
|
295
|
+
:host => 'test.mocked.com',
|
296
|
+
:port => 636,
|
297
|
+
:instrumentation_service => @service
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_write_net_ldap_connection_event
|
301
|
+
ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""])
|
302
|
+
ber.ber_identifier = Net::LDAP::PDU::BindResult
|
303
|
+
read_result = [1, ber]
|
304
|
+
@tcp_socket.should_receive(:read_ber).and_return(read_result)
|
305
|
+
|
306
|
+
events = @service.subscribe "write.net_ldap_connection"
|
307
|
+
|
308
|
+
result = @connection.bind(method: :anon)
|
309
|
+
assert result.success?, "should be success"
|
310
|
+
|
311
|
+
# a write event
|
312
|
+
payload, result = events.pop
|
313
|
+
assert payload.has_key?(:result)
|
314
|
+
assert payload.has_key?(:content_length)
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_read_net_ldap_connection_event
|
318
|
+
ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""])
|
319
|
+
ber.ber_identifier = Net::LDAP::PDU::BindResult
|
320
|
+
read_result = [1, ber]
|
321
|
+
@tcp_socket.should_receive(:read_ber).and_return(read_result)
|
322
|
+
|
323
|
+
events = @service.subscribe "read.net_ldap_connection"
|
324
|
+
|
325
|
+
result = @connection.bind(method: :anon)
|
326
|
+
assert result.success?, "should be success"
|
327
|
+
|
328
|
+
# a read event
|
329
|
+
payload, result = events.pop
|
330
|
+
assert payload.has_key?(:result)
|
331
|
+
assert_equal read_result, result
|
332
|
+
end
|
333
|
+
|
334
|
+
def test_parse_pdu_net_ldap_connection_event
|
335
|
+
ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""])
|
336
|
+
ber.ber_identifier = Net::LDAP::PDU::BindResult
|
337
|
+
read_result = [1, ber]
|
338
|
+
@tcp_socket.should_receive(:read_ber).and_return(read_result)
|
339
|
+
|
340
|
+
events = @service.subscribe "parse_pdu.net_ldap_connection"
|
341
|
+
|
342
|
+
result = @connection.bind(method: :anon)
|
343
|
+
assert result.success?, "should be success"
|
344
|
+
|
345
|
+
# a parse_pdu event
|
346
|
+
payload, result = events.pop
|
347
|
+
assert payload.has_key?(:pdu)
|
348
|
+
assert payload.has_key?(:app_tag)
|
349
|
+
assert payload.has_key?(:message_id)
|
350
|
+
assert_equal Net::LDAP::PDU::BindResult, payload[:app_tag]
|
351
|
+
assert_equal 1, payload[:message_id]
|
352
|
+
pdu = payload[:pdu]
|
353
|
+
assert_equal Net::LDAP::ResultCodeSuccess, pdu.result_code
|
354
|
+
end
|
355
|
+
|
356
|
+
def test_bind_net_ldap_connection_event
|
357
|
+
ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""])
|
358
|
+
ber.ber_identifier = Net::LDAP::PDU::BindResult
|
359
|
+
bind_result = [1, ber]
|
360
|
+
@tcp_socket.should_receive(:read_ber).and_return(bind_result)
|
361
|
+
|
362
|
+
events = @service.subscribe "bind.net_ldap_connection"
|
363
|
+
|
364
|
+
result = @connection.bind(method: :anon)
|
365
|
+
assert result.success?, "should be success"
|
366
|
+
|
367
|
+
# a read event
|
368
|
+
payload, result = events.pop
|
369
|
+
assert payload.has_key?(:result)
|
370
|
+
assert result.success?, "should be success"
|
371
|
+
end
|
372
|
+
|
373
|
+
def test_search_net_ldap_connection_event
|
374
|
+
# search data
|
375
|
+
search_data_ber = Net::BER::BerIdentifiedArray.new([1, [
|
376
|
+
"uid=user1,ou=People,dc=rubyldap,dc=com",
|
377
|
+
[ ["uid", ["user1"]] ]
|
378
|
+
]])
|
379
|
+
search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData
|
380
|
+
search_data = [1, search_data_ber]
|
381
|
+
# search result (end of results)
|
382
|
+
search_result_ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""])
|
383
|
+
search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult
|
384
|
+
search_result = [1, search_result_ber]
|
385
|
+
@tcp_socket.should_receive(:read_ber).and_return(search_data).
|
386
|
+
and_return(search_result)
|
387
|
+
|
388
|
+
events = @service.subscribe "search.net_ldap_connection"
|
389
|
+
unread = @service.subscribe "search_messages_unread.net_ldap_connection"
|
390
|
+
|
391
|
+
result = @connection.search(filter: "(uid=user1)", base: "ou=People,dc=rubyldap,dc=com")
|
392
|
+
assert result.success?, "should be success"
|
393
|
+
|
394
|
+
# a search event
|
395
|
+
payload, result = events.pop
|
396
|
+
assert payload.has_key?(:result)
|
397
|
+
assert payload.has_key?(:filter)
|
398
|
+
assert_equal "(uid=user1)", payload[:filter].to_s
|
399
|
+
assert result
|
400
|
+
|
401
|
+
# ensure no unread
|
402
|
+
assert unread.empty?, "should not have any leftover unread messages"
|
403
|
+
end
|
24
404
|
end
|