From bb798c4d77defc08d17a4565be9b26e855a00d3b Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 01:26:48 -0700 Subject: [PATCH 01/10] Add failing test for add nested in an open search This is because Net::LDAP::Connection#add calls read without queueing, meaning it can read the wrong message off the socket. --- test/integration/test_open.rb | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/integration/test_open.rb b/test/integration/test_open.rb index 6d86f49a..36724f5d 100644 --- a/test/integration/test_open.rb +++ b/test/integration/test_open.rb @@ -21,6 +21,10 @@ def test_binds_with_open assert_equal 1, events.size end + # NOTE: query for two or more entries so that the socket must be read + # multiple times. + # See The Problem: https://github.com/ruby-ldap/ruby-net-ldap/issues/136 + def test_nested_search_without_open entries = [] nested_entry = nil @@ -48,4 +52,37 @@ def test_nested_search_with_open assert_equal "user3", nested_entry.uid.first assert_equal %w(user1 user2), entries end + + def test_nested_add_with_open + entries = [] + nested_entry = nil + + dn = "uid=nested-open-added-user1,ou=People,dc=rubyldap,dc=com" + attrs = { + objectclass: %w(top inetOrgPerson organizationalPerson person), + uid: "nested-open-added-user1", + cn: "nested-open-added-user1", + sn: "nested-open-added-user1", + mail: "nested-open-added-user1@rubyldap.com" + } + + @ldap.authenticate "cn=admin,dc=rubyldap,dc=com", "passworD1" + @ldap.delete dn: dn + + @ldap.open do + @ldap.search(filter: "(|(uid=user1)(uid=user2))", base: "ou=People,dc=rubyldap,dc=com") do |entry| + entries << entry.uid.first + + nested_entry ||= begin + assert @ldap.add(dn: dn, attributes: attrs), @ldap.get_operation_result.inspect + @ldap.search(base: dn, scope: Net::LDAP::SearchScope_BaseObject).first + end + end + end + + assert_equal %w(user1 user2), entries + assert_equal "nested-open-added-user1", nested_entry.uid.first + ensure + @ldap.delete dn: dn + end end From b8ffde7d02e6868ee3421141a2cc18ee84eb867c Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Wed, 22 Oct 2014 01:29:16 -0700 Subject: [PATCH 02/10] Use queued_read for Net::LDAP::Connection#add --- lib/net/ldap/connection.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index cafa30d4..d9c234ad 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -610,10 +610,11 @@ def add(args) add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence } - request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(8) - write(request) + message_id = next_msgid + request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(8) - pdu = read + write(request, nil, message_id) + pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::AddResponse raise Net::LDAP::LdapError, "response missing or invalid" From c00105eb8e47e7f04893bb416992fc99fc4883ff Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 01:17:59 -0700 Subject: [PATCH 03/10] Unit test queued_read and usage --- test/test_ldap_connection.rb | 84 +++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 46e535ff..1164883f 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -67,6 +67,86 @@ def test_write_increments_msgid end end +class TestLDAPConnectionSocketReads < Test::Unit::TestCase + def make_message(message_id, app_tag: Net::LDAP::PDU::SearchResult, code: Net::LDAP::ResultCodeSuccess, matched_dn: "", error_message: "") + result = Net::BER::BerIdentifiedArray.new([code, matched_dn, error_message]) + result.ber_identifier = app_tag + [message_id, result] + end + + def test_queued_read_drains_queue_before_read + result1a = make_message(1, error_message: "one") + result1b = make_message(1, error_message: "two") + + mock = flexmock("socket") + mock.should_receive(:read_ber).and_return(result1b) + conn = Net::LDAP::Connection.new(:socket => mock) + + conn.message_queue[1].push Net::LDAP::PDU.new(result1a) + + assert msg1 = conn.queued_read(1) + assert msg2 = conn.queued_read(1) + + assert_equal 1, msg1.message_id + assert_equal "one", msg1.error_message + assert_equal 1, msg2.message_id + assert_equal "two", msg2.error_message + end + + def test_queued_read_reads_until_message_id_match + result1 = make_message(1) + result2 = make_message(2) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + conn = Net::LDAP::Connection.new(:socket => mock) + + assert result = conn.queued_read(2) + assert_equal 2, result.message_id + assert_equal 1, conn.queued_read(1).message_id + end + + def test_queued_read_modify + result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult) + result2 = make_message(2, app_tag: Net::LDAP::PDU::ModifyResponse) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + mock.should_receive(:write) + conn = Net::LDAP::Connection.new(:socket => mock) + + conn.next_msgid # simulates ongoing query + + conn.instance_variable_get("@msgid") + + assert result = conn.modify(dn: "uid=modified-user1,ou=People,dc=rubyldap,dc=com", + operations: [[:add, :mail, "modified-user1@example.com"]]) + assert result.success? + assert_equal 2, result.message_id + end + + def test_queued_read_add + result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult) + result2 = make_message(2, app_tag: Net::LDAP::PDU::AddResponse) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + mock.should_receive(:write) + conn = Net::LDAP::Connection.new(:socket => mock) + + conn.next_msgid # simulates ongoing query + + assert result = conn.add(dn: "uid=added-user1,ou=People,dc=rubyldap,dc=com") + assert result.success? + assert_equal 2, result.message_id + end +end class TestLDAPConnectionErrors < Test::Unit::TestCase def setup @@ -79,7 +159,7 @@ def setup def test_error_failed_operation 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"]) ber.ber_identifier = Net::LDAP::PDU::ModifyResponse - @tcp_socket.should_receive(:read_ber).and_return([2, ber]) + @tcp_socket.should_receive(:read_ber).and_return([1, ber]) result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) assert result.failure?, "should be failure" @@ -89,7 +169,7 @@ def test_error_failed_operation def test_no_error_on_success ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::ModifyResponse - @tcp_socket.should_receive(:read_ber).and_return([2, ber]) + @tcp_socket.should_receive(:read_ber).and_return([1, ber]) result = @connection.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]]) assert result.success?, "should be success" From 8b77189c2254305e29580dece8898a0b7fd65bdd Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 01:18:19 -0700 Subject: [PATCH 04/10] Use queued_read in modify --- lib/net/ldap/connection.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 565eb7bc..4327c242 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -583,11 +583,15 @@ def self.modify_ops(operations) def modify(args) modify_dn = args[:dn] or raise "Unable to modify empty DN" ops = self.class.modify_ops args[:operations] - request = [ modify_dn.to_ber, - ops.to_ber_sequence ].to_ber_appsequence(Net::LDAP::PDU::ModifyRequest) - write(request) - pdu = read + message_id = next_msgid + request = [ + modify_dn.to_ber, + ops.to_ber_sequence + ].to_ber_appsequence(Net::LDAP::PDU::ModifyRequest) + + write(request, nil, message_id) + pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyResponse raise Net::LDAP::LdapError, "response missing or invalid" From 04bad5f2f07a127da8ae95cef6341686ae274dc9 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 01:27:24 -0700 Subject: [PATCH 05/10] Can't use keyword args in 1.9 --- test/test_ldap_connection.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 1164883f..2b1c6983 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -68,9 +68,15 @@ def test_write_increments_msgid end class TestLDAPConnectionSocketReads < Test::Unit::TestCase - def make_message(message_id, app_tag: Net::LDAP::PDU::SearchResult, code: Net::LDAP::ResultCodeSuccess, matched_dn: "", error_message: "") - result = Net::BER::BerIdentifiedArray.new([code, matched_dn, error_message]) - result.ber_identifier = app_tag + def make_message(message_id, options = {}) + options = { + app_tag: Net::LDAP::PDU::SearchResult, + code: Net::LDAP::ResultCodeSuccess, + matched_dn: "", + error_message: "" + }.merge(options) + result = Net::BER::BerIdentifiedArray.new([options[:code], options[:matched_dn], options[:error_message]]) + result.ber_identifier = options[:app_tag] [message_id, result] end From 4132f28fef62759122796762062302069115fa54 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 17:18:45 -0700 Subject: [PATCH 06/10] Use queued_read for rename operation --- lib/net/ldap/connection.rb | 10 +++++----- test/test_ldap_connection.rb | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 4327c242..4ed1812a 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -636,12 +636,12 @@ def rename(args) delete_attrs = args[:delete_attributes] ? true : false new_superior = args[:new_superior] - request = [old_dn.to_ber, new_rdn.to_ber, delete_attrs.to_ber] - request << new_superior.to_ber_contextspecific(0) unless new_superior == nil - - write(request.to_ber_appsequence(Net::LDAP::PDU::ModifyRDNRequest)) + message_id = next_msgid + request = [old_dn.to_ber, new_rdn.to_ber, delete_attrs.to_ber] + request << new_superior.to_ber_contextspecific(0) unless new_superior == nil - pdu = read + write(request.to_ber_appsequence(Net::LDAP::PDU::ModifyRDNRequest), nil, message_id) + pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::ModifyRDNResponse raise Net::LDAP::LdapError.new "response missing or invalid" diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 2b1c6983..09c97b0b 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -152,6 +152,27 @@ def test_queued_read_add assert result.success? assert_equal 2, result.message_id end + + def test_queued_read_rename + result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult) + result2 = make_message(2, app_tag: Net::LDAP::PDU::ModifyRDNResponse) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + mock.should_receive(:write) + conn = Net::LDAP::Connection.new(:socket => mock) + + conn.next_msgid # simulates ongoing query + + assert result = conn.rename( + olddn: "uid=renamable-user1,ou=People,dc=rubyldap,dc=com", + newrdn: "uid=renamed-user1" + ) + assert result.success? + assert_equal 2, result.message_id + end end class TestLDAPConnectionErrors < Test::Unit::TestCase From e015dfb0396d3748d64768add5b3d55465c9ae53 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 17:24:32 -0700 Subject: [PATCH 07/10] Use queued_read for delete operation --- lib/net/ldap/connection.rb | 9 +++++---- test/test_ldap_connection.rb | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 4ed1812a..7bb56473 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -655,11 +655,12 @@ def rename(args) #++ def delete(args) dn = args[:dn] or raise "Unable to delete empty DN" - controls = args.include?(:control_codes) ? args[:control_codes].to_ber_control : nil #use nil so we can compact later - request = dn.to_s.to_ber_application_string(Net::LDAP::PDU::DeleteRequest) - write(request, controls) + controls = args.include?(:control_codes) ? args[:control_codes].to_ber_control : nil #use nil so we can compact later + message_id = next_msgid + request = dn.to_s.to_ber_application_string(Net::LDAP::PDU::DeleteRequest) - pdu = read + write(request, controls, message_id) + pdu = queued_read(message_id) if !pdu || pdu.app_tag != Net::LDAP::PDU::DeleteResponse raise Net::LDAP::LdapError, "response missing or invalid" diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 09c97b0b..9222ea84 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -173,6 +173,24 @@ def test_queued_read_rename assert result.success? assert_equal 2, result.message_id end + + def test_queued_read_delete + result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult) + result2 = make_message(2, app_tag: Net::LDAP::PDU::DeleteResponse) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + mock.should_receive(:write) + conn = Net::LDAP::Connection.new(:socket => mock) + + conn.next_msgid # simulates ongoing query + + assert result = conn.delete(dn: "uid=deletable-user1,ou=People,dc=rubyldap,dc=com") + assert result.success? + assert_equal 2, result.message_id + end end class TestLDAPConnectionErrors < Test::Unit::TestCase From 6186e419346c0e0311963628936cfefa882edd92 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 17:40:48 -0700 Subject: [PATCH 08/10] Use queued_read for start_tls --- lib/net/ldap/connection.rb | 16 ++++++++++++---- test/test_ldap_connection.rb | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 7bb56473..8206bec4 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -87,10 +87,18 @@ def setup_encryption(args) # additional branches requiring server validation and peer certs, etc. # go here. when :start_tls - request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) - write(request) - pdu = read - raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil? + message_id = next_msgid + request = [ + Net::LDAP::StartTlsOid.to_ber_contextspecific(0) + ].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest) + + write(request, nil, message_id) + pdu = queued_read(message_id) + + if pdu.nil? || pdu.app_tag != Net::LDAP::PDU::ExtendedResponse + raise Net::LDAP::LdapError, "no start_tls result" + end + if pdu.result_code.zero? @conn = self.class.wrap_with_ssl(@conn) else diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 9222ea84..f6f9846e 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -191,6 +191,25 @@ def test_queued_read_delete assert result.success? assert_equal 2, result.message_id end + + def test_queued_read_setup_encryption_with_start_tls + result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult) + result2 = make_message(2, app_tag: Net::LDAP::PDU::ExtendedResponse) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + mock.should_receive(:write) + conn = Net::LDAP::Connection.new(:socket => mock) + flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock). + and_return(mock) + + conn.next_msgid # simulates ongoing query + + assert result = conn.setup_encryption(method: :start_tls) + assert_equal mock, result + end end class TestLDAPConnectionErrors < Test::Unit::TestCase From 47017f1621e0792d0b39ecc7b0432636514a5754 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 17:56:31 -0700 Subject: [PATCH 09/10] Use queued_read for bind_simple --- lib/net/ldap/connection.rb | 16 +++++++++++----- test/test_ldap_connection.rb | 31 ++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 8206bec4..42315996 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -234,12 +234,18 @@ def bind_simple(auth) raise Net::LDAP::LdapError, "Invalid binding information" unless (user && psw) - request = [LdapVersion.to_ber, user.to_ber, - psw.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::BindRequest) - write(request) + message_id = next_msgid + request = [ + LdapVersion.to_ber, user.to_ber, + psw.to_ber_contextspecific(0) + ].to_ber_appsequence(Net::LDAP::PDU::BindRequest) + + write(request, nil, message_id) + pdu = queued_read(message_id) - pdu = read - raise Net::LDAP::LdapError, "no bind result" unless pdu + if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult + raise Net::LDAP::LdapError, "no bind result" + end pdu end diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index f6f9846e..5759c805 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -210,6 +210,27 @@ def test_queued_read_setup_encryption_with_start_tls assert result = conn.setup_encryption(method: :start_tls) assert_equal mock, result end + + def test_queued_read_bind_simple + result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult) + result2 = make_message(2, app_tag: Net::LDAP::PDU::BindResult) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + mock.should_receive(:write) + conn = Net::LDAP::Connection.new(:socket => mock) + + conn.next_msgid # simulates ongoing query + + assert result = conn.bind( + method: :simple, + username: "uid=user1,ou=People,dc=rubyldap,dc=com", + password: "passworD1") + assert result.success? + assert_equal 2, result.message_id + end end class TestLDAPConnectionErrors < Test::Unit::TestCase @@ -257,7 +278,7 @@ def setup def test_write_net_ldap_connection_event ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult - read_result = [2, ber] + read_result = [1, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) events = @service.subscribe "write.net_ldap_connection" @@ -274,7 +295,7 @@ def test_write_net_ldap_connection_event def test_read_net_ldap_connection_event ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult - read_result = [2, ber] + read_result = [1, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) events = @service.subscribe "read.net_ldap_connection" @@ -291,7 +312,7 @@ def test_read_net_ldap_connection_event def test_parse_pdu_net_ldap_connection_event ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult - read_result = [2, ber] + read_result = [1, ber] @tcp_socket.should_receive(:read_ber).and_return(read_result) events = @service.subscribe "parse_pdu.net_ldap_connection" @@ -305,7 +326,7 @@ def test_parse_pdu_net_ldap_connection_event assert payload.has_key?(:app_tag) assert payload.has_key?(:message_id) assert_equal Net::LDAP::PDU::BindResult, payload[:app_tag] - assert_equal 2, payload[:message_id] + assert_equal 1, payload[:message_id] pdu = payload[:pdu] assert_equal Net::LDAP::ResultCodeSuccess, pdu.result_code end @@ -313,7 +334,7 @@ def test_parse_pdu_net_ldap_connection_event def test_bind_net_ldap_connection_event ber = Net::BER::BerIdentifiedArray.new([Net::LDAP::ResultCodeSuccess, "", ""]) ber.ber_identifier = Net::LDAP::PDU::BindResult - bind_result = [2, ber] + bind_result = [1, ber] @tcp_socket.should_receive(:read_ber).and_return(bind_result) events = @service.subscribe "bind.net_ldap_connection" From d1241820f046b05be086477500294c115df47bb8 Mon Sep 17 00:00:00 2001 From: Matt Todd Date: Thu, 23 Oct 2014 18:11:02 -0700 Subject: [PATCH 10/10] Use queued_read for bind_sasl --- lib/net/ldap/connection.rb | 15 +++++++++++---- test/test_ldap_connection.rb | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb index 42315996..91fb7e90 100644 --- a/lib/net/ldap/connection.rb +++ b/lib/net/ldap/connection.rb @@ -276,14 +276,21 @@ def bind_sasl(auth) auth[:challenge_response] raise Net::LDAP::LdapError, "Invalid binding information" unless (mech && cred && chall) + message_id = next_msgid + n = 0 loop { sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3) - request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(Net::LDAP::PDU::BindRequest) - write(request) + request = [ + LdapVersion.to_ber, "".to_ber, sasl + ].to_ber_appsequence(Net::LDAP::PDU::BindRequest) + + write(request, nil, message_id) + pdu = queued_read(message_id) - pdu = read - raise Net::LDAP::LdapError, "no bind result" unless pdu + if !pdu || pdu.app_tag != Net::LDAP::PDU::BindResult + raise Net::LDAP::LdapError, "no bind result" + end return pdu unless pdu.result_code == Net::LDAP::ResultCodeSaslBindInProgress raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges) diff --git a/test/test_ldap_connection.rb b/test/test_ldap_connection.rb index 5759c805..56dfe813 100644 --- a/test/test_ldap_connection.rb +++ b/test/test_ldap_connection.rb @@ -231,6 +231,28 @@ def test_queued_read_bind_simple assert result.success? assert_equal 2, result.message_id end + + def test_queued_read_bind_sasl + result1 = make_message(1, app_tag: Net::LDAP::PDU::SearchResult) + result2 = make_message(2, app_tag: Net::LDAP::PDU::BindResult) + + mock = flexmock("socket") + mock.should_receive(:read_ber). + and_return(result1). + and_return(result2) + mock.should_receive(:write) + conn = Net::LDAP::Connection.new(:socket => mock) + + conn.next_msgid # simulates ongoing query + + assert result = conn.bind( + method: :sasl, + mechanism: "fake", + initial_credential: "passworD1", + challenge_response: flexmock("challenge proc")) + assert result.success? + assert_equal 2, result.message_id + end end class TestLDAPConnectionErrors < Test::Unit::TestCase pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy